mirror of
https://github.com/panda3d/panda3d.git
synced 2026-02-20 14:19:25 -06:00
Also remove most `using namespace std;` statements. The only one that remains is in py_panda.h. Closes #350 Closes #335
225 lines
5.7 KiB
C++
225 lines
5.7 KiB
C++
/**
|
|
* PANDA 3D SOFTWARE
|
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
*
|
|
* All use of this software is subject to the terms of the revised BSD
|
|
* license. You should have received a copy of this license along
|
|
* with this source code in a file named "LICENSE."
|
|
*
|
|
* @file mkdir_complete.cxx
|
|
* @author drose
|
|
* @date 2009-06-29
|
|
*/
|
|
|
|
#include "mkdir_complete.h"
|
|
#include "is_pathsep.h"
|
|
#include "wstring_encode.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <io.h> // chmod()
|
|
#else
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h> // for mkdir()
|
|
#include <errno.h>
|
|
#include <string.h> // strerror()
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
using std::ostream;
|
|
using std::string;
|
|
using std::wstring;
|
|
|
|
/**
|
|
* Returns the directory component of the indicated pathname, or the empty
|
|
* string if there is no directory prefix.
|
|
*/
|
|
static string
|
|
get_dirname(const string &filename) {
|
|
size_t p = filename.length();
|
|
while (p > 0) {
|
|
--p;
|
|
if (is_pathsep(filename[p])) {
|
|
return filename.substr(0, p);
|
|
}
|
|
}
|
|
|
|
return string();
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
/**
|
|
* The wide-character implementation of get_dirname(). Only implemented (and
|
|
* needed) on Windows.
|
|
*/
|
|
static wstring
|
|
get_dirname_w(const wstring &filename) {
|
|
size_t p = filename.length();
|
|
while (p > 0) {
|
|
--p;
|
|
if (is_pathsep(filename[p])) {
|
|
return filename.substr(0, p);
|
|
}
|
|
}
|
|
|
|
return wstring();
|
|
}
|
|
#endif // _WIN32
|
|
|
|
|
|
|
|
/**
|
|
* Creates a new directory, with normal access privileges. Returns true on
|
|
* success, false on failure. Will create intervening directories if
|
|
* necessary.
|
|
*/
|
|
bool
|
|
mkdir_complete(const string &dirname, ostream &logfile) {
|
|
#ifdef _WIN32
|
|
wstring dirname_w;
|
|
if (!string_to_wstring(dirname_w, dirname)) {
|
|
return false;
|
|
}
|
|
return mkdir_complete_w(dirname_w, logfile);
|
|
|
|
#else //_WIN32
|
|
if (mkdir(dirname.c_str(), 0755) == 0) {
|
|
// Success!
|
|
return true;
|
|
}
|
|
|
|
// Failed.
|
|
if (errno == EEXIST) {
|
|
// Not really an error: the directory is already there.
|
|
return true;
|
|
}
|
|
|
|
if (errno == ENOENT || errno == EACCES) {
|
|
// We need to make the parent directory first.
|
|
string parent = get_dirname(dirname);
|
|
if (!parent.empty() && mkdir_complete(parent, logfile)) {
|
|
// Parent successfully created. Try again to make the child.
|
|
if (mkdir(dirname.c_str(), 0755) == 0) {
|
|
// Got it!
|
|
return true;
|
|
}
|
|
// Couldn't create the directory. :(
|
|
logfile
|
|
<< "Couldn't create " << dirname << ": " << strerror(errno) << "\n";
|
|
}
|
|
}
|
|
return false;
|
|
|
|
#endif // _WIN32
|
|
}
|
|
|
|
/**
|
|
* Creates a new file with normal access priviledges. Returns true on
|
|
* success, false on failure. This will create intervening directories if
|
|
* needed.
|
|
*/
|
|
bool
|
|
mkfile_complete(const string &filename, ostream &logfile) {
|
|
#ifdef _WIN32
|
|
wstring filename_w;
|
|
if (!string_to_wstring(filename_w, filename)) {
|
|
return false;
|
|
}
|
|
return mkfile_complete_w(filename_w, logfile);
|
|
#else // _WIN32
|
|
// Make sure we delete any previously-existing file first.
|
|
unlink(filename.c_str());
|
|
|
|
int fd = creat(filename.c_str(), 0755);
|
|
if (fd == -1) {
|
|
// Try to make the parent directory first.
|
|
string parent = get_dirname(filename);
|
|
if (!parent.empty() && mkdir_complete(parent, logfile)) {
|
|
// Parent successfully created. Try again to make the file.
|
|
fd = creat(filename.c_str(), 0755);
|
|
}
|
|
if (fd == -1) {
|
|
logfile
|
|
<< "Couldn't create " << filename << ": " << strerror(errno) << "\n";
|
|
return false;
|
|
}
|
|
}
|
|
close(fd);
|
|
return true;
|
|
|
|
#endif // _WIN32
|
|
}
|
|
|
|
|
|
#ifdef _WIN32
|
|
/**
|
|
* The wide-character implementation of mkdir_complete(). Only implemented
|
|
* (and needed) on Windows.
|
|
*/
|
|
bool
|
|
mkdir_complete_w(const wstring &dirname, ostream &logfile) {
|
|
if (CreateDirectoryW(dirname.c_str(), nullptr) != 0) {
|
|
// Success!
|
|
return true;
|
|
}
|
|
|
|
// Failed.
|
|
DWORD last_error = GetLastError();
|
|
if (last_error == ERROR_ALREADY_EXISTS) {
|
|
// Not really an error: the directory is already there.
|
|
return true;
|
|
}
|
|
|
|
if (last_error == ERROR_PATH_NOT_FOUND) {
|
|
// We need to make the parent directory first.
|
|
wstring parent = get_dirname_w(dirname);
|
|
if (!parent.empty() && mkdir_complete_w(parent, logfile)) {
|
|
// Parent successfully created. Try again to make the child.
|
|
if (CreateDirectoryW(dirname.c_str(), nullptr) != 0) {
|
|
// Got it!
|
|
return true;
|
|
}
|
|
logfile
|
|
<< "Couldn't create " << dirname << "\n";
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
#endif // _WIN32
|
|
|
|
#ifdef _WIN32
|
|
/**
|
|
* The wide-character implementation of mkfile_complete(). Only implemented
|
|
* (and needed) on Windows.
|
|
*/
|
|
bool
|
|
mkfile_complete_w(const wstring &filename, ostream &logfile) {
|
|
// Make sure we delete any previously-existing file first.
|
|
|
|
// Windows can't delete a file if it's read-only. Weird.
|
|
_wchmod(filename.c_str(), 0644);
|
|
_wunlink(filename.c_str());
|
|
|
|
HANDLE file = CreateFileW(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if (file == INVALID_HANDLE_VALUE) {
|
|
// Try to make the parent directory first.
|
|
wstring parent = get_dirname_w(filename);
|
|
if (!parent.empty() && mkdir_complete_w(parent, logfile)) {
|
|
// Parent successfully created. Try again to make the file.
|
|
file = CreateFileW(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
}
|
|
if (file == INVALID_HANDLE_VALUE) {
|
|
logfile
|
|
<< "Couldn't create " << filename << "\n";
|
|
return false;
|
|
}
|
|
}
|
|
CloseHandle(file);
|
|
return true;
|
|
}
|
|
#endif // _WIN32
|