Improve LLFile to be consistent between Windows and Linux/Mac
parent
6f1df1a8d2
commit
e12958161c
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headers.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#include <vector>
|
||||
#else
|
||||
#include <errno.h>
|
||||
|
|
@ -49,6 +48,86 @@ static std::string empty;
|
|||
// variants of strerror() to report errors.
|
||||
|
||||
#if LL_WINDOWS
|
||||
namespace
|
||||
{
|
||||
struct errentry
|
||||
{
|
||||
unsigned long oserr; // OS return value
|
||||
int errcode; // System V error code
|
||||
};
|
||||
}
|
||||
|
||||
static errentry const errtable[]
|
||||
{
|
||||
{ ERROR_INVALID_FUNCTION, EINVAL }, // 1
|
||||
{ ERROR_FILE_NOT_FOUND, ENOENT }, // 2
|
||||
{ ERROR_PATH_NOT_FOUND, ENOENT }, // 3
|
||||
{ ERROR_TOO_MANY_OPEN_FILES, EMFILE }, // 4
|
||||
{ ERROR_ACCESS_DENIED, EACCES }, // 5
|
||||
{ ERROR_INVALID_HANDLE, EBADF }, // 6
|
||||
{ ERROR_ARENA_TRASHED, ENOMEM }, // 7
|
||||
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, // 8
|
||||
{ ERROR_INVALID_BLOCK, ENOMEM }, // 9
|
||||
{ ERROR_BAD_ENVIRONMENT, E2BIG }, // 10
|
||||
{ ERROR_BAD_FORMAT, ENOEXEC }, // 11
|
||||
{ ERROR_INVALID_ACCESS, EINVAL }, // 12
|
||||
{ ERROR_INVALID_DATA, EINVAL }, // 13
|
||||
{ ERROR_INVALID_DRIVE, ENOENT }, // 15
|
||||
{ ERROR_CURRENT_DIRECTORY, EACCES }, // 16
|
||||
{ ERROR_NOT_SAME_DEVICE, EXDEV }, // 17
|
||||
{ ERROR_NO_MORE_FILES, ENOENT }, // 18
|
||||
{ ERROR_LOCK_VIOLATION, EACCES }, // 33
|
||||
{ ERROR_BAD_NETPATH, ENOENT }, // 53
|
||||
{ ERROR_NETWORK_ACCESS_DENIED, EACCES }, // 65
|
||||
{ ERROR_BAD_NET_NAME, ENOENT }, // 67
|
||||
{ ERROR_FILE_EXISTS, EEXIST }, // 80
|
||||
{ ERROR_CANNOT_MAKE, EACCES }, // 82
|
||||
{ ERROR_FAIL_I24, EACCES }, // 83
|
||||
{ ERROR_INVALID_PARAMETER, EINVAL }, // 87
|
||||
{ ERROR_NO_PROC_SLOTS, EAGAIN }, // 89
|
||||
{ ERROR_DRIVE_LOCKED, EACCES }, // 108
|
||||
{ ERROR_BROKEN_PIPE, EPIPE }, // 109
|
||||
{ ERROR_DISK_FULL, ENOSPC }, // 112
|
||||
{ ERROR_INVALID_TARGET_HANDLE, EBADF }, // 114
|
||||
{ ERROR_WAIT_NO_CHILDREN, ECHILD }, // 128
|
||||
{ ERROR_CHILD_NOT_COMPLETE, ECHILD }, // 129
|
||||
{ ERROR_DIRECT_ACCESS_HANDLE, EBADF }, // 130
|
||||
{ ERROR_NEGATIVE_SEEK, EINVAL }, // 131
|
||||
{ ERROR_SEEK_ON_DEVICE, EACCES }, // 132
|
||||
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, // 145
|
||||
{ ERROR_NOT_LOCKED, EACCES }, // 158
|
||||
{ ERROR_BAD_PATHNAME, ENOENT }, // 161
|
||||
{ ERROR_MAX_THRDS_REACHED, EAGAIN }, // 164
|
||||
{ ERROR_LOCK_FAILED, EACCES }, // 167
|
||||
{ ERROR_ALREADY_EXISTS, EEXIST }, // 183
|
||||
{ ERROR_FILENAME_EXCED_RANGE, ENOENT }, // 206
|
||||
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, // 215
|
||||
{ ERROR_NO_UNICODE_TRANSLATION, EILSEQ }, // 1113
|
||||
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM } // 1816
|
||||
};
|
||||
|
||||
// Number of elements in the error translation table
|
||||
#define ERRTABLECOUNT (sizeof(errtable) / sizeof(errtable[0]))
|
||||
|
||||
static int set_errno_from_oserror(unsigned long oserr)
|
||||
{
|
||||
if (!oserr)
|
||||
return 0;
|
||||
|
||||
// Check the table for the OS error code
|
||||
for (unsigned i{0}; i < ERRTABLECOUNT; ++i)
|
||||
{
|
||||
if (oserr == errtable[i].oserr)
|
||||
{
|
||||
_set_errno(errtable[i].errcode);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// On Windows, use strerror_s().
|
||||
std::string strerr(int errn)
|
||||
{
|
||||
|
|
@ -57,7 +136,61 @@ std::string strerr(int errn)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
typedef std::basic_ios<char,std::char_traits < char > > _Myios;
|
||||
inline bool is_slash(wchar_t const c)
|
||||
{
|
||||
return c == L'\\' || c == L'/';
|
||||
}
|
||||
|
||||
static std::wstring utf8path_to_wstring(const std::string& utf8path)
|
||||
{
|
||||
if (utf8path.size() >= MAX_PATH)
|
||||
{
|
||||
// By prepending "\\?\" to a path, Windows widechar file APIs will not fail on long path names
|
||||
std::wstring utf16path = L"\\\\?\\" + ll_convert<std::wstring>(utf8path);
|
||||
// We need to make sure that the path does not contain forward slashes as above
|
||||
// prefix does bypass the path normalization that replaces slashes with backslashes
|
||||
// before passing the path to kernel mode APIs
|
||||
std::replace(utf16path.begin(), utf16path.end(), L'/', L'\\');
|
||||
return utf16path;
|
||||
}
|
||||
return ll_convert<std::wstring>(utf8path);
|
||||
}
|
||||
|
||||
static unsigned short get_fileattr(const std::wstring& utf16path)
|
||||
{
|
||||
unsigned short st_mode = 0;
|
||||
HANDLE file_handle = CreateFileW(utf16path.c_str(), FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
set_errno_from_oserror(GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE_ATTRIBUTE_TAG_INFO attribute_info;
|
||||
if (GetFileInformationByHandleEx(file_handle, FileAttributeTagInfo, &attribute_info, sizeof(attribute_info)))
|
||||
{
|
||||
// A volume path alone (only drive letter) is not recognized as directory while it technically is
|
||||
bool is_directory = (attribute_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
||||
(iswalpha(utf16path[0]) && utf16path[1] == ':' &&
|
||||
(!utf16path[2] || (is_slash(utf16path[2]) && !utf16path[3])));
|
||||
st_mode |= is_directory ? S_IFDIR : S_IFREG;
|
||||
st_mode |= (attribute_info.FileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE;
|
||||
// we do not try to guess executable flag
|
||||
|
||||
// propagate user bits to group/other fields:
|
||||
st_mode |= (st_mode & 0700) >> 3;
|
||||
st_mode |= (st_mode & 0700) >> 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retrieve last error before calling CloseHandle()
|
||||
set_errno_from_oserror(GetLastError());
|
||||
}
|
||||
CloseHandle(file_handle);
|
||||
return st_mode;
|
||||
}
|
||||
|
||||
#else
|
||||
// On Posix we want to call strerror_r(), but alarmingly, there are two
|
||||
|
|
@ -108,18 +241,13 @@ std::string strerr(int errn)
|
|||
}
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
// On either system, shorthand call just infers global 'errno'.
|
||||
std::string strerr()
|
||||
{
|
||||
return strerr(errno);
|
||||
}
|
||||
|
||||
int warnif(const std::string& desc, const std::string& filename, int rc, int accept=0)
|
||||
int warnif(const std::string& desc, const std::string& filename, int rc, int accept = 0)
|
||||
{
|
||||
if (rc < 0)
|
||||
{
|
||||
// Capture errno before we start emitting output
|
||||
int errn = errno;
|
||||
|
||||
// For certain operations, a particular errno value might be
|
||||
// acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
|
||||
// EEXIST. Don't warn if caller explicitly says this errno is okay.
|
||||
|
|
@ -176,62 +304,58 @@ int warnif(const std::string& desc, const std::string& filename, int rc, int acc
|
|||
// static
|
||||
int LLFile::mkdir(const std::string& dirname, int perms)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
// permissions are ignored on Windows
|
||||
std::wstring utf16dirname = ll_convert<std::wstring>(dirname);
|
||||
int rc = _wmkdir(utf16dirname.c_str());
|
||||
#else
|
||||
int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
|
||||
#endif
|
||||
// We often use mkdir() to ensure the existence of a directory that might
|
||||
// already exist. There is no known case in which we want to call out as
|
||||
// an error the requested directory already existing.
|
||||
#if LL_WINDOWS
|
||||
// permissions are ignored on Windows
|
||||
int rc = 0;
|
||||
std::wstring utf16dirname = utf8path_to_wstring(dirname);
|
||||
if (!CreateDirectoryW(utf16dirname.c_str(), nullptr))
|
||||
{
|
||||
// Only treat other errors than an already existing file as a real error
|
||||
unsigned long oserr = GetLastError();
|
||||
if (oserr != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
rc = set_errno_from_oserror(oserr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
|
||||
if (rc < 0 && errno == EEXIST)
|
||||
{
|
||||
// this is not the error you want, move along
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// anything else might be a problem
|
||||
return warnif("mkdir", dirname, rc, EEXIST);
|
||||
return warnif("mkdir", dirname, rc);
|
||||
}
|
||||
|
||||
// static
|
||||
int LLFile::rmdir(const std::string& dirname)
|
||||
int LLFile::rmdir(const std::string& dirname, int supress_error)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
// permissions are ignored on Windows
|
||||
std::wstring utf16dirname = ll_convert<std::wstring>(dirname);
|
||||
std::wstring utf16dirname = utf8path_to_wstring(dirname);
|
||||
int rc = _wrmdir(utf16dirname.c_str());
|
||||
#else
|
||||
int rc = ::rmdir(dirname.c_str());
|
||||
#endif
|
||||
return warnif("rmdir", dirname, rc);
|
||||
return warnif("rmdir", dirname, rc, supress_error);
|
||||
}
|
||||
|
||||
// static
|
||||
LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
std::wstring utf16filename = ll_convert<std::wstring>(filename);
|
||||
std::wstring utf16filename = utf8path_to_wstring(filename);
|
||||
std::wstring utf16mode = ll_convert<std::wstring>(std::string(mode));
|
||||
return _wfopen(utf16filename.c_str(),utf16mode.c_str());
|
||||
return _wfopen(utf16filename.c_str(), utf16mode.c_str());
|
||||
#else
|
||||
return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
|
||||
#endif
|
||||
}
|
||||
|
||||
LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
std::wstring utf16filename = ll_convert<std::wstring>(filename);
|
||||
std::wstring utf16mode = ll_convert<std::wstring>(std::string(mode));
|
||||
return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
|
||||
#else
|
||||
llassert(0);//No corresponding function on non-windows
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int LLFile::close(LLFILE * file)
|
||||
{
|
||||
int ret_value = 0;
|
||||
|
|
@ -264,8 +388,27 @@ std::string LLFile::getContents(const std::string& filename)
|
|||
int LLFile::remove(const std::string& filename, int supress_error)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
std::wstring utf16filename = ll_convert<std::wstring>(filename);
|
||||
int rc = _wremove(utf16filename.c_str());
|
||||
// Posix remove() works on both files and directories although on Windows
|
||||
// remove() and its wide char variant _wremove() only removes files just
|
||||
// as its siblings unlink() and _wunlink().
|
||||
// If we really only want to support files we should instead use
|
||||
// unlink() in the non-Windows part below too
|
||||
int rc = 0;
|
||||
;
|
||||
std::wstring utf16filename = utf8path_to_wstring(filename);
|
||||
unsigned short st_mode = get_fileattr(utf16filename);
|
||||
if (S_ISDIR(st_mode))
|
||||
{
|
||||
rc = _wrmdir(utf16filename.c_str());
|
||||
}
|
||||
else if (S_ISREG(st_mode))
|
||||
{
|
||||
rc = _wunlink(utf16filename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = set_errno_from_oserror(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
#else
|
||||
int rc = ::remove(filename.c_str());
|
||||
#endif
|
||||
|
|
@ -275,28 +418,38 @@ int LLFile::remove(const std::string& filename, int supress_error)
|
|||
int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
std::wstring utf16filename = ll_convert<std::wstring>(filename);
|
||||
std::wstring utf16newname = ll_convert<std::wstring>(newname);
|
||||
int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
|
||||
// Posix rename() will gladly overwrite a file at newname if it exists, the Windows
|
||||
// rename(), respectively _wrename(), will bark on that. Instead call directly the Windows
|
||||
// API MoveFileEx() and use its flags to specify that overwrite is allowed.
|
||||
std::wstring utf16filename = utf8path_to_wstring(filename);
|
||||
std::wstring utf16newname = utf8path_to_wstring(newname);
|
||||
int rc = 0;
|
||||
if (!MoveFileExW(utf16filename.c_str(), utf16newname.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
|
||||
{
|
||||
rc = set_errno_from_oserror(GetLastError());
|
||||
}
|
||||
#else
|
||||
int rc = ::rename(filename.c_str(),newname.c_str());
|
||||
#endif
|
||||
return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error);
|
||||
}
|
||||
|
||||
// Make this a define rather than using magic numbers multiple times in the code
|
||||
#define LLFILE_COPY_BUFFER_SIZE 16384
|
||||
|
||||
bool LLFile::copy(const std::string& from, const std::string& to)
|
||||
{
|
||||
bool copied = false;
|
||||
LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */
|
||||
LLFILE* in = fopen(from, "rb"); /* Flawfinder: ignore */
|
||||
if (in)
|
||||
{
|
||||
LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */
|
||||
LLFILE* out = fopen(to, "wb"); /* Flawfinder: ignore */
|
||||
if (out)
|
||||
{
|
||||
char buf[16384]; /* Flawfinder: ignore */
|
||||
char buf[LLFILE_COPY_BUFFER_SIZE]; /* Flawfinder: ignore */
|
||||
size_t readbytes;
|
||||
bool write_ok = true;
|
||||
while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
|
||||
while (write_ok && (readbytes = fread(buf, 1, LLFILE_COPY_BUFFER_SIZE, in))) /* Flawfinder: ignore */
|
||||
{
|
||||
if (fwrite(buf, 1, readbytes, out) != readbytes)
|
||||
{
|
||||
|
|
@ -315,31 +468,51 @@ bool LLFile::copy(const std::string& from, const std::string& to)
|
|||
return copied;
|
||||
}
|
||||
|
||||
int LLFile::stat(const std::string& filename, llstat* filestatus)
|
||||
int LLFile::stat(const std::string& filename, llstat* filestatus, int supress_error)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
std::wstring utf16filename = ll_convert<std::wstring>(filename);
|
||||
int rc = _wstat(utf16filename.c_str(),filestatus);
|
||||
std::wstring utf16filename = utf8path_to_wstring(filename);
|
||||
int rc = _wstat64(utf16filename.c_str(), filestatus);
|
||||
#else
|
||||
int rc = ::stat(filename.c_str(),filestatus);
|
||||
int rc = ::stat(filename.c_str(), filestatus);
|
||||
#endif
|
||||
// We use stat() to determine existence (see isfile(), isdir()).
|
||||
// Don't spam the log if the subject pathname doesn't exist.
|
||||
return warnif("stat", filename, rc, ENOENT);
|
||||
return warnif("stat", filename, rc, supress_error);
|
||||
}
|
||||
|
||||
// _wstat() is a bit heavyweight on Windows, use a more lightweight API
|
||||
// to just get the attributes
|
||||
unsigned short LLFile::getattr(const std::string& filename, int suppress_error)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
int rc = -1;
|
||||
std::wstring utf16filename = utf8path_to_wstring(filename);
|
||||
unsigned short st_mode = get_fileattr(utf16filename);
|
||||
if (st_mode)
|
||||
{
|
||||
return st_mode;
|
||||
}
|
||||
#else
|
||||
llstat filestatus;
|
||||
int rc = ::stat(filename.c_str(), &filestatus);
|
||||
if (rc == 0)
|
||||
{
|
||||
return filestatus.st_mode;
|
||||
}
|
||||
#endif
|
||||
warnif("getattr", filename, rc, suppress_error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LLFile::isdir(const std::string& filename)
|
||||
{
|
||||
llstat st;
|
||||
|
||||
return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
|
||||
// Don't spam the log if the subject pathname doesn't exist.
|
||||
return S_ISDIR(getattr(filename, ENOENT));
|
||||
}
|
||||
|
||||
bool LLFile::isfile(const std::string& filename)
|
||||
{
|
||||
llstat st;
|
||||
|
||||
return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
|
||||
// Don't spam the log if the subject pathname doesn't exist.
|
||||
return S_ISREG(getattr(filename, ENOENT));
|
||||
}
|
||||
|
||||
const char *LLFile::tmpdir()
|
||||
|
|
@ -368,75 +541,8 @@ const char *LLFile::tmpdir()
|
|||
return utf8path.c_str();
|
||||
}
|
||||
|
||||
|
||||
/***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
||||
LLFILE * LLFile::_Fiopen(const std::string& filename,
|
||||
std::ios::openmode mode)
|
||||
{ // open a file
|
||||
static const char *mods[] =
|
||||
{ // fopen mode strings corresponding to valid[i]
|
||||
"r", "w", "w", "a", "rb", "wb", "wb", "ab",
|
||||
"r+", "w+", "a+", "r+b", "w+b", "a+b",
|
||||
0};
|
||||
static const int valid[] =
|
||||
{ // valid combinations of open flags
|
||||
ios_base::in,
|
||||
ios_base::out,
|
||||
ios_base::out | ios_base::trunc,
|
||||
ios_base::out | ios_base::app,
|
||||
ios_base::in | ios_base::binary,
|
||||
ios_base::out | ios_base::binary,
|
||||
ios_base::out | ios_base::trunc | ios_base::binary,
|
||||
ios_base::out | ios_base::app | ios_base::binary,
|
||||
ios_base::in | ios_base::out,
|
||||
ios_base::in | ios_base::out | ios_base::trunc,
|
||||
ios_base::in | ios_base::out | ios_base::app,
|
||||
ios_base::in | ios_base::out | ios_base::binary,
|
||||
ios_base::in | ios_base::out | ios_base::trunc
|
||||
| ios_base::binary,
|
||||
ios_base::in | ios_base::out | ios_base::app
|
||||
| ios_base::binary,
|
||||
0};
|
||||
|
||||
LLFILE *fp = 0;
|
||||
int n;
|
||||
ios_base::openmode atendflag = mode & ios_base::ate;
|
||||
ios_base::openmode norepflag = mode & ios_base::_Noreplace;
|
||||
|
||||
if (mode & ios_base::_Nocreate)
|
||||
mode |= ios_base::in; // file must exist
|
||||
mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
|
||||
for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
|
||||
; // look for a valid mode
|
||||
|
||||
if (valid[n] == 0)
|
||||
return (0); // no valid mode
|
||||
else if (norepflag && mode & (ios_base::out | ios_base::app)
|
||||
&& (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
|
||||
{ // file must not exist, close and fail
|
||||
fclose(fp);
|
||||
return (0);
|
||||
}
|
||||
else if (fp != 0 && fclose(fp) != 0)
|
||||
return (0); // can't close after test open
|
||||
// should open with protection here, if other than default
|
||||
else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
|
||||
return (0); // open failed
|
||||
|
||||
if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
|
||||
return (fp); // no need to seek to end, or seek succeeded
|
||||
|
||||
fclose(fp); // can't position at end
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* LL_WINDOWS */
|
||||
|
||||
|
||||
#if LL_WINDOWS
|
||||
/************** input file stream ********************************/
|
||||
|
||||
llifstream::llifstream() {}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ typedef FILE LLFILE;
|
|||
#include <sys/stat.h>
|
||||
|
||||
#if LL_WINDOWS
|
||||
// windows version of stat function and stat data structure are called _stat
|
||||
typedef struct _stat llstat;
|
||||
// windows version of stat function and stat data structure are called _statxx
|
||||
typedef struct _stat64 llstat;
|
||||
#else
|
||||
typedef struct stat llstat;
|
||||
#include <sys/types.h>
|
||||
|
|
@ -58,33 +58,89 @@ typedef struct stat llstat;
|
|||
|
||||
#include "llstring.h" // safe char* -> std::string conversion
|
||||
|
||||
/// LLFile is a class of static functions operating on paths
|
||||
/// All the functions with a path string input take UTF8 path/filenames
|
||||
class LL_COMMON_API LLFile
|
||||
{
|
||||
public:
|
||||
// All these functions take UTF8 path/filenames.
|
||||
static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */
|
||||
static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag);
|
||||
/// open a file with the specified access mode
|
||||
static LLFILE* fopen(const std::string& filename, const char* accessmode); /* Flawfinder: ignore */
|
||||
///< 'accessmode' follows the rules of the Posix fopen() mode parameter
|
||||
/// "r" open the file for reading only and positions the stream at the beginning
|
||||
/// "r+" open the file for reading and writing and positions the stream at the beginning
|
||||
/// "w" open the file for reading and writing and truncate it to zero length
|
||||
/// "w+" open or create the file for reading and writing and truncate to zero length if it existed
|
||||
/// "a" open the file for reading and writing and position the stream at the end of the file
|
||||
/// "a+" open or create the file for reading and writing and position the stream at the end of the file
|
||||
///
|
||||
/// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac
|
||||
/// this is strictly for compatibility and has no effect. On Windows this makes the file functions not
|
||||
/// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither
|
||||
/// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT.
|
||||
/// This means that it is always a good idea to append "b" specifically for binary file access to
|
||||
/// avoid corruption of the binary consistency of the data stream when reading or writing
|
||||
/// Other characters in 'accessmode' will usually cause an error as fopen will verify this parameter
|
||||
/// @returns a valid LLFILE* pointer on success or NULL on failure
|
||||
|
||||
static int close(LLFILE * file);
|
||||
|
||||
/// retrieve the content of a file into a string
|
||||
static std::string getContents(const std::string& filename);
|
||||
///< @returns the content of the file or an empty string on failure
|
||||
|
||||
// perms is a permissions mask like 0777 or 0700. In most cases it will
|
||||
// be overridden by the user's umask. It is ignored on Windows.
|
||||
// mkdir() considers "directory already exists" to be SUCCESS.
|
||||
/// create a directory
|
||||
static int mkdir(const std::string& filename, int perms = 0700);
|
||||
///< perms is a permissions mask like 0777 or 0700. In most cases it will be
|
||||
/// overridden by the user's umask. It is ignored on Windows.
|
||||
/// mkdir() considers "directory already exists" to be not an error.
|
||||
/// @returns 0 on success and -1 on failure.
|
||||
|
||||
static int rmdir(const std::string& filename);
|
||||
//// remove a directory
|
||||
static int rmdir(const std::string& filename, int supress_error = 0);
|
||||
///< pass ENOENT in the optional 'supress_error' parameter
|
||||
/// if you don't want a warning in the log when the directory does not exist
|
||||
/// @returns 0 on success and -1 on failure.
|
||||
|
||||
/// remove a file or directory
|
||||
static int remove(const std::string& filename, int supress_error = 0);
|
||||
static int rename(const std::string& filename,const std::string& newname, int supress_error = 0);
|
||||
///< pass ENOENT in the optional 'supress_error' parameter
|
||||
/// if you don't want a warning in the log when the directory does not exist
|
||||
/// @returns 0 on success and -1 on failure.
|
||||
|
||||
/// rename a file,
|
||||
static int rename(const std::string& filename, const std::string& newname, int supress_error = 0);
|
||||
///< it will silently overwrite newname if it exists without returning an error
|
||||
/// @returns 0 on success and -1 on failure.
|
||||
|
||||
|
||||
// copy the contents of file from 'from' to 'to' filename
|
||||
static bool copy(const std::string& from, const std::string& to);
|
||||
///< @returns true on success and false on failure.
|
||||
|
||||
static int stat(const std::string& filename,llstat* file_status);
|
||||
static bool isdir(const std::string& filename);
|
||||
static bool isfile(const std::string& filename);
|
||||
static LLFILE * _Fiopen(const std::string& filename,
|
||||
std::ios::openmode mode);
|
||||
/// return the file stat structure for filename
|
||||
static int stat(const std::string& filename, llstat* file_status, int supress_error = ENOENT);
|
||||
///< for compatibility with existing uses of LL_File::stat() we use ENOENT as default in the
|
||||
/// optional 'supress_error' parameter to avoid spamming the log with warnings when the API
|
||||
/// is used to detect if a file exists
|
||||
/// @returns 0 on success and -1 on failure.
|
||||
|
||||
/// get the file or directory attributes for filename
|
||||
static unsigned short getattr(const std::string& filename, int supress_error = 0);
|
||||
///< a more lightweight function on Windows to stat, that just returns the file attribute flags
|
||||
/// pass ENOENT in the optional 'supress_error' parameter if you don't want a warning
|
||||
/// in the log when the file or directory does not exist
|
||||
/// @returns 0 on failure and a st_mode value with either S_IFDIR or S_IFREG set otherwise
|
||||
/// together with the three access bits which under Windows only the write bit is relevant.
|
||||
|
||||
/// check if filename is an existing directory
|
||||
static bool isdir(const std::string& filename);
|
||||
///< @returns true if the path is for an existing directory
|
||||
|
||||
/// check if filename is an existing file
|
||||
static bool isfile(const std::string& filename);
|
||||
///< @returns true if the path is for an existing file
|
||||
|
||||
/// return a path to the temporary directory on the system
|
||||
static const char * tmpdir();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1348,10 +1348,6 @@ bool gunzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
} while(gzeof(src) == 0);
|
||||
fclose(dst);
|
||||
dst = NULL;
|
||||
#if LL_WINDOWS
|
||||
// Rename in windows needs the dstfile to not exist.
|
||||
LLFile::remove(dstfile, ENOENT);
|
||||
#endif
|
||||
if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
|
||||
retval = true;
|
||||
err:
|
||||
|
|
@ -1399,10 +1395,6 @@ bool gzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
|
||||
gzclose(dst);
|
||||
dst = NULL;
|
||||
#if LL_WINDOWS
|
||||
// Rename in windows needs the dstfile to not exist.
|
||||
LLFile::remove(dstfile);
|
||||
#endif
|
||||
if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
|
||||
retval = true;
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -576,10 +576,6 @@ bool LLCrashLogger::init()
|
|||
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old");
|
||||
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log");
|
||||
|
||||
#if LL_WINDOWS
|
||||
LLAPRFile::remove(old_log_file);
|
||||
#endif
|
||||
|
||||
LLFile::rename(log_file.c_str(), old_log_file.c_str());
|
||||
|
||||
// Set the log file to crashreport.log
|
||||
|
|
|
|||
|
|
@ -103,9 +103,6 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
|
|||
const std::string old_filename = LLDiskCache::metaDataToFilepath(old_file_id, old_file_type);
|
||||
const std::string new_filename = LLDiskCache::metaDataToFilepath(new_file_id, new_file_type);
|
||||
|
||||
// Rename needs the new file to not exist.
|
||||
LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT);
|
||||
|
||||
if (LLFile::rename(old_filename, new_filename) != 0)
|
||||
{
|
||||
// We would like to return false here indicating the operation
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ LLViewerEventRecorder::LLViewerEventRecorder() {
|
|||
logEvents = false;
|
||||
// Remove any previous event log file
|
||||
std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old");
|
||||
LLFile::remove(old_log_ui_events_to_llsd_file, ENOENT);
|
||||
|
||||
|
||||
mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd");
|
||||
LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file, ENOENT);
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,6 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
|
|||
std::string old_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SLVoice.old");
|
||||
if (gDirUtilp->fileExists(new_log))
|
||||
{
|
||||
LLFile::remove(old_log, ENOENT);
|
||||
LLFile::rename(new_log, old_log);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue