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