in source/code/scxcorelib/pal/scxfilesystem.cpp [787:986]
SCXFileSystem::Attributes SCXFileSystem::GetAttributes(SCXStatStruct* pStat)
{
SCXFileSystem::Attributes attributes;
if (0 == pStat)
{
throw SCXInvalidArgumentException(L"pstat", L"Argument is NULL", SCXSRCLOCATION);
}
#if defined(S_ISDIR)
if (S_ISDIR(pStat->st_mode)) { // Do not check the directory bit alone since some sys files have the directory bit set too.
#else
if (pStat->st_mode & _S_IFDIR) {
#endif
attributes.insert(SCXFileSystem::eDirectory);
}
if (pStat->st_mode & S_IREAD) {
attributes.insert(SCXFileSystem::eReadable);
}
if (pStat->st_mode & S_IWRITE) {
attributes.insert(SCXFileSystem::eWritable);
}
#if defined(SCX_UNIX)
if (pStat->st_mode & S_IRUSR) {
attributes.insert(SCXFileSystem::eUserRead);
}
if (pStat->st_mode & S_IWUSR) {
attributes.insert(SCXFileSystem::eUserWrite);
}
if (pStat->st_mode & S_IXUSR) {
attributes.insert(SCXFileSystem::eUserExecute);
}
if (pStat->st_mode & S_IRGRP) {
attributes.insert(SCXFileSystem::eGroupRead);
}
if (pStat->st_mode & S_IWGRP) {
attributes.insert(SCXFileSystem::eGroupWrite);
}
if (pStat->st_mode & S_IXGRP) {
attributes.insert(SCXFileSystem::eGroupExecute);
}
if (pStat->st_mode & S_IROTH) {
attributes.insert(SCXFileSystem::eOtherRead);
}
if (pStat->st_mode & S_IWOTH) {
attributes.insert(SCXFileSystem::eOtherWrite);
}
if (pStat->st_mode & S_IXOTH) {
attributes.insert(SCXFileSystem::eOtherExecute);
}
#endif
return attributes;
}
/*--------------------------------------------------------------*/
/**
Sets the specified FileAttributes of the file or directory on the specified path
\param[in] path The path to the file or directory.
\param[in] attributes The desired FileAttributes, such as Readable and Writable
\throws SCXUnauthorizedFileSystemAccessException The caller does not have the required permission
\throws SCXFilePathNotFoundException If no file or directory is found at path
The path parameter is permitted to specify relative or absolute path information.
Relative path information is interpreted as relative to the current working directory.
To obtain the current working directory, see GetCurrentDirectory.
It is not possible to change the compression status of a File object using the
SetAttributes method
*/
void SCXFileSystem::SetAttributes(const SCXFilePath& path, const SCXFileSystem::Attributes& attributes) {
int permissions = 0;
if (attributes.count(SCXFileSystem::eWritable) > 0) {
permissions |= S_IWRITE;
}
if (attributes.count(SCXFileSystem::eReadable) > 0) {
permissions |= S_IREAD;
}
#if defined(SCX_UNIX)
if (attributes.count(SCXFileSystem::eUserRead) > 0) {
permissions |= S_IRUSR;
}
if (attributes.count(SCXFileSystem::eUserWrite) > 0) {
permissions |= S_IWUSR;
}
if (attributes.count(SCXFileSystem::eUserExecute) > 0) {
permissions |= S_IXUSR;
}
if (attributes.count(SCXFileSystem::eGroupRead) > 0) {
permissions |= S_IRGRP;
}
if (attributes.count(SCXFileSystem::eGroupWrite) > 0) {
permissions |= S_IWGRP;
}
if (attributes.count(SCXFileSystem::eGroupExecute) > 0) {
permissions |= S_IXGRP;
}
if (attributes.count(SCXFileSystem::eOtherRead) > 0) {
permissions |= S_IROTH;
}
if (attributes.count(SCXFileSystem::eOtherWrite) > 0) {
permissions |= S_IWOTH;
}
if (attributes.count(SCXFileSystem::eOtherExecute) > 0) {
permissions |= S_IXOTH;
}
#endif
#if defined(WIN32)
int failure = _wchmod(path.Get().c_str(), permissions);
#elif defined(SCX_UNIX)
std::string localizedPath = SCXFileSystem::EncodePath(path);
int failure = chmod(localizedPath.c_str(), permissions);
#else
#error
#endif
if (failure) {
switch (errno)
{
case EACCES:
case EPERM:
case EROFS:
throw SCXUnauthorizedFileSystemAccessException(path, GetAttributes(path), SCXSRCLOCATION);
case ENAMETOOLONG:
case EINVAL:
throw SCXInvalidArgumentException(L"path", path.Get(), SCXSRCLOCATION);
#if defined(SCX_UNIX)
case ELOOP:
#endif
case ENOENT:
case ENOTDIR:
throw SCXFilePathNotFoundException(path, SCXSRCLOCATION);
default:
wstring problem(L"Failed to set attributes for " + path.Get());
throw SCXInternalErrorException(UnexpectedErrno(problem, errno), SCXSRCLOCATION);
}
}
}
/*--------------------------------------------------------------*/
/**
Moves a specified file or directory to a new location, providing the option to specify a
new file name.
\param[in] oldPath Existing file or directory to be moved
\param[in] newPath New path, directory or file
\throws SCXUnauthorizedFileSystemAccessException If oldPath specifies a directory and
newPath specifies a file
\throws SCXFilePathNotFoundException If no file is found at oldPath
If oldPath is a path to a file and newPath is a path not to a file but to an existing
directory, the file is moved to that directory using the old name.
This method works across disk volumes, and it does not throw an exception if the
source and destination are the same. Note that if you attempt to replace a file by
moving a file of the same name into that directory, you get an IOException. You
cannot use the Move method to overwrite an existing file.
The oldPath and newPath arguments are permitted to specify relative or
absolute path information. Relative path information is interpreted as relative
to the current working directory.
\note The current implementation is restricted by the underlying API and requires newName to be complete
*/
void SCXFileSystem::Move(const SCXFilePath& oldPath, const SCXFilePath &newPath) {
#if defined(WIN32)
int failure = _wrename(oldPath.Get().c_str(), newPath.Get().c_str());
#elif defined(SCX_UNIX)
std::string oldLocalizedPath = SCXFileSystem::EncodePath(oldPath);
std::string newLocalizedPath = SCXFileSystem::EncodePath(newPath);
int failure = rename(oldLocalizedPath.c_str(), newLocalizedPath.c_str());
#else
#error
#endif
if (failure) {
if (errno == EINVAL) {
throw SCXInvalidArgumentException(L"path",
oldPath.Get() + L" or " + newPath.Get(), SCXSRCLOCATION);
} else if (errno == EACCES || errno == EBUSY || errno == EROFS ||
errno == EISDIR || errno == EEXIST || errno == ENOTEMPTY ||
errno == ENOTDIR) {
throw SCXUnauthorizedFileSystemAccessException(newPath, SCXFileSystem::GetAttributes(newPath), SCXSRCLOCATION);
} else if (errno == ENOENT) {
throw SCXFilePathNotFoundException(oldPath, SCXSRCLOCATION);
} else if (errno == EMLINK) {
throw SCXFileSystemExhaustedException(L"directory entry", newPath, SCXSRCLOCATION);
} else if (errno == ENOSPC) {
throw SCXFileSystemExhaustedException(L"filesystem space", newPath, SCXSRCLOCATION);
} else if (errno == EXDEV) {
// May perhaps be implemented as copy and delete
throw SCXNotSupportedException(L"Move files between file systems", SCXSRCLOCATION);
} else {
wstring problem(L"Failed to move " + oldPath.Get());
throw SCXInternalErrorException(UnexpectedErrno(problem, errno), SCXSRCLOCATION);
}
}
}
}