00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "filename.h"
00016 #include "filename_assist.h"
00017 #include "dSearchPath.h"
00018 #include "executionEnvironment.h"
00019 #include "vector_string.h"
00020 #include "atomicAdjust.h"
00021
00022 #include <stdio.h>
00023 #include <time.h>
00024 #include <sys/stat.h>
00025 #include <algorithm>
00026
00027 #ifdef PHAVE_UTIME_H
00028 #include <utime.h>
00029
00030
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 #endif
00034
00035 #ifdef PHAVE_GLOB_H
00036 #include <glob.h>
00037 #ifndef GLOB_NOMATCH
00038 #define GLOB_NOMATCH -3
00039 #endif
00040 #endif
00041
00042 #ifdef PHAVE_DIRENT_H
00043 #include <dirent.h>
00044 #endif
00045
00046
00047
00048 #ifdef PHAVE_UNISTD_H
00049 #include <unistd.h>
00050 #endif
00051
00052 TextEncoder::Encoding Filename::_filesystem_encoding = TextEncoder::E_utf8;
00053
00054 TVOLATILE AtomicAdjust::Pointer Filename::_home_directory;
00055 TVOLATILE AtomicAdjust::Pointer Filename::_temp_directory;
00056 TVOLATILE AtomicAdjust::Pointer Filename::_user_appdata_directory;
00057 TVOLATILE AtomicAdjust::Pointer Filename::_common_appdata_directory;
00058 TypeHandle Filename::_type_handle;
00059
00060 #ifdef WIN32
00061
00062
00063 #ifdef WIN32_VC
00064 #include <direct.h>
00065 #include <windows.h>
00066 #include <shlobj.h>
00067 #include <io.h>
00068 #endif
00069
00070
00071
00072 #ifndef FILE_ATTRIBUTE_DEVICE
00073 #define FILE_ATTRIBUTE_DEVICE 0x00000040
00074 #endif
00075
00076
00077
00078
00079
00080
00081 #ifdef HAVE_CYGWIN
00082 extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32);
00083 extern "C" void cygwin_conv_to_posix_path(const char *path, char *posix);
00084 #endif
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 static const char *hosts_prefix = "/hosts/";
00110 static size_t hosts_prefix_length = 7;
00111
00112 static string
00113 front_to_back_slash(const string &str) {
00114 string result = str;
00115 string::iterator si;
00116 for (si = result.begin(); si != result.end(); ++si) {
00117 if ((*si) == '/') {
00118 (*si) = '\\';
00119 }
00120 }
00121
00122 return result;
00123 }
00124
00125 static string
00126 back_to_front_slash(const string &str) {
00127 string result = str;
00128 string::iterator si;
00129 for (si = result.begin(); si != result.end(); ++si) {
00130 if ((*si) == '\\') {
00131 (*si) = '/';
00132 }
00133 }
00134
00135 return result;
00136 }
00137
00138 static const string &
00139 get_panda_root() {
00140 static string *panda_root = NULL;
00141
00142 if (panda_root == NULL) {
00143 panda_root = new string;
00144 const char *envvar = getenv("PANDA_ROOT");
00145 if (envvar != (const char *)NULL) {
00146 (*panda_root) = front_to_back_slash(envvar);
00147 }
00148
00149
00150
00151
00152
00153 if ((*panda_root).empty() || (*panda_root)[(*panda_root).length() - 1] != '\\') {
00154 (*panda_root) += '\\';
00155 }
00156 }
00157
00158 return (*panda_root);
00159 }
00160
00161 static string
00162 convert_pathname(const string &unix_style_pathname) {
00163 if (unix_style_pathname.empty()) {
00164 return string();
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 string windows_pathname;
00180
00181 if (unix_style_pathname[0] != '/') {
00182
00183
00184
00185 windows_pathname = front_to_back_slash(unix_style_pathname);
00186
00187 } else if (unix_style_pathname.length() >= 2 &&
00188 isalpha(unix_style_pathname[1]) &&
00189 (unix_style_pathname.length() == 2 || unix_style_pathname[2] == '/')) {
00190
00191
00192
00193 string remainder = unix_style_pathname.substr(2);
00194 if (remainder.empty()) {
00195
00196 remainder = "/";
00197 }
00198 remainder = front_to_back_slash(remainder);
00199
00200
00201
00202
00203
00204 windows_pathname =
00205 string(1, (char)toupper(unix_style_pathname[1])) + ":" + remainder;
00206
00207 } else if (unix_style_pathname.length() > hosts_prefix_length &&
00208 unix_style_pathname.substr(0, hosts_prefix_length) == hosts_prefix) {
00209
00210 windows_pathname = "\\\\" + front_to_back_slash(unix_style_pathname.substr(hosts_prefix_length));
00211
00212 } else {
00213
00214
00215
00216 #ifdef HAVE_CYGWIN
00217
00218 char result[4096] = "";
00219 cygwin_conv_to_win32_path(unix_style_pathname.c_str(), result);
00220 windows_pathname = result;
00221
00222 #else // HAVE_CYGWIN
00223
00224 windows_pathname = get_panda_root();
00225 windows_pathname += front_to_back_slash(unix_style_pathname.substr(1));
00226
00227 #endif // HAVE_CYGWIN
00228 }
00229
00230 return windows_pathname;
00231 }
00232
00233 static string
00234 convert_dso_pathname(const string &unix_style_pathname) {
00235
00236 size_t dot = unix_style_pathname.rfind('.');
00237 if (dot == string::npos ||
00238 unix_style_pathname.find('/', dot) != string::npos) {
00239
00240 return convert_pathname(unix_style_pathname);
00241 }
00242 if (unix_style_pathname.substr(dot) != ".so") {
00243
00244 return convert_pathname(unix_style_pathname);
00245 }
00246
00247 string dll_basename = unix_style_pathname.substr(0, dot);
00248
00249 #ifdef _DEBUG
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 return convert_pathname(dll_basename + "_d.dll");
00262 #else
00263 return convert_pathname(dll_basename + ".dll");
00264 #endif
00265 }
00266
00267 static string
00268 convert_executable_pathname(const string &unix_style_pathname) {
00269
00270 size_t dot = unix_style_pathname.rfind('.');
00271 if (dot == string::npos ||
00272 unix_style_pathname.find('/', dot) != string::npos) {
00273
00274 return convert_pathname(unix_style_pathname + ".exe");
00275 }
00276 if (unix_style_pathname.substr(dot) != ".exe") {
00277
00278 return convert_pathname(unix_style_pathname + ".exe");
00279 }
00280
00281 return convert_pathname(unix_style_pathname);
00282 }
00283 #endif //WIN32
00284
00285
00286
00287
00288
00289
00290
00291
00292 Filename::
00293 Filename(const Filename &dirname, const Filename &basename) {
00294 if (dirname.empty()) {
00295 (*this) = basename;
00296 } else {
00297 _flags = basename._flags;
00298 string dirpath = dirname.get_fullpath();
00299 if (dirpath[dirpath.length() - 1] == '/') {
00300 (*this) = dirpath + basename.get_fullpath();
00301 } else {
00302 (*this) = dirpath + "/" + basename.get_fullpath();
00303 }
00304 }
00305 }
00306
00307 #ifdef HAVE_PYTHON
00308
00309
00310
00311
00312
00313
00314 PyObject *Filename::
00315 __reduce__(PyObject *self) const {
00316
00317
00318
00319
00320 PyObject *this_class = PyObject_Type(self);
00321 if (this_class == NULL) {
00322 return NULL;
00323 }
00324
00325 PyObject *result = Py_BuildValue("(O(s))", this_class, c_str());
00326 Py_DECREF(this_class);
00327 return result;
00328 }
00329 #endif // HAVE_PYTHON
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 Filename Filename::
00352 from_os_specific(const string &os_specific, Filename::Type type) {
00353 #ifdef WIN32
00354 string result = back_to_front_slash(os_specific);
00355 const string &panda_root = get_panda_root();
00356
00357
00358 if (!panda_root.empty() && panda_root != string("\\") &&
00359 panda_root.length() < result.length()) {
00360 bool matches = true;
00361 size_t p;
00362 for (p = 0; p < panda_root.length() && matches; ++p) {
00363 char c = tolower(panda_root[p]);
00364 if (c == '\\') {
00365 c = '/';
00366 }
00367 matches = (c == tolower(result[p]));
00368 }
00369
00370 if (matches) {
00371
00372
00373 result = result.substr(panda_root.length());
00374 assert(!result.empty());
00375 if (result[0] != '/') {
00376 result = '/' + result;
00377 }
00378 Filename filename(result);
00379 filename.set_type(type);
00380 return filename;
00381 }
00382 }
00383
00384
00385
00386 if (result.size() >= 3 && isalpha(result[0]) &&
00387 result[1] == ':' && result[2] == '/') {
00388 result[1] = tolower(result[0]);
00389 result[0] = '/';
00390
00391
00392
00393 if (result.size() == 3) {
00394 result = result.substr(0, 2);
00395 }
00396
00397 } else if (result.substr(0, 2) == "//") {
00398
00399 result = hosts_prefix + result.substr(2);
00400 }
00401
00402 Filename filename(result);
00403 filename.set_type(type);
00404 return filename;
00405 #else // WIN32
00406
00407 Filename filename(os_specific);
00408 filename.set_type(type);
00409 return filename;
00410 #endif // WIN32
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420 Filename Filename::
00421 from_os_specific_w(const wstring &os_specific, Filename::Type type) {
00422 TextEncoder encoder;
00423 encoder.set_encoding(get_filesystem_encoding());
00424 encoder.set_wtext(os_specific);
00425 return from_os_specific(encoder.get_text(), type);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 Filename Filename::
00438 expand_from(const string &os_specific, Filename::Type type) {
00439 Filename file = from_os_specific(ExecutionEnvironment::expand_string(os_specific),
00440 type);
00441 file.make_true_case();
00442 return file;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 Filename Filename::
00459 temporary(const string &dirname, const string &prefix, const string &suffix,
00460 Type type) {
00461 Filename fdirname = dirname;
00462 #ifdef WIN32
00463
00464
00465 if (fdirname.empty()) {
00466 fdirname = Filename::get_temp_directory();
00467 }
00468 #endif
00469
00470 if (fdirname.empty()) {
00471
00472
00473 char *name = tempnam(NULL, prefix.c_str());
00474 Filename result = Filename::from_os_specific(name);
00475 free(name);
00476 result.set_type(type);
00477 return result;
00478 }
00479
00480
00481
00482
00483
00484 Filename result;
00485 do {
00486
00487
00488
00489 int hash = (clock() * time(NULL)) & 0xffffff;
00490 char hex_code[10];
00491 sprintf(hex_code, "%06x", hash);
00492 result = Filename(fdirname, Filename(prefix + hex_code + suffix));
00493 result.set_type(type);
00494 } while (result.exists());
00495
00496 return result;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 const Filename &Filename::
00508 get_home_directory() {
00509 if (AtomicAdjust::get_ptr(_home_directory) == NULL) {
00510 Filename home_directory;
00511
00512
00513 char *home = getenv("HOME");
00514 if (home != (char *)NULL) {
00515 Filename dirname = from_os_specific(home);
00516 if (dirname.is_directory()) {
00517 if (dirname.make_canonical()) {
00518 home_directory = dirname;
00519 }
00520 }
00521 }
00522
00523 if (home_directory.empty()) {
00524 #ifdef WIN32
00525 wchar_t buffer[MAX_PATH];
00526
00527
00528 if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, true)) {
00529 Filename dirname = from_os_specific_w(buffer);
00530 if (dirname.is_directory()) {
00531 if (dirname.make_canonical()) {
00532 home_directory = dirname;
00533 }
00534 }
00535 }
00536
00537 #elif defined(IS_OSX)
00538 home_directory = get_osx_home_directory();
00539
00540 #else
00541
00542
00543 #endif // WIN32
00544 }
00545
00546 if (home_directory.empty()) {
00547
00548 home_directory = ExecutionEnvironment::get_cwd();
00549 }
00550
00551 Filename *newdir = new Filename(home_directory);
00552 if (AtomicAdjust::compare_and_exchange_ptr(_home_directory, NULL, newdir) != NULL) {
00553
00554 assert(_home_directory != NULL);
00555 delete newdir;
00556 }
00557 }
00558
00559 return (*(Filename *)_home_directory);
00560 }
00561
00562
00563
00564
00565
00566
00567
00568 const Filename &Filename::
00569 get_temp_directory() {
00570 if (AtomicAdjust::get_ptr(_temp_directory) == NULL) {
00571 Filename temp_directory;
00572
00573 #ifdef WIN32
00574 static const size_t buffer_size = 4096;
00575 wchar_t buffer[buffer_size];
00576 if (GetTempPathW(buffer_size, buffer) != 0) {
00577 Filename dirname = from_os_specific_w(buffer);
00578 if (dirname.is_directory()) {
00579 if (dirname.make_canonical()) {
00580 temp_directory = dirname;
00581 }
00582 }
00583 }
00584
00585 #elif defined(IS_OSX)
00586 temp_directory = get_osx_temp_directory();
00587
00588 #else
00589
00590 temp_directory = "/tmp";
00591 #endif // WIN32
00592
00593 if (temp_directory.empty()) {
00594
00595 temp_directory = ExecutionEnvironment::get_cwd();
00596 }
00597
00598 Filename *newdir = new Filename(temp_directory);
00599 if (AtomicAdjust::compare_and_exchange_ptr(_temp_directory, NULL, newdir) != NULL) {
00600
00601 assert(_temp_directory != NULL);
00602 delete newdir;
00603 }
00604 }
00605
00606 return (*(Filename *)_temp_directory);
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 const Filename &Filename::
00618 get_user_appdata_directory() {
00619 if (AtomicAdjust::get_ptr(_user_appdata_directory) == NULL) {
00620 Filename user_appdata_directory;
00621
00622 #ifdef WIN32
00623 wchar_t buffer[MAX_PATH];
00624
00625 if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_LOCAL_APPDATA, true)) {
00626 Filename dirname = from_os_specific_w(buffer);
00627 if (dirname.is_directory()) {
00628 if (dirname.make_canonical()) {
00629 user_appdata_directory = dirname;
00630 }
00631 }
00632 }
00633
00634 #elif defined(IS_OSX)
00635 user_appdata_directory = get_osx_user_appdata_directory();
00636
00637 #else
00638
00639 user_appdata_directory = get_home_directory();
00640
00641 #endif // WIN32
00642
00643 if (user_appdata_directory.empty()) {
00644
00645 user_appdata_directory = ExecutionEnvironment::get_cwd();
00646 }
00647
00648 Filename *newdir = new Filename(user_appdata_directory);
00649 if (AtomicAdjust::compare_and_exchange_ptr(_user_appdata_directory, NULL, newdir) != NULL) {
00650
00651 assert(_user_appdata_directory != NULL);
00652 delete newdir;
00653 }
00654 }
00655
00656 return (*(Filename *)_user_appdata_directory);
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666 const Filename &Filename::
00667 get_common_appdata_directory() {
00668 if (AtomicAdjust::get_ptr(_common_appdata_directory) == NULL) {
00669 Filename common_appdata_directory;
00670
00671 #ifdef WIN32
00672 wchar_t buffer[MAX_PATH];
00673
00674 if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_COMMON_APPDATA, true)) {
00675 Filename dirname = from_os_specific_w(buffer);
00676 if (dirname.is_directory()) {
00677 if (dirname.make_canonical()) {
00678 common_appdata_directory = dirname;
00679 }
00680 }
00681 }
00682
00683 #elif defined(IS_OSX)
00684 common_appdata_directory = get_osx_common_appdata_directory();
00685
00686 #else
00687
00688 common_appdata_directory = "/var";
00689 #endif // WIN32
00690
00691 if (common_appdata_directory.empty()) {
00692
00693 common_appdata_directory = ExecutionEnvironment::get_cwd();
00694 }
00695
00696 Filename *newdir = new Filename(common_appdata_directory);
00697 if (AtomicAdjust::compare_and_exchange_ptr(_common_appdata_directory, NULL, newdir) != NULL) {
00698
00699 assert(_common_appdata_directory != NULL);
00700 delete newdir;
00701 }
00702 }
00703
00704 return (*(Filename *)_common_appdata_directory);
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 void Filename::
00715 set_fullpath(const string &s) {
00716 (*this) = s;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 void Filename::
00727 set_dirname(const string &s) {
00728 if (s.empty()) {
00729
00730 _filename.replace(0, _basename_start, "");
00731
00732 int length_change = - ((int)_basename_start);
00733
00734 _dirname_end = 0;
00735 _basename_start += length_change;
00736 _basename_end += length_change;
00737 _extension_start += length_change;
00738
00739 } else {
00740
00741
00742
00743 string ss;
00744 if (s[s.length()-1] == '/') {
00745 ss = s;
00746 } else {
00747 ss = s+'/';
00748 }
00749
00750 int length_change = ss.length() - _basename_start;
00751
00752 _filename.replace(0, _basename_start, ss);
00753
00754 _dirname_end = ss.length() - 1;
00755
00756
00757
00758 if (ss.length() == 1) {
00759 _dirname_end = 1;
00760 }
00761
00762 _basename_start += length_change;
00763
00764 if (_basename_end != string::npos) {
00765 _basename_end += length_change;
00766 _extension_start += length_change;
00767 }
00768 }
00769 locate_hash();
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779 void Filename::
00780 set_basename(const string &s) {
00781 _filename.replace(_basename_start, string::npos, s);
00782 locate_extension();
00783 locate_hash();
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793 void Filename::
00794 set_fullpath_wo_extension(const string &s) {
00795 int length_change = s.length() - _basename_end;
00796
00797 _filename.replace(0, _basename_end, s);
00798
00799 if (_basename_end != string::npos) {
00800 _basename_end += length_change;
00801 _extension_start += length_change;
00802 }
00803 locate_hash();
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813 void Filename::
00814 set_basename_wo_extension(const string &s) {
00815 int length_change = s.length() - (_basename_end - _basename_start);
00816
00817 if (_basename_end == string::npos) {
00818 _filename.replace(_basename_start, string::npos, s);
00819
00820 } else {
00821 _filename.replace(_basename_start, _basename_end - _basename_start, s);
00822
00823 _basename_end += length_change;
00824 _extension_start += length_change;
00825 }
00826 locate_hash();
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void Filename::
00838 set_extension(const string &s) {
00839 if (s.empty()) {
00840
00841 if (_basename_end != string::npos) {
00842 _filename.replace(_basename_end, string::npos, "");
00843 _basename_end = string::npos;
00844 _extension_start = string::npos;
00845 }
00846
00847 } else if (_basename_end == string::npos) {
00848
00849 _basename_end = _filename.length();
00850 _extension_start = _filename.length() + 1;
00851 _filename += '.' + s;
00852
00853 } else {
00854
00855 _filename.replace(_extension_start, string::npos, s);
00856 }
00857 locate_hash();
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 Filename Filename::
00874 get_filename_index(int index) const {
00875 Filename file(*this);
00876
00877 if (_hash_end != _hash_start) {
00878 ostringstream strm;
00879 strm << _filename.substr(0, _hash_start)
00880 << setw(_hash_end - _hash_start) << setfill('0') << index
00881 << _filename.substr(_hash_end);
00882 file.set_fullpath(strm.str());
00883 }
00884 file.set_pattern(false);
00885
00886 return file;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895 void Filename::
00896 set_hash_to_end(const string &s) {
00897 _filename.replace(_hash_start, string::npos, s);
00898
00899 locate_basename();
00900 locate_extension();
00901 locate_hash();
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 void Filename::
00915 extract_components(vector_string &components) const {
00916 components.clear();
00917
00918 size_t p = 0;
00919 if (!_filename.empty() && _filename[0] == '/') {
00920
00921 p = 1;
00922 }
00923 while (p < _filename.length()) {
00924 size_t q = _filename.find('/', p);
00925 if (q == string::npos) {
00926 components.push_back(_filename.substr(p));
00927 return;
00928 }
00929 components.push_back(_filename.substr(p, q - p));
00930 p = q + 1;
00931 }
00932
00933
00934 components.push_back(string());
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 void Filename::
00946 standardize() {
00947 assert(!_filename.empty());
00948 if (_filename == ".") {
00949
00950 return;
00951 }
00952
00953 vector_string components;
00954
00955
00956 bool global = (_filename[0] == '/');
00957
00958 size_t p = 0;
00959 while (p < _filename.length() && _filename[p] == '/') {
00960 p++;
00961 }
00962 while (p < _filename.length()) {
00963 size_t slash = _filename.find('/', p);
00964 string component = _filename.substr(p, slash - p);
00965 if (component == "." && p != 0) {
00966
00967 } else if (component == ".." && !components.empty() &&
00968 !(components.back() == "..")) {
00969 if (components.back() == ".") {
00970
00971
00972 components.pop_back();
00973 components.push_back(component);
00974 } else {
00975
00976 components.pop_back();
00977 }
00978 } else {
00979 components.push_back(component);
00980 }
00981
00982 p = slash;
00983 while (p < _filename.length() && _filename[p] == '/') {
00984 p++;
00985 }
00986 }
00987
00988
00989 string result;
00990 if (global) {
00991 result = "/";
00992 }
00993 if (!components.empty()) {
00994 result += components[0];
00995 for (int i = 1; i < (int)components.size(); i++) {
00996 result += "/" + components[i];
00997 }
00998 }
00999
01000 (*this) = result;
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 void Filename::
01020 make_absolute() {
01021 if (is_local()) {
01022 make_absolute(ExecutionEnvironment::get_cwd());
01023 } else {
01024 standardize();
01025 }
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 void Filename::
01038 make_absolute(const Filename &start_directory) {
01039 if (is_local()) {
01040 Filename new_filename(start_directory, _filename);
01041 new_filename._flags = _flags;
01042 (*this) = new_filename;
01043 }
01044
01045 standardize();
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 bool Filename::
01073 make_canonical() {
01074 if (empty()) {
01075
01076
01077 return false;
01078 }
01079
01080 if (get_fullpath() == "/") {
01081
01082 return true;
01083 }
01084
01085 #ifndef WIN32
01086
01087 char newpath [PATH_MAX + 1];
01088 if (realpath(c_str(), newpath) != NULL) {
01089 Filename newpath_fn(newpath);
01090 newpath_fn._flags = _flags;
01091 (*this) = newpath_fn;
01092 }
01093 #endif
01094
01095 Filename cwd = ExecutionEnvironment::get_cwd();
01096 if (!r_make_canonical(cwd)) {
01097 return false;
01098 }
01099
01100 return make_true_case();
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120 bool Filename::
01121 make_true_case() {
01122 assert(!get_pattern());
01123
01124 if (empty()) {
01125 return true;
01126 }
01127
01128 #ifdef WIN32
01129 wstring os_specific = to_os_specific_w();
01130
01131
01132
01133
01134
01135 wchar_t short_name[MAX_PATH + 1];
01136 DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1);
01137 if (l == 0) {
01138
01139
01140 return false;
01141 }
01142
01143
01144
01145 assert(l < MAX_PATH + 1);
01146
01147 wchar_t long_name[MAX_PATH + 1];
01148 l = GetLongPathNameW(short_name, long_name, MAX_PATH + 1);
01149 if (l == 0) {
01150
01151
01152 return false;
01153 }
01154 assert(l < MAX_PATH + 1);
01155
01156 Filename true_case = Filename::from_os_specific_w(long_name);
01157
01158
01159
01160 wstring orig_filename = get_fullpath_w();
01161 wstring new_filename = true_case.get_fullpath_w();
01162 bool match = (orig_filename.length() == new_filename.length());
01163 for (size_t i = 0; i < orig_filename.length() && match; ++i) {
01164 match = (TextEncoder::unicode_tolower(orig_filename[i]) == TextEncoder::unicode_tolower(new_filename[i]));
01165 }
01166 if (!match) {
01167
01168
01169
01170 return true;
01171 }
01172
01173 true_case._flags = _flags;
01174 (*this) = true_case;
01175 return true;
01176
01177 #else // WIN32
01178 return true;
01179 #endif // WIN32
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 string Filename::
01197 to_os_specific() const {
01198 assert(!get_pattern());
01199
01200 if (empty()) {
01201 return string();
01202 }
01203 Filename standard(*this);
01204 standard.standardize();
01205
01206 #ifdef IS_OSX
01207 if (get_type() == T_dso) {
01208 std::string workname = standard.get_fullpath();
01209 size_t dot = workname.rfind('.');
01210 if (dot != string::npos) {
01211 if (workname.substr(dot) == ".so") {
01212 string dyLibBase = workname.substr(0, dot)+".dylib";
01213 return dyLibBase;
01214 }
01215 }
01216 }
01217 #endif
01218
01219 #ifdef WIN32
01220 switch (get_type()) {
01221 case T_dso:
01222 return convert_dso_pathname(standard.get_fullpath());
01223 case T_executable:
01224 return convert_executable_pathname(standard.get_fullpath());
01225 default:
01226 return convert_pathname(standard.get_fullpath());
01227 }
01228 #else // WIN32
01229 return standard.c_str();
01230 #endif // WIN32
01231 }
01232
01233
01234
01235
01236
01237
01238 wstring Filename::
01239 to_os_specific_w() const {
01240 TextEncoder encoder;
01241 encoder.set_encoding(get_filesystem_encoding());
01242 encoder.set_text(to_os_specific());
01243 return encoder.get_wtext();
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 string Filename::
01262 to_os_generic() const {
01263 assert(!get_pattern());
01264
01265 #ifdef WIN32
01266 return back_to_front_slash(to_os_specific());
01267 #else // WIN32
01268 return to_os_specific();
01269 #endif // WIN32
01270 }
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 string Filename::
01286 to_os_short_name() const {
01287 assert(!get_pattern());
01288
01289 #ifdef WIN32
01290 wstring os_specific = to_os_specific_w();
01291
01292 wchar_t short_name[MAX_PATH + 1];
01293 DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1);
01294 if (l == 0) {
01295
01296
01297 return to_os_specific();
01298 }
01299
01300
01301
01302 assert(l < MAX_PATH + 1);
01303
01304 TextEncoder encoder;
01305 encoder.set_encoding(get_filesystem_encoding());
01306 encoder.set_wtext(short_name);
01307 return encoder.get_text();
01308
01309 #else // WIN32
01310 return to_os_specific();
01311 #endif // WIN32
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 string Filename::
01323 to_os_long_name() const {
01324 assert(!get_pattern());
01325
01326 #ifdef WIN32
01327 wstring os_specific = to_os_specific_w();
01328
01329 wchar_t long_name[MAX_PATH + 1];
01330 DWORD l = GetLongPathNameW(os_specific.c_str(), long_name, MAX_PATH + 1);
01331 if (l == 0) {
01332
01333
01334 return to_os_specific();
01335 }
01336 assert(l < MAX_PATH + 1);
01337
01338 TextEncoder encoder;
01339 encoder.set_encoding(get_filesystem_encoding());
01340 encoder.set_wtext(long_name);
01341 return encoder.get_text();
01342
01343 #else // WIN32
01344 return to_os_specific();
01345 #endif // WIN32
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356 bool Filename::
01357 exists() const {
01358 #ifdef WIN32_VC
01359 wstring os_specific = get_filename_index(0).to_os_specific_w();
01360
01361 bool exists = false;
01362
01363 DWORD results = GetFileAttributesW(os_specific.c_str());
01364 if (results != -1) {
01365 exists = true;
01366 }
01367
01368 #else // WIN32_VC
01369 string os_specific = get_filename_index(0).to_os_specific();
01370
01371 struct stat this_buf;
01372 bool exists = false;
01373
01374 if (stat(os_specific.c_str(), &this_buf) == 0) {
01375 exists = true;
01376 }
01377 #endif
01378
01379 return exists;
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389 bool Filename::
01390 is_regular_file() const {
01391 #ifdef WIN32_VC
01392 wstring os_specific = get_filename_index(0).to_os_specific_w();
01393
01394 bool isreg = false;
01395
01396 DWORD results = GetFileAttributesW(os_specific.c_str());
01397 if (results != -1) {
01398 isreg = ((results & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0);
01399 }
01400
01401 #else // WIN32_VC
01402 string os_specific = get_filename_index(0).to_os_specific();
01403
01404 struct stat this_buf;
01405 bool isreg = false;
01406
01407 if (stat(os_specific.c_str(), &this_buf) == 0) {
01408 isreg = S_ISREG(this_buf.st_mode);
01409 }
01410 #endif
01411
01412 return isreg;
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422 bool Filename::
01423 is_writable() const {
01424 bool writable = false;
01425
01426 #ifdef WIN32_VC
01427 wstring os_specific = get_filename_index(0).to_os_specific_w();
01428
01429 DWORD results = GetFileAttributesW(os_specific.c_str());
01430 if (results != -1) {
01431 if ((results & FILE_ATTRIBUTE_DIRECTORY) != 0) {
01432
01433 writable = true;
01434 } else if ((results & FILE_ATTRIBUTE_READONLY) == 0) {
01435
01436 writable = true;
01437 }
01438 }
01439 #else // WIN32_VC
01440 string os_specific = get_filename_index(0).to_os_specific();
01441
01442 if (access(os_specific.c_str(), W_OK) == 0) {
01443 writable = true;
01444 }
01445 #endif
01446
01447 return writable;
01448 }
01449
01450
01451
01452
01453
01454
01455
01456 bool Filename::
01457 is_directory() const {
01458 #ifdef WIN32_VC
01459 wstring os_specific = get_filename_index(0).to_os_specific_w();
01460
01461 bool isdir = false;
01462
01463 DWORD results = GetFileAttributesW(os_specific.c_str());
01464 if (results != -1) {
01465 isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
01466 }
01467 #else // WIN32_VC
01468 string os_specific = get_filename_index(0).to_os_specific();
01469
01470 struct stat this_buf;
01471 bool isdir = false;
01472
01473 if (stat(os_specific.c_str(), &this_buf) == 0) {
01474 isdir = S_ISDIR(this_buf.st_mode);
01475 }
01476 #endif
01477
01478 return isdir;
01479 }
01480
01481
01482
01483
01484
01485
01486
01487 bool Filename::
01488 is_executable() const {
01489 #ifdef WIN32_VC
01490
01491
01492 string extension = get_extension();
01493 if (extension == "exe" || extension == "com") {
01494 return exists();
01495 }
01496
01497 #else
01498 string os_specific = get_filename_index(0).to_os_specific();
01499 if (access(os_specific.c_str(), X_OK) == 0) {
01500 return true;
01501 }
01502 #endif
01503
01504 return false;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 int Filename::
01522 compare_timestamps(const Filename &other,
01523 bool this_missing_is_old,
01524 bool other_missing_is_old) const {
01525 #ifdef WIN32_VC
01526 wstring os_specific = get_filename_index(0).to_os_specific_w();
01527 wstring other_os_specific = other.get_filename_index(0).to_os_specific_w();
01528
01529 struct _stat this_buf;
01530 bool this_exists = false;
01531
01532 if (_wstat(os_specific.c_str(), &this_buf) == 0) {
01533 this_exists = true;
01534 }
01535
01536 struct _stat other_buf;
01537 bool other_exists = false;
01538
01539 if (_wstat(other_os_specific.c_str(), &other_buf) == 0) {
01540 other_exists = true;
01541 }
01542 #else // WIN32_VC
01543 string os_specific = get_filename_index(0).to_os_specific();
01544 string other_os_specific = other.get_filename_index(0).to_os_specific();
01545
01546 struct stat this_buf;
01547 bool this_exists = false;
01548
01549 if (stat(os_specific.c_str(), &this_buf) == 0) {
01550 this_exists = true;
01551 }
01552
01553 struct stat other_buf;
01554 bool other_exists = false;
01555
01556 if (stat(other_os_specific.c_str(), &other_buf) == 0) {
01557 other_exists = true;
01558 }
01559 #endif
01560
01561 if (this_exists && other_exists) {
01562
01563 return (int)this_buf.st_mtime - (int)other_buf.st_mtime;
01564
01565 } else if (!this_exists && !other_exists) {
01566
01567 if (this_missing_is_old == other_missing_is_old) {
01568
01569 return 0;
01570 }
01571 if (this_missing_is_old) {
01572
01573 return -1;
01574 } else {
01575
01576 return 1;
01577 }
01578
01579 } else if (!this_exists) {
01580
01581 return this_missing_is_old ? -1 : 1;
01582
01583 }
01584
01585 assert(!other_exists);
01586
01587
01588 return other_missing_is_old ? 1 : -1;
01589 }
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605 time_t Filename::
01606 get_timestamp() const {
01607 #ifdef WIN32_VC
01608 wstring os_specific = get_filename_index(0).to_os_specific_w();
01609
01610 struct _stat this_buf;
01611
01612 if (_wstat(os_specific.c_str(), &this_buf) == 0) {
01613 return this_buf.st_mtime;
01614 }
01615 #else // WIN32_VC
01616 string os_specific = get_filename_index(0).to_os_specific();
01617
01618 struct stat this_buf;
01619
01620 if (stat(os_specific.c_str(), &this_buf) == 0) {
01621 return this_buf.st_mtime;
01622 }
01623 #endif
01624
01625 return 0;
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636 time_t Filename::
01637 get_access_timestamp() const {
01638 #ifdef WIN32_VC
01639 wstring os_specific = get_filename_index(0).to_os_specific_w();
01640
01641 struct _stat this_buf;
01642
01643 if (_wstat(os_specific.c_str(), &this_buf) == 0) {
01644 return this_buf.st_atime;
01645 }
01646 #else // WIN32_VC
01647 string os_specific = get_filename_index(0).to_os_specific();
01648
01649 struct stat this_buf;
01650
01651 if (stat(os_specific.c_str(), &this_buf) == 0) {
01652 return this_buf.st_atime;
01653 }
01654 #endif
01655
01656 return 0;
01657 }
01658
01659
01660
01661
01662
01663
01664
01665 off_t Filename::
01666 get_file_size() const {
01667 #ifdef WIN32_VC
01668 wstring os_specific = get_filename_index(0).to_os_specific_w();
01669
01670 struct _stat this_buf;
01671
01672 if (_wstat(os_specific.c_str(), &this_buf) == 0) {
01673 return this_buf.st_size;
01674 }
01675 #else // WIN32_VC
01676 string os_specific = get_filename_index(0).to_os_specific();
01677
01678 struct stat this_buf;
01679
01680 if (stat(os_specific.c_str(), &this_buf) == 0) {
01681 return this_buf.st_size;
01682 }
01683 #endif
01684
01685 return 0;
01686 }
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696 bool Filename::
01697 resolve_filename(const DSearchPath &searchpath,
01698 const string &default_extension) {
01699 Filename found;
01700
01701 if (is_local()) {
01702 found = searchpath.find_file(*this);
01703
01704 if (found.empty()) {
01705
01706
01707 if (get_extension().empty() && !default_extension.empty()) {
01708 Filename try_ext = *this;
01709 try_ext.set_extension(default_extension);
01710 found = searchpath.find_file(try_ext);
01711 }
01712 }
01713 } else {
01714 if (exists()) {
01715
01716 return true;
01717 } else {
01718
01719
01720 if (get_extension().empty() && !default_extension.empty()) {
01721 Filename try_ext = *this;
01722 try_ext.set_extension(default_extension);
01723 if (try_ext.exists()) {
01724 found = try_ext;
01725 }
01726 }
01727 }
01728 }
01729
01730 if (!found.empty()) {
01731 (*this) = found;
01732 return true;
01733 }
01734
01735 return false;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 bool Filename::
01764 make_relative_to(Filename directory, bool allow_backups) {
01765 if (_filename.empty() || directory.empty() ||
01766 _filename[0] != '/' || directory[0] != '/') {
01767 return false;
01768 }
01769
01770 standardize();
01771 directory.standardize();
01772
01773 if (directory == "/") {
01774
01775 return false;
01776 }
01777
01778 string rel_to_file = directory.get_fullpath() + "/.";
01779
01780 size_t common = get_common_prefix(rel_to_file);
01781 if (common < 2) {
01782
01783 return false;
01784 }
01785
01786 string result;
01787 int slashes = count_slashes(rel_to_file.substr(common));
01788 if (slashes > 0 && !allow_backups) {
01789
01790 return false;
01791 }
01792
01793 for (int i = 0; i < slashes; i++) {
01794 result += "../";
01795 }
01796 result += _filename.substr(common);
01797 (*this) = result;
01798
01799 return true;
01800 }
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817 int Filename::
01818 find_on_searchpath(const DSearchPath &searchpath) {
01819 if (_filename.empty() || _filename[0] != '/') {
01820 return -1;
01821 }
01822
01823 int num_directories = searchpath.get_num_directories();
01824 for (int i = 0; i < num_directories; i++) {
01825 Filename directory = searchpath.get_directory(i);
01826 directory.make_absolute();
01827 if (make_relative_to(directory, false)) {
01828 return i;
01829 }
01830 }
01831
01832 return -1;
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 bool Filename::
01852 scan_directory(vector_string &contents) const {
01853 assert(!get_pattern());
01854
01855 #if defined(WIN32_VC)
01856
01857
01858 size_t orig_size = contents.size();
01859
01860 wstring match;
01861 if (empty()) {
01862 match = L"*.*";
01863 } else {
01864 match = to_os_specific_w() + L"\\*.*";
01865 }
01866 WIN32_FIND_DATAW find_data;
01867
01868 HANDLE handle = FindFirstFileW(match.c_str(), &find_data);
01869 if (handle == INVALID_HANDLE_VALUE) {
01870 if (GetLastError() == ERROR_NO_MORE_FILES) {
01871
01872 return true;
01873 }
01874 return false;
01875 }
01876
01877 TextEncoder encoder;
01878 encoder.set_encoding(get_filesystem_encoding());
01879 do {
01880 thread_consider_yield();
01881 wstring filename = find_data.cFileName;
01882 if (filename != L"." && filename != L"..") {
01883 encoder.set_wtext(filename);
01884 contents.push_back(encoder.get_text());
01885 }
01886 } while (FindNextFileW(handle, &find_data));
01887
01888 bool scan_ok = (GetLastError() == ERROR_NO_MORE_FILES);
01889 FindClose(handle);
01890
01891 sort(contents.begin() + orig_size, contents.end());
01892 return scan_ok;
01893
01894 #elif defined(PHAVE_DIRENT_H)
01895
01896
01897 size_t orig_size = contents.size();
01898
01899 string dirname;
01900 if (empty()) {
01901 dirname = ".";
01902 } else {
01903 dirname = _filename;
01904 }
01905 DIR *root = opendir(dirname.c_str());
01906 if (root == (DIR *)NULL) {
01907 if (errno != ENOTDIR) {
01908 perror(dirname.c_str());
01909 }
01910 return false;
01911 }
01912
01913 struct dirent *d;
01914 d = readdir(root);
01915 while (d != (struct dirent *)NULL) {
01916 thread_consider_yield();
01917 if (d->d_name[0] != '.') {
01918 contents.push_back(d->d_name);
01919 }
01920 d = readdir(root);
01921 }
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 closedir(root);
01936
01937 sort(contents.begin() + orig_size, contents.end());
01938 return true;
01939
01940 #elif defined(PHAVE_GLOB_H)
01941
01942
01943
01944
01945 string dirname;
01946 if (empty()) {
01947 dirname = "*";
01948 } else if (_filename[_filename.length() - 1] == '/') {
01949 dirname = _filename + "*";
01950 } else {
01951 dirname = _filename + "/*";
01952 }
01953
01954 glob_t globbuf;
01955
01956 int r = glob(dirname.c_str(), GLOB_ERR, NULL, &globbuf);
01957
01958 if (r != 0) {
01959
01960
01961
01962 #ifdef GLOB_NOMATCH
01963 if (r != GLOB_NOMATCH) {
01964 perror(dirname.c_str());
01965 return false;
01966 }
01967 #endif
01968
01969
01970
01971 return true;
01972 }
01973
01974 size_t offset = dirname.size() - 1;
01975
01976 for (int i = 0; globbuf.gl_pathv[i] != NULL; i++) {
01977 contents.push_back(globbuf.gl_pathv[i] + offset);
01978 }
01979 globfree(&globbuf);
01980
01981 return true;
01982
01983 #else
01984
01985 return false;
01986 #endif
01987 }
01988
01989 #ifdef HAVE_PYTHON
01990
01991
01992
01993
01994
01995
01996 PyObject *Filename::
01997 scan_directory() const {
01998 vector_string contents;
01999 if (!scan_directory(contents)) {
02000 PyObject *result = Py_None;
02001 Py_INCREF(result);
02002 return result;
02003 }
02004
02005 PyObject *result = PyList_New(contents.size());
02006 for (size_t i = 0; i < contents.size(); ++i) {
02007 const string &filename = contents[i];
02008 PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
02009 PyList_SET_ITEM(result, i, str);
02010 }
02011
02012 return result;
02013 }
02014 #endif // HAVE_PYTHON
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 bool Filename::
02028 open_read(ifstream &stream) const {
02029 assert(!get_pattern());
02030 assert(is_binary_or_text());
02031
02032 ios_openmode open_mode = ios::in;
02033
02034 #ifdef HAVE_IOS_BINARY
02035
02036
02037 if (!is_text()) {
02038 open_mode |= ios::binary;
02039 }
02040 #endif
02041
02042 stream.clear();
02043 #ifdef WIN32_VC
02044 wstring os_specific = to_os_specific_w();
02045 stream.open(os_specific.c_str(), open_mode);
02046 #else
02047 string os_specific = to_os_specific();
02048 stream.open(os_specific.c_str(), open_mode);
02049 #endif // WIN32_VC
02050
02051 return (!stream.fail());
02052 }
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069 bool Filename::
02070 open_write(ofstream &stream, bool truncate) const {
02071 assert(!get_pattern());
02072 assert(is_binary_or_text());
02073
02074 ios_openmode open_mode = ios::out;
02075
02076 if (truncate) {
02077 open_mode |= ios::trunc;
02078
02079 } else {
02080
02081
02082
02083
02084
02085 if (exists()) {
02086 open_mode |= ios::in;
02087 }
02088 }
02089
02090 #ifdef HAVE_IOS_BINARY
02091
02092
02093 if (!is_text()) {
02094 open_mode |= ios::binary;
02095 }
02096 #endif
02097
02098 stream.clear();
02099 #ifdef WIN32_VC
02100 wstring os_specific = to_os_specific_w();
02101 stream.open(os_specific.c_str(), open_mode);
02102 #else
02103 string os_specific = to_os_specific();
02104 #ifdef HAVE_OPEN_MASK
02105 stream.open(os_specific.c_str(), open_mode, 0666);
02106 #else
02107 stream.open(os_specific.c_str(), open_mode);
02108 #endif
02109 #endif // WIN32_VC
02110
02111 return (!stream.fail());
02112 }
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125 bool Filename::
02126 open_append(ofstream &stream) const {
02127 assert(!get_pattern());
02128 assert(is_binary_or_text());
02129
02130 ios_openmode open_mode = ios::app;
02131
02132 #ifdef HAVE_IOS_BINARY
02133
02134
02135 if (!is_text()) {
02136 open_mode |= ios::binary;
02137 }
02138 #endif
02139
02140 stream.clear();
02141 #ifdef WIN32_VC
02142 wstring os_specific = to_os_specific_w();
02143 stream.open(os_specific.c_str(), open_mode);
02144 #else
02145 string os_specific = to_os_specific();
02146 #ifdef HAVE_OPEN_MASK
02147 stream.open(os_specific.c_str(), open_mode, 0666);
02148 #else
02149 stream.open(os_specific.c_str(), open_mode);
02150 #endif
02151 #endif // WIN32_VC
02152
02153 return (!stream.fail());
02154 }
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167 bool Filename::
02168 open_read_write(fstream &stream, bool truncate) const {
02169 assert(!get_pattern());
02170 assert(is_binary_or_text());
02171
02172 ios_openmode open_mode = ios::out | ios::in;
02173
02174 if (truncate) {
02175 open_mode |= ios::trunc;
02176 }
02177
02178
02179
02180 if (!exists()) {
02181 touch();
02182 }
02183
02184 #ifdef HAVE_IOS_BINARY
02185
02186
02187 if (!is_text()) {
02188 open_mode |= ios::binary;
02189 }
02190 #endif
02191
02192 stream.clear();
02193 #ifdef WIN32_VC
02194 wstring os_specific = to_os_specific_w();
02195 stream.open(os_specific.c_str(), open_mode);
02196 #else
02197 string os_specific = to_os_specific();
02198 #ifdef HAVE_OPEN_MASK
02199 stream.open(os_specific.c_str(), open_mode, 0666);
02200 #else
02201 stream.open(os_specific.c_str(), open_mode);
02202 #endif
02203 #endif // WIN32_VC
02204
02205 return (!stream.fail());
02206 }
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220 bool Filename::
02221 open_read_append(fstream &stream) const {
02222 assert(!get_pattern());
02223 assert(is_binary_or_text());
02224
02225 ios_openmode open_mode = ios::app | ios::in;
02226
02227 #ifdef HAVE_IOS_BINARY
02228
02229
02230 if (!is_text()) {
02231 open_mode |= ios::binary;
02232 }
02233 #endif
02234
02235 stream.clear();
02236 #ifdef WIN32_VC
02237 wstring os_specific = to_os_specific_w();
02238 stream.open(os_specific.c_str(), open_mode);
02239 #else
02240 string os_specific = to_os_specific();
02241 #ifdef HAVE_OPEN_MASK
02242 stream.open(os_specific.c_str(), open_mode, 0666);
02243 #else
02244 stream.open(os_specific.c_str(), open_mode);
02245 #endif
02246 #endif // WIN32_VC
02247
02248 return (!stream.fail());
02249 }
02250
02251 #ifdef USE_PANDAFILESTREAM
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263 bool Filename::
02264 open_read(pifstream &stream) const {
02265 assert(!get_pattern());
02266 assert(is_binary_or_text());
02267
02268 ios_openmode open_mode = ios::in;
02269
02270 #ifdef HAVE_IOS_BINARY
02271
02272
02273 if (!is_text()) {
02274 open_mode |= ios::binary;
02275 }
02276 #endif
02277
02278 string os_specific = to_os_specific();
02279 stream.clear();
02280 stream.open(os_specific.c_str(), open_mode);
02281 return (!stream.fail());
02282 }
02283 #endif // USE_PANDAFILESTREAM
02284
02285 #ifdef USE_PANDAFILESTREAM
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301 bool Filename::
02302 open_write(pofstream &stream, bool truncate) const {
02303 assert(!get_pattern());
02304 assert(is_binary_or_text());
02305
02306 ios_openmode open_mode = ios::out;
02307
02308 if (truncate) {
02309 open_mode |= ios::trunc;
02310
02311 } else {
02312
02313
02314
02315
02316
02317 if (exists()) {
02318 open_mode |= ios::in;
02319 }
02320 }
02321
02322 #ifdef HAVE_IOS_BINARY
02323
02324
02325 if (!is_text()) {
02326 open_mode |= ios::binary;
02327 }
02328 #endif
02329
02330 stream.clear();
02331 string os_specific = to_os_specific();
02332 #ifdef HAVE_OPEN_MASK
02333 stream.open(os_specific.c_str(), open_mode, 0666);
02334 #else
02335 stream.open(os_specific.c_str(), open_mode);
02336 #endif
02337
02338 return (!stream.fail());
02339 }
02340 #endif // USE_PANDAFILESTREAM
02341
02342 #ifdef USE_PANDAFILESTREAM
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354 bool Filename::
02355 open_append(pofstream &stream) const {
02356 assert(!get_pattern());
02357 assert(is_binary_or_text());
02358
02359 ios_openmode open_mode = ios::app;
02360
02361 #ifdef HAVE_IOS_BINARY
02362
02363
02364 if (!is_text()) {
02365 open_mode |= ios::binary;
02366 }
02367 #endif
02368
02369 stream.clear();
02370 string os_specific = to_os_specific();
02371 #ifdef HAVE_OPEN_MASK
02372 stream.open(os_specific.c_str(), open_mode, 0666);
02373 #else
02374 stream.open(os_specific.c_str(), open_mode);
02375 #endif
02376
02377 return (!stream.fail());
02378 }
02379 #endif // USE_PANDAFILESTREAM
02380
02381 #ifdef USE_PANDAFILESTREAM
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 bool Filename::
02394 open_read_write(pfstream &stream, bool truncate) const {
02395 assert(!get_pattern());
02396 assert(is_binary_or_text());
02397
02398 ios_openmode open_mode = ios::out | ios::in;
02399
02400 if (truncate) {
02401 open_mode |= ios::trunc;
02402 }
02403
02404
02405
02406 if (!exists()) {
02407 touch();
02408 }
02409
02410 #ifdef HAVE_IOS_BINARY
02411
02412
02413 if (!is_text()) {
02414 open_mode |= ios::binary;
02415 }
02416 #endif
02417
02418 stream.clear();
02419 string os_specific = to_os_specific();
02420 #ifdef HAVE_OPEN_MASK
02421 stream.open(os_specific.c_str(), open_mode, 0666);
02422 #else
02423 stream.open(os_specific.c_str(), open_mode);
02424 #endif
02425
02426 return (!stream.fail());
02427 }
02428 #endif // USE_PANDAFILESTREAM
02429
02430 #ifdef USE_PANDAFILESTREAM
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443 bool Filename::
02444 open_read_append(pfstream &stream) const {
02445 assert(!get_pattern());
02446 assert(is_binary_or_text());
02447
02448 ios_openmode open_mode = ios::app | ios::in;
02449
02450 #ifdef HAVE_IOS_BINARY
02451
02452
02453 if (!is_text()) {
02454 open_mode |= ios::binary;
02455 }
02456 #endif
02457
02458 stream.clear();
02459 string os_specific = to_os_specific();
02460 #ifdef HAVE_OPEN_MASK
02461 stream.open(os_specific.c_str(), open_mode, 0666);
02462 #else
02463 stream.open(os_specific.c_str(), open_mode);
02464 #endif
02465
02466 return (!stream.fail());
02467 }
02468 #endif // USE_PANDAFILESTREAM
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478 bool Filename::
02479 touch() const {
02480 assert(!get_pattern());
02481 #ifdef WIN32_VC
02482
02483
02484
02485 wstring os_specific = to_os_specific_w();
02486 HANDLE fhandle;
02487 fhandle = CreateFileW(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
02488 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
02489 if (fhandle == INVALID_HANDLE_VALUE) {
02490 return false;
02491 }
02492
02493
02494 SYSTEMTIME sysnow;
02495 FILETIME ftnow;
02496 GetSystemTime(&sysnow);
02497 if (!SystemTimeToFileTime(&sysnow, &ftnow)) {
02498 CloseHandle(fhandle);
02499 return false;
02500 }
02501
02502 if (!SetFileTime(fhandle, NULL, NULL, &ftnow)) {
02503 CloseHandle(fhandle);
02504 return false;
02505 }
02506
02507 CloseHandle(fhandle);
02508 return true;
02509
02510 #elif defined(PHAVE_UTIME_H)
02511
02512
02513 string os_specific = to_os_specific();
02514 #ifdef HAVE_CYGWIN
02515
02516
02517
02518
02519
02520
02521 {
02522 char result[4096] = "";
02523 cygwin_conv_to_posix_path(os_specific.c_str(), result);
02524 os_specific = result;
02525 }
02526 #endif // HAVE_CYGWIN
02527 int result = utime(os_specific.c_str(), NULL);
02528 if (result < 0) {
02529 if (errno == ENOENT) {
02530
02531 int fd = creat(os_specific.c_str(), 0666);
02532 if (fd < 0) {
02533 perror(os_specific.c_str());
02534 return false;
02535 }
02536 close(fd);
02537 return true;
02538 }
02539 perror(os_specific.c_str());
02540 return false;
02541 }
02542 return true;
02543 #else // WIN32, PHAVE_UTIME_H
02544
02545
02546
02547
02548 pfstream file;
02549 return open_append(file);
02550 #endif // WIN32, PHAVE_UTIME_H
02551 }
02552
02553
02554
02555
02556
02557
02558
02559 bool Filename::
02560 chdir() const {
02561 #ifdef WIN32_VC
02562 wstring os_specific = to_os_specific_w();
02563 return (_wchdir(os_specific.c_str()) >= 0);
02564 #else
02565 string os_specific = to_os_specific();
02566 return (::chdir(os_specific.c_str()) >= 0);
02567 #endif // WIN32_VC
02568 }
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578 bool Filename::
02579 unlink() const {
02580 assert(!get_pattern());
02581 #ifdef WIN32_VC
02582
02583 wstring os_specific = to_os_specific_w();
02584 _wchmod(os_specific.c_str(), 0644);
02585 return (_wunlink(os_specific.c_str()) == 0);
02586 #else
02587 string os_specific = to_os_specific();
02588 return (::unlink(os_specific.c_str()) == 0);
02589 #endif // WIN32_VC
02590 }
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601 bool Filename::
02602 rename_to(const Filename &other) const {
02603 assert(!get_pattern());
02604
02605 if (*this == other) {
02606
02607 return true;
02608 }
02609
02610 #ifdef WIN32_VC
02611 wstring os_specific = to_os_specific_w();
02612 wstring other_os_specific = other.to_os_specific_w();
02613
02614 if (_wrename(os_specific.c_str(),
02615 other_os_specific.c_str()) == 0) {
02616
02617 return true;
02618 }
02619
02620
02621
02622
02623 string dirname = other.get_dirname();
02624 if (dirname.empty()) {
02625 dirname = ".";
02626 }
02627 Filename temp = Filename::temporary(dirname, "");
02628 temp.set_binary();
02629 if (!Filename::binary_filename(*this).copy_to(temp)) {
02630 return false;
02631 }
02632
02633 wstring temp_os_specific = temp.to_os_specific_w();
02634 if (_wrename(temp_os_specific.c_str(),
02635 other_os_specific.c_str()) == 0) {
02636
02637 unlink();
02638 return true;
02639 }
02640
02641
02642 other.unlink();
02643 if (_wrename(temp_os_specific.c_str(),
02644 other_os_specific.c_str()) == 0) {
02645
02646 unlink();
02647 return true;
02648 }
02649 #else // WIN32_VC
02650 string os_specific = to_os_specific();
02651 string other_os_specific = other.to_os_specific();
02652
02653 if (rename(os_specific.c_str(),
02654 other_os_specific.c_str()) == 0) {
02655
02656 return true;
02657 }
02658
02659
02660
02661
02662 string dirname = other.get_dirname();
02663 if (dirname.empty()) {
02664 dirname = ".";
02665 }
02666 Filename temp = Filename::temporary(dirname, "");
02667 temp.set_binary();
02668 if (!Filename::binary_filename(*this).copy_to(temp)) {
02669 return false;
02670 }
02671
02672 string temp_os_specific = temp.to_os_specific();
02673 if (rename(temp_os_specific.c_str(),
02674 other_os_specific.c_str()) == 0) {
02675
02676 unlink();
02677 return true;
02678 }
02679
02680
02681 other.unlink();
02682 if (rename(temp_os_specific.c_str(),
02683 other_os_specific.c_str()) == 0) {
02684
02685 unlink();
02686 return true;
02687 }
02688 #endif // WIN32_VC
02689
02690
02691 temp.unlink();
02692 return false;
02693 }
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704 bool Filename::
02705 copy_to(const Filename &other) const {
02706 Filename this_filename = Filename::binary_filename(*this);
02707 pifstream in;
02708 if (!this_filename.open_read(in)) {
02709 return false;
02710 }
02711
02712 Filename other_filename = Filename::binary_filename(other);
02713 pofstream out;
02714 if (!other_filename.open_write(out)) {
02715 return false;
02716 }
02717
02718 static const size_t buffer_size = 4096;
02719 char buffer[buffer_size];
02720
02721 in.read(buffer, buffer_size);
02722 size_t count = in.gcount();
02723 while (count != 0) {
02724 out.write(buffer, count);
02725 if (out.fail()) {
02726 other.unlink();
02727 return false;
02728 }
02729 in.read(buffer, buffer_size);
02730 count = in.gcount();
02731 }
02732
02733 if (!in.eof()) {
02734 other.unlink();
02735 return false;
02736 }
02737
02738 return true;
02739 }
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754 bool Filename::
02755 make_dir() const {
02756 assert(!get_pattern());
02757 if (empty()) {
02758 return false;
02759 }
02760 Filename path;
02761 if (_filename[_filename.length() - 1] == '/') {
02762
02763 path = (*this);
02764
02765 } else {
02766
02767 path = get_dirname();
02768 }
02769
02770 if (path.empty()) {
02771 return false;
02772 }
02773 string dirname = path.get_fullpath();
02774
02775
02776
02777
02778 size_t slash = dirname.find('/');
02779 while (slash != string::npos) {
02780 Filename component(dirname.substr(0, slash));
02781 #ifdef WIN32_VC
02782 wstring os_specific = component.to_os_specific_w();
02783 _wmkdir(os_specific.c_str());
02784 #else
02785 string os_specific = component.to_os_specific();
02786 ::mkdir(os_specific.c_str(), 0777);
02787 #endif // WIN32_VC
02788 slash = dirname.find('/', slash + 1);
02789 }
02790
02791
02792 Filename component(dirname);
02793 #ifdef WIN32_VC
02794 wstring os_specific = component.to_os_specific_w();
02795 int result = _wmkdir(os_specific.c_str());
02796 #else
02797 string os_specific = component.to_os_specific();
02798 int result = ::mkdir(os_specific.c_str(), 0777);
02799 #endif // WIN32_VC
02800
02801 return (result == 0);
02802 }
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813 bool Filename::
02814 mkdir() const {
02815 #ifdef WIN32_VC
02816 wstring os_specific = to_os_specific_w();
02817 int result = _wmkdir(os_specific.c_str());
02818 #else
02819 string os_specific = to_os_specific();
02820 int result = ::mkdir(os_specific.c_str(), 0777);
02821 #endif // WIN32_VC
02822
02823 return (result == 0);
02824 }
02825
02826
02827
02828
02829
02830
02831
02832 bool Filename::
02833 rmdir() const {
02834 #ifdef WIN32_VC
02835 wstring os_specific = to_os_specific_w();
02836
02837 int result = _wrmdir(os_specific.c_str());
02838 if (result != 0) {
02839
02840
02841 _wchmod(os_specific.c_str(), 0777);
02842 result = _wrmdir(os_specific.c_str());
02843 }
02844
02845 #else // WIN32_VC
02846 string os_specific = to_os_specific();
02847 int result = ::rmdir(os_specific.c_str());
02848 #endif // WIN32_VC
02849
02850 return (result == 0);
02851 }
02852
02853
02854
02855
02856
02857
02858
02859 int Filename::
02860 get_hash() const {
02861 static const int primes[] = {
02862 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
02863 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
02864 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
02865 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
02866 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
02867 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
02868 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
02869 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
02870 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
02871 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
02872 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
02873 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
02874 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
02875 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
02876 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
02877 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
02878 947, 953, 967, 971, 977, 983, 991, 997
02879 };
02880 static const size_t num_primes = sizeof(primes) / sizeof(int);
02881
02882 int hash = 0;
02883 for (size_t i = 0; i < _filename.size(); ++i) {
02884 hash += (int)_filename[i] * primes[i % num_primes];
02885 }
02886
02887 return hash;
02888 }
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930 bool Filename::
02931 atomic_compare_and_exchange_contents(string &orig_contents,
02932 const string &old_contents,
02933 const string &new_contents) const {
02934 #ifdef WIN32_VC
02935 wstring os_specific = to_os_specific_w();
02936 HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
02937 0, NULL, OPEN_ALWAYS,
02938 FILE_ATTRIBUTE_NORMAL, NULL);
02939 while (hfile == INVALID_HANDLE_VALUE) {
02940 DWORD error = GetLastError();
02941 if (error == ERROR_SHARING_VIOLATION) {
02942
02943 Sleep(0);
02944 hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
02945 0, NULL, OPEN_ALWAYS,
02946 FILE_ATTRIBUTE_NORMAL, NULL);
02947 } else {
02948 cerr << "Couldn't open file: " << os_specific
02949 << ", error " << error << "\n";
02950 return false;
02951 }
02952 }
02953
02954 if (hfile == INVALID_HANDLE_VALUE) {
02955 cerr << "Couldn't open file: " << os_specific
02956 << ", error " << GetLastError() << "\n";
02957 return false;
02958 }
02959
02960 static const size_t buf_size = 512;
02961 char buf[buf_size];
02962
02963 orig_contents = string();
02964
02965 DWORD bytes_read;
02966 if (!ReadFile(hfile, buf, buf_size, &bytes_read, NULL)) {
02967 cerr << "Error reading file: " << os_specific
02968 << ", error " << GetLastError() << "\n";
02969 CloseHandle(hfile);
02970 return false;
02971 }
02972 while (bytes_read > 0) {
02973 orig_contents += string(buf, bytes_read);
02974
02975 if (!ReadFile(hfile, buf, buf_size, &bytes_read, NULL)) {
02976 cerr << "Error reading file: " << os_specific
02977 << ", error " << GetLastError() << "\n";
02978 CloseHandle(hfile);
02979 return false;
02980 }
02981 }
02982
02983 bool match = false;
02984 if (orig_contents == old_contents) {
02985 match = true;
02986 SetFilePointer(hfile, 0, 0, FILE_BEGIN);
02987 DWORD bytes_written;
02988 if (!WriteFile(hfile, new_contents.data(), new_contents.size(),
02989 &bytes_written, NULL)) {
02990 cerr << "Error writing file: " << os_specific
02991 << ", error " << GetLastError() << "\n";
02992 CloseHandle(hfile);
02993 return false;
02994 }
02995 }
02996
02997 CloseHandle(hfile);
02998 return match;
02999
03000 #else // WIN32_VC
03001 string os_specific = to_os_specific();
03002 int fd = open(os_specific.c_str(), O_RDWR | O_CREAT, 0666);
03003 if (fd < 0) {
03004 perror(os_specific.c_str());
03005 return false;
03006 }
03007
03008 static const size_t buf_size = 512;
03009 char buf[buf_size];
03010
03011 orig_contents = string();
03012
03013 if (lockf(fd, F_LOCK, 0) != 0) {
03014 perror(os_specific.c_str());
03015 close(fd);
03016 return false;
03017 }
03018
03019 size_t bytes_read = read(fd, buf, buf_size);
03020 while (bytes_read > 0) {
03021 orig_contents += string(buf, bytes_read);
03022 bytes_read = read(fd, buf, buf_size);
03023 }
03024
03025 if (bytes_read < 0) {
03026 perror(os_specific.c_str());
03027 close(fd);
03028 return false;
03029 }
03030
03031 bool match = false;
03032 if (orig_contents == old_contents) {
03033 match = true;
03034 lseek(fd, 0, SEEK_SET);
03035 ssize_t bytes_written = write(fd, new_contents.data(), new_contents.size());
03036 if (bytes_written < 0) {
03037 perror(os_specific.c_str());
03038 close(fd);
03039 return false;
03040 }
03041 }
03042
03043 if (close(fd) < 0) {
03044 perror(os_specific.c_str());
03045 return false;
03046 }
03047
03048 return match;
03049 #endif // WIN32_VC
03050 }
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069 bool Filename::
03070 atomic_read_contents(string &contents) const {
03071 #ifdef WIN32_VC
03072 wstring os_specific = to_os_specific_w();
03073 HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ,
03074 FILE_SHARE_READ, NULL, OPEN_ALWAYS,
03075 FILE_ATTRIBUTE_NORMAL, NULL);
03076 while (hfile == INVALID_HANDLE_VALUE) {
03077 DWORD error = GetLastError();
03078 if (error == ERROR_SHARING_VIOLATION) {
03079
03080 Sleep(0);
03081 hfile = CreateFileW(os_specific.c_str(), GENERIC_READ,
03082 FILE_SHARE_READ, NULL, OPEN_ALWAYS,
03083 FILE_ATTRIBUTE_NORMAL, NULL);
03084 } else {
03085 cerr << "Couldn't open file: " << os_specific
03086 << ", error " << error << "\n";
03087 return false;
03088 }
03089 }
03090
03091 static const size_t buf_size = 512;
03092 char buf[buf_size];
03093
03094 contents = string();
03095
03096 DWORD bytes_read;
03097 if (!ReadFile(hfile, buf, buf_size, &bytes_read, NULL)) {
03098 cerr << "Error reading file: " << os_specific
03099 << ", error " << GetLastError() << "\n";
03100 CloseHandle(hfile);
03101 return false;
03102 }
03103 while (bytes_read > 0) {
03104 contents += string(buf, bytes_read);
03105
03106 if (!ReadFile(hfile, buf, buf_size, &bytes_read, NULL)) {
03107 cerr << "Error reading file: " << os_specific
03108 << ", error " << GetLastError() << "\n";
03109 CloseHandle(hfile);
03110 return false;
03111 }
03112 }
03113
03114 CloseHandle(hfile);
03115 return true;
03116
03117 #else // WIN32_VC
03118 string os_specific = to_os_specific();
03119 int fd = open(os_specific.c_str(), O_RDWR | O_CREAT, 0666);
03120 if (fd < 0) {
03121 perror(os_specific.c_str());
03122 return false;
03123 }
03124
03125 static const size_t buf_size = 512;
03126 char buf[buf_size];
03127
03128 contents = string();
03129
03130 if (lockf(fd, F_LOCK, 0) != 0) {
03131 perror(os_specific.c_str());
03132 close(fd);
03133 return false;
03134 }
03135
03136 size_t bytes_read = read(fd, buf, buf_size);
03137 while (bytes_read > 0) {
03138 contents += string(buf, bytes_read);
03139 bytes_read = read(fd, buf, buf_size);
03140 }
03141
03142 if (bytes_read < 0) {
03143 perror(os_specific.c_str());
03144 close(fd);
03145 return false;
03146 }
03147
03148 close(fd);
03149 return true;
03150 #endif // WIN32_VC
03151 }
03152
03153
03154
03155
03156
03157
03158
03159
03160 void Filename::
03161 locate_basename() {
03162
03163
03164 if (_filename.empty()) {
03165 _dirname_end = 0;
03166 _basename_start = 0;
03167
03168 } else {
03169
03170 string::size_type slash = _filename.rfind('/');
03171 if (slash != string::npos) {
03172 _basename_start = slash + 1;
03173 _dirname_end = _basename_start;
03174
03175
03176
03177
03178 while (_dirname_end > 0 && _filename[_dirname_end-1] == '/') {
03179 _dirname_end--;
03180 }
03181
03182
03183
03184
03185 if (_dirname_end == 0) {
03186 _dirname_end = 1;
03187 }
03188
03189 } else {
03190 _dirname_end = 0;
03191 _basename_start = 0;
03192 }
03193 }
03194
03195
03196
03197
03198
03199
03200
03201
03202 }
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214 void Filename::
03215 locate_extension() {
03216
03217 if (_filename.empty()) {
03218 _basename_end = string::npos;
03219 _extension_start = string::npos;
03220
03221 } else {
03222 string::size_type dot = _filename.length() - 1;
03223
03224 while (dot+1 > _basename_start && _filename[dot] != '.') {
03225 --dot;
03226 }
03227
03228 if (dot+1 > _basename_start) {
03229 _basename_end = dot;
03230 _extension_start = dot + 1;
03231 } else {
03232 _basename_end = string::npos;
03233 _extension_start = string::npos;
03234 }
03235 }
03236
03237
03238
03239
03240
03241
03242
03243 }
03244
03245
03246
03247
03248
03249
03250
03251 void Filename::
03252 locate_hash() {
03253 if (!get_pattern()) {
03254
03255
03256 _hash_end = string::npos;
03257 _hash_start = string::npos;
03258
03259 } else {
03260
03261
03262
03263 _hash_end = _filename.rfind('#');
03264 if (_hash_end == string::npos) {
03265 _hash_end = string::npos;
03266 _hash_start = string::npos;
03267
03268 } else {
03269 _hash_start = _hash_end;
03270 ++_hash_end;
03271 while (_hash_start > 0 && _filename[_hash_start - 1] == '#') {
03272 --_hash_start;
03273 }
03274 }
03275 }
03276 }
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287 size_t Filename::
03288 get_common_prefix(const string &other) const {
03289 size_t len = 0;
03290
03291
03292 while (len < length() && len < other.length() &&
03293 _filename[len] == other[len]) {
03294 len++;
03295 }
03296
03297
03298 while (len > 0 && _filename[len-1] != '/') {
03299 len--;
03300 }
03301
03302 return len;
03303 }
03304
03305
03306
03307
03308
03309
03310
03311 int Filename::
03312 count_slashes(const string &str) {
03313 int count = 0;
03314 string::const_iterator si;
03315 si = str.begin();
03316
03317 while (si != str.end()) {
03318 if (*si == '/') {
03319 count++;
03320
03321
03322 ++si;
03323 while (*si == '/') {
03324 ++si;
03325 }
03326 if (si == str.end()) {
03327
03328 count--;
03329 }
03330
03331 } else {
03332 ++si;
03333 }
03334 }
03335
03336 return count;
03337 }
03338
03339
03340
03341
03342
03343
03344
03345 bool Filename::
03346 r_make_canonical(const Filename &cwd) {
03347 if (get_fullpath() == "/") {
03348
03349
03350 return false;
03351 }
03352
03353 #ifdef WIN32_VC
03354
03355 wstring os_specific = to_os_specific_w();
03356 if (_wchdir(os_specific.c_str()) >= 0) {
03357
03358 (*this) = ExecutionEnvironment::get_cwd();
03359
03360
03361 wstring osdir = cwd.to_os_specific_w();
03362 if (_wchdir(osdir.c_str()) < 0) {
03363 cerr << "Error! Cannot change back to " << osdir << "\n";
03364 }
03365 return true;
03366 }
03367 #else // WIN32_VC
03368
03369 string os_specific = to_os_specific();
03370 if (::chdir(os_specific.c_str()) >= 0) {
03371
03372 (*this) = ExecutionEnvironment::get_cwd();
03373
03374
03375 string osdir = cwd.to_os_specific();
03376 if (::chdir(osdir.c_str()) < 0) {
03377 cerr << "Error! Cannot change back to " << osdir << "\n";
03378 }
03379 return true;
03380 }
03381 #endif // WIN32_VC
03382
03383
03384
03385
03386 Filename dir(get_dirname());
03387
03388 if (dir.empty()) {
03389
03390 set_dirname(cwd);
03391 return true;
03392 }
03393
03394 if (!dir.r_make_canonical(cwd)) {
03395 return false;
03396 }
03397 set_dirname(dir);
03398 return true;
03399 }
03400