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 (rename(a_from.c_str(), a_to.c_str()) != 0) {
00738                 TRY_nomem(es = "Could not rename file: \"");
00739                 TRY_nomem(es += a_from);
00740                 TRY_nomem(es += "\" to \"");
00741                 TRY_nomem(es += a_to);
00742                 TRY_nomem(es += "\"");
00743                 throw(ERROR(errno,es));
00744         }
00745 }
00746 
00747 /** Create a symbolic link */
00748 void mk_symlink(const std::string a_from, const std::string a_to)
00749 {
00750         if (symlink(a_from.c_str(), a_to.c_str()) != 0) {
00751                 std::string es;
00752 
00753                 TRY_nomem(es = "Could not link: \"");
00754                 TRY_nomem(es += a_from);
00755                 TRY_nomem(es += "\" to: \"");
00756                 TRY_nomem(es += a_to);
00757                 TRY_nomem(es += "\"");
00758 
00759                 throw(ERROR(errno,es));
00760         }
00761 }
00762 
00763 /** Given a from and to path, create a relative symbolic link */
00764 void mk_relative_symlink(const std::string a_from, const std::string a_to)
00765 {
00766         std::string from_dirname, to_dirname, from_basename;
00767         std::string rel;
00768 
00769         TRY_nomem(from_dirname = path_dirname(a_from));
00770         TRY_nomem(to_dirname = path_dirname(a_to));
00771         TRY_nomem(from_basename = path_basename(a_from));
00772         TRY_nomem(rel = mk_relative_path(from_dirname, to_dirname));
00773         if (rel.size() != 0) {
00774                 TRY_nomem(rel += "/");
00775         }
00776         TRY_nomem(rel += from_basename);
00777         TRY_nomem(rel = reform_path(rel));
00778 
00779         try {
00780                 mk_symlink(rel,a_to);
00781         }
00782         catch(error e) {
00783                 std::string es;
00784 
00785                 TRY_nomem(es = "Could not link: \"");
00786                 TRY_nomem(es += a_to);
00787                 TRY_nomem(es += "\" as: \"");
00788                 TRY_nomem(es += rel);
00789                 TRY_nomem(es += "\"");
00790 
00791                 e.push_back(ERROR_INSTANCE(es));
00792                 throw(e);
00793         }
00794         catch(...) {
00795                 throw(err_unknown);
00796         }
00797 }
00798 
00799 //----------------------------------------------------------------------------
00800 
00801 /** C'tor */
00802 filestatus::filestatus()
00803 {
00804 }
00805 
00806 /** C'tor */
00807 filestatus::filestatus(const std::string a_path)
00808 {
00809         path(a_path);
00810 }
00811 
00812 /** D'tor */
00813 filestatus::~filestatus()
00814 {
00815 }
00816 
00817 /** Retrieve information about a pathname */
00818 void filestatus::path(const std::string a_path)
00819 {
00820         std::string es;
00821         struct passwd *passwd_ptr = 0;
00822         struct group *group_ptr = 0;
00823         struct stat statbuf;
00824         char path_buf[PATH_MAX] = { 0 };
00825 
00826         clear();
00827         TRY_nomem(m_path = reform_path(a_path));
00828         if (lstat(m_path.c_str(), &statbuf) < 0) {
00829                 TRY_nomem(es = "For path: \"");
00830                 TRY_nomem(es += a_path);
00831                 TRY_nomem(es += "\"");
00832                 throw(ERROR(errno,es));
00833         }
00834         if (lstat(m_path.c_str(), &m_stat) == -1) {
00835                 TRY_nomem(es = "For path: \"");
00836                 TRY_nomem(es += a_path);
00837                 TRY_nomem(es += "\"");
00838                 throw(ERROR(errno,es));
00839         }
00840 #ifdef S_ISFIFO
00841         if (S_ISFIFO(m_stat.st_mode)) {
00842                 m_major = major(m_stat.st_rdev);
00843                 m_minor = minor(m_stat.st_rdev);
00844         }
00845 #endif
00846 #ifdef S_ISCHR
00847         if (S_ISCHR(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_ISBLK
00853         if (S_ISBLK(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_ISLNK
00859         if (S_ISLNK(m_stat.st_mode)) {
00860                 if (readlink(a_path.c_str(), path_buf, PATH_MAX) < 0) {
00861                         TRY_nomem(es = "Could not read path's link: \"");
00862                         TRY_nomem(es += a_path);
00863                         TRY_nomem(es += "\"");
00864                         throw(ERROR(errno,es));
00865                 }
00866                 TRY_nomem(m_link = path_buf);
00867         }
00868 #endif
00869         passwd_ptr = getpwuid(m_stat.st_uid);
00870         if (passwd_ptr != 0) {
00871                 m_uidfound = true;
00872                 TRY_nomem(m_uname = passwd_ptr->pw_name);
00873         }
00874         group_ptr = getgrgid(m_stat.st_gid);
00875         if (group_ptr != 0) {
00876                 m_gidfound = true;
00877                 TRY_nomem(m_gname = group_ptr->gr_name);
00878         }
00879 }
00880 
00881 /** Return the pathname that this filestatus object has information about */
00882 const std::string filestatus::path(void) const
00883 {
00884         return(m_path);
00885 }
00886 
00887 /** Return the type of file */
00888 const filestatus::filetype filestatus::type(void) const
00889 {
00890 #ifdef S_ISFIFO
00891         if (S_ISFIFO(m_stat.st_mode)) {
00892                 return(type_fifo_special);
00893         }
00894 #endif
00895 #ifdef S_ISCHR
00896         if (S_ISCHR(m_stat.st_mode)) {
00897                 return(type_character_special);
00898         }
00899 #endif
00900 #ifdef S_ISDIR
00901         if (S_ISDIR(m_stat.st_mode)) {
00902                 return(type_directory);
00903         }
00904 #endif
00905 #ifdef S_ISBLK
00906         if (S_ISBLK(m_stat.st_mode)) {
00907                 return(type_block_special);
00908         }
00909 #endif
00910 #ifdef S_ISREG
00911         if (S_ISREG(m_stat.st_mode)) {
00912                 return(type_regular_file);
00913         }
00914 #endif
00915 #ifdef S_ISLNK
00916         if (S_ISLNK(m_stat.st_mode)) {
00917                 return(type_link);
00918         }
00919 #endif
00920 #ifdef S_ISSOCK
00921         if (S_ISSOCK(m_stat.st_mode)) {
00922                 return(type_socket);
00923         }
00924 #endif
00925 #ifdef S_ISDOOR
00926         if (S_ISDOOR(m_stat.st_mode)) {
00927                 return(type_door);
00928         }
00929 #endif
00930         return(type_unknown);
00931 }
00932 
00933 /** If the pathname is a link, return the path it is linked to */
00934 const std::string filestatus::link(void) const
00935 {
00936         return(m_link);
00937 }
00938 
00939 /** Return the file mode */
00940 const filestatus::mode_type filestatus::mode(void) const
00941 {
00942         return(m_stat.st_mode);
00943 }
00944 
00945 /** Return the file inode */
00946 const filestatus::inode_type filestatus::inode(void) const
00947 {
00948         return(m_stat.st_ino);
00949 }
00950 
00951 /** Return the file's device */
00952 const filestatus::device_type filestatus::dev(void) const
00953 {
00954         return(m_stat.st_dev);
00955 }
00956 
00957 /** Return the file's raw device */
00958 const filestatus::device_type filestatus::rdev(void) const
00959 {
00960         return(m_stat.st_rdev);
00961 }
00962 
00963 /** If the pathname is a special file, return it's major number */
00964 const filestatus::major_type filestatus::get_major(void) const
00965 {
00966         return(m_major);
00967 }
00968 
00969 /** If the pathname is a special file, return it's minor number */
00970 const filestatus::minor_type filestatus::get_minor(void) const
00971 {
00972         return(m_minor);
00973 }
00974 
00975 /** Return the number of links to this file */
00976 const filestatus::num_links_type filestatus::num_links(void) const
00977 {
00978         return(m_stat.st_nlink);
00979 }
00980 
00981 /** Return the file's owner's UID */
00982 const filestatus::uid_type filestatus::uid(void) const
00983 {
00984         return(m_stat.st_uid);
00985 }
00986 
00987 /** Return the file's owner's GID */
00988 const filestatus::gid_type filestatus::gid(void) const
00989 {
00990         return(m_stat.st_gid);
00991 }
00992 
00993 /** Return the file size in bytes */
00994 const filestatus::size_type filestatus::size(void) const
00995 {
00996         size_type value;
00997 
00998         value = static_cast<uint64>(m_stat.st_size);
00999 
01000         return(value);
01001 }
01002 
01003 /** Return the last access time of this file */
01004 const filestatus::time_type filestatus::last_access_time(void) const
01005 {
01006         return(m_stat.st_atime);
01007 }
01008 
01009 /** Return the last modification time of this file */
01010 const filestatus::time_type filestatus::last_modification_time(void) const
01011 {
01012         return(m_stat.st_mtime);
01013 }
01014 
01015 /** Return the last status change time of this file */
01016 const filestatus::time_type filestatus::last_status_change_time(void) const
01017 {
01018         return(m_stat.st_ctime);
01019 }
01020 
01021 /** Return the blocksize used to store this file */
01022 const filestatus::size_type filestatus::blocksize(void) const
01023 {
01024         size_type value;
01025 
01026         value = static_cast<uint64>(m_stat.st_blksize);
01027 
01028         return(value);
01029 }
01030 
01031 /** Return the number of blocks used to store this file */
01032 const filestatus::size_type filestatus::blocks(void) const
01033 {
01034         size_type value;
01035 
01036         value = static_cast<uint64>(m_stat.st_blocks);
01037 
01038         return(value);
01039 }
01040 
01041 /** If the file's owner's UID is found in the passwd file, return true */
01042 const bool filestatus::uid_is_found(void) const
01043 {
01044         return(m_uidfound);
01045 }
01046 
01047 /** If the file's owner's GID is found in the passwd file, return true */
01048 const bool filestatus::gid_is_found(void) const
01049 {
01050         return(m_gidfound);
01051 }
01052 
01053 /** Return the file's owner's user name (from UID) */
01054 const std::string filestatus::uid_name(void) const
01055 {
01056         return(m_uname);
01057 }
01058 
01059 /** Return the file's owner's group name (from UID) */
01060 const std::string filestatus::gid_name(void) const
01061 {
01062         return(m_gname);
01063 }
01064 
01065 #ifdef S_ISFIFO
01066 /** Return true if the file is a fifo-special */
01067 const bool filestatus::is_fifo_special(void) const
01068 {
01069         bool value;
01070 
01071         value = (type() == type_fifo_special);
01072 
01073         return(value);
01074 }
01075 #endif
01076 
01077 #ifdef S_ISCHR
01078 /** Return true if the file is a char-special */
01079 const bool filestatus::is_character_special(void) const
01080 {
01081         bool value;
01082 
01083         value = (type() == type_character_special);
01084 
01085         return(value);
01086 }
01087 #endif
01088 
01089 #ifdef S_ISBLK
01090 /** Return true if the file is a block-special */
01091 const bool filestatus::is_block_special(void) const
01092 {
01093         bool value;
01094 
01095         value = (type() == type_block_special);
01096 
01097         return(value);
01098 }
01099 #endif
01100 
01101 #ifdef S_ISLNK
01102 /** Return true if the file is a link */
01103 const bool filestatus::is_link(void) const
01104 {
01105         bool value;
01106 
01107         value = (type() == type_link);
01108 
01109         return(value);
01110 }
01111 #endif
01112 
01113 #ifdef S_ISSOCK
01114 /** Return true if the file is a socket */
01115 const bool filestatus::is_socket(void) const
01116 {
01117         bool value;
01118 
01119         value = (type() == type_socket);
01120 
01121         return(value);
01122 }
01123 #endif
01124 
01125 #ifdef S_ISDOOR
01126 /** Return true if the file is a door */
01127 const bool filestatus::is_door(void) const
01128 {
01129         bool value;
01130 
01131         value = (type() == type_door);
01132 
01133         return(value);
01134 }
01135 #endif
01136 
01137 #ifdef S_ISDIR
01138 /** Return true if the file is a directory */
01139 const bool filestatus::is_directory(void) const
01140 {
01141         bool value;
01142 
01143         value = (type() == type_directory);
01144 
01145         return(value);
01146 }
01147 #endif
01148 
01149 #ifdef S_ISREG
01150 /** Return true if the file is a regular file */
01151 const bool filestatus::is_regular_file(void) const
01152 {
01153         bool value;
01154 
01155         value = (type() == type_regular_file);
01156 
01157         return(value);
01158 }
01159 #endif
01160 
01161 #ifdef S_IRUSR
01162 /** Return true if the file is readable by it's owner */
01163 const bool filestatus::user_can_read(void) const
01164 {
01165         bool value;
01166 
01167         value = ((m_stat.st_mode & S_IRUSR) != 0);
01168 
01169         return(value);
01170 }
01171 #endif
01172 
01173 #ifdef S_IWUSR
01174 /** Return true if the file is writable by it's owner */
01175 const bool filestatus::user_can_write(void) const
01176 {
01177         bool value;
01178 
01179         value = ((m_stat.st_mode & S_IWUSR) != 0);
01180 
01181         return(value);
01182 }
01183 #endif
01184 
01185 #ifdef S_IXUSR
01186 /** Return true if the file is executable by it's owner */
01187 const bool filestatus::user_can_execute(void) const
01188 {
01189         bool value;
01190 
01191         value = ((m_stat.st_mode & S_IXUSR) != 0);
01192 
01193         return(value);
01194 }
01195 #endif
01196 
01197 #ifdef S_IRGRP
01198 /** Return true if the file is readable by users in the same group */
01199 const bool filestatus::group_can_read(void) const
01200 {
01201         bool value;
01202 
01203         value = ((m_stat.st_mode & S_IRGRP) != 0);
01204 
01205         return(value);
01206 }
01207 #endif
01208 
01209 #ifdef S_IWGRP
01210 /** Return true if the file is writable by users in the same group */
01211 const bool filestatus::group_can_write(void) const
01212 {
01213         bool value;
01214         
01215         value = ((m_stat.st_mode & S_IWGRP) != 0);
01216 
01217         return(value);
01218 }
01219 #endif
01220 
01221 #ifdef S_IXGRP
01222 /** Return true if the file is executable by users in the same group */
01223 const bool filestatus::group_can_execute(void) const
01224 {
01225         bool value;
01226 
01227         value = ((m_stat.st_mode & S_IXGRP) != 0);
01228 
01229         return(value);
01230 }
01231 #endif
01232 
01233 #ifdef S_IROTH
01234 /** Return true if the file is readable by others */
01235 const bool filestatus::other_can_read(void) const
01236 {
01237         bool value;
01238 
01239         value = ((m_stat.st_mode & S_IROTH) != 0);
01240 
01241         return(value);
01242 }
01243 #endif
01244 
01245 #ifdef S_IWOTH
01246 /** Return true if the file is writable by others */
01247 const bool filestatus::other_can_write(void) const
01248 {
01249         bool value;
01250 
01251         value = ((m_stat.st_mode & S_IWOTH) != 0);
01252 
01253         return(value);
01254 }
01255 #endif
01256 
01257 #ifdef S_IXOTH
01258 /** Return true if the file is executable by others */
01259 const bool filestatus::other_can_execute(void) const
01260 {
01261         bool value;
01262 
01263         value = ((m_stat.st_mode & S_IXOTH) != 0);
01264 
01265         return(value);
01266 }
01267 #endif
01268 
01269 #ifdef S_ISUID
01270 /** Return true if the file's mode has it's set-uid bit set */
01271 const bool filestatus::is_set_uid(void) const
01272 {
01273         bool value;
01274 
01275         value = ((m_stat.st_mode & S_ISUID) != 0);
01276 
01277         return(value);
01278 }
01279 #endif
01280 
01281 #ifdef S_ISGID
01282 /** Return true if the file's mode has it's set-gid bit set */
01283 const bool filestatus::is_set_gid(void) const
01284 {
01285         bool value;
01286 
01287         value = ((m_stat.st_mode & S_ISGID) != 0);
01288 
01289         return(value);
01290 }
01291 #endif
01292 
01293 #ifdef S_ISVTX
01294 /** Return true if the file's mode has it's sticky bit set */
01295 const bool filestatus::is_set_sticky(void) const
01296 {
01297         bool value;
01298 
01299         value = ((m_stat.st_mode & S_ISVTX) != 0);
01300 
01301         return(value);
01302 }
01303 #endif
01304 
01305 /** Clear all values */
01306 void filestatus::clear(void)
01307 {
01308         TRY_nomem(m_path = "");
01309         memset(&m_stat, 0, sizeof(m_stat));
01310         m_major = 0;
01311         m_minor = 0;
01312         m_uidfound = false;
01313         m_gidfound = false;
01314         TRY_nomem(m_uname = "");
01315         TRY_nomem(m_gname = "");
01316 }
01317 
01318 //----------------------------------------------------------------------------
01319 
01320 /** C'tor */
01321 subdirectory::subdirectory()
01322 {
01323 }
01324 
01325 /** C'tor */
01326 subdirectory::subdirectory(const subdirectory& a_class)
01327 {
01328         assign(a_class);
01329 }
01330 
01331 /** C'or */
01332 subdirectory::subdirectory(
01333         const std::string a_path, const std::string a_filter)
01334 {
01335         path(a_path, a_filter);
01336 }
01337 
01338 /** D'tor */
01339 subdirectory::~subdirectory()
01340 {
01341 }
01342 
01343 /** Assign the contents of a given subdirectory to this subdirectory */
01344 void subdirectory::assign(const subdirectory& a_class)
01345 {
01346         type::assign(a_class.begin(), a_class.end());
01347 }
01348 
01349 /** Return a vector of strings of a list of files in a subdirectory
01350 
01351         Files in the list do not contain the pathname to the file.  Only filenames
01352         that match the given wildcard filter will be listed.
01353  */
01354 const subdirectory::type& 
01355         subdirectory::path(const std::string a_path, const std::string a_filter)
01356 {
01357         std::string es;
01358         std::string name;
01359         DIR *dp = 0;
01360         struct dirent *dirp = 0;
01361         filestatus filestat;
01362 
01363         clear();
01364 
01365         TRY(filestat.path(a_path),"Could not stat directory");
01366 
01367         dp = opendir(a_path.c_str());
01368         if (dp == 0) {
01369                 TRY_nomem(es = "For path: \"");
01370                 TRY_nomem(es += a_path);
01371                 TRY_nomem(es += "\"");
01372                 throw(ERROR(errno,es));
01373         }
01374         while ( (dirp = readdir(dp)) != 0 ) {
01375                 name = dirp->d_name;
01376                 if (
01377                         ((a_filter != ".") && (a_filter != "..")) 
01378                         && 
01379                         ((name == ".") || (name == ".."))
01380                         )
01381                         continue;
01382                 if (fnmatch(a_filter.c_str(), name.c_str(), 0) == 0) {
01383                         TRY_nomem(type::push_back(name));
01384                 }
01385         }
01386         if (closedir(dp) < 0) {
01387                 TRY_nomem(es = "Error closing directory \"");
01388                 TRY_nomem(es += a_path);
01389                 TRY_nomem(es += "\"");
01390                 throw(ERROR(errno,es));
01391         }
01392 
01393         std::sort(begin(), end());
01394 
01395         return(*this);
01396 }
01397 
01398 subdirectory& subdirectory::operator=(const subdirectory& a_class)
01399 {
01400         assign(a_class);
01401 
01402         return(*this);
01403 }
01404 
01405 //----------------------------------------------------------------------------
01406 
01407 /** Recursively delete the contents of a directory */
01408 void rm_recursive(const std::string a_path)
01409 {
01410         subdirectory d;
01411         subdirectory::const_iterator di;
01412         filestatus f;
01413         std::string pathstr;
01414         std::string es;
01415 
01416         TRY_nomem(es = "Could not recursively delete: \"");
01417         TRY_nomem(es += a_path);
01418         TRY_nomem(es += "\"");
01419 
01420         if (!exists(a_path)) {
01421                 if (is_link(a_path)) {
01422                         TRY(rm_file(a_path),es);
01423                 }
01424                 return;
01425         }
01426         TRY(f.path(a_path),es);
01427         if (f.is_directory()) {
01428                 TRY(d.path(a_path),es);
01429                 if (d.size() != 0) {
01430         
01431                         for (di = d.begin(); di != d.end(); ++di) {
01432                                 TRY_nomem(
01433                                         pathstr = static_cast<std::string>(a_path)
01434                                                 + static_cast<std::string>("/")
01435                                                 + static_cast<std::string>(*di)
01436                                                 );
01437                                 TRY(f.path(pathstr),es);
01438                                 if (f.is_directory()) {
01439                                         TRY(rm_recursive(pathstr),es);
01440                                 }
01441                                 else {
01442                                         rm_file(pathstr);
01443                                 }
01444                         }
01445                 }
01446                 rm_dir(a_path);
01447         }
01448         else {
01449                 rm_file(a_path);
01450         }
01451 }
01452 
01453 //----------------------------------------------------------------------------
01454 
01455 /** C'tor */
01456 directory::directory()
01457 {
01458 }
01459 
01460 /** C'tor */
01461 directory::directory(const directory& a_class)
01462 {
01463         // TODO: Isn't this supposed to do something!?
01464 }
01465 
01466 /** C'tor */
01467 directory::directory(const std::string& a_str)
01468 {
01469         path(a_str);
01470 }
01471 
01472 /** D'tor */
01473 directory::~directory()
01474 {
01475 }
01476 
01477 /** Retrieve a list of paths that match the wildcard path given */
01478 const directory::type& directory::path(const std::string& a_path)
01479 {
01480         std::string es;
01481         std::string::size_type idx;
01482         std::string path;
01483         std::string subdir_path;
01484         std::string new_subdir_path;
01485         subdirectory subdir;
01486         subdirectory::const_iterator sdi;
01487         filestatus filestat;
01488         const_iterator di;
01489         type list;
01490 
01491         TRY_nomem(path = reform_path(a_path));
01492         if (path.size() == 0) {
01493                 return(*this);
01494         }
01495         
01496         idx = path.find('/');
01497         if (idx != std::string::npos) {
01498                 TRY_nomem(subdir_path = path.substr(0,idx));
01499                 path.erase(0,idx+1);
01500         }
01501         else {
01502                 TRY_nomem(subdir_path = path);
01503                 path.erase();
01504         }
01505         if (subdir_path.size() == 0)
01506                 TRY_nomem(subdir_path = "/");
01507         
01508         if (!exists(subdir_path)) {
01509                 return(*this);
01510         }
01511         TRY_nomem(push_back(subdir_path));
01512 
01513         while (path.size() != 0) {
01514                 idx = path.find('/');
01515                 if (idx != std::string::npos) {
01516                         TRY_nomem(subdir_path = path.substr(0,idx));
01517                         path.erase(0,idx+1);
01518                 }
01519                 else {
01520                         TRY_nomem(subdir_path = path);
01521                         path.erase();
01522                 }
01523                 list.clear();
01524                 for (di = begin(); di != end(); di++) {
01525                         TRY_nomem(list.push_back(*di));
01526                 }
01527                 clear();
01528                 for (di = list.begin(); di != list.end(); di++) {
01529                         filestat.path(*di);
01530                         if (!filestat.is_directory())
01531                                 continue;
01532                         subdir.path(*di, subdir_path);
01533                         for (sdi = subdir.begin(); sdi != subdir.end(); sdi++) {
01534                                 TRY_nomem(new_subdir_path = *di);
01535                                 TRY_nomem(new_subdir_path += "/");
01536                                 TRY_nomem(new_subdir_path += *sdi);
01537                                 TRY_nomem(new_subdir_path = reform_path(new_subdir_path));
01538                                 TRY_nomem(push_back(new_subdir_path));
01539                         }
01540                 }
01541         }
01542         return(*this);
01543 }
01544 
01545 //----------------------------------------------------------------------------
01546 
01547 /** C'tor */
01548 filesystem::filesystem()
01549 {
01550         clear();
01551 }
01552 
01553 /** C'tor */
01554 filesystem::filesystem(const std::string& a_path)
01555 {
01556         clear();
01557         path(a_path);
01558 }
01559 
01560 /** Clear the filesystem object */
01561 void filesystem::clear(void)
01562 {
01563         TRY_nomem(m_path = "");
01564         memset(&m_statfs, 0, sizeof(m_statfs));
01565 }
01566 
01567 /** Retrieve information about the filesystem on which the given path resides */
01568 void filesystem::path(const std::string& a_path)
01569 {
01570         std::string es;
01571 
01572         TRY_nomem(m_path = reform_path(a_path));
01573         if (STATFS(a_path.c_str(), &m_statfs) != 0) {
01574                 TRY_nomem(es = "Could not stat filesystem: \"");
01575                 TRY_nomem(es += a_path);
01576                 TRY_nomem(es += "\"");
01577                 throw(ERROR(errno,es));
01578         }
01579 }
01580 
01581 /** Return the path from which this filesystem information was obtained */
01582 const std::string filesystem::path(void) const
01583 {
01584         return(m_path);
01585 }
01586 
01587 /** Return the filesystem block size */
01588 const filesystem::size_type filesystem::blocksize(void) const
01589 {
01590         size_type value;
01591 
01592         value = static_cast<uint64>(m_statfs.f_bsize);
01593 
01594         return(value);
01595 }
01596 
01597 /** Return the filesystem's total number of blocks */
01598 const filesystem::size_type filesystem::total_blocks(void) const
01599 {
01600         size_type value;
01601 
01602         value = static_cast<uint64>(m_statfs.f_blocks);
01603 
01604         return(value);
01605 }
01606 
01607 /** Return the filesystem's number of free blocks */
01608 const filesystem::size_type filesystem::free_blocks(void) const
01609 {
01610         size_type value;
01611 
01612         value = static_cast<uint64>(m_statfs.f_bfree);
01613 
01614         return(value);
01615 }
01616 
01617 /** Return the filesystem's number of used blocks */
01618 const filesystem::size_type filesystem::used_blocks(void) const
01619 {
01620         size_type value;
01621 
01622         value = total_blocks() - free_blocks();
01623 
01624         return(value);
01625 }
01626 
01627 /** Return the filesystem's total number of inodes, if supported by the
01628         filesystem, otherwise the result is system-dependent, but usually 0.
01629  */
01630 const filesystem::size_type filesystem::total_inodes(void) const
01631 {
01632         size_type value;
01633 
01634         value = static_cast<uint64>(m_statfs.f_files);
01635 
01636         return(value);
01637 }
01638 
01639 /** Return the filesystem's total number of free inodes, if supported by the
01640         filesystem, otherwise the result is system-dependent, but usually 0.
01641  */
01642 const filesystem::size_type filesystem::free_inodes(void) const
01643 {
01644         size_type value;
01645         
01646         value = static_cast<uint64>(m_statfs.f_ffree);
01647 
01648         return(value);
01649 }
01650 
01651 /** Return the filesystem's number of used inodes */
01652 const filesystem::size_type filesystem::used_inodes(void) const
01653 {
01654         size_type value;
01655 
01656         value = total_inodes() - free_inodes();
01657 
01658         return(value);
01659 }
01660 
01661 /** Copy values from another instance */
01662 filesystem& filesystem::operator=(const filesystem& a_class)
01663 {
01664         TRY_nomem(m_path = a_class.m_path);
01665         memcpy(&m_statfs, &a_class.m_statfs, sizeof(m_statfs));
01666         
01667         return(*this);
01668 }
01669 
01670 //----------------------------------------------------------------------------
01671 
01672 /** C'tor */
01673 simple_lock::simple_lock()
01674 {
01675         clear();
01676 }
01677 
01678 /** C'tor */
01679 simple_lock::simple_lock(const std::string& a_lockfile)
01680 {
01681         clear();
01682         lockfile(a_lockfile);
01683 }
01684 
01685 /** D'tor */
01686 simple_lock::~simple_lock()
01687 {
01688         clear();
01689 }
01690 
01691 /** Clear the simple_lock object */
01692 void simple_lock::clear(void)
01693 {
01694         if (is_locked() && (locked_by() == getpid())) {
01695                 unlock();
01696         }
01697         m_lockfile.clear();
01698 }
01699 
01700 /** Set the lockfile path */
01701 void simple_lock::lockfile(const std::string& a_lockfile)
01702 {
01703         clear();
01704         m_lockfile = a_lockfile;
01705 }
01706 
01707 /** Get the lockfile path */
01708 const std::string simple_lock::lockfile(void) const
01709 {
01710         return(m_lockfile);
01711 }
01712 
01713 /** Get the PID of the locking process */
01714 const simple_lock::pid_type simple_lock::locked_by(void) const
01715 {
01716         simple_lock::pid_type pid;
01717         std::ifstream in;
01718 
01719         pid = 0;
01720         if (m_lockfile.size() == 0) return(0);
01721         if (!exists(m_lockfile)) return(0);
01722         in.open(m_lockfile.c_str());
01723         if (!in.is_open()) return(0);
01724         in >> pid;
01725         if (!in) {
01726                 in.close();
01727                 return(0);
01728         }
01729         return(pid);
01730 }
01731 
01732 /** Find out whether or not the lock is in place */
01733 const bool simple_lock::is_locked(void) const
01734 {
01735         simple_lock::pid_type pid;
01736 
01737         pid = locked_by();
01738         if (pid == 0) return(false);
01739         if (pid == getpid()) return(true);
01740         if (kill(pid,0) >= 0) return(true);
01741         errno = 0;
01742         return(false);
01743 }
01744 
01745 /** Lock */
01746 bool simple_lock::lock(void)
01747 {
01748         std::ofstream out;
01749         simple_lock::pid_type pid;
01750 
01751         if (is_locked()) return(false);
01752         if (m_lockfile.size() == 0) return(false);
01753         out.open(m_lockfile.c_str());
01754         if (!out.is_open()) return(false);
01755         pid = getpid();
01756         out << pid << std::endl;
01757         if (!out) {
01758                 clear();
01759                 return(false);
01760         }
01761         out.close();
01762         return(true);
01763 }
01764 
01765 /** Unlock */
01766 void simple_lock::unlock(void)
01767 {
01768         std::string es;
01769 
01770         if (m_lockfile.size() == 0) return;
01771         if (!exists(m_lockfile)) return;
01772         TRY_nomem(es = "Cannot unlock: \"");
01773         TRY_nomem(es += m_lockfile);
01774         TRY_nomem(es += "\"");
01775         TRY(rm_file(m_lockfile),es);
01776 }
01777 
01778 //----------------------------------------------------------------------------
01779 

Generated on Fri Jun 23 16:46:30 2006 for rvm by  doxygen 1.4.2