rvm 1.08
|
00001 #include "config.h" 00002 00003 #include <iostream> 00004 #include <fstream> 00005 00006 #ifdef STAT_MACROS_BROKEN 00007 #error Sorry, S_ISDIR, S_ISREG et. al. appear to be broken on this system. 00008 #endif 00009 00010 #include <cstring> 00011 #include <cerrno> 00012 00013 #ifdef HAVE_SYS_MKDEV_H 00014 #include <sys/mkdev.h> 00015 #endif 00016 #ifdef HAVE_SYS_TYPES_H 00017 #include <sys/types.h> 00018 #endif 00019 #ifdef HAVE_SYS_STAT_H 00020 #include <sys/stat.h> 00021 #endif 00022 #ifdef HAVE_UNISTD_H 00023 #include <unistd.h> 00024 #endif 00025 00026 #ifdef TIME_WITH_SYS_TIME 00027 #include <sys/time.h> 00028 #include <time.h> 00029 #else 00030 #ifdef HAVE_SYS_TIME_H 00031 #include <sys/time.h> 00032 #else 00033 #include <time.h> 00034 #endif 00035 #endif 00036 00037 #ifdef HAVE_DIRENT_H 00038 #include <dirent.h> 00039 #define NAMELEN(dirent) strlen((dirent)->d_name) 00040 #else 00041 #define dirent direct 00042 #define NAMELEN(dirent) (dirent)->d_namlen 00043 #ifdef HAVE_SYS_NDIR_H 00044 #include <sys/ndir.h> 00045 #endif 00046 #ifdef HAVE_SYS_DIR_H 00047 #include <sys/dir.h> 00048 #endif 00049 #ifdef HAVE_NDIR_H 00050 #include <ndir.h> 00051 #endif 00052 #endif 00053 00054 #ifdef HAVE_FNMATCH_H 00055 #include <fnmatch.h> 00056 #endif 00057 00058 #include <stdio.h> 00059 00060 #include "asserts.h" 00061 #include "error.h" 00062 #include "estring.h" 00063 #include "fs.h" 00064 00065 // 00066 // Define certain file attribute elements if they don't already exist 00067 // 00068 #ifndef S_IFMT 00069 #define S_IFMT (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) 00070 #endif 00071 00072 #ifndef S_IAMB 00073 #define S_IAMB (S_ISUID|S_ISGID|S_ISVTX\ 00074 |S_IRUSR|S_IWUSR|S_IXUSR\ 00075 |S_IRGRP|S_IWGRP|S_IXGRP\ 00076 |S_IROTH|S_IWOTH|S_IXOTH\ 00077 ) 00078 00079 #endif 00080 00081 #ifdef S_IFIFO 00082 #ifndef S_ISFIFO 00083 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 00084 #endif 00085 #endif 00086 00087 #ifdef S_IFCHR 00088 #ifndef S_ISCHR 00089 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 00090 #endif 00091 #endif 00092 00093 #ifdef S_IFDIR 00094 #ifndef S_ISDIR 00095 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 00096 #endif 00097 #endif 00098 00099 #ifdef S_IFBLK 00100 #ifndef S_ISBLK 00101 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 00102 #endif 00103 #endif 00104 00105 #ifdef S_IFREG 00106 #ifndef S_ISREG 00107 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 00108 #endif 00109 #endif 00110 00111 #ifdef S_IFLNK 00112 #ifndef S_ISLNK 00113 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 00114 #endif 00115 #endif 00116 00117 #ifdef S_IFSOCK 00118 #ifndef S_ISSOCK 00119 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 00120 #endif 00121 #endif 00122 00123 #ifdef S_IFDOOR 00124 #ifndef S_ISDOOR 00125 #define S_ISDOOR(mode) (((mode) & S_IFMT) == S_IFDOOR) 00126 #endif 00127 #endif 00128 00129 #ifndef S_IRWXU 00130 #define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR) 00131 #endif 00132 00133 #ifndef S_IRWXG 00134 #define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP) 00135 #endif 00136 00137 #ifndef S_IRWXO 00138 #define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH) 00139 #endif 00140 00141 #ifndef ACCESSPERMS 00142 #define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) 00143 #endif 00144 00145 //---------------------------------------------------------------------------- 00146 00147 /** Return the current working directory */ 00148 const std::string cwd(void) 00149 { 00150 std::string s; 00151 char buf[PATH_MAX] = { 0 }; 00152 00153 if (getcwd(buf, PATH_MAX) == 0) 00154 throw(ERROR(errno,"Could not determine current directory")); 00155 00156 TRY_nomem(s = buf); 00157 00158 return(s); 00159 } 00160 00161 /** Return the PID of this process */ 00162 const pid_t pid(void) 00163 { 00164 pid_t pid; 00165 00166 pid = getpid(); 00167 if (pid == -1) 00168 throw(ERROR(errno,"Could not determine PID")); 00169 00170 return(pid); 00171 } 00172 00173 /** Return the PID of the parent process */ 00174 const pid_t parent_pid(void) 00175 { 00176 pid_t pid; 00177 00178 pid = getppid(); 00179 if (pid == -1) 00180 throw(ERROR(errno,"Could not determine PID")); 00181 00182 return(pid); 00183 } 00184 00185 /** Return true if the string looks like an absolute path */ 00186 bool absolute_path(const std::string& a_path) 00187 { 00188 if ((a_path.size() > 0) && (a_path[0] == '/')) { 00189 return(true); 00190 } 00191 return(false); 00192 } 00193 00194 /** Return true if the string looks like a relative path */ 00195 bool relative_path(const std::string& a_path) 00196 { 00197 bool value; 00198 00199 value = !absolute_path(a_path); 00200 00201 return(value); 00202 } 00203 00204 /** Reformat a path to remove double slashes */ 00205 std::string reform_path(const std::string& a_path) 00206 { 00207 std::string::size_type idx; 00208 std::string str; 00209 00210 TRY_nomem(str = a_path); 00211 idx = str.find('/'); 00212 while (idx != std::string::npos) { 00213 while ((idx != str.size()-1) && (str[idx+1] == '/')) 00214 str.erase(idx+1,1); 00215 idx = str.find('/',idx+1); 00216 } 00217 00218 return(str); 00219 } 00220 00221 /** Reformat a path to remove the begining and trailing slashes, and replace 00222 all other slashes with underscores 00223 */ 00224 std::string permute_path(const std::string& a_path) 00225 { 00226 std::string path; 00227 std::string::size_type idx; 00228 00229 TRY_nomem(path = reform_path(a_path)); 00230 idx = path.find('/'); 00231 while (idx != std::string::npos) { 00232 if ((idx == 0) || (idx == path.size()-1)) 00233 path.erase(idx,1); 00234 else 00235 path[idx] = '-'; 00236 idx = path.find('/'); 00237 } 00238 if (path.size() == 0) 00239 TRY_nomem(path = "root"); 00240 if (path.substr(0,2) == ".-") 00241 path.erase(0,2); 00242 00243 return(path); 00244 } 00245 00246 /** Return everything after the last slash from a path */ 00247 std::string path_basename(const std::string& a_path) 00248 { 00249 std::string path; 00250 std::string::size_type idx; 00251 00252 idx = a_path.rfind('/'); 00253 if (idx == std::string::npos) { 00254 TRY_nomem(path = a_path); 00255 } 00256 else { 00257 TRY_nomem(path = a_path.substr(idx+1)); 00258 } 00259 00260 return(path); 00261 } 00262 00263 /** Return everything up to the last slash from a path */ 00264 std::string path_dirname(const std::string& a_path) 00265 { 00266 std::string path; 00267 std::string::size_type idx; 00268 00269 idx = a_path.rfind('/'); 00270 if (idx == std::string::npos) { 00271 TRY_nomem(path = "."); 00272 } 00273 else { 00274 TRY_nomem(path = a_path.substr(0,idx)); 00275 } 00276 00277 return(path); 00278 } 00279 00280 /** Make the path a_rel_path absolute with respect to a_path, where a_rel_path 00281 * and a_path are directory names */ 00282 std::string mk_absolute_path( 00283 const std::string a_path, 00284 const std::string a_rel_path 00285 ) 00286 { 00287 std::string es; 00288 std::string path; 00289 00290 if (a_rel_path.size() == 0) { 00291 TRY_nomem(es = "Invalid relative path: \""); 00292 TRY_nomem(es += a_rel_path); 00293 TRY_nomem(es += "\""); 00294 throw(ERROR(0,es)); 00295 } 00296 if (relative_path(a_path)) { 00297 TRY_nomem(es = "Invalid absolute reference path: \""); 00298 TRY_nomem(es += a_path); 00299 TRY_nomem(es += "\""); 00300 throw(INTERNAL_ERROR(0,es)); 00301 } 00302 if (relative_path(a_rel_path)) { 00303 TRY_nomem(path = a_path); 00304 TRY_nomem(path += "/"); 00305 } 00306 TRY_nomem(path += a_rel_path); 00307 path = reform_path(path); 00308 00309 return(path); 00310 } 00311 00312 /** Make the path a_path_to relative from a_path_from, where a_path_to and 00313 * a_path_from are directory names */ 00314 std::string mk_relative_path( 00315 const std::string a_path_to, 00316 const std::string a_path_from 00317 ) 00318 { 00319 std::string::size_type idx_to, idx_from, idx; 00320 std::string path_to, path_from, path; 00321 std::string path_to_substr, path_from_substr; 00322 00323 TRY_nomem(path_to = a_path_to); 00324 TRY_nomem(path_from = a_path_from); 00325 TRY_nomem(path = ""); 00326 00327 idx_to = path_to.find("/"); 00328 if (idx_to != std::string::npos) { 00329 TRY_nomem(path_to_substr = path_to.substr(0,idx_to)); 00330 } 00331 else { 00332 TRY_nomem(path_to_substr = path_to); 00333 } 00334 idx_from = path_from.find("/"); 00335 if (idx_from != std::string::npos) { 00336 TRY_nomem(path_from_substr = path_from.substr(0,idx_from)); 00337 } 00338 else { 00339 TRY_nomem(path_from_substr = path_from); 00340 } 00341 00342 while ( 00343 (path_to.size() > 0 && path_from.size() > 0) 00344 && (path_to_substr == path_from_substr) 00345 ) 00346 { 00347 path_to.erase(0,path_to_substr.size()); 00348 if ((path_to.size() > 0) && (path_to[0] == '/')) 00349 path_to.erase(0,1); 00350 path_from.erase(0,path_from_substr.size()); 00351 if ((path_from.size() > 0) && (path_from[0] == '/')) 00352 path_from.erase(0,1); 00353 00354 idx_to = path_to.find("/"); 00355 if (idx_to != std::string::npos) { 00356 TRY_nomem(path_to_substr = path_to.substr(0,idx_to)); 00357 } 00358 else { 00359 TRY_nomem(path_to_substr = path_to); 00360 } 00361 idx_from = path_from.find("/"); 00362 if (idx_from != std::string::npos) { 00363 TRY_nomem(path_from_substr = path_from.substr(0,idx_from)); 00364 } 00365 else { 00366 TRY_nomem(path_from_substr = path_from); 00367 } 00368 } 00369 00370 while (path_from.size() > 0) { 00371 TRY_nomem(path += "../"); 00372 idx = path_from.find('/'); 00373 if (idx == std::string::npos) 00374 path_from.erase(); 00375 else 00376 path_from.erase(0,idx+1); 00377 } 00378 TRY_nomem(path += path_to); 00379 TRY_nomem(path = reform_path(path)); 00380 00381 return(path); 00382 } 00383 00384 /** Return true if the file or directory exists */ 00385 bool exists(const std::string& a_path) 00386 { 00387 if (access(a_path.c_str(), F_OK) == 0) return(true); 00388 errno = 0; 00389 #ifdef S_ISFIFO 00390 if (is_fifo_special(a_path)) return(true); 00391 #endif 00392 #ifdef S_ISCHR 00393 if (is_char_special(a_path)) return(true); 00394 #endif 00395 #ifdef S_ISDIR 00396 if (is_dir(a_path)) return(true); 00397 #endif 00398 #ifdef S_ISREG 00399 if (is_file(a_path)) return(true); 00400 #endif 00401 #ifdef S_ISBLK 00402 if (is_block_special(a_path)) return(true); 00403 #endif 00404 #ifdef S_ISLNK 00405 if (is_link(a_path)) return(true); 00406 #endif 00407 #ifdef S_ISSOCK 00408 if (is_socket(a_path)) return(true); 00409 #endif 00410 #ifdef S_ISDOOR 00411 if (is_door(a_path)) return(true); 00412 #endif 00413 return(false); 00414 } 00415 00416 /** Return true if the file or directory exists and is readable */ 00417 bool readable(const std::string& a_path) 00418 { 00419 if (access(a_path.c_str(), R_OK) != 0) { 00420 errno = 0; 00421 return(false); 00422 } 00423 return(true); 00424 } 00425 00426 /** Return true if the file or directory exists and is writable */ 00427 bool writable(const std::string& a_path) 00428 { 00429 if (access(a_path.c_str(), W_OK) != 0) { 00430 errno = 0; 00431 return(false); 00432 } 00433 return(true); 00434 } 00435 00436 /** Return true if the file or directory exists and is executable */ 00437 bool executable(const std::string& a_path) 00438 { 00439 if (access(a_path.c_str(), X_OK) != 0) { 00440 errno = 0; 00441 return(false); 00442 } 00443 return(true); 00444 } 00445 00446 #ifdef S_ISFIFO 00447 /** Return true if the file is a fifo-special */ 00448 bool is_fifo_special(const std::string& a_path) 00449 { 00450 filestatus fstat; 00451 00452 try { 00453 fstat.path(a_path); 00454 if (fstat.is_fifo_special()) { 00455 return(true); 00456 } 00457 } 00458 catch(...) { 00459 return(false); 00460 } 00461 return(false); 00462 } 00463 #endif 00464 00465 #ifdef S_ISCHR 00466 /** Return true if the file is a char-special */ 00467 bool is_char_special(const std::string& a_path) 00468 { 00469 filestatus fstat; 00470 00471 try { 00472 fstat.path(a_path); 00473 if (fstat.is_character_special()) { 00474 return(true); 00475 } 00476 } 00477 catch(...) { 00478 return(false); 00479 } 00480 return(false); 00481 } 00482 #endif 00483 00484 #ifdef S_ISDIR 00485 /** Return true if the file is a directory */ 00486 bool is_dir(const std::string& a_path) 00487 { 00488 filestatus fstat; 00489 00490 try { 00491 fstat.path(a_path); 00492 if (fstat.is_directory()) { 00493 return(true); 00494 } 00495 } 00496 catch(...) { 00497 return(false); 00498 } 00499 return(false); 00500 } 00501 #endif 00502 00503 #ifdef S_ISREG 00504 /** Return true if the file is a regular file */ 00505 bool is_file(const std::string& a_path) 00506 { 00507 filestatus fstat; 00508 00509 try { 00510 fstat.path(a_path); 00511 if (fstat.is_regular_file()) { 00512 return(true); 00513 } 00514 } 00515 catch(...) { 00516 return(false); 00517 } 00518 return(false); 00519 } 00520 #endif 00521 00522 #ifdef S_ISBLK 00523 /** Return true if the file is a block-special */ 00524 bool is_block_special(const std::string& a_path) 00525 { 00526 filestatus fstat; 00527 00528 try { 00529 fstat.path(a_path); 00530 if (fstat.is_block_special()) { 00531 return(true); 00532 } 00533 } 00534 catch(...) { 00535 return(false); 00536 } 00537 return(false); 00538 } 00539 #endif 00540 00541 #ifdef S_ISLNK 00542 /** Return true is the file is a link */ 00543 bool is_link(const std::string& a_path) 00544 { 00545 filestatus fstat; 00546 00547 try { 00548 fstat.path(a_path); 00549 if (fstat.is_link()) { 00550 return(true); 00551 } 00552 } 00553 catch(...) { 00554 return(false); 00555 } 00556 return(false); 00557 } 00558 #endif 00559 00560 #ifdef S_ISSOCK 00561 /** Return true if the file is a socket */ 00562 bool is_socket(const std::string& a_path) 00563 { 00564 filestatus fstat; 00565 00566 try { 00567 fstat.path(a_path); 00568 if (fstat.is_socket()) { 00569 return(true); 00570 } 00571 } 00572 catch(...) { 00573 return(false); 00574 } 00575 return(false); 00576 } 00577 #endif 00578 00579 #ifdef S_ISDOOR 00580 /** Return true if the file is a door */ 00581 bool is_door(const std::string& a_path) 00582 { 00583 filestatus fstat; 00584 00585 try { 00586 fstat.path(a_path); 00587 if (fstat.is_door()) { 00588 return(true); 00589 } 00590 } 00591 catch(...) { 00592 return(false); 00593 } 00594 return(false); 00595 } 00596 #endif 00597 00598 /** Create a directory */ 00599 void mk_dir(const std::string& a_path) 00600 { 00601 std::string es; 00602 00603 if (mkdir(a_path.c_str(), ACCESSPERMS) != 0) { 00604 TRY_nomem(es = "Could not create directory: \""); 00605 TRY_nomem(es += a_path); 00606 TRY_nomem(es += "\""); 00607 throw(ERROR(errno,es)); 00608 } 00609 } 00610 00611 /** Remove a directory */ 00612 void rm_dir(const std::string a_path) 00613 { 00614 if (!exists(a_path)) return; 00615 if (rmdir(a_path.c_str()) != 0) { 00616 std::string es; 00617 00618 TRY_nomem(es = "Could not remove directory: \""); 00619 TRY_nomem(es += a_path); 00620 TRY_nomem(es += "\""); 00621 00622 if (exists(a_path)) { 00623 if (writable(a_path)) { 00624 throw(ERROR(errno,es)); 00625 } 00626 else { 00627 error e = ERROR(errno,es); 00628 00629 e.push_back(ERROR_INSTANCE("No write permissions")); 00630 throw(e); 00631 } 00632 } 00633 } 00634 } 00635 00636 /** Remove a file */ 00637 void rm_file(const std::string a_path) 00638 { 00639 if (!exists(a_path)) return; 00640 if (unlink(a_path.c_str()) != 0) { 00641 std::string es; 00642 00643 TRY_nomem(es = "Could not remove file: \""); 00644 TRY_nomem(es += a_path); 00645 TRY_nomem(es += "\""); 00646 00647 if (exists(a_path)) { 00648 if (writable(a_path)) { 00649 throw(ERROR(errno,es)); 00650 } 00651 else { 00652 error e = ERROR(errno,es); 00653 00654 e.push_back(ERROR_INSTANCE("No write permissions")); 00655 throw(e); 00656 } 00657 } 00658 } 00659 } 00660 00661 /** Recursively create a directory heirarchy */ 00662 void mk_dirhier_recursive_(const std::string a_path) 00663 { 00664 std::string parent_dir; 00665 int ce; 00666 00667 if (a_path.size() == 0) 00668 return; 00669 if (exists(a_path)) 00670 return; 00671 00672 for (ce = a_path.size()-1; ((ce > 0) && (a_path[ce] != '/')); ce--); 00673 00674 if (ce > 0) { 00675 TRY_nomem(parent_dir = a_path.substr(0,ce)); 00676 mk_dirhier_recursive_(parent_dir); 00677 } 00678 if (!exists(a_path)) 00679 mk_dir(a_path); 00680 } 00681 00682 /** Recursively create a directory heirarchy */ 00683 void mk_dirhier(const std::string a_path) 00684 { 00685 if (a_path.size() == 0) 00686 return; 00687 if (exists(a_path)) 00688 return; 00689 00690 try { 00691 mk_dirhier_recursive_(a_path); 00692 } 00693 catch(error e) { 00694 std::string es; 00695 00696 TRY_nomem(es = "Could not create directory hierarchy: \""); 00697 TRY_nomem(es += a_path); 00698 TRY_nomem(es += "\""); 00699 00700 e.push_back(ERROR_INSTANCE(es)); 00701 throw(e); 00702 } 00703 catch(...) { 00704 throw(err_unknown); 00705 } 00706 } 00707 00708 /** Rename a file or directory */ 00709 void rename_file(const std::string a_from, const std::string a_to) 00710 { 00711 std::string es; 00712 00713 if (a_from.size() == 0) { 00714 TRY_nomem(es = "Illegal from filename: \""); 00715 TRY_nomem(es += a_from); 00716 TRY_nomem(es += "\""); 00717 throw(INTERNAL_ERROR(0,es)); 00718 } 00719 if (!exists(a_from)) { 00720 TRY_nomem(es = "From filename does not exist: \""); 00721 TRY_nomem(es += a_from); 00722 TRY_nomem(es += "\""); 00723 throw(ERROR(0,es)); 00724 } 00725 if (a_to.size() == 0) { 00726 TRY_nomem(es = "Illegal to filename: \""); 00727 TRY_nomem(es += a_to); 00728 TRY_nomem(es += "\""); 00729 throw(INTERNAL_ERROR(0,es)); 00730 } 00731 if (exists(a_to)) { 00732 TRY_nomem(es = "To filename already exists: \""); 00733 TRY_nomem(es += a_to); 00734 TRY_nomem(es += "\""); 00735 throw(ERROR(0,es)); 00736 } 00737 if (!writable(a_from)) { 00738 TRY_nomem(es = "From filename is not writable: \""); 00739 TRY_nomem(es += a_from); 00740 TRY_nomem(es += "\""); 00741 throw(ERROR(0,es)); 00742 } 00743 if (rename(a_from.c_str(), a_to.c_str()) != 0) { 00744 TRY_nomem(es = "Could not rename file: \""); 00745 TRY_nomem(es += a_from); 00746 TRY_nomem(es += "\" to \""); 00747 TRY_nomem(es += a_to); 00748 TRY_nomem(es += "\""); 00749 throw(ERROR(errno,es)); 00750 } 00751 } 00752 00753 /** Create a symbolic link */ 00754 void mk_symlink(const std::string a_from, const std::string a_to) 00755 { 00756 if (symlink(a_from.c_str(), a_to.c_str()) != 0) { 00757 std::string es; 00758 00759 TRY_nomem(es = "Could not link: \""); 00760 TRY_nomem(es += a_from); 00761 TRY_nomem(es += "\" to: \""); 00762 TRY_nomem(es += a_to); 00763 TRY_nomem(es += "\""); 00764 00765 throw(ERROR(errno,es)); 00766 } 00767 } 00768 00769 /** Given a from and to path, create a relative symbolic link */ 00770 void mk_relative_symlink(const std::string a_from, const std::string a_to) 00771 { 00772 std::string from_dirname, to_dirname, from_basename; 00773 std::string rel; 00774 00775 TRY_nomem(from_dirname = path_dirname(a_from)); 00776 TRY_nomem(to_dirname = path_dirname(a_to)); 00777 TRY_nomem(from_basename = path_basename(a_from)); 00778 TRY_nomem(rel = mk_relative_path(from_dirname, to_dirname)); 00779 if (rel.size() != 0) { 00780 TRY_nomem(rel += "/"); 00781 } 00782 TRY_nomem(rel += from_basename); 00783 TRY_nomem(rel = reform_path(rel)); 00784 00785 try { 00786 mk_symlink(rel,a_to); 00787 } 00788 catch(error e) { 00789 std::string es; 00790 00791 TRY_nomem(es = "Could not link: \""); 00792 TRY_nomem(es += a_to); 00793 TRY_nomem(es += "\" as: \""); 00794 TRY_nomem(es += rel); 00795 TRY_nomem(es += "\""); 00796 00797 e.push_back(ERROR_INSTANCE(es)); 00798 throw(e); 00799 } 00800 catch(...) { 00801 throw(err_unknown); 00802 } 00803 } 00804 00805 //---------------------------------------------------------------------------- 00806 00807 /** C'tor */ 00808 filestatus::filestatus() 00809 { 00810 } 00811 00812 /** C'tor */ 00813 filestatus::filestatus(const std::string a_path) 00814 { 00815 path(a_path); 00816 } 00817 00818 /** D'tor */ 00819 filestatus::~filestatus() 00820 { 00821 } 00822 00823 /** Retrieve information about a pathname */ 00824 void filestatus::path(const std::string a_path) 00825 { 00826 std::string es; 00827 struct passwd *passwd_ptr = 0; 00828 struct group *group_ptr = 0; 00829 struct stat statbuf; 00830 char path_buf[PATH_MAX] = { 0 }; 00831 00832 clear(); 00833 TRY_nomem(m_path = reform_path(a_path)); 00834 if (lstat(m_path.c_str(), &statbuf) < 0) { 00835 TRY_nomem(es = "For path: \""); 00836 TRY_nomem(es += a_path); 00837 TRY_nomem(es += "\""); 00838 throw(ERROR(errno,es)); 00839 } 00840 if (lstat(m_path.c_str(), &m_stat) == -1) { 00841 TRY_nomem(es = "For path: \""); 00842 TRY_nomem(es += a_path); 00843 TRY_nomem(es += "\""); 00844 throw(ERROR(errno,es)); 00845 } 00846 #ifdef S_ISFIFO 00847 if (S_ISFIFO(m_stat.st_mode)) { 00848 m_major = major(m_stat.st_rdev); 00849 m_minor = minor(m_stat.st_rdev); 00850 } 00851 #endif 00852 #ifdef S_ISCHR 00853 if (S_ISCHR(m_stat.st_mode)) { 00854 m_major = major(m_stat.st_rdev); 00855 m_minor = minor(m_stat.st_rdev); 00856 } 00857 #endif 00858 #ifdef S_ISBLK 00859 if (S_ISBLK(m_stat.st_mode)) { 00860 m_major = major(m_stat.st_rdev); 00861 m_minor = minor(m_stat.st_rdev); 00862 } 00863 #endif 00864 #ifdef S_ISLNK 00865 if (S_ISLNK(m_stat.st_mode)) { 00866 if (readlink(a_path.c_str(), path_buf, PATH_MAX) < 0) { 00867 TRY_nomem(es = "Could not read path's link: \""); 00868 TRY_nomem(es += a_path); 00869 TRY_nomem(es += "\""); 00870 throw(ERROR(errno,es)); 00871 } 00872 TRY_nomem(m_link = path_buf); 00873 } 00874 #endif 00875 passwd_ptr = getpwuid(m_stat.st_uid); 00876 if (passwd_ptr != 0) { 00877 m_uidfound = true; 00878 TRY_nomem(m_uname = passwd_ptr->pw_name); 00879 } 00880 group_ptr = getgrgid(m_stat.st_gid); 00881 if (group_ptr != 0) { 00882 m_gidfound = true; 00883 TRY_nomem(m_gname = group_ptr->gr_name); 00884 } 00885 } 00886 00887 /** Return the pathname that this filestatus object has information about */ 00888 const std::string filestatus::path(void) const 00889 { 00890 return(m_path); 00891 } 00892 00893 /** Return the type of file */ 00894 const filestatus::filetype filestatus::type(void) const 00895 { 00896 #ifdef S_ISFIFO 00897 if (S_ISFIFO(m_stat.st_mode)) { 00898 return(type_fifo_special); 00899 } 00900 #endif 00901 #ifdef S_ISCHR 00902 if (S_ISCHR(m_stat.st_mode)) { 00903 return(type_character_special); 00904 } 00905 #endif 00906 #ifdef S_ISDIR 00907 if (S_ISDIR(m_stat.st_mode)) { 00908 return(type_directory); 00909 } 00910 #endif 00911 #ifdef S_ISBLK 00912 if (S_ISBLK(m_stat.st_mode)) { 00913 return(type_block_special); 00914 } 00915 #endif 00916 #ifdef S_ISREG 00917 if (S_ISREG(m_stat.st_mode)) { 00918 return(type_regular_file); 00919 } 00920 #endif 00921 #ifdef S_ISLNK 00922 if (S_ISLNK(m_stat.st_mode)) { 00923 return(type_link); 00924 } 00925 #endif 00926 #ifdef S_ISSOCK 00927 if (S_ISSOCK(m_stat.st_mode)) { 00928 return(type_socket); 00929 } 00930 #endif 00931 #ifdef S_ISDOOR 00932 if (S_ISDOOR(m_stat.st_mode)) { 00933 return(type_door); 00934 } 00935 #endif 00936 return(type_unknown); 00937 } 00938 00939 /** If the pathname is a link, return the path it is linked to */ 00940 const std::string filestatus::link(void) const 00941 { 00942 return(m_link); 00943 } 00944 00945 /** Return the file mode */ 00946 const filestatus::mode_type filestatus::mode(void) const 00947 { 00948 return(m_stat.st_mode); 00949 } 00950 00951 /** Return the file inode */ 00952 const filestatus::inode_type filestatus::inode(void) const 00953 { 00954 return(m_stat.st_ino); 00955 } 00956 00957 /** Return the file's device */ 00958 const filestatus::device_type filestatus::dev(void) const 00959 { 00960 return(m_stat.st_dev); 00961 } 00962 00963 /** Return the file's raw device */ 00964 const filestatus::device_type filestatus::rdev(void) const 00965 { 00966 return(m_stat.st_rdev); 00967 } 00968 00969 /** If the pathname is a special file, return it's major number */ 00970 const filestatus::major_type filestatus::get_major(void) const 00971 { 00972 return(m_major); 00973 } 00974 00975 /** If the pathname is a special file, return it's minor number */ 00976 const filestatus::minor_type filestatus::get_minor(void) const 00977 { 00978 return(m_minor); 00979 } 00980 00981 /** Return the number of links to this file */ 00982 const filestatus::num_links_type filestatus::num_links(void) const 00983 { 00984 return(m_stat.st_nlink); 00985 } 00986 00987 /** Return the file's owner's UID */ 00988 const filestatus::uid_type filestatus::uid(void) const 00989 { 00990 return(m_stat.st_uid); 00991 } 00992 00993 /** Return the file's owner's GID */ 00994 const filestatus::gid_type filestatus::gid(void) const 00995 { 00996 return(m_stat.st_gid); 00997 } 00998 00999 /** Return the file size in bytes */ 01000 const filestatus::size_type filestatus::size(void) const 01001 { 01002 size_type value; 01003 01004 value = static_cast<uint64>(m_stat.st_size); 01005 01006 return(value); 01007 } 01008 01009 /** Return the last access time of this file */ 01010 const filestatus::time_type filestatus::last_access_time(void) const 01011 { 01012 return(m_stat.st_atime); 01013 } 01014 01015 /** Return the last modification time of this file */ 01016 const filestatus::time_type filestatus::last_modification_time(void) const 01017 { 01018 return(m_stat.st_mtime); 01019 } 01020 01021 /** Return the last status change time of this file */ 01022 const filestatus::time_type filestatus::last_status_change_time(void) const 01023 { 01024 return(m_stat.st_ctime); 01025 } 01026 01027 /** Return the blocksize used to store this file */ 01028 const filestatus::size_type filestatus::blocksize(void) const 01029 { 01030 size_type value; 01031 01032 value = static_cast<uint64>(m_stat.st_blksize); 01033 01034 return(value); 01035 } 01036 01037 /** Return the number of blocks used to store this file */ 01038 const filestatus::size_type filestatus::blocks(void) const 01039 { 01040 size_type value; 01041 01042 value = static_cast<uint64>(m_stat.st_blocks); 01043 01044 return(value); 01045 } 01046 01047 /** If the file's owner's UID is found in the passwd file, return true */ 01048 const bool filestatus::uid_is_found(void) const 01049 { 01050 return(m_uidfound); 01051 } 01052 01053 /** If the file's owner's GID is found in the passwd file, return true */ 01054 const bool filestatus::gid_is_found(void) const 01055 { 01056 return(m_gidfound); 01057 } 01058 01059 /** Return the file's owner's user name (from UID) */ 01060 const std::string filestatus::uid_name(void) const 01061 { 01062 return(m_uname); 01063 } 01064 01065 /** Return the file's owner's group name (from UID) */ 01066 const std::string filestatus::gid_name(void) const 01067 { 01068 return(m_gname); 01069 } 01070 01071 #ifdef S_ISFIFO 01072 /** Return true if the file is a fifo-special */ 01073 const bool filestatus::is_fifo_special(void) const 01074 { 01075 bool value; 01076 01077 value = (type() == type_fifo_special); 01078 01079 return(value); 01080 } 01081 #endif 01082 01083 #ifdef S_ISCHR 01084 /** Return true if the file is a char-special */ 01085 const bool filestatus::is_character_special(void) const 01086 { 01087 bool value; 01088 01089 value = (type() == type_character_special); 01090 01091 return(value); 01092 } 01093 #endif 01094 01095 #ifdef S_ISBLK 01096 /** Return true if the file is a block-special */ 01097 const bool filestatus::is_block_special(void) const 01098 { 01099 bool value; 01100 01101 value = (type() == type_block_special); 01102 01103 return(value); 01104 } 01105 #endif 01106 01107 #ifdef S_ISLNK 01108 /** Return true if the file is a link */ 01109 const bool filestatus::is_link(void) const 01110 { 01111 bool value; 01112 01113 value = (type() == type_link); 01114 01115 return(value); 01116 } 01117 #endif 01118 01119 #ifdef S_ISSOCK 01120 /** Return true if the file is a socket */ 01121 const bool filestatus::is_socket(void) const 01122 { 01123 bool value; 01124 01125 value = (type() == type_socket); 01126 01127 return(value); 01128 } 01129 #endif 01130 01131 #ifdef S_ISDOOR 01132 /** Return true if the file is a door */ 01133 const bool filestatus::is_door(void) const 01134 { 01135 bool value; 01136 01137 value = (type() == type_door); 01138 01139 return(value); 01140 } 01141 #endif 01142 01143 #ifdef S_ISDIR 01144 /** Return true if the file is a directory */ 01145 const bool filestatus::is_directory(void) const 01146 { 01147 bool value; 01148 01149 value = (type() == type_directory); 01150 01151 return(value); 01152 } 01153 #endif 01154 01155 #ifdef S_ISREG 01156 /** Return true if the file is a regular file */ 01157 const bool filestatus::is_regular_file(void) const 01158 { 01159 bool value; 01160 01161 value = (type() == type_regular_file); 01162 01163 return(value); 01164 } 01165 #endif 01166 01167 #ifdef S_IRUSR 01168 /** Return true if the file is readable by it's owner */ 01169 const bool filestatus::user_can_read(void) const 01170 { 01171 bool value; 01172 01173 value = ((m_stat.st_mode & S_IRUSR) != 0); 01174 01175 return(value); 01176 } 01177 #endif 01178 01179 #ifdef S_IWUSR 01180 /** Return true if the file is writable by it's owner */ 01181 const bool filestatus::user_can_write(void) const 01182 { 01183 bool value; 01184 01185 value = ((m_stat.st_mode & S_IWUSR) != 0); 01186 01187 return(value); 01188 } 01189 #endif 01190 01191 #ifdef S_IXUSR 01192 /** Return true if the file is executable by it's owner */ 01193 const bool filestatus::user_can_execute(void) const 01194 { 01195 bool value; 01196 01197 value = ((m_stat.st_mode & S_IXUSR) != 0); 01198 01199 return(value); 01200 } 01201 #endif 01202 01203 #ifdef S_IRGRP 01204 /** Return true if the file is readable by users in the same group */ 01205 const bool filestatus::group_can_read(void) const 01206 { 01207 bool value; 01208 01209 value = ((m_stat.st_mode & S_IRGRP) != 0); 01210 01211 return(value); 01212 } 01213 #endif 01214 01215 #ifdef S_IWGRP 01216 /** Return true if the file is writable by users in the same group */ 01217 const bool filestatus::group_can_write(void) const 01218 { 01219 bool value; 01220 01221 value = ((m_stat.st_mode & S_IWGRP) != 0); 01222 01223 return(value); 01224 } 01225 #endif 01226 01227 #ifdef S_IXGRP 01228 /** Return true if the file is executable by users in the same group */ 01229 const bool filestatus::group_can_execute(void) const 01230 { 01231 bool value; 01232 01233 value = ((m_stat.st_mode & S_IXGRP) != 0); 01234 01235 return(value); 01236 } 01237 #endif 01238 01239 #ifdef S_IROTH 01240 /** Return true if the file is readable by others */ 01241 const bool filestatus::other_can_read(void) const 01242 { 01243 bool value; 01244 01245 value = ((m_stat.st_mode & S_IROTH) != 0); 01246 01247 return(value); 01248 } 01249 #endif 01250 01251 #ifdef S_IWOTH 01252 /** Return true if the file is writable by others */ 01253 const bool filestatus::other_can_write(void) const 01254 { 01255 bool value; 01256 01257 value = ((m_stat.st_mode & S_IWOTH) != 0); 01258 01259 return(value); 01260 } 01261 #endif 01262 01263 #ifdef S_IXOTH 01264 /** Return true if the file is executable by others */ 01265 const bool filestatus::other_can_execute(void) const 01266 { 01267 bool value; 01268 01269 value = ((m_stat.st_mode & S_IXOTH) != 0); 01270 01271 return(value); 01272 } 01273 #endif 01274 01275 #ifdef S_ISUID 01276 /** Return true if the file's mode has it's set-uid bit set */ 01277 const bool filestatus::is_set_uid(void) const 01278 { 01279 bool value; 01280 01281 value = ((m_stat.st_mode & S_ISUID) != 0); 01282 01283 return(value); 01284 } 01285 #endif 01286 01287 #ifdef S_ISGID 01288 /** Return true if the file's mode has it's set-gid bit set */ 01289 const bool filestatus::is_set_gid(void) const 01290 { 01291 bool value; 01292 01293 value = ((m_stat.st_mode & S_ISGID) != 0); 01294 01295 return(value); 01296 } 01297 #endif 01298 01299 #ifdef S_ISVTX 01300 /** Return true if the file's mode has it's sticky bit set */ 01301 const bool filestatus::is_set_sticky(void) const 01302 { 01303 bool value; 01304 01305 value = ((m_stat.st_mode & S_ISVTX) != 0); 01306 01307 return(value); 01308 } 01309 #endif 01310 01311 /** Clear all values */ 01312 void filestatus::clear(void) 01313 { 01314 TRY_nomem(m_path = ""); 01315 memset(&m_stat, 0, sizeof(m_stat)); 01316 m_major = 0; 01317 m_minor = 0; 01318 m_uidfound = false; 01319 m_gidfound = false; 01320 TRY_nomem(m_uname = ""); 01321 TRY_nomem(m_gname = ""); 01322 } 01323 01324 //---------------------------------------------------------------------------- 01325 01326 /** C'tor */ 01327 subdirectory::subdirectory() 01328 { 01329 } 01330 01331 /** C'tor */ 01332 subdirectory::subdirectory(const subdirectory& a_class) 01333 { 01334 assign(a_class); 01335 } 01336 01337 /** C'or */ 01338 subdirectory::subdirectory( 01339 const std::string a_path, const std::string a_filter) 01340 { 01341 path(a_path, a_filter); 01342 } 01343 01344 /** D'tor */ 01345 subdirectory::~subdirectory() 01346 { 01347 } 01348 01349 /** Assign the contents of a given subdirectory to this subdirectory */ 01350 void subdirectory::assign(const subdirectory& a_class) 01351 { 01352 type::assign(a_class.begin(), a_class.end()); 01353 } 01354 01355 /** Return a vector of strings of a list of files in a subdirectory 01356 01357 Files in the list do not contain the pathname to the file. Only filenames 01358 that match the given wildcard filter will be listed. 01359 */ 01360 const subdirectory::type& 01361 subdirectory::path(const std::string a_path, const std::string a_filter) 01362 { 01363 std::string es; 01364 std::string name; 01365 DIR *dp = 0; 01366 struct dirent *dirp = 0; 01367 filestatus filestat; 01368 01369 clear(); 01370 01371 TRY(filestat.path(a_path),"Could not stat directory"); 01372 01373 dp = opendir(a_path.c_str()); 01374 if (dp == 0) { 01375 TRY_nomem(es = "For path: \""); 01376 TRY_nomem(es += a_path); 01377 TRY_nomem(es += "\""); 01378 throw(ERROR(errno,es)); 01379 } 01380 while ( (dirp = readdir(dp)) != 0 ) { 01381 name = dirp->d_name; 01382 if ( 01383 ((a_filter != ".") && (a_filter != "..")) 01384 && 01385 ((name == ".") || (name == "..")) 01386 ) 01387 continue; 01388 if (fnmatch(a_filter.c_str(), name.c_str(), 0) == 0) { 01389 TRY_nomem(type::push_back(name)); 01390 } 01391 } 01392 if (closedir(dp) < 0) { 01393 TRY_nomem(es = "Error closing directory \""); 01394 TRY_nomem(es += a_path); 01395 TRY_nomem(es += "\""); 01396 throw(ERROR(errno,es)); 01397 } 01398 01399 std::sort(begin(), end()); 01400 01401 return(*this); 01402 } 01403 01404 subdirectory& subdirectory::operator=(const subdirectory& a_class) 01405 { 01406 assign(a_class); 01407 01408 return(*this); 01409 } 01410 01411 //---------------------------------------------------------------------------- 01412 01413 /** Recursively delete the contents of a directory */ 01414 void rm_recursive(const std::string a_path) 01415 { 01416 subdirectory d; 01417 subdirectory::const_iterator di; 01418 filestatus f; 01419 std::string pathstr; 01420 std::string es; 01421 01422 TRY_nomem(es = "Could not recursively delete: \""); 01423 TRY_nomem(es += a_path); 01424 TRY_nomem(es += "\""); 01425 01426 if (!exists(a_path)) { 01427 if (is_link(a_path)) { 01428 TRY(rm_file(a_path),es); 01429 } 01430 return; 01431 } 01432 TRY(f.path(a_path),es); 01433 if (f.is_directory()) { 01434 TRY(d.path(a_path),es); 01435 if (d.size() != 0) { 01436 01437 for (di = d.begin(); di != d.end(); ++di) { 01438 TRY_nomem( 01439 pathstr = static_cast<std::string>(a_path) 01440 + static_cast<std::string>("/") 01441 + static_cast<std::string>(*di) 01442 ); 01443 TRY(f.path(pathstr),es); 01444 if (f.is_directory()) { 01445 TRY(rm_recursive(pathstr),es); 01446 } 01447 else { 01448 rm_file(pathstr); 01449 } 01450 } 01451 } 01452 rm_dir(a_path); 01453 } 01454 else { 01455 rm_file(a_path); 01456 } 01457 } 01458 01459 //---------------------------------------------------------------------------- 01460 01461 /** C'tor */ 01462 directory::directory() 01463 { 01464 } 01465 01466 /** C'tor */ 01467 directory::directory(const directory& a_class) 01468 { 01469 // TODO: Isn't this supposed to do something!? 01470 } 01471 01472 /** C'tor */ 01473 directory::directory(const std::string& a_str) 01474 { 01475 path(a_str); 01476 } 01477 01478 /** D'tor */ 01479 directory::~directory() 01480 { 01481 } 01482 01483 /** Retrieve a list of paths that match the wildcard path given */ 01484 const directory::type& directory::path(const std::string& a_path) 01485 { 01486 std::string es; 01487 std::string::size_type idx; 01488 std::string path; 01489 std::string subdir_path; 01490 std::string new_subdir_path; 01491 subdirectory subdir; 01492 subdirectory::const_iterator sdi; 01493 filestatus filestat; 01494 const_iterator di; 01495 type list; 01496 01497 TRY_nomem(path = reform_path(a_path)); 01498 if (path.size() == 0) { 01499 return(*this); 01500 } 01501 01502 idx = path.find('/'); 01503 if (idx != std::string::npos) { 01504 TRY_nomem(subdir_path = path.substr(0,idx)); 01505 path.erase(0,idx+1); 01506 } 01507 else { 01508 TRY_nomem(subdir_path = path); 01509 path.erase(); 01510 } 01511 if (subdir_path.size() == 0) 01512 TRY_nomem(subdir_path = "/"); 01513 01514 if (!exists(subdir_path)) { 01515 return(*this); 01516 } 01517 TRY_nomem(push_back(subdir_path)); 01518 01519 while (path.size() != 0) { 01520 idx = path.find('/'); 01521 if (idx != std::string::npos) { 01522 TRY_nomem(subdir_path = path.substr(0,idx)); 01523 path.erase(0,idx+1); 01524 } 01525 else { 01526 TRY_nomem(subdir_path = path); 01527 path.erase(); 01528 } 01529 list.clear(); 01530 for (di = begin(); di != end(); di++) { 01531 TRY_nomem(list.push_back(*di)); 01532 } 01533 clear(); 01534 for (di = list.begin(); di != list.end(); di++) { 01535 filestat.path(*di); 01536 if (!filestat.is_directory()) 01537 continue; 01538 subdir.path(*di, subdir_path); 01539 for (sdi = subdir.begin(); sdi != subdir.end(); sdi++) { 01540 TRY_nomem(new_subdir_path = *di); 01541 TRY_nomem(new_subdir_path += "/"); 01542 TRY_nomem(new_subdir_path += *sdi); 01543 TRY_nomem(new_subdir_path = reform_path(new_subdir_path)); 01544 TRY_nomem(push_back(new_subdir_path)); 01545 } 01546 } 01547 } 01548 return(*this); 01549 } 01550 01551 //---------------------------------------------------------------------------- 01552 01553 /** C'tor */ 01554 filesystem::filesystem() 01555 { 01556 clear(); 01557 } 01558 01559 /** C'tor */ 01560 filesystem::filesystem(const std::string& a_path) 01561 { 01562 clear(); 01563 path(a_path); 01564 } 01565 01566 /** Clear the filesystem object */ 01567 void filesystem::clear(void) 01568 { 01569 TRY_nomem(m_path = ""); 01570 memset(&m_statfs, 0, sizeof(m_statfs)); 01571 } 01572 01573 /** Retrieve information about the filesystem on which the given path resides */ 01574 void filesystem::path(const std::string& a_path) 01575 { 01576 std::string es; 01577 01578 TRY_nomem(m_path = reform_path(a_path)); 01579 if (STATFS(a_path.c_str(), &m_statfs) != 0) { 01580 TRY_nomem(es = "Could not stat filesystem: \""); 01581 TRY_nomem(es += a_path); 01582 TRY_nomem(es += "\""); 01583 throw(ERROR(errno,es)); 01584 } 01585 } 01586 01587 /** Return the path from which this filesystem information was obtained */ 01588 const std::string filesystem::path(void) const 01589 { 01590 return(m_path); 01591 } 01592 01593 /** Return the filesystem block size */ 01594 const filesystem::size_type filesystem::blocksize(void) const 01595 { 01596 size_type value; 01597 01598 value = static_cast<uint64>(m_statfs.f_bsize); 01599 01600 return(value); 01601 } 01602 01603 /** Return the filesystem's total number of blocks */ 01604 const filesystem::size_type filesystem::total_blocks(void) const 01605 { 01606 size_type value; 01607 01608 value = static_cast<uint64>(m_statfs.f_blocks); 01609 01610 return(value); 01611 } 01612 01613 /** Return the filesystem's number of free blocks */ 01614 const filesystem::size_type filesystem::free_blocks(void) const 01615 { 01616 size_type value; 01617 01618 value = static_cast<uint64>(m_statfs.f_bfree); 01619 01620 return(value); 01621 } 01622 01623 /** Return the filesystem's number of used blocks */ 01624 const filesystem::size_type filesystem::used_blocks(void) const 01625 { 01626 size_type value; 01627 01628 value = total_blocks() - free_blocks(); 01629 01630 return(value); 01631 } 01632 01633 /** Return the filesystem's total number of inodes, if supported by the 01634 filesystem, otherwise the result is system-dependent, but usually 0. 01635 */ 01636 const filesystem::size_type filesystem::total_inodes(void) const 01637 { 01638 size_type value; 01639 01640 value = static_cast<uint64>(m_statfs.f_files); 01641 01642 return(value); 01643 } 01644 01645 /** Return the filesystem's total number of free inodes, if supported by the 01646 filesystem, otherwise the result is system-dependent, but usually 0. 01647 */ 01648 const filesystem::size_type filesystem::free_inodes(void) const 01649 { 01650 size_type value; 01651 01652 value = static_cast<uint64>(m_statfs.f_ffree); 01653 01654 return(value); 01655 } 01656 01657 /** Return the filesystem's number of used inodes */ 01658 const filesystem::size_type filesystem::used_inodes(void) const 01659 { 01660 size_type value; 01661 01662 value = total_inodes() - free_inodes(); 01663 01664 return(value); 01665 } 01666 01667 /** Copy values from another instance */ 01668 filesystem& filesystem::operator=(const filesystem& a_class) 01669 { 01670 TRY_nomem(m_path = a_class.m_path); 01671 memcpy(&m_statfs, &a_class.m_statfs, sizeof(m_statfs)); 01672 01673 return(*this); 01674 } 01675 01676 //---------------------------------------------------------------------------- 01677 01678 /** C'tor */ 01679 simple_lock::simple_lock() 01680 { 01681 clear(); 01682 } 01683 01684 /** C'tor */ 01685 simple_lock::simple_lock(const std::string& a_lockfile) 01686 { 01687 clear(); 01688 lockfile(a_lockfile); 01689 } 01690 01691 /** D'tor */ 01692 simple_lock::~simple_lock() 01693 { 01694 clear(); 01695 } 01696 01697 /** Clear the simple_lock object */ 01698 void simple_lock::clear(void) 01699 { 01700 if (is_locked() && (locked_by() == getpid())) { 01701 unlock(); 01702 } 01703 m_lockfile.clear(); 01704 } 01705 01706 /** Set the lockfile path */ 01707 void simple_lock::lockfile(const std::string& a_lockfile) 01708 { 01709 clear(); 01710 m_lockfile = a_lockfile; 01711 } 01712 01713 /** Get the lockfile path */ 01714 const std::string simple_lock::lockfile(void) const 01715 { 01716 return(m_lockfile); 01717 } 01718 01719 /** Get the PID of the locking process */ 01720 const simple_lock::pid_type simple_lock::locked_by(void) const 01721 { 01722 simple_lock::pid_type pid; 01723 std::ifstream in; 01724 01725 pid = 0; 01726 if (m_lockfile.size() == 0) return(0); 01727 if (!exists(m_lockfile)) return(0); 01728 in.open(m_lockfile.c_str()); 01729 if (!in.is_open()) return(0); 01730 in >> pid; 01731 if (!in) { 01732 in.close(); 01733 return(0); 01734 } 01735 return(pid); 01736 } 01737 01738 /** Find out whether or not the lock is in place */ 01739 const bool simple_lock::is_locked(void) const 01740 { 01741 simple_lock::pid_type pid; 01742 01743 pid = locked_by(); 01744 if (pid == 0) return(false); 01745 if (pid == getpid()) return(true); 01746 if (kill(pid,0) >= 0) return(true); 01747 errno = 0; 01748 return(false); 01749 } 01750 01751 /** Lock */ 01752 bool simple_lock::lock(void) 01753 { 01754 std::ofstream out; 01755 simple_lock::pid_type pid; 01756 01757 if (is_locked()) return(false); 01758 if (m_lockfile.size() == 0) return(false); 01759 out.open(m_lockfile.c_str()); 01760 if (!out.is_open()) return(false); 01761 pid = getpid(); 01762 out << pid << std::endl; 01763 if (!out) { 01764 clear(); 01765 return(false); 01766 } 01767 out.close(); 01768 return(true); 01769 } 01770 01771 /** Unlock */ 01772 void simple_lock::unlock(void) 01773 { 01774 std::string es; 01775 01776 if (m_lockfile.size() == 0) return; 01777 if (!exists(m_lockfile)) return; 01778 TRY_nomem(es = "Cannot unlock: \""); 01779 TRY_nomem(es += m_lockfile); 01780 TRY_nomem(es += "\""); 01781 TRY(rm_file(m_lockfile),es); 01782 } 01783 01784 //---------------------------------------------------------------------------- 01785