00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "filename.h"
00020 #include "dSearchPath.h"
00021 #include "executionEnvironment.h"
00022
00023 #include <stdio.h>
00024 #include <time.h>
00025 #include <sys/stat.h>
00026 #include <algorithm>
00027
00028 #ifdef HAVE_UTIME_H
00029 #include <utime.h>
00030
00031
00032 #include <errno.h>
00033 #include <fcntl.h>
00034 #endif
00035
00036 #ifdef HAVE_DIRENT_H
00037 #include <dirent.h>
00038 #endif
00039
00040
00041
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045
00046
00047 #ifdef WIN32
00048
00049
00050 #ifdef WIN32_VC
00051 #include <direct.h>
00052 #include <windows.h>
00053 #endif
00054
00055
00056
00057 #ifndef FILE_ATTRIBUTE_DEVICE
00058 #define FILE_ATTRIBUTE_DEVICE 0x00000040
00059 #endif
00060
00061
00062
00063
00064
00065
00066 #ifdef HAVE_CYGWIN
00067 extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32);
00068 extern "C" void cygwin_conv_to_posix_path(const char *path, char *posix);
00069 #endif
00070
00071 static string
00072 front_to_back_slash(const string &str) {
00073 string result = str;
00074 string::iterator si;
00075 for (si = result.begin(); si != result.end(); ++si) {
00076 if ((*si) == '/') {
00077 (*si) = '\\';
00078 }
00079 }
00080
00081 return result;
00082 }
00083
00084 static string
00085 back_to_front_slash(const string &str) {
00086 string result = str;
00087 string::iterator si;
00088 for (si = result.begin(); si != result.end(); ++si) {
00089 if ((*si) == '\\') {
00090 (*si) = '/';
00091 }
00092 }
00093
00094 return result;
00095 }
00096
00097 static const string &
00098 get_panda_root() {
00099 static string panda_root;
00100 static bool got_panda_root = false;
00101
00102 if (!got_panda_root) {
00103 const char *envvar = getenv("PANDA_ROOT");
00104 if (envvar != (const char *)NULL) {
00105 panda_root = front_to_back_slash(envvar);
00106 }
00107
00108 if (panda_root.empty() || panda_root[panda_root.length() - 1] != '\\') {
00109 panda_root += '\\';
00110 }
00111
00112 got_panda_root = true;
00113 }
00114
00115 return panda_root;
00116 }
00117
00118 static string
00119 convert_pathname(const string &unix_style_pathname, bool use_backslash) {
00120 if (unix_style_pathname.empty()) {
00121 return string();
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 string windows_pathname;
00137
00138 if (unix_style_pathname[0] != '/') {
00139
00140
00141
00142 if (use_backslash) {
00143 windows_pathname = front_to_back_slash(unix_style_pathname);
00144 } else {
00145 windows_pathname = unix_style_pathname;
00146 }
00147
00148 } else if (unix_style_pathname.length() > 3 &&
00149 isalpha(unix_style_pathname[1]) &&
00150 unix_style_pathname[2] == '/') {
00151
00152
00153
00154
00155
00156
00157
00158 if (use_backslash) {
00159 windows_pathname =
00160 string(1, (char)toupper(unix_style_pathname[1])) + ":" +
00161 front_to_back_slash(unix_style_pathname.substr(2));
00162 } else {
00163 windows_pathname =
00164 string(1, (char)toupper(unix_style_pathname[1])) + ":" +
00165 unix_style_pathname.substr(2);
00166 }
00167
00168 } else {
00169
00170
00171
00172 #ifdef HAVE_CYGWIN
00173
00174 char result[4096] = "";
00175 cygwin_conv_to_win32_path(unix_style_pathname.c_str(), result);
00176 if (use_backslash) {
00177 windows_pathname = result;
00178 } else {
00179 windows_pathname = back_to_front_slash(result);
00180 }
00181 #else // HAVE_CYGWIN
00182
00183 windows_pathname = get_panda_root();
00184 if (use_backslash) {
00185 windows_pathname += front_to_back_slash(unix_style_pathname.substr(1));
00186 } else {
00187 windows_pathname += unix_style_pathname.substr(1);
00188 }
00189 #endif // HAVE_CYGWIN
00190 }
00191
00192 return windows_pathname;
00193 }
00194
00195 static string
00196 convert_dso_pathname(const string &unix_style_pathname, bool use_backslash) {
00197
00198 size_t dot = unix_style_pathname.rfind('.');
00199 if (dot == string::npos ||
00200 unix_style_pathname.find('/', dot) != string::npos) {
00201
00202 return convert_pathname(unix_style_pathname, use_backslash);
00203 }
00204 if (unix_style_pathname.substr(dot) != ".so") {
00205
00206 return convert_pathname(unix_style_pathname, use_backslash);
00207 }
00208
00209 string dll_basename = unix_style_pathname.substr(0, dot);
00210
00211 #ifdef _DEBUG
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 return convert_pathname(dll_basename + "_d.dll", use_backslash);
00224 #else
00225 return convert_pathname(dll_basename + ".dll", use_backslash);
00226 #endif
00227 }
00228
00229 static string
00230 convert_executable_pathname(const string &unix_style_pathname, bool use_backslash) {
00231
00232 size_t dot = unix_style_pathname.rfind('.');
00233 if (dot == string::npos ||
00234 unix_style_pathname.find('/', dot) != string::npos) {
00235
00236 return convert_pathname(unix_style_pathname + ".exe", use_backslash);
00237 }
00238 if (unix_style_pathname.substr(dot) != ".exe") {
00239
00240 return convert_pathname(unix_style_pathname + ".exe", use_backslash);
00241 }
00242
00243 return convert_pathname(unix_style_pathname, use_backslash);
00244 }
00245 #endif //WIN32
00246
00247
00248
00249
00250
00251
00252
00253
00254 Filename::
00255 Filename(const Filename &dirname, const Filename &basename) {
00256 if (dirname.empty()) {
00257 (*this) = basename;
00258 } else {
00259 string dirpath = dirname.get_fullpath();
00260 if (dirpath[dirpath.length() - 1] == '/') {
00261 (*this) = dirpath + basename.get_fullpath();
00262 } else {
00263 (*this) = dirpath + "/" + basename.get_fullpath();
00264 }
00265 }
00266 _flags = 0;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 Filename Filename::
00290 from_os_specific(const string &os_specific, Filename::Type type) {
00291 #ifdef WIN32
00292 string result = back_to_front_slash(os_specific);
00293 const string &panda_root = get_panda_root();
00294
00295
00296 if (!panda_root.empty() && panda_root.length() < result.length()) {
00297 bool matches = true;
00298 size_t p;
00299 for (p = 0; p < panda_root.length() && matches; p++) {
00300 char c = tolower(panda_root[p]);
00301 if (c == '\\') {
00302 c = '/';
00303 }
00304 matches = (c == tolower(result[p]));
00305 }
00306
00307 if (matches) {
00308
00309
00310 result = result.substr(panda_root.length());
00311 assert(!result.empty());
00312 if (result[0] != '/') {
00313 result = '/' + result;
00314 }
00315 Filename filename(result);
00316 filename.set_type(type);
00317 return filename;
00318 }
00319 }
00320
00321
00322
00323 if (result.size() >= 3 && isalpha(result[0]) &&
00324 result[1] == ':' && result[2] == '/') {
00325 result[1] = tolower(result[0]);
00326 result[0] = '/';
00327 }
00328
00329 Filename filename(result);
00330 filename.set_type(type);
00331 return filename;
00332 #else // WIN32
00333
00334 Filename filename(os_specific);
00335 filename.set_type(type);
00336 return filename;
00337 #endif // WIN32
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347 Filename Filename::
00348 expand_from(const string &os_specific, Filename::Type type) {
00349 return from_os_specific(ExecutionEnvironment::expand_string(os_specific),
00350 type);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 Filename Filename::
00367 temporary(const string &dirname, const string &prefix, Type type) {
00368 if (dirname.empty()) {
00369
00370
00371 char *name = tempnam(NULL, prefix.c_str());
00372 Filename result(name);
00373 free(name);
00374 result.set_type(type);
00375 return result;
00376 }
00377
00378
00379
00380
00381
00382 Filename result(dirname, "");
00383 result.set_type(type);
00384 do {
00385
00386
00387
00388 int hash = (clock() * time(NULL)) & 0xffffff;
00389 char hex_code[10];
00390 sprintf(hex_code, "%06x", hash);
00391 result.set_basename(prefix + hex_code);
00392 } while (result.exists());
00393
00394 return result;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 void Filename::
00405 set_fullpath(const string &s) {
00406 (*this) = s;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 void Filename::
00417 set_dirname(const string &s) {
00418 if (s.empty()) {
00419
00420 _filename.replace(0, _basename_start, "");
00421
00422 int length_change = - ((int)_basename_start);
00423
00424 _dirname_end = 0;
00425 _basename_start += length_change;
00426 _basename_end += length_change;
00427 _extension_start += length_change;
00428
00429 } else {
00430
00431
00432
00433 string ss;
00434 if (s[s.length()-1] == '/') {
00435 ss = s;
00436 } else {
00437 ss = s+'/';
00438 }
00439
00440 int length_change = ss.length() - _basename_start;
00441
00442 _filename.replace(0, _basename_start, ss);
00443
00444 _dirname_end = ss.length() - 1;
00445
00446
00447
00448 if (ss.length() == 1) {
00449 _dirname_end = 1;
00450 }
00451
00452 _basename_start += length_change;
00453
00454 if (_basename_end != string::npos) {
00455 _basename_end += length_change;
00456 _extension_start += length_change;
00457 }
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468 void Filename::
00469 set_basename(const string &s) {
00470 _filename.replace(_basename_start, string::npos, s);
00471 locate_extension();
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481 void Filename::
00482 set_fullpath_wo_extension(const string &s) {
00483 int length_change = s.length() - _basename_end;
00484
00485 _filename.replace(0, _basename_end, s);
00486
00487 if (_basename_end != string::npos) {
00488 _basename_end += length_change;
00489 _extension_start += length_change;
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500 void Filename::
00501 set_basename_wo_extension(const string &s) {
00502 int length_change = s.length() - (_basename_end - _basename_start);
00503
00504 if (_basename_end == string::npos) {
00505 _filename.replace(_basename_start, string::npos, s);
00506
00507 } else {
00508 _filename.replace(_basename_start, _basename_end - _basename_start, s);
00509
00510 _basename_end += length_change;
00511 _extension_start += length_change;
00512 }
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 void Filename::
00524 set_extension(const string &s) {
00525 if (s.empty()) {
00526
00527 if (_basename_end != string::npos) {
00528 _filename.replace(_basename_end, string::npos, "");
00529 _basename_end = string::npos;
00530 _extension_start = string::npos;
00531 }
00532
00533 } else if (_basename_end == string::npos) {
00534
00535 _basename_end = _filename.length();
00536 _extension_start = _filename.length() + 1;
00537 _filename += '.' + s;
00538
00539 } else {
00540
00541 _filename.replace(_extension_start, string::npos, s);
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 void Filename::
00556 extract_components(vector_string &components) const {
00557 components.clear();
00558
00559 size_t p = 0;
00560 if (!_filename.empty() && _filename[0] == '/') {
00561
00562 p = 1;
00563 }
00564 while (p < _filename.length()) {
00565 size_t q = _filename.find('/', p);
00566 if (q == string::npos) {
00567 components.push_back(_filename.substr(p));
00568 return;
00569 }
00570 components.push_back(_filename.substr(p, q - p));
00571 p = q + 1;
00572 }
00573
00574
00575 components.push_back(string());
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 void Filename::
00587 standardize() {
00588 assert(!_filename.empty());
00589 if (_filename == ".") {
00590
00591 return;
00592 }
00593
00594 vector<string> components;
00595
00596
00597 bool global = (_filename[0] == '/');
00598
00599 size_t p = 0;
00600 while (p < _filename.length() && _filename[p] == '/') {
00601 p++;
00602 }
00603 while (p < _filename.length()) {
00604 size_t slash = _filename.find('/', p);
00605 string component = _filename.substr(p, slash - p);
00606 if (component == ".") {
00607
00608 } else if (component == ".." && !components.empty() &&
00609 !(components.back() == "..")) {
00610
00611 components.pop_back();
00612 } else {
00613 components.push_back(component);
00614 }
00615
00616 p = slash;
00617 while (p < _filename.length() && _filename[p] == '/') {
00618 p++;
00619 }
00620 }
00621
00622
00623 string result;
00624 if (global) {
00625 result = "/";
00626 }
00627 if (!components.empty()) {
00628 result += components[0];
00629 for (int i = 1; i < (int)components.size(); i++) {
00630 result += "/" + components[i];
00631 }
00632 }
00633
00634 (*this) = result;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 void Filename::
00654 make_absolute() {
00655 make_absolute(ExecutionEnvironment::get_cwd());
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 void Filename::
00668 make_absolute(const Filename &start_directory) {
00669 if (is_local()) {
00670 (*this) = Filename(start_directory, _filename);
00671 }
00672
00673 standardize();
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 bool Filename::
00701 make_canonical() {
00702 if (empty()) {
00703
00704
00705 return false;
00706 }
00707
00708
00709 Filename cwd = ExecutionEnvironment::get_cwd();
00710
00711 if (is_directory()) {
00712
00713
00714 string dirname = to_os_specific();
00715
00716 if (chdir(dirname.c_str()) < 0) {
00717 return false;
00718 }
00719 (*this) = ExecutionEnvironment::get_cwd();
00720
00721 } else {
00722
00723
00724 Filename dir(get_dirname());
00725
00726 if (dir.empty()) {
00727
00728 set_dirname(cwd);
00729 return true;
00730 }
00731
00732 string dirname = dir.to_os_specific();
00733 if (chdir(dirname.c_str()) < 0) {
00734 return false;
00735 }
00736 set_dirname(ExecutionEnvironment::get_cwd().get_fullpath());
00737 }
00738
00739
00740 string osdir = cwd.to_os_specific();
00741 if (chdir(osdir.c_str()) < 0) {
00742 cerr << "Error! Cannot change back to " << cwd << "\n";
00743 }
00744
00745 return true;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 string Filename::
00763 to_os_specific() const {
00764 if (empty()) {
00765 return string();
00766 }
00767 Filename standard(*this);
00768 standard.standardize();
00769
00770 #ifdef WIN32
00771 switch (get_type()) {
00772 case T_dso:
00773 return convert_dso_pathname(standard.get_fullpath(), true);
00774 case T_executable:
00775 return convert_executable_pathname(standard.get_fullpath(), true);
00776 default:
00777 return convert_pathname(standard.get_fullpath(), true);
00778 }
00779 #else // WIN32
00780 return standard;
00781 #endif // WIN32
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 string Filename::
00800 to_os_generic() const {
00801 if (empty()) {
00802 return string();
00803 }
00804 Filename standard(*this);
00805 standard.standardize();
00806
00807 #ifdef WIN32
00808 switch (get_type()) {
00809 case T_dso:
00810 return convert_dso_pathname(standard.get_fullpath(), false);
00811 case T_executable:
00812 return convert_executable_pathname(standard.get_fullpath(), false);
00813 default:
00814 return convert_pathname(standard.get_fullpath(), false);
00815 }
00816 #else // WIN32
00817 return standard;
00818 #endif // WIN32
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 bool Filename::
00830 exists() const {
00831 string os_specific = to_os_specific();
00832
00833 #ifdef WIN32_VC
00834 bool exists = false;
00835
00836 DWORD results = GetFileAttributes(os_specific.c_str());
00837 if (results != -1) {
00838 exists = true;
00839 }
00840
00841 #else // WIN32_VC
00842 struct stat this_buf;
00843 bool exists = false;
00844
00845 if (stat(os_specific.c_str(), &this_buf) == 0) {
00846 exists = true;
00847 }
00848 #endif
00849
00850 return exists;
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860 bool Filename::
00861 is_regular_file() const {
00862 string os_specific = to_os_specific();
00863
00864 #ifdef WIN32_VC
00865 bool isreg = false;
00866
00867 DWORD results = GetFileAttributes(os_specific.c_str());
00868 if (results != -1) {
00869 isreg = ((results & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0);
00870 }
00871
00872 #else // WIN32_VC
00873 struct stat this_buf;
00874 bool isreg = false;
00875
00876 if (stat(os_specific.c_str(), &this_buf) == 0) {
00877 isreg = S_ISREG(this_buf.st_mode);
00878 }
00879 #endif
00880
00881 return isreg;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890 bool Filename::
00891 is_directory() const {
00892 string os_specific = to_os_specific();
00893
00894 #ifdef WIN32_VC
00895 bool isdir = false;
00896
00897 DWORD results = GetFileAttributes(os_specific.c_str());
00898 if (results != -1) {
00899 isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
00900 }
00901 #else // WIN32_VC
00902 struct stat this_buf;
00903 bool isdir = false;
00904
00905 if (stat(os_specific.c_str(), &this_buf) == 0) {
00906 isdir = S_ISDIR(this_buf.st_mode);
00907 }
00908 #endif
00909
00910 return isdir;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919 bool Filename::
00920 is_executable() const {
00921 #ifdef WIN32_VC
00922
00923
00924 string extension = get_extension();
00925 if (extension == "exe" || extension == "com") {
00926 return exists();
00927 }
00928
00929 #else
00930 string os_specific = to_os_specific();
00931 if (access(os_specific.c_str(), X_OK) == 0) {
00932 return true;
00933 }
00934 #endif
00935
00936 return false;
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953 int Filename::
00954 compare_timestamps(const Filename &other,
00955 bool this_missing_is_old,
00956 bool other_missing_is_old) const {
00957 string os_specific = to_os_specific();
00958 string other_os_specific = other.to_os_specific();
00959
00960 #ifdef WIN32_VC
00961 struct _stat this_buf;
00962 bool this_exists = false;
00963
00964 if (_stat(os_specific.c_str(), &this_buf) == 0) {
00965 this_exists = true;
00966 }
00967
00968 struct _stat other_buf;
00969 bool other_exists = false;
00970
00971 if (_stat(other_os_specific.c_str(), &other_buf) == 0) {
00972 other_exists = true;
00973 }
00974 #else // WIN32_VC
00975 struct stat this_buf;
00976 bool this_exists = false;
00977
00978 if (stat(os_specific.c_str(), &this_buf) == 0) {
00979 this_exists = true;
00980 }
00981
00982 struct stat other_buf;
00983 bool other_exists = false;
00984
00985 if (stat(other_os_specific.c_str(), &other_buf) == 0) {
00986 other_exists = true;
00987 }
00988 #endif
00989
00990 if (this_exists && other_exists) {
00991
00992 return (int)this_buf.st_mtime - (int)other_buf.st_mtime;
00993
00994 } else if (!this_exists && !other_exists) {
00995
00996 if (this_missing_is_old == other_missing_is_old) {
00997
00998 return 0;
00999 }
01000 if (this_missing_is_old) {
01001
01002 return -1;
01003 } else {
01004
01005 return 1;
01006 }
01007
01008 } else if (!this_exists) {
01009
01010 return this_missing_is_old ? -1 : 1;
01011
01012 } else {
01013 assert(!other_exists);
01014
01015
01016 return other_missing_is_old ? 1 : -1;
01017 }
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 bool Filename::
01029 resolve_filename(const DSearchPath &searchpath,
01030 const string &default_extension) {
01031 string found;
01032
01033 if (is_local()) {
01034 found = searchpath.find_file(get_fullpath());
01035
01036 if (found.empty()) {
01037
01038
01039 if (get_extension().empty() && !default_extension.empty()) {
01040 Filename try_ext = *this;
01041 try_ext.set_extension(default_extension);
01042 found = searchpath.find_file(try_ext.get_fullpath());
01043 }
01044 }
01045
01046 } else {
01047 if (exists()) {
01048
01049 return true;
01050
01051 } else {
01052
01053
01054 if (get_extension().empty() && !default_extension.empty()) {
01055 Filename try_ext = *this;
01056 try_ext.set_extension(default_extension);
01057 if (try_ext.exists()) {
01058 found = try_ext;
01059 }
01060 }
01061 }
01062 }
01063
01064 if (!found.empty()) {
01065 (*this) = found;
01066 return true;
01067 }
01068
01069 return false;
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 bool Filename::
01098 make_relative_to(Filename directory, bool allow_backups) {
01099 if (_filename.empty() || directory.empty() ||
01100 _filename[0] != '/' || directory[0] != '/') {
01101 return false;
01102 }
01103
01104 standardize();
01105 directory.standardize();
01106
01107 if (directory == "/") {
01108
01109 return false;
01110 }
01111
01112 string rel_to_file = directory.get_fullpath() + "/.";
01113
01114 size_t common = get_common_prefix(rel_to_file);
01115 if (common < 2) {
01116
01117 return false;
01118 }
01119
01120 string result;
01121 int slashes = count_slashes(rel_to_file.substr(common));
01122 if (slashes > 0 && !allow_backups) {
01123
01124 return false;
01125 }
01126
01127 for (int i = 0; i < slashes; i++) {
01128 result += "../";
01129 }
01130 result += _filename.substr(common);
01131 (*this) = result;
01132
01133 return true;
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 int Filename::
01152 find_on_searchpath(const DSearchPath &searchpath) {
01153 if (_filename.empty() || _filename[0] != '/') {
01154 return -1;
01155 }
01156
01157 int num_directories = searchpath.get_num_directories();
01158 for (int i = 0; i < num_directories; i++) {
01159 if (make_relative_to(searchpath.get_directory(i), false)) {
01160 return i;
01161 }
01162 }
01163
01164 return -1;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 bool Filename::
01184 scan_directory(vector_string &contents) const {
01185 #if defined(HAVE_DIRENT_H)
01186 size_t orig_size = contents.size();
01187
01188 string dirname;
01189 if (empty()) {
01190 dirname = ".";
01191 } else {
01192 dirname = _filename;
01193 }
01194 DIR *root = opendir(dirname.c_str());
01195 if (root == (DIR *)NULL) {
01196 return false;
01197 }
01198
01199 struct dirent *d;
01200 d = readdir(root);
01201 while (d != (struct dirent *)NULL) {
01202 if (d->d_name[0] != '.') {
01203 contents.push_back(d->d_name);
01204 }
01205 d = readdir(root);
01206 }
01207 closedir(root);
01208
01209 sort(contents.begin() + orig_size, contents.end());
01210 return true;
01211
01212 #elif defined(WIN32_VC)
01213
01214
01215 size_t orig_size = contents.size();
01216
01217 string match;
01218 if (empty()) {
01219 match = "*.*";
01220 } else {
01221 match = to_os_specific() + "\\*.*";
01222 }
01223 WIN32_FIND_DATA find_data;
01224
01225 HANDLE handle = FindFirstFile(match.c_str(), &find_data);
01226 if (handle == INVALID_HANDLE_VALUE) {
01227 if (GetLastError() == ERROR_NO_MORE_FILES) {
01228
01229 return true;
01230 }
01231 return false;
01232 }
01233
01234 do {
01235 string filename = find_data.cFileName;
01236 if (filename != "." && filename != "..") {
01237 contents.push_back(filename);
01238 }
01239 } while (FindNextFile(handle, &find_data));
01240
01241 bool scan_ok = (GetLastError() == ERROR_NO_MORE_FILES);
01242 FindClose(handle);
01243
01244 sort(contents.begin() + orig_size, contents.end());
01245 return scan_ok;
01246
01247 #else
01248
01249 return false;
01250 #endif
01251 }
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 bool Filename::
01265 open_read(ifstream &stream) const {
01266 assert(is_text() || is_binary());
01267
01268 ios_openmode open_mode = ios::in;
01269
01270 #ifdef HAVE_IOS_BINARY
01271
01272
01273 if (!is_text()) {
01274 open_mode |= ios::binary;
01275 }
01276 #endif
01277
01278 string os_specific = to_os_specific();
01279 stream.clear();
01280 stream.open(os_specific.c_str(), open_mode);
01281 return (!stream.fail());
01282 }
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 bool Filename::
01300 open_write(ofstream &stream, bool truncate) const {
01301 assert(is_text() || is_binary());
01302
01303 ios_openmode open_mode = ios::out;
01304
01305 if (truncate) {
01306 open_mode |= ios::trunc;
01307
01308 } else {
01309
01310
01311
01312
01313
01314 if (exists()) {
01315 open_mode |= ios::in;
01316 }
01317 }
01318
01319 #ifdef HAVE_IOS_BINARY
01320
01321
01322 if (!is_text()) {
01323 open_mode |= ios::binary;
01324 }
01325 #endif
01326
01327 stream.clear();
01328 string os_specific = to_os_specific();
01329 #ifdef HAVE_OPEN_MASK
01330 stream.open(os_specific.c_str(), open_mode, 0666);
01331 #else
01332 stream.open(os_specific.c_str(), open_mode);
01333 #endif
01334
01335 return (!stream.fail());
01336 }
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 bool Filename::
01350 open_append(ofstream &stream) const {
01351 assert(is_text() || is_binary());
01352
01353 ios_openmode open_mode = ios::app;
01354
01355 #ifdef HAVE_IOS_BINARY
01356
01357
01358 if (!is_text()) {
01359 open_mode |= ios::binary;
01360 }
01361 #endif
01362
01363 stream.clear();
01364 string os_specific = to_os_specific();
01365 #ifdef HAVE_OPEN_MASK
01366 stream.open(os_specific.c_str(), open_mode, 0666);
01367 #else
01368 stream.open(os_specific.c_str(), open_mode);
01369 #endif
01370
01371 return (!stream.fail());
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 bool Filename::
01386 open_read_write(fstream &stream) const {
01387 assert(is_text() || is_binary());
01388
01389 ios_openmode open_mode = ios::in | ios::out;
01390
01391 #ifdef HAVE_IOS_BINARY
01392
01393
01394 if (!is_text()) {
01395 open_mode |= ios::binary;
01396 }
01397 #endif
01398
01399 stream.clear();
01400 string os_specific = to_os_specific();
01401 #ifdef HAVE_OPEN_MASK
01402 stream.open(os_specific.c_str(), open_mode, 0666);
01403 #else
01404 stream.open(os_specific.c_str(), open_mode);
01405 #endif
01406
01407 return (!stream.fail());
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 bool Filename::
01419 touch() const {
01420 #ifdef WIN32_VC
01421
01422
01423
01424 string os_specific = to_os_specific();
01425 HANDLE fhandle;
01426 fhandle = CreateFile(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
01427 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
01428 if (fhandle == INVALID_HANDLE_VALUE) {
01429 return false;
01430 }
01431
01432
01433 SYSTEMTIME sysnow;
01434 FILETIME ftnow;
01435 GetSystemTime(&sysnow);
01436 if (!SystemTimeToFileTime(&sysnow, &ftnow)) {
01437 CloseHandle(fhandle);
01438 return false;
01439 }
01440
01441 if (!SetFileTime(fhandle, NULL, NULL, &ftnow)) {
01442 CloseHandle(fhandle);
01443 return false;
01444 }
01445
01446 CloseHandle(fhandle);
01447 return true;
01448
01449 #elif defined(HAVE_UTIME_H)
01450
01451
01452 string os_specific = to_os_specific();
01453 #ifdef HAVE_CYGWIN
01454
01455
01456
01457
01458
01459
01460 {
01461 char result[4096] = "";
01462 cygwin_conv_to_posix_path(os_specific.c_str(), result);
01463 os_specific = result;
01464 }
01465 #endif // HAVE_CYGWIN
01466 int result = utime(os_specific.c_str(), NULL);
01467 if (result < 0) {
01468 if (errno == ENOENT) {
01469
01470 int fd = creat(os_specific.c_str(), 0666);
01471 if (fd < 0) {
01472 perror(os_specific.c_str());
01473 return false;
01474 }
01475 close(fd);
01476 return true;
01477 }
01478 perror(os_specific.c_str());
01479 return false;
01480 }
01481 return true;
01482 #else // WIN32, HAVE_UTIME_H
01483
01484
01485
01486
01487 ofstream file;
01488 return open_append(file);
01489 #endif // WIN32, HAVE_UTIME_H
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 bool Filename::
01501 unlink() const {
01502 string os_specific = to_os_specific();
01503 return (::unlink(os_specific.c_str()) == 0);
01504 }
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 bool Filename::
01516 rename_to(const Filename &other) const {
01517 string os_specific = to_os_specific();
01518 string other_os_specific = other.to_os_specific();
01519 return (rename(os_specific.c_str(),
01520 other_os_specific.c_str()) == 0);
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 bool Filename::
01537 make_dir() const {
01538 if (empty()) {
01539 return false;
01540 }
01541 Filename path = *this;
01542 path.standardize();
01543 string dirname;
01544 if (_filename[_filename.length() - 1] == '/') {
01545
01546 dirname = path.get_fullpath();
01547
01548 } else {
01549
01550 dirname = path.get_dirname();
01551 }
01552
01553
01554
01555
01556 size_t slash = dirname.find('/');
01557 while (slash != string::npos) {
01558 Filename component(dirname.substr(0, slash));
01559 string os_specific = component.to_os_specific();
01560 #ifndef WIN32_VC
01561 mkdir(os_specific.c_str(), 0777);
01562 #else
01563 mkdir(os_specific.c_str());
01564 #endif
01565 slash = dirname.find('/', slash + 1);
01566 }
01567
01568
01569 Filename component(dirname);
01570 string os_specific = component.to_os_specific();
01571 #ifndef WIN32_VC
01572 int result = mkdir(os_specific.c_str(), 0777);
01573 #else
01574 int result = mkdir(os_specific.c_str());
01575 #endif
01576
01577 return (result == 0);
01578 }
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 void Filename::
01589 locate_basename() {
01590
01591
01592 if (_filename.empty()) {
01593 _dirname_end = 0;
01594 _basename_start = 0;
01595
01596 } else {
01597
01598 string::size_type slash = _filename.rfind('/');
01599 if (slash != string::npos) {
01600 _basename_start = slash + 1;
01601 _dirname_end = _basename_start;
01602
01603
01604
01605
01606 while (_dirname_end > 0 && _filename[_dirname_end-1] == '/') {
01607 _dirname_end--;
01608 }
01609
01610
01611
01612
01613 if (_dirname_end == 0) {
01614 _dirname_end = 1;
01615 }
01616
01617 } else {
01618 _dirname_end = 0;
01619 _basename_start = 0;
01620 }
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630 }
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642 void Filename::
01643 locate_extension() {
01644
01645 if (_filename.empty()) {
01646 _basename_end = string::npos;
01647 _extension_start = string::npos;
01648
01649 } else {
01650 string::size_type dot = _filename.length() - 1;
01651
01652 while (dot+1 > _basename_start && _filename[dot] != '.') {
01653 --dot;
01654 }
01655
01656 if (dot+1 > _basename_start) {
01657 _basename_end = dot;
01658 _extension_start = dot + 1;
01659 } else {
01660 _basename_end = string::npos;
01661 _extension_start = string::npos;
01662 }
01663 }
01664
01665
01666
01667
01668
01669
01670
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 size_t Filename::
01683 get_common_prefix(const string &other) const {
01684 size_t len = 0;
01685
01686
01687 while (len < length() && len < other.length() &&
01688 _filename[len] == other[len]) {
01689 len++;
01690 }
01691
01692
01693 while (len > 0 && _filename[len-1] != '/') {
01694 len--;
01695 }
01696
01697 return len;
01698 }
01699
01700
01701
01702
01703
01704
01705
01706 int Filename::
01707 count_slashes(const string &str) {
01708 int count = 0;
01709 string::const_iterator si;
01710 si = str.begin();
01711
01712 while (si != str.end()) {
01713 if (*si == '/') {
01714 count++;
01715
01716
01717 ++si;
01718 while (*si == '/') {
01719 ++si;
01720 }
01721 if (si == str.end()) {
01722
01723 count--;
01724 }
01725
01726 } else {
01727 ++si;
01728 }
01729 }
01730
01731 return count;
01732 }
01733