00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00052 #ifndef UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
00053 #define UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
00054
00055 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00056 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS_MAJOR 4
00057 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS_MINOR 3
00058 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS_REVISION 11
00059 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS_EDIT 110
00060 #endif
00061
00062
00063
00064
00065
00066 #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
00067 # include <unixstl/unixstl.h>
00068 #endif
00069 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
00070 # include <stlsoft/memory/auto_buffer.hpp>
00071 #endif
00072 #ifndef UNIXSTL_INCL_UNIXSTL_SYSTEM_HPP_SYSTEM_TRAITS
00073 # include <unixstl/system/system_traits.hpp>
00074 #endif
00075
00076 #ifdef _WIN32
00077 # include <ctype.h>
00078 #endif
00079 #ifndef STLSOFT_INCL_H_ERRNO
00080 # define STLSOFT_INCL_H_ERRNO
00081 # include <errno.h>
00082 #endif
00083 #ifndef STLSOFT_INCL_H_FCNTL
00084 # define STLSOFT_INCL_H_FCNTL
00085 # include <fcntl.h>
00086 #endif
00087 #ifdef _WIN32
00088 # include <io.h>
00089 # if defined(STLSOFT_COMPILER_IS_INTEL) || \
00090 defined(STLSOFT_COMPILER_IS_MSVC)
00091 # include <direct.h>
00092 # endif
00093 #endif
00094 #ifndef STLSOFT_INCL_H_DLFCN
00095 # define STLSOFT_INCL_H_DLFCN
00096 # include <dlfcn.h>
00097 #endif
00098 #ifndef STLSOFT_INCL_H_DIRENT
00099 # define STLSOFT_INCL_H_DIRENT
00100 # include <dirent.h>
00101 #endif
00102 #ifndef STLSOFT_INCL_H_LIMITS
00103 # define STLSOFT_INCL_H_LIMITS
00104 # include <limits.h>
00105 #endif
00106 #ifndef STLSOFT_INCL_H_STDIO
00107 # define STLSOFT_INCL_H_STDIO
00108 # include <stdio.h>
00109 #endif
00110 #ifndef STLSOFT_INCL_H_STDLIB
00111 # define STLSOFT_INCL_H_STDLIB
00112 # include <stdlib.h>
00113 #endif
00114 #ifndef STLSOFT_INCL_H_STRING
00115 # define STLSOFT_INCL_H_STRING
00116 # include <string.h>
00117 #endif
00118 #ifndef STLSOFT_INCL_H_UNISTD
00119 # define STLSOFT_INCL_H_UNISTD
00120 # include <unistd.h>
00121 #endif
00122 #ifndef STLSOFT_INCL_H_WCHAR
00123 # define STLSOFT_INCL_H_WCHAR
00124 # include <wchar.h>
00125 #endif
00126 #ifndef STLSOFT_INCL_SYS_H_TYPES
00127 # define STLSOFT_INCL_SYS_H_TYPES
00128 # include <sys/types.h>
00129 #endif
00130 #ifndef STLSOFT_INCL_SYS_H_STAT
00131 # define STLSOFT_INCL_SYS_H_STAT
00132 # include <sys/stat.h>
00133 #endif
00134
00135
00136
00137
00138
00139 #ifndef _UNIXSTL_NO_NAMESPACE
00140 # if defined(_STLSOFT_NO_NAMESPACE) || \
00141 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00142
00143 namespace unixstl
00144 {
00145 # else
00146
00147
00148 namespace stlsoft
00149 {
00150
00151 namespace unixstl_project
00152 {
00153
00154 # endif
00155 #endif
00156
00157
00158
00159
00160
00161 #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
00162
00171 template <ss_typename_param_k C>
00172 struct filesystem_traits
00173 : public system_traits<C>
00174 {
00177 private:
00178 typedef system_traits<C> parent_class_type;
00179 public:
00181 typedef C char_type;
00183 typedef us_size_t size_type;
00185 typedef us_ptrdiff_t difference_type;
00187 typedef struct stat stat_data_type;
00189 typedef struct stat fstat_data_type;
00191 typedef filesystem_traits<C> class_type;
00193 typedef us_int_t int_type;
00195 typedef us_bool_t bool_type;
00197 typedef int file_handle_type;
00199 typedef void* module_type;
00201 typedef int error_type;
00203 #ifdef _WIN32
00204 typedef unsigned short mode_type;
00205 #else
00206 typedef mode_t mode_type;
00207 #endif
00209
00210 #ifdef PATH_MAX
00213 public:
00214 enum
00215 {
00216 maxPathLength = 1 + PATH_MAX
00217 };
00219 #endif
00220
00223 public:
00227 static char_type* ensure_dir_end(char_type* dir);
00231 static char_type* remove_dir_end(char_type* dir);
00235 static bool_type has_dir_end(char_type const* dir);
00236
00238 static bool_type is_dots(char_type const* dir);
00244 static bool_type is_path_rooted(char_type const* path);
00250 static bool_type is_path_absolute(char_type const* path);
00255 static bool_type is_path_UNC(char_type const* path);
00263 static bool_type is_root_designator(char_type const* path);
00265 static bool_type is_path_name_separator(char_type ch);
00266
00270 static char_type path_separator();
00274 static char_type path_name_separator();
00278 static char_type const* pattern_all();
00282 static size_type path_max();
00284 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer, char_type** ppFile);
00286 static size_type get_full_path_name(char_type const* fileName, char_type* buffer, size_type cchBuffer);
00290 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer);
00292 static size_type get_short_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer);
00294
00297 public:
00298
00299
00301 static DIR* open_dir(char_type const* dir);
00303 static struct dirent const* read_dir(DIR *h);
00305 static void close_dir(DIR *h);
00306
00308
00311 public:
00313 static bool_type set_current_directory(char_type const* dir);
00317 static size_type get_current_directory(size_type cchBuffer, char_type* buffer);
00319 static size_type get_current_directory(char_type* buffer, size_type cchBuffer);
00321
00324 public:
00326 static bool_type file_exists(char_type const* path);
00328 static bool_type is_file(char_type const* path);
00330 static bool_type is_directory(char_type const* path);
00332 static bool_type stat(char_type const* path, stat_data_type *stat_data);
00334 static bool_type lstat(char_type const* path, stat_data_type *stat_data);
00336 static bool_type fstat(file_handle_type fd, fstat_data_type *fstat_data);
00337
00339 static bool_type is_file(stat_data_type const* stat_data);
00341 static bool_type is_directory(stat_data_type const* stat_data);
00343 static bool_type is_link(stat_data_type const* stat_data);
00345 static bool_type is_readonly(stat_data_type const* stat_data);
00347
00350 public:
00352 static bool_type create_directory(char_type const* dir);
00354 static bool_type remove_directory(char_type const* dir);
00355
00357 static bool_type unlink_file(char_type const* file);
00361 static bool_type delete_file(char_type const* file);
00363 static bool_type rename_file(char_type const* currentName, char_type const* newName);
00365
00366
00368 static file_handle_type open_file(char_type const* fileName, int oflag, int pmode);
00370 static bool_type close_file(file_handle_type fd);
00374 static file_handle_type open(char_type const* fileName, int oflag, int pmode);
00378 static bool_type close(file_handle_type fd);
00379 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00381 static us_uint64_t get_file_size(file_handle_type fd);
00382 #endif
00384 };
00385
00386 #else
00387
00388 template <ss_typename_param_k C>
00389 struct filesystem_traits;
00390
00391 STLSOFT_TEMPLATE_SPECIALISATION
00392 struct filesystem_traits<us_char_a_t>
00393 : public system_traits<us_char_a_t>
00394 {
00395 public:
00396 typedef us_char_a_t char_type;
00397 typedef us_size_t size_type;
00398 typedef us_ptrdiff_t difference_type;
00399 typedef struct stat stat_data_type;
00400 typedef struct stat fstat_data_type;
00401 typedef filesystem_traits<us_char_a_t> class_type;
00402 typedef us_int_t int_type;
00403 typedef us_bool_t bool_type;
00404 typedef int file_handle_type;
00405 typedef void* module_type;
00406 typedef int error_type;
00407 #ifdef _WIN32
00408 typedef unsigned short mode_type;
00409 #else
00410 typedef mode_t mode_type;
00411 #endif
00412 private:
00413 typedef stlsoft_ns_qual(auto_buffer_old)<char_type> buffer_type_;
00414 public:
00415
00416
00417 #ifdef PATH_MAX
00418 enum
00419 {
00420 maxPathLength = 1 + PATH_MAX
00421 };
00422 #endif
00423
00424 public:
00425 static char_type* ensure_dir_end(char_type* dir)
00426 {
00427 UNIXSTL_ASSERT(NULL != dir);
00428
00429 char_type* end = str_end(dir);
00430
00431 if( dir < end &&
00432 !is_path_name_separator(*(end - 1)))
00433 {
00434 *end = path_name_separator();
00435 *(end + 1) = '\0';
00436 }
00437
00438 return dir;
00439 }
00440
00441 static char_type* remove_dir_end(char_type* dir)
00442 {
00443 UNIXSTL_ASSERT(NULL != dir);
00444
00445 #ifdef _WIN32
00446
00447 if( isalpha(dir[0]) &&
00448 ':' == dir[1] &&
00449 is_path_name_separator(dir[2]) &&
00450 '\0' == dir[3])
00451 {
00452 return dir;
00453 }
00454
00455
00456 if( '\\' == dir[0] &&
00457 '\\' == dir[1] &&
00458 '\0' == dir[3])
00459 {
00460 return dir;
00461 }
00462 #endif
00463
00464 char_type* end = str_end(dir);
00465
00466 if( dir < end &&
00467 is_path_name_separator(*(end - 1)))
00468 {
00469 *(end - 1) = '\0';
00470 }
00471
00472 return dir;
00473 }
00474
00475 static bool_type has_dir_end(char_type const* dir)
00476 {
00477 UNIXSTL_ASSERT(NULL != dir);
00478
00479 size_type len = str_len(dir);
00480
00481 return (0 < len) && is_path_name_separator(dir[len - 1]);
00482 }
00483
00484 static bool_type is_dots(char_type const* dir)
00485 {
00486 UNIXSTL_ASSERT(NULL != dir);
00487
00488 return dir[0] == '.' &&
00489 ( dir[1] == '\0' ||
00490 ( dir[1] == '.' &&
00491 dir[2] == '\0'));
00492 }
00493
00494 static bool_type is_path_rooted(char_type const* path)
00495 {
00496 UNIXSTL_ASSERT(NULL != path);
00497
00498 #ifdef _WIN32
00499
00500
00501
00502 if( '\\' == path[0] &&
00503 '\\' == path[1])
00504 {
00505 return true;
00506 }
00507
00508
00509 if( isalpha(path[0]) &&
00510 ':' == path[1])
00511 {
00512 path += 2;
00513 }
00514
00515
00516
00517
00518 #endif
00519
00520 return is_path_name_separator(*path);
00521 }
00522
00523 static bool_type is_path_absolute(char_type const* path)
00524 {
00525 UNIXSTL_ASSERT(NULL != path);
00526
00527 #ifdef _WIN32
00528
00529
00530
00531 if(is_path_UNC(path))
00532 {
00533 return true;
00534 }
00535
00536 if( isalpha(path[0]) &&
00537 ':' == path[1] &&
00538 is_path_name_separator(path[2]))
00539 {
00540 return true;
00541 }
00542
00543 if('/' == path[0])
00544 {
00545 return true;
00546 }
00547
00548 return false;
00549 #else
00550 return is_path_rooted(path);
00551 #endif
00552 }
00553
00554 static bool_type is_path_UNC(char_type const* path)
00555 {
00556 UNIXSTL_ASSERT(NULL != path);
00557
00558 #ifdef _WIN32
00559 return ('\\' == path[0] && '\\' == path[1]);
00560 #else
00561 STLSOFT_SUPPRESS_UNUSED(path);
00562
00563 return false;
00564 #endif
00565 }
00566
00567 private:
00568 static bool_type is_root_drive_(char_type const* path)
00569 {
00570 #ifdef _WIN32
00571 if( isalpha(path[0]) &&
00572 ':' == path[1] &&
00573 is_path_name_separator(path[2]) &&
00574 '\0' == path[3])
00575 {
00576 return true;
00577 }
00578 #else
00579 STLSOFT_SUPPRESS_UNUSED(path);
00580 #endif
00581
00582 return false;
00583 }
00584 static bool_type is_root_UNC_(char_type const* path)
00585 {
00586 #ifdef _WIN32
00587 if(is_path_UNC(path))
00588 {
00589 char_type const* sep = str_pbrk(path + 2, "\\/");
00590
00591 if( NULL == sep ||
00592 '\0' == sep[1])
00593 {
00594 return true;
00595 }
00596 }
00597 #else
00598 STLSOFT_SUPPRESS_UNUSED(path);
00599 #endif
00600
00601 return false;
00602 }
00603 static bool_type is_root_directory_(char_type const* path)
00604 {
00605 if( is_path_name_separator(path[0]) &&
00606 '\0' == path[1])
00607 {
00608 return true;
00609 }
00610
00611 return false;
00612 }
00613 public:
00614 static bool_type is_root_designator(char_type const* path)
00615 {
00616 UNIXSTL_ASSERT(NULL != path);
00617
00618 return is_root_directory_(path) || is_root_drive_(path) || is_root_UNC_(path);
00619 }
00620
00621 static bool_type is_path_name_separator(char_type ch)
00622 {
00623 #ifdef _WIN32
00624 return '\\' == ch || '/' == ch;
00625 #else
00626 return '/' == ch;
00627 #endif
00628 }
00629
00630 static char_type path_separator()
00631 {
00632 return ':';
00633 }
00634
00635 static char_type path_name_separator()
00636 {
00637 return '/';
00638 }
00639
00640 static char_type const* pattern_all()
00641 {
00642 return "*";
00643 }
00644
00645 static size_type path_max()
00646 {
00647 #if defined(PATH_MAX)
00648 return 1 + PATH_MAX;
00649 #else
00650 return 1 + pathconf("/", _PC_PATH_MAX);
00651 #endif
00652 }
00653
00654 private:
00655 static size_type get_full_path_name_impl2(char_type const* fileName, us_size_t len, char_type* buffer, size_type cchBuffer)
00656 {
00657
00658
00659 if(is_path_rooted(fileName))
00660 {
00661
00662 if(NULL == buffer)
00663 {
00664 len = len;
00665 }
00666 else if(cchBuffer < len)
00667 {
00668 char_copy(&buffer[0], fileName, cchBuffer);
00669 len = cchBuffer;
00670 }
00671 else
00672 {
00673
00674 char_copy(&buffer[0], fileName, len);
00675 buffer[len] = '\0';
00676 }
00677 }
00678 else
00679 {
00680
00681 buffer_type_ directory(1 + path_max());
00682
00683 if(0 == directory.size())
00684 {
00685 set_last_error(ENOMEM);
00686
00687 return 0;
00688 }
00689 else if(NULL != buffer &&
00690 0 == cchBuffer)
00691 {
00692 return 0;
00693 }
00694 else
00695 {
00696 size_type lenDir = get_current_directory(&directory[0], directory.size());
00697
00698 if(0 == lenDir)
00699 {
00700
00701 len = 0;
00702 }
00703 else
00704 {
00705 if( 1 == len &&
00706 '.' == fileName[0])
00707 {
00708 if(NULL == buffer)
00709 {
00710 len = lenDir;
00711 }
00712 else
00713 {
00714 if(cchBuffer < lenDir)
00715 {
00716 char_copy(&buffer[0], directory.data(), cchBuffer);
00717 len = cchBuffer;
00718 }
00719 else
00720 {
00721
00722 char_copy(buffer, directory.data(), lenDir);
00723 buffer[lenDir] = '\0';
00724 len = lenDir;
00725 }
00726 }
00727 }
00728 else
00729 {
00730 if(!has_dir_end(&directory[0] + (lenDir - 1)))
00731 {
00732 ++lenDir;
00733 }
00734 ensure_dir_end(&directory[0]);
00735
00736 len += lenDir;
00737
00738 if(NULL != buffer)
00739 {
00740 char_copy(&buffer[0], directory.data(), cchBuffer);
00741
00742 if(cchBuffer > lenDir)
00743 {
00744 char_copy(&buffer[0] + lenDir, fileName, cchBuffer - lenDir);
00745 }
00746
00747 if(cchBuffer < len)
00748 {
00749 len = cchBuffer;
00750 }
00751 }
00752 }
00753 }
00754 }
00755 }
00756
00757 return len;
00758 }
00759
00760 static size_type get_full_path_name_impl(char_type const* fileName, us_size_t len, char_type* buffer, size_type cchBuffer)
00761 {
00762 UNIXSTL_ASSERT(len > 0);
00763
00764 if(NULL != class_type::str_pbrk(fileName, "<>|*?"))
00765 {
00766 errno = ENOENT;
00767
00768 return 0;
00769 }
00770
00771 if('\0' != fileName[len])
00772 {
00773 buffer_type_ fileName_(1 + (len - 1));
00774
00775
00776
00777
00778
00779
00780 if(0 == fileName_.size())
00781 {
00782 set_last_error(ENOMEM);
00783
00784 return 0;
00785 }
00786 else
00787 {
00788 fileName_[len] = '\0';
00789
00790 return get_full_path_name_impl2(char_copy(&fileName_[0], fileName, len)
00791 , len
00792 , buffer
00793 , cchBuffer);
00794 }
00795 }
00796 else
00797 {
00798 return get_full_path_name_impl2(fileName, len, buffer, cchBuffer);
00799 }
00800 }
00801
00802 public:
00803 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer, char_type** ppFile)
00804 {
00805 UNIXSTL_ASSERT(NULL != ppFile);
00806
00807 size_type r = get_full_path_name(fileName, buffer, cchBuffer);
00808
00809 *ppFile = NULL;
00810
00811 if( NULL != buffer &&
00812 0 != r &&
00813 r <= cchBuffer)
00814 {
00815 size_type cchRequired = get_full_path_name(fileName, static_cast<char_type*>(NULL), 0);
00816
00817 if(r == cchRequired)
00818 {
00819
00820 char_type* pFile = str_rchr(buffer, path_name_separator());
00821 #if defined(_WIN32)
00822 char_type* pFile2 = str_rchr(buffer, '\\');
00823
00824 if(NULL == pFile)
00825 {
00826 pFile = pFile2;
00827 }
00828 else if(NULL != pFile2)
00829 {
00830 if(pFile2 > pFile)
00831 {
00832 pFile = pFile2;
00833 }
00834 }
00835 #endif
00836
00837 if(NULL != (*ppFile = pFile))
00838 {
00839 (*ppFile)++;
00840 }
00841 }
00842 }
00843
00844 return r;
00845 }
00846
00847 static size_type get_full_path_name(char_type const* fileName, char_type* buffer, size_type cchBuffer)
00848 {
00849 UNIXSTL_ASSERT(NULL != fileName);
00850 UNIXSTL_ASSERT(0 == cchBuffer || NULL != buffer);
00851
00852 if('\0' == *fileName)
00853 {
00854 static const char s_dot[2] = { '.', '\0' };
00855
00856 fileName = s_dot;
00857 }
00858
00859
00860 return get_full_path_name_impl(fileName, str_len(fileName), buffer, cchBuffer);
00861 }
00862
00863 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer)
00864 {
00865 return get_full_path_name(fileName, buffer, cchBuffer);
00866 }
00867
00868 static size_type get_short_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer)
00869 {
00870 return get_full_path_name(fileName, cchBuffer, buffer);
00871 }
00872
00873
00874
00875 static DIR *open_dir(char_type const* dir)
00876 {
00877 return ::opendir(dir);
00878 }
00879 static struct dirent const* read_dir(DIR *h)
00880 {
00881 return ::readdir(h);
00882 }
00883 static void close_dir(DIR *h)
00884 {
00885 ::closedir(h);
00886 }
00887
00888
00889 static bool_type set_current_directory(char_type const* dir)
00890 {
00891 #if defined(_WIN32) && \
00892 ( defined(STLSOFT_COMPILER_IS_MSVC) || \
00893 defined(STLSOFT_COMPILER_IS_INTEL))
00894 return 0 == ::_chdir(dir);
00895 #else
00896 return 0 == ::chdir(dir);
00897 #endif
00898 }
00899
00900 static size_type get_current_directory(size_type cchBuffer, char_type* buffer)
00901 {
00902 return get_current_directory(buffer, cchBuffer);
00903 }
00904
00905 static size_type get_current_directory(char_type* buffer, size_type cchBuffer)
00906 {
00907 #if defined(_WIN32) && \
00908 ( defined(STLSOFT_COMPILER_IS_INTEL) || \
00909 defined(STLSOFT_COMPILER_IS_MSVC))
00910 char_type const* dir = ::_getcwd(buffer, int(cchBuffer));
00911 #else
00912 char_type const* dir = ::getcwd(buffer, int(cchBuffer));
00913 #endif
00914
00915 return (NULL == dir) ? 0 : str_len(dir);
00916 }
00917
00918 static bool_type file_exists(char_type const* fileName)
00919 {
00920 stat_data_type sd;
00921
00922 return class_type::stat(fileName, &sd) ;
00923 }
00924
00925 static bool_type is_file(char_type const* path)
00926 {
00927 stat_data_type sd;
00928
00929 return class_type::stat(path, &sd) && S_IFREG == (sd.st_mode & S_IFMT);
00930 }
00931
00932 static bool_type is_directory(char_type const* path)
00933 {
00934 stat_data_type sd;
00935
00936 return class_type::stat(path, &sd) && S_IFDIR == (sd.st_mode & S_IFMT);
00937 }
00938
00939 static bool_type stat(char_type const* path, stat_data_type *stat_data)
00940 {
00941 UNIXSTL_ASSERT(NULL != path);
00942 UNIXSTL_ASSERT(NULL != stat_data);
00943
00944 #ifdef _WIN32
00945 if(NULL != class_type::str_pbrk(path, "*?"))
00946 {
00947
00948 set_last_error(EBADF);
00949
00950 return false;
00951 }
00952
00953 if(has_dir_end(path))
00954 {
00955
00956 size_type len = str_len(path);
00957
00958 if( len > 3 ||
00959 ( is_path_name_separator(*path) &&
00960 len > 2))
00961 {
00962 buffer_type_ directory(1 + len);
00963
00964 if(0 == directory.size())
00965 {
00966 set_last_error(ENOMEM);
00967
00968 return false;
00969 }
00970 else
00971 {
00972 char_copy(&directory[0], path, len);
00973 directory[len] = '\0';
00974
00975 class_type::remove_dir_end(&directory[0]);
00976
00977 return class_type::stat(directory.data(), stat_data);
00978 }
00979 }
00980 }
00981 #endif
00982
00983 return 0 == ::stat(path, stat_data);
00984 }
00985
00986 static bool_type lstat(char_type const* path, stat_data_type *stat_data)
00987 {
00988 UNIXSTL_ASSERT(NULL != path);
00989 UNIXSTL_ASSERT(NULL != stat_data);
00990
00991 #ifdef _WIN32
00992 return 0 == class_type::stat(path, stat_data);
00993 #else
00994 return 0 == ::lstat(path, stat_data);
00995 #endif
00996 }
00997
00998 static bool_type fstat(file_handle_type fd, fstat_data_type *fstat_data)
00999 {
01000 UNIXSTL_ASSERT(-1 != fd);
01001 UNIXSTL_ASSERT(NULL != fstat_data);
01002
01003 return 0 == ::fstat(fd, fstat_data);
01004 }
01005
01006 static bool_type is_file(stat_data_type const* stat_data)
01007 {
01008 return S_IFREG == (stat_data->st_mode & S_IFREG);
01009 }
01010 static bool_type is_directory(stat_data_type const* stat_data)
01011 {
01012 return S_IFDIR == (stat_data->st_mode & S_IFDIR);
01013 }
01014 static bool_type is_link(stat_data_type const* stat_data)
01015 {
01016 #ifdef _WIN32
01017 STLSOFT_SUPPRESS_UNUSED(stat_data);
01018
01019 return false;
01020 #else
01021 return S_IFLNK == (stat_data->st_mode & S_IFLNK);
01022 #endif
01023 }
01024 static bool_type is_readonly(stat_data_type const* stat_data)
01025 {
01026 #ifdef _WIN32
01027 return S_IREAD == (stat_data->st_mode & (S_IREAD | S_IWRITE));
01028 #else
01029 return S_IRUSR == (stat_data->st_mode & (S_IRUSR | S_IWUSR));
01030 #endif
01031 }
01032
01033 static bool_type create_directory(char_type const* dir)
01034 {
01035 mode_type mode = 0;
01036
01037 #ifdef _WIN32
01038 mode = S_IREAD | S_IWRITE | S_IEXEC;
01039 #else
01040 mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
01041 #endif
01042
01043 return create_directory(dir, 0);
01044 }
01045
01046 static bool_type create_directory(char_type const* dir, mode_type permissions)
01047 {
01048 #if defined(_WIN32) && \
01049 ( defined(STLSOFT_COMPILER_IS_INTEL) || \
01050 defined(STLSOFT_COMPILER_IS_MSVC))
01051
01052 STLSOFT_SUPPRESS_UNUSED(permissions);
01053
01054 return 0 == ::_mkdir(dir);
01055 #else
01056 return 0 == ::mkdir(dir, permissions);
01057 #endif
01058 }
01059
01060 static bool_type remove_directory(char_type const* dir)
01061 {
01062 #if defined(_WIN32) && \
01063 ( defined(STLSOFT_COMPILER_IS_INTEL) || \
01064 defined(STLSOFT_COMPILER_IS_MSVC))
01065 return 0 == ::_rmdir(dir);
01066 #else
01067 return 0 == ::rmdir(dir);
01068 #endif
01069 }
01070
01071 static bool_type unlink_file(char_type const* file)
01072 {
01073 return 0 == ::remove(file);
01074 }
01075
01076 static bool_type delete_file(char_type const* file)
01077 {
01078 return unlink_file(file);
01079 }
01080
01081 static bool_type rename_file(char_type const* currentName, char_type const* newName)
01082 {
01083 return 0 == ::rename(currentName, newName);
01084 }
01085
01086 #if ( defined(STLSOFT_COMPILER_IS_MSVC) || \
01087 defined(STLSOFT_COMPILER_IS_INTEL)) && \
01088 defined(STLSOFT_USING_SAFE_STR_FUNCTIONS)
01089 # if _MSC_VER >= 1200
01090 # pragma warning(push)
01091 # endif
01092 # pragma warning(disable : 4996)
01093 #endif
01094
01095 static file_handle_type open_file(char_type const* fileName, int oflag, int pmode)
01096 {
01097 #if defined(_WIN32) && \
01098 ( defined(STLSOFT_COMPILER_IS_INTEL) || \
01099 defined(STLSOFT_COMPILER_IS_MSVC))
01100 return ::_open(fileName, oflag, pmode);
01101 #else
01102 return ::open(fileName, oflag, pmode);
01103 #endif
01104 }
01105
01106 #if ( defined(STLSOFT_COMPILER_IS_MSVC) || \
01107 defined(STLSOFT_COMPILER_IS_INTEL)) && \
01108 defined(STLSOFT_USING_SAFE_STR_FUNCTIONS)
01109 # if _MSC_VER >= 1200
01110 # pragma warning(pop)
01111 # else
01112 # pragma warning(default : 4996)
01113 # endif
01114 #endif
01115
01116 static bool_type close_file(file_handle_type fd)
01117 {
01118 #if defined(_WIN32) && \
01119 ( defined(STLSOFT_COMPILER_IS_INTEL) || \
01120 defined(STLSOFT_COMPILER_IS_MSVC))
01121 return 0 == ::_close(fd);
01122 #else
01123 return 0 == ::close(fd);
01124 #endif
01125 }
01126
01127 static file_handle_type open(char_type const* fileName, int oflag, int pmode)
01128 {
01129 return class_type::open_file(fileName, oflag, pmode);
01130 }
01131
01132 static bool_type close(file_handle_type fd)
01133 {
01134 return class_type::close_file(fd);
01135 }
01136
01137 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
01138 static us_uint64_t get_file_size(file_handle_type fd)
01139 {
01140 struct stat st;
01141
01142 return class_type::fstat(fd, &st) ? st.st_size : 0;
01143 }
01144 #endif
01145 };
01146
01147 STLSOFT_TEMPLATE_SPECIALISATION
01148 struct filesystem_traits<us_char_w_t>
01149 : public system_traits<us_char_w_t>
01150 {
01151 public:
01152 typedef us_char_w_t char_type;
01153 typedef us_size_t size_type;
01154
01155 #ifdef PATH_MAX
01156 enum
01157 {
01158 maxPathLength = 1 + PATH_MAX
01159 };
01160 #endif
01161
01162 public:
01163 static char_type* ensure_dir_end(char_type* dir)
01164 {
01165 UNIXSTL_ASSERT(NULL != dir);
01166
01167 char_type* end = str_end(dir);
01168
01169 if( dir < end &&
01170 !is_path_name_separator(*(end - 1)))
01171 {
01172 *end = path_name_separator();
01173 *(end + 1) = L'\0';
01174 }
01175
01176 return dir;
01177 }
01178
01179 static char_type* remove_dir_end(char_type* dir)
01180 {
01181 UNIXSTL_ASSERT(NULL != dir);
01182
01183 #ifdef _WIN32
01184
01185 if( isalpha(dir[0]) &&
01186 L':' == dir[1] &&
01187 is_path_name_separator(dir[2]) &&
01188 L'\0' == dir[3])
01189 {
01190 return dir;
01191 }
01192
01193
01194 if( L'\\' == dir[0] &&
01195 L'\\' == dir[1] &&
01196 L'\0' == dir[3])
01197 {
01198 return dir;
01199 }
01200 #endif
01201
01202 char_type* end = str_end(dir);
01203
01204 if( dir < end &&
01205 is_path_name_separator(*(end - 1)))
01206 {
01207 *(end - 1) = L'\0';
01208 }
01209
01210 return dir;
01211 }
01212
01213 static bool_type has_dir_end(char_type const* dir)
01214 {
01215 UNIXSTL_ASSERT(NULL != dir);
01216
01217 size_type len = str_len(dir);
01218
01219 return (0 < len) && is_path_name_separator(dir[len - 1]);
01220 }
01221
01222 static bool_type is_dots(char_type const* dir)
01223 {
01224 UNIXSTL_ASSERT(NULL != dir);
01225
01226 return dir[0] == '.' &&
01227 ( dir[1] == L'\0' ||
01228 ( dir[1] == L'.' &&
01229 dir[2] == L'\0'));
01230 }
01231
01232 static bool_type is_path_rooted(char_type const* path)
01233 {
01234 UNIXSTL_ASSERT(NULL != path);
01235
01236 #ifdef _WIN32
01237
01238 if( isalpha(path[0]) &&
01239 ':' == path[1])
01240 {
01241 path += 2;
01242 }
01243
01244
01245
01246 if('\\' == *path)
01247 {
01248 return true;
01249 }
01250 #endif
01251
01252 return '/' == *path;
01253 }
01254
01255 static bool_type is_path_absolute(char_type const* path)
01256 {
01257 UNIXSTL_ASSERT(NULL != path);
01258
01259 #ifdef _WIN32
01260
01261
01262
01263 if(is_path_UNC(path))
01264 {
01265 return true;
01266 }
01267
01268 if( isalpha(path[0]) &&
01269 ':' == path[1] &&
01270 is_path_name_separator(path[2]))
01271 {
01272 return true;
01273 }
01274
01275 if('/' == path[0])
01276 {
01277 return true;
01278 }
01279
01280 return false;
01281 #else
01282 return is_path_rooted(path);
01283 #endif
01284 }
01285
01286 static bool_type is_path_UNC(char_type const* path)
01287 {
01288 UNIXSTL_ASSERT(NULL != path);
01289
01290 #ifdef _WIN32
01291 return (L'\\' == path[0] && L'\\' == path[1]);
01292 #else
01293 STLSOFT_SUPPRESS_UNUSED(path);
01294
01295 return false;
01296 #endif
01297 }
01298
01299 static bool_type is_path_name_separator(char_type ch)
01300 {
01301 #ifdef _WIN32
01302 return L'\\' == ch || L'/' == ch;
01303 #else
01304 return L'/' == ch;
01305 #endif
01306 }
01307
01308 static char_type path_separator()
01309 {
01310 return L':';
01311 }
01312
01313 static char_type path_name_separator()
01314 {
01315 return L'/';
01316 }
01317
01318 static char_type const* pattern_all()
01319 {
01320 return L"*";
01321 }
01322
01323 static size_type path_max()
01324 {
01325 #if defined(PATH_MAX)
01326 return 1 + PATH_MAX;
01327 #else
01328 return 1 + pathconf("/", _PC_PATH_MAX);
01329 #endif
01330 }
01331
01332 #if 0
01333 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer, char_type** ppFile);
01334
01335 static size_type get_full_path_name(char_type const* fileName, char_type* buffer, size_type cchBuffer)
01336 {
01337 char_type* pFile;
01338
01339 return get_full_path_name(fileName, cchBuffer, buffer, &pFile);
01340 }
01341
01342 static size_type get_full_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer)
01343 {
01344 return get_full_path_name(fileName, buffer, cchBuffer);
01345 }
01346
01347 static size_type get_short_path_name(char_type const* fileName, size_type cchBuffer, char_type* buffer)
01348 {
01349 return get_full_path_name(fileName, cchBuffer, buffer);
01350 }
01351 #endif
01352
01353
01354 static bool_type set_current_directory(char_type const* dir);
01355
01356 static size_type get_current_directory(size_type cchBuffer, char_type* buffer);
01357
01358 static size_type get_current_directory(char_type* buffer, size_type cchBuffer);
01359 };
01360
01361 #endif
01362
01363
01364
01365
01366
01367 #ifdef STLSOFT_UNITTEST
01368 # include "./unittest/filesystem_traits_unittest_.h"
01369 #endif
01370
01371
01372
01373 #ifndef _UNIXSTL_NO_NAMESPACE
01374 # if defined(_STLSOFT_NO_NAMESPACE) || \
01375 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
01376 }
01377 # else
01378 }
01379 }
01380 # endif
01381 #endif
01382
01383
01384
01385 #endif
01386
01387