📄 filesystem_traits.hpp
字号:
}
else if(NULL != buffer &&
0 == cchBuffer)
{
return 0;
}
else
{
size_type lenDir = get_current_directory(directory.size(), &directory[0]);
if(0 == lenDir)
{
// The call failed, so indicate that to caller
len = 0;
}
else
{
if( 1 == len &&
'.' == fileName[0])
{
if(NULL == buffer)
{
len = lenDir;
}
else
{
if(cchBuffer < lenDir)
{
str_n_copy(&buffer[0], directory.data(), cchBuffer);
len = cchBuffer;
}
else
{
// Given buffer is large enough, so copy
str_copy(buffer, directory.data());
len = lenDir;
}
}
}
else
{
if(!has_dir_end(&directory[0] + (lenDir - 1)))
{
++lenDir;
}
ensure_dir_end(&directory[0]);
len += lenDir;
if(NULL != buffer)
{
str_n_copy(&buffer[0], directory.data(), cchBuffer);
if(cchBuffer > lenDir)
{
str_n_copy(&buffer[0] + lenDir, fileName, cchBuffer - lenDir);
}
if(cchBuffer < len)
{
len = cchBuffer;
}
}
}
}
}
}
return len;
}
static size_type get_full_path_name_impl(char_type const *fileName, us_size_t len, char_type *buffer, size_type cchBuffer)
{
UNIXSTL_ASSERT(len > 0);
if('\0' != fileName[len])
{
buffer_type_ fileName_(1 + (len - 1));
// May be being compiled absent exception support, so need to check the
// file path buffers. (This _could_ be done with a compile-time #ifdef,
// but it's best not, since some translators support exceptions but yet
// don't throw on mem exhaustion, and in any case a user could change
// ::new)
if(0 == fileName_.size())
{
set_last_error(ENOMEM);
return 0;
}
else
{
fileName_[len] = '\0';
return get_full_path_name_impl2(str_n_copy(&fileName_[0], fileName, len)
, len
, buffer
, cchBuffer);
}
}
else
{
return get_full_path_name_impl2(fileName, len, buffer, cchBuffer);
}
}
public:
static size_type get_full_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer, char_type **ppFile)
{
UNIXSTL_ASSERT(NULL != ppFile);
size_type r = get_full_path_name(fileName, cchBuffer, buffer);
*ppFile = NULL;
if( NULL != buffer &&
0 != r &&
r <= cchBuffer)
{
size_type cchRequired = get_full_path_name(fileName, 0, NULL);
if(r == cchRequired)
{
// Now search for the file separator
char_type *pFile = str_rchr(buffer, path_name_separator());
#if defined(_WIN32)
char_type *pFile2 = str_rchr(buffer, '\\');
if(NULL == pFile)
{
pFile = pFile2;
}
else if(NULL != pFile2)
{
if(pFile2 > pFile)
{
pFile = pFile2;
}
}
#endif /* _WIN32 */
if(NULL != (*ppFile = pFile))
{
(*ppFile)++;
}
}
}
return r;
}
static size_type get_full_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer)
{
UNIXSTL_ASSERT(NULL != fileName);
UNIXSTL_ASSERT(0 == cchBuffer || NULL != buffer);
if('\0' == *fileName)
{
static const char s_dot[2] = { '.', '\0' };
fileName = s_dot;
}
#if 1
// Can't call realpath(), since that requires that the file exists
return get_full_path_name_impl(fileName, str_len(fileName), buffer, cchBuffer);
#else /* ? 0 */
buffer_type_ directory(1 + path_max());
if( 0 == directory.size() ||
NULL == ::realpath(fileName, &directory[0]))
{
return 0;
}
else
{
const size_type len = str_len(directory.data());
if(NULL == buffer)
{
return len;
}
else if(0 == cchBuffer)
{
return 0;
}
else
{
if(len < cchBuffer)
{
str_copy(&buffer[0], directory.data());
return len;
}
else
{
str_n_copy(&buffer[0], directory.data(), cchBuffer);
return cchBuffer;
}
}
}
#endif /* 0 */
}
static size_type get_short_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer)
{
return get_full_path_name(fileName, cchBuffer, buffer);
}
// File-system enumeration
static DIR *open_dir(char_type const *dir)
{
return ::opendir(dir);
}
static struct dirent const *read_dir(DIR *h)
{
return ::readdir(h);
}
static void close_dir(DIR *h)
{
::closedir(h);
}
// Dynamic Loading
static module_type load_library(char_type const *name)
{
return ::dlopen(name, RTLD_NOW);
}
static bool_type free_library(module_type hModule)
{
return 0 == ::dlclose(hModule);
}
static void *find_symbol(module_type hModule, char const *symbolName)
{
return ::dlsym(hModule, symbolName);
}
// File-system state
static bool_type set_current_directory(char_type const *dir)
{
return 0 == ::chdir(dir);
}
static size_type get_current_directory(size_type cchBuffer, char_type *buffer)
{
char_type const *dir = ::getcwd(buffer, cchBuffer);
return (NULL == dir) ? 0 : str_len(dir);
}
static bool_type file_exists(char_type const *fileName)
{
stat_data_type sd;
return class_type::stat(fileName, &sd) /* || errno != ENOENT */;
}
static bool_type is_file(char_type const *path)
{
stat_data_type sd;
return class_type::stat(path, &sd) && S_IFREG == (sd.st_mode & S_IFMT);
}
static bool_type is_directory(char_type const *path)
{
stat_data_type sd;
return class_type::stat(path, &sd) && S_IFDIR == (sd.st_mode & S_IFMT);
}
static bool_type stat(char_type const *path, stat_data_type *stat_data)
{
UNIXSTL_ASSERT(NULL != path);
UNIXSTL_ASSERT(NULL != stat_data);
#ifdef _WIN32
if(NULL != class_type::str_pbrk(path, "*?"))
{
// Sometimes the VC6 CRT libs crash with a wildcard stat
set_last_error(EBADF);
return false;
}
if(has_dir_end(path))
{
// Win32 impl does not like a trailing slash
size_type len = str_len(path);
if( len > 3 ||
( is_path_name_separator(*path) &&
len > 2))
{
buffer_type_ directory(1 + len);
if(0 == directory.size())
{
set_last_error(ENOMEM);
return false;
}
else
{
str_copy(&directory[0], path);
class_type::remove_dir_end(&directory[0]);
return class_type::stat(&directory[0], stat_data);
}
}
}
#endif /* _WIN32 */
return 0 == ::stat(path, stat_data);
}
static bool_type lstat(char_type const *path, stat_data_type *stat_data)
{
UNIXSTL_ASSERT(NULL != path);
UNIXSTL_ASSERT(NULL != stat_data);
#ifdef _WIN32
return 0 == class_type::stat(path, stat_data);
#else /* ? _WIN32 */
return 0 == ::lstat(path, stat_data);
#endif /* _WIN32 */
}
static bool_type fstat(file_handle_type fd, fstat_data_type *fstat_data)
{
UNIXSTL_ASSERT(-1 != fd);
UNIXSTL_ASSERT(NULL != fstat_data);
return 0 == ::fstat(fd, fstat_data);
}
static bool_type is_file(stat_data_type const *stat_data)
{
return S_IFREG == (stat_data->st_mode & S_IFREG);
}
static bool_type is_directory(stat_data_type const *stat_data)
{
return S_IFDIR == (stat_data->st_mode & S_IFDIR);
}
static bool_type is_link(stat_data_type const *stat_data)
{
#ifdef _WIN32
STLSOFT_SUPPRESS_UNUSED(stat_data);
return false;
#else /* ? _WIN32 */
return S_IFLNK == (stat_data->st_mode & S_IFLNK);
#endif /* _WIN32 */
}
static bool_type is_readonly(stat_data_type const *stat_data)
{
#ifdef _WIN32
return S_IREAD == (stat_data->st_mode & (S_IREAD | S_IWRITE));
#else /* ? _WIN32 */
return S_IRUSR == (stat_data->st_mode & (S_IRUSR | S_IWUSR));
#endif /* _WIN32 */
}
// File-system control
static bool_type create_directory(char_type const *dir)
{
mode_type mode = 0;
#ifdef _WIN32
mode = S_IREAD | S_IWRITE | S_IEXEC;
#else /* ? _WIN32 */
mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
#endif /* _WIN32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -