rvm 1.08

fs.cc

Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines