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
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
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
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
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
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
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
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
00222
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
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
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
00281
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
00313
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
00385 bool exists(const std::string& a_path)
00386 {
00387 if (access(a_path.c_str(), F_OK) != 0) {
00388 errno = 0;
00389 return(false);
00390 }
00391 return(true);
00392 }
00393
00394
00395 bool readable(const std::string& a_path)
00396 {
00397 if (access(a_path.c_str(), R_OK) != 0) {
00398 errno = 0;
00399 return(false);
00400 }
00401 return(true);
00402 }
00403
00404
00405 bool writable(const std::string& a_path)
00406 {
00407 if (access(a_path.c_str(), W_OK) != 0) {
00408 errno = 0;
00409 return(false);
00410 }
00411 return(true);
00412 }
00413
00414
00415 bool executable(const std::string& a_path)
00416 {
00417 if (access(a_path.c_str(), X_OK) != 0) {
00418 errno = 0;
00419 return(false);
00420 }
00421 return(true);
00422 }
00423
00424 #ifdef S_ISFIFO
00425
00426 bool is_fifo_special(const std::string& a_path)
00427 {
00428 filestatus fstat;
00429
00430 try {
00431 fstat.path(a_path);
00432 if (fstat.is_fifo_special()) {
00433 return(true);
00434 }
00435 }
00436 catch(...) {
00437 return(false);
00438 }
00439 return(false);
00440 }
00441 #endif
00442
00443 #ifdef S_ISCHR
00444
00445 bool is_char_special(const std::string& a_path)
00446 {
00447 filestatus fstat;
00448
00449 try {
00450 fstat.path(a_path);
00451 if (fstat.is_character_special()) {
00452 return(true);
00453 }
00454 }
00455 catch(...) {
00456 return(false);
00457 }
00458 return(false);
00459 }
00460 #endif
00461
00462 #ifdef S_ISDIR
00463
00464 bool is_dir(const std::string& a_path)
00465 {
00466 filestatus fstat;
00467
00468 try {
00469 fstat.path(a_path);
00470 if (fstat.is_directory()) {
00471 return(true);
00472 }
00473 }
00474 catch(...) {
00475 return(false);
00476 }
00477 return(false);
00478 }
00479 #endif
00480
00481 #ifdef S_ISREG
00482
00483 bool is_file(const std::string& a_path)
00484 {
00485 filestatus fstat;
00486
00487 try {
00488 fstat.path(a_path);
00489 if (fstat.is_regular_file()) {
00490 return(true);
00491 }
00492 }
00493 catch(...) {
00494 return(false);
00495 }
00496 return(false);
00497 }
00498 #endif
00499
00500 #ifdef S_ISBLK
00501
00502 bool is_block_special(const std::string& a_path)
00503 {
00504 filestatus fstat;
00505
00506 try {
00507 fstat.path(a_path);
00508 if (fstat.is_block_special()) {
00509 return(true);
00510 }
00511 }
00512 catch(...) {
00513 return(false);
00514 }
00515 return(false);
00516 }
00517 #endif
00518
00519 #ifdef S_ISLNK
00520
00521 bool is_link(const std::string& a_path)
00522 {
00523 filestatus fstat;
00524
00525 try {
00526 fstat.path(a_path);
00527 if (fstat.is_link()) {
00528 return(true);
00529 }
00530 }
00531 catch(...) {
00532 return(false);
00533 }
00534 return(false);
00535 }
00536 #endif
00537
00538 #ifdef S_ISSOCK
00539
00540 bool is_socket(const std::string& a_path)
00541 {
00542 filestatus fstat;
00543
00544 try {
00545 fstat.path(a_path);
00546 if (fstat.is_socket()) {
00547 return(true);
00548 }
00549 }
00550 catch(...) {
00551 return(false);
00552 }
00553 return(false);
00554 }
00555 #endif
00556
00557 #ifdef S_ISDOOR
00558
00559 bool is_door(const std::string& a_path)
00560 {
00561 filestatus fstat;
00562
00563 try {
00564 fstat.path(a_path);
00565 if (fstat.is_door()) {
00566 return(true);
00567 }
00568 }
00569 catch(...) {
00570 return(false);
00571 }
00572 return(false);
00573 }
00574 #endif
00575
00576
00577 void mk_dir(const std::string& a_path)
00578 {
00579 std::string es;
00580
00581 if (mkdir(a_path.c_str(), ACCESSPERMS) != 0) {
00582 TRY_nomem(es = "Could not create directory: \"");
00583 TRY_nomem(es += a_path);
00584 TRY_nomem(es += "\"");
00585 throw(ERROR(errno,es));
00586 }
00587 }
00588
00589
00590 void rm_dir(const std::string a_path)
00591 {
00592 if (rmdir(a_path.c_str()) != 0) {
00593 std::string es;
00594
00595 TRY_nomem(es = "Could not remove directory: \"");
00596 TRY_nomem(es += a_path);
00597 TRY_nomem(es += "\"");
00598
00599 throw(ERROR(errno,es));
00600 }
00601 }
00602
00603
00604 void rm_file(const std::string a_path)
00605 {
00606 if (unlink(a_path.c_str()) != 0) {
00607 std::string es;
00608
00609 TRY_nomem(es = "Could not remove file: \"");
00610 TRY_nomem(es += a_path);
00611 TRY_nomem(es += "\"");
00612
00613 throw(ERROR(errno,es));
00614 }
00615 }
00616
00617
00618 void mk_dirhier_recursive_(const std::string a_path)
00619 {
00620 std::string parent_dir;
00621 int ce;
00622
00623 if (a_path.size() == 0)
00624 return;
00625 if (exists(a_path))
00626 return;
00627
00628 for (ce = a_path.size()-1; ((ce > 0) && (a_path[ce] != '/')); ce--);
00629
00630 if (ce > 0) {
00631 TRY_nomem(parent_dir = a_path.substr(0,ce));
00632 mk_dirhier_recursive_(parent_dir);
00633 }
00634 if (!exists(a_path))
00635 mk_dir(a_path);
00636 }
00637
00638
00639 void mk_dirhier(const std::string a_path)
00640 {
00641 if (a_path.size() == 0)
00642 return;
00643 if (exists(a_path))
00644 return;
00645
00646 try {
00647 mk_dirhier_recursive_(a_path);
00648 }
00649 catch(error e) {
00650 std::string es;
00651
00652 TRY_nomem(es = "Could not create directory hierarchy: \"");
00653 TRY_nomem(es += a_path);
00654 TRY_nomem(es += "\"");
00655
00656 e.push_back(ERROR_INSTANCE(es));
00657 throw(e);
00658 }
00659 catch(...) {
00660 throw(err_unknown);
00661 }
00662 }
00663
00664
00665 void rename_file(const std::string a_from, const std::string a_to)
00666 {
00667 std::string es;
00668
00669 if (a_from.size() == 0) {
00670 TRY_nomem(es = "Illegal from filename: \"");
00671 TRY_nomem(es += a_from);
00672 TRY_nomem(es += "\"");
00673 throw(INTERNAL_ERROR(0,es));
00674 }
00675 if (!exists(a_from)) {
00676 TRY_nomem(es = "From filename does not exist: \"");
00677 TRY_nomem(es += a_from);
00678 TRY_nomem(es += "\"");
00679 throw(ERROR(0,es));
00680 }
00681 if (a_to.size() == 0) {
00682 TRY_nomem(es = "Illegal to filename: \"");
00683 TRY_nomem(es += a_to);
00684 TRY_nomem(es += "\"");
00685 throw(INTERNAL_ERROR(0,es));
00686 }
00687 if (exists(a_to)) {
00688 TRY_nomem(es = "To filename already exists: \"");
00689 TRY_nomem(es += a_to);
00690 TRY_nomem(es += "\"");
00691 throw(ERROR(0,es));
00692 }
00693 if (rename(a_from.c_str(), a_to.c_str()) != 0) {
00694 TRY_nomem(es = "Could not rename file: \"");
00695 TRY_nomem(es += a_from);
00696 TRY_nomem(es += "\" to \"");
00697 TRY_nomem(es += a_to);
00698 TRY_nomem(es += "\"");
00699 throw(ERROR(errno,es));
00700 }
00701 }
00702
00703
00704 void mk_symlink(const std::string a_from, const std::string a_to)
00705 {
00706 if (symlink(a_from.c_str(), a_to.c_str()) != 0) {
00707 std::string es;
00708
00709 TRY_nomem(es = "Could not link: \"");
00710 TRY_nomem(es += a_from);
00711 TRY_nomem(es += "\" to: \"");
00712 TRY_nomem(es += a_to);
00713 TRY_nomem(es += "\"");
00714
00715 throw(ERROR(errno,es));
00716 }
00717 }
00718
00719
00720 void mk_relative_symlink(const std::string a_from, const std::string a_to)
00721 {
00722 std::string from_dirname, to_dirname, from_basename;
00723 std::string rel;
00724
00725 TRY_nomem(from_dirname = path_dirname(a_from));
00726 TRY_nomem(to_dirname = path_dirname(a_to));
00727 TRY_nomem(from_basename = path_basename(a_from));
00728 TRY_nomem(rel = mk_relative_path(from_dirname, to_dirname));
00729 if (rel.size() != 0) {
00730 TRY_nomem(rel += "/");
00731 }
00732 TRY_nomem(rel += from_basename);
00733 TRY_nomem(rel = reform_path(rel));
00734
00735 try {
00736 mk_symlink(rel,a_to);
00737 }
00738 catch(error e) {
00739 std::string es;
00740
00741 TRY_nomem(es = "Could not link: \"");
00742 TRY_nomem(es += a_to);
00743 TRY_nomem(es += "\" as: \"");
00744 TRY_nomem(es += rel);
00745 TRY_nomem(es += "\"");
00746
00747 e.push_back(ERROR_INSTANCE(es));
00748 throw(e);
00749 }
00750 catch(...) {
00751 throw(err_unknown);
00752 }
00753 }
00754
00755
00756
00757
00758 filestatus::filestatus()
00759 {
00760 }
00761
00762
00763 filestatus::filestatus(const std::string a_path)
00764 {
00765 path(a_path);
00766 }
00767
00768
00769 filestatus::~filestatus()
00770 {
00771 }
00772
00773
00774 void filestatus::path(const std::string a_path)
00775 {
00776 std::string es;
00777 struct passwd *passwd_ptr = 0;
00778 struct group *group_ptr = 0;
00779 struct stat statbuf;
00780 char path_buf[PATH_MAX] = { 0 };
00781
00782 clear();
00783 TRY_nomem(m_path = reform_path(a_path));
00784 if (lstat(m_path.c_str(), &statbuf) < 0) {
00785 TRY_nomem(es = "For path: \"");
00786 TRY_nomem(es += a_path);
00787 TRY_nomem(es += "\"");
00788 throw(ERROR(errno,es));
00789 }
00790 if (lstat(m_path.c_str(), &m_stat) == -1) {
00791 TRY_nomem(es = "For path: \"");
00792 TRY_nomem(es += a_path);
00793 TRY_nomem(es += "\"");
00794 throw(ERROR(errno,es));
00795 }
00796 #ifdef S_ISFIFO
00797 if (S_ISFIFO(m_stat.st_mode)) {
00798 m_major = major(m_stat.st_rdev);
00799 m_minor = minor(m_stat.st_rdev);
00800 }
00801 #endif
00802 #ifdef S_ISCHR
00803 if (S_ISCHR(m_stat.st_mode)) {
00804 m_major = major(m_stat.st_rdev);
00805 m_minor = minor(m_stat.st_rdev);
00806 }
00807 #endif
00808 #ifdef S_ISBLK
00809 if (S_ISBLK(m_stat.st_mode)) {
00810 m_major = major(m_stat.st_rdev);
00811 m_minor = minor(m_stat.st_rdev);
00812 }
00813 #endif
00814 #ifdef S_ISLNK
00815 if (S_ISLNK(m_stat.st_mode)) {
00816 if (readlink(a_path.c_str(), path_buf, PATH_MAX) < 0) {
00817 TRY_nomem(es = "Could not read path's link: \"");
00818 TRY_nomem(es += a_path);
00819 TRY_nomem(es += "\"");
00820 throw(ERROR(errno,es));
00821 }
00822 TRY_nomem(m_link = path_buf);
00823 }
00824 #endif
00825 passwd_ptr = getpwuid(m_stat.st_uid);
00826 if (passwd_ptr != 0) {
00827 m_uidfound = true;
00828 TRY_nomem(m_uname = passwd_ptr->pw_name);
00829 }
00830 group_ptr = getgrgid(m_stat.st_gid);
00831 if (group_ptr != 0) {
00832 m_gidfound = true;
00833 TRY_nomem(m_gname = group_ptr->gr_name);
00834 }
00835 }
00836
00837
00838 const std::string filestatus::path(void) const
00839 {
00840 return(m_path);
00841 }
00842
00843
00844 const filestatus::filetype filestatus::type(void) const
00845 {
00846 #ifdef S_ISFIFO
00847 if (S_ISFIFO(m_stat.st_mode)) {
00848 return(type_fifo_special);
00849 }
00850 #endif
00851 #ifdef S_ISCHR
00852 if (S_ISCHR(m_stat.st_mode)) {
00853 return(type_character_special);
00854 }
00855 #endif
00856 #ifdef S_ISDIR
00857 if (S_ISDIR(m_stat.st_mode)) {
00858 return(type_directory);
00859 }
00860 #endif
00861 #ifdef S_ISBLK
00862 if (S_ISBLK(m_stat.st_mode)) {
00863 return(type_block_special);
00864 }
00865 #endif
00866 #ifdef S_ISREG
00867 if (S_ISREG(m_stat.st_mode)) {
00868 return(type_regular_file);
00869 }
00870 #endif
00871 #ifdef S_ISLNK
00872 if (S_ISLNK(m_stat.st_mode)) {
00873 return(type_link);
00874 }
00875 #endif
00876 #ifdef S_ISSOCK
00877 if (S_ISSOCK(m_stat.st_mode)) {
00878 return(type_socket);
00879 }
00880 #endif
00881 #ifdef S_ISDOOR
00882 if (S_ISDOOR(m_stat.st_mode)) {
00883 return(type_door);
00884 }
00885 #endif
00886 return(type_unknown);
00887 }
00888
00889
00890 const std::string filestatus::link(void) const
00891 {
00892 return(m_link);
00893 }
00894
00895
00896 const filestatus::mode_type filestatus::mode(void) const
00897 {
00898 return(m_stat.st_mode);
00899 }
00900
00901
00902 const filestatus::inode_type filestatus::inode(void) const
00903 {
00904 return(m_stat.st_ino);
00905 }
00906
00907
00908 const filestatus::device_type filestatus::dev(void) const
00909 {
00910 return(m_stat.st_dev);
00911 }
00912
00913
00914 const filestatus::device_type filestatus::rdev(void) const
00915 {
00916 return(m_stat.st_rdev);
00917 }
00918
00919
00920 const filestatus::major_type filestatus::get_major(void) const
00921 {
00922 return(m_major);
00923 }
00924
00925
00926 const filestatus::minor_type filestatus::get_minor(void) const
00927 {
00928 return(m_minor);
00929 }
00930
00931
00932 const filestatus::num_links_type filestatus::num_links(void) const
00933 {
00934 return(m_stat.st_nlink);
00935 }
00936
00937
00938 const filestatus::uid_type filestatus::uid(void) const
00939 {
00940 return(m_stat.st_uid);
00941 }
00942
00943
00944 const filestatus::gid_type filestatus::gid(void) const
00945 {
00946 return(m_stat.st_gid);
00947 }
00948
00949
00950 const filestatus::size_type filestatus::size(void) const
00951 {
00952 size_type value;
00953
00954 value = static_cast<uint64>(m_stat.st_size);
00955
00956 return(value);
00957 }
00958
00959
00960 const filestatus::time_type filestatus::last_access_time(void) const
00961 {
00962 return(m_stat.st_atime);
00963 }
00964
00965
00966 const filestatus::time_type filestatus::last_modification_time(void) const
00967 {
00968 return(m_stat.st_mtime);
00969 }
00970
00971
00972 const filestatus::time_type filestatus::last_status_change_time(void) const
00973 {
00974 return(m_stat.st_ctime);
00975 }
00976
00977
00978 const filestatus::size_type filestatus::blocksize(void) const
00979 {
00980 size_type value;
00981
00982 value = static_cast<uint64>(m_stat.st_blksize);
00983
00984 return(value);
00985 }
00986
00987
00988 const filestatus::size_type filestatus::blocks(void) const
00989 {
00990 size_type value;
00991
00992 value = static_cast<uint64>(m_stat.st_blocks);
00993
00994 return(value);
00995 }
00996
00997
00998 const bool filestatus::uid_is_found(void) const
00999 {
01000 return(m_uidfound);
01001 }
01002
01003
01004 const bool filestatus::gid_is_found(void) const
01005 {
01006 return(m_gidfound);
01007 }
01008
01009
01010 const std::string filestatus::uid_name(void) const
01011 {
01012 return(m_uname);
01013 }
01014
01015
01016 const std::string filestatus::gid_name(void) const
01017 {
01018 return(m_gname);
01019 }
01020
01021 #ifdef S_ISFIFO
01022
01023 const bool filestatus::is_fifo_special(void) const
01024 {
01025 bool value;
01026
01027 value = (type() == type_fifo_special);
01028
01029 return(value);
01030 }
01031 #endif
01032
01033 #ifdef S_ISCHR
01034
01035 const bool filestatus::is_character_special(void) const
01036 {
01037 bool value;
01038
01039 value = (type() == type_character_special);
01040
01041 return(value);
01042 }
01043 #endif
01044
01045 #ifdef S_ISBLK
01046
01047 const bool filestatus::is_block_special(void) const
01048 {
01049 bool value;
01050
01051 value = (type() == type_block_special);
01052
01053 return(value);
01054 }
01055 #endif
01056
01057 #ifdef S_ISLNK
01058
01059 const bool filestatus::is_link(void) const
01060 {
01061 bool value;
01062
01063 value = (type() == type_link);
01064
01065 return(value);
01066 }
01067 #endif
01068
01069 #ifdef S_ISSOCK
01070
01071 const bool filestatus::is_socket(void) const
01072 {
01073 bool value;
01074
01075 value = (type() == type_socket);
01076
01077 return(value);
01078 }
01079 #endif
01080
01081 #ifdef S_ISDOOR
01082
01083 const bool filestatus::is_door(void) const
01084 {
01085 bool value;
01086
01087 value = (type() == type_door);
01088
01089 return(value);
01090 }
01091 #endif
01092
01093 #ifdef S_ISDIR
01094
01095 const bool filestatus::is_directory(void) const
01096 {
01097 bool value;
01098
01099 value = (type() == type_directory);
01100
01101 return(value);
01102 }
01103 #endif
01104
01105 #ifdef S_ISREG
01106
01107 const bool filestatus::is_regular_file(void) const
01108 {
01109 bool value;
01110
01111 value = (type() == type_regular_file);
01112
01113 return(value);
01114 }
01115 #endif
01116
01117 #ifdef S_IRUSR
01118
01119 const bool filestatus::user_can_read(void) const
01120 {
01121 bool value;
01122
01123 value = ((m_stat.st_mode & S_IRUSR) != 0);
01124
01125 return(value);
01126 }
01127 #endif
01128
01129 #ifdef S_IWUSR
01130
01131 const bool filestatus::user_can_write(void) const
01132 {
01133 bool value;
01134
01135 value = ((m_stat.st_mode & S_IWUSR) != 0);
01136
01137 return(value);
01138 }
01139 #endif
01140
01141 #ifdef S_IXUSR
01142
01143 const bool filestatus::user_can_execute(void) const
01144 {
01145 bool value;
01146
01147 value = ((m_stat.st_mode & S_IXUSR) != 0);
01148
01149 return(value);
01150 }
01151 #endif
01152
01153 #ifdef S_IRGRP
01154
01155 const bool filestatus::group_can_read(void) const
01156 {
01157 bool value;
01158
01159 value = ((m_stat.st_mode & S_IRGRP) != 0);
01160
01161 return(value);
01162 }
01163 #endif
01164
01165 #ifdef S_IWGRP
01166
01167 const bool filestatus::group_can_write(void) const
01168 {
01169 bool value;
01170
01171 value = ((m_stat.st_mode & S_IWGRP) != 0);
01172
01173 return(value);
01174 }
01175 #endif
01176
01177 #ifdef S_IXGRP
01178
01179 const bool filestatus::group_can_execute(void) const
01180 {
01181 bool value;
01182
01183 value = ((m_stat.st_mode & S_IXGRP) != 0);
01184
01185 return(value);
01186 }
01187 #endif
01188
01189 #ifdef S_IROTH
01190
01191 const bool filestatus::other_can_read(void) const
01192 {
01193 bool value;
01194
01195 value = ((m_stat.st_mode & S_IROTH) != 0);
01196
01197 return(value);
01198 }
01199 #endif
01200
01201 #ifdef S_IWOTH
01202
01203 const bool filestatus::other_can_write(void) const
01204 {
01205 bool value;
01206
01207 value = ((m_stat.st_mode & S_IWOTH) != 0);
01208
01209 return(value);
01210 }
01211 #endif
01212
01213 #ifdef S_IXOTH
01214
01215 const bool filestatus::other_can_execute(void) const
01216 {
01217 bool value;
01218
01219 value = ((m_stat.st_mode & S_IXOTH) != 0);
01220
01221 return(value);
01222 }
01223 #endif
01224
01225 #ifdef S_ISUID
01226
01227 const bool filestatus::is_set_uid(void) const
01228 {
01229 bool value;
01230
01231 value = ((m_stat.st_mode & S_ISUID) != 0);
01232
01233 return(value);
01234 }
01235 #endif
01236
01237 #ifdef S_ISGID
01238
01239 const bool filestatus::is_set_gid(void) const
01240 {
01241 bool value;
01242
01243 value = ((m_stat.st_mode & S_ISGID) != 0);
01244
01245 return(value);
01246 }
01247 #endif
01248
01249 #ifdef S_ISVTX
01250
01251 const bool filestatus::is_set_sticky(void) const
01252 {
01253 bool value;
01254
01255 value = ((m_stat.st_mode & S_ISVTX) != 0);
01256
01257 return(value);
01258 }
01259 #endif
01260
01261
01262 void filestatus::clear(void)
01263 {
01264 TRY_nomem(m_path = "");
01265 memset(&m_stat, 0, sizeof(m_stat));
01266 m_major = 0;
01267 m_minor = 0;
01268 m_uidfound = false;
01269 m_gidfound = false;
01270 TRY_nomem(m_uname = "");
01271 TRY_nomem(m_gname = "");
01272 }
01273
01274
01275
01276
01277 subdirectory::subdirectory()
01278 {
01279 }
01280
01281
01282 subdirectory::subdirectory(const subdirectory& a_class)
01283 {
01284 assign(a_class);
01285 }
01286
01287
01288 subdirectory::subdirectory(
01289 const std::string a_path, const std::string a_filter)
01290 {
01291 path(a_path, a_filter);
01292 }
01293
01294
01295 subdirectory::~subdirectory()
01296 {
01297 }
01298
01299
01300 void subdirectory::assign(const subdirectory& a_class)
01301 {
01302 type::assign(a_class.begin(), a_class.end());
01303 }
01304
01305
01306
01307
01308
01309
01310 const subdirectory::type&
01311 subdirectory::path(const std::string a_path, const std::string a_filter)
01312 {
01313 std::string es;
01314 std::string name;
01315 DIR *dp = 0;
01316 struct dirent *dirp = 0;
01317 filestatus filestat;
01318
01319 clear();
01320
01321 TRY(filestat.path(a_path),"Could not stat directory");
01322
01323 dp = opendir(a_path.c_str());
01324 if (dp == 0) {
01325 TRY_nomem(es = "For path: \"");
01326 TRY_nomem(es += a_path);
01327 TRY_nomem(es += "\"");
01328 throw(ERROR(errno,es));
01329 }
01330 while ( (dirp = readdir(dp)) != 0 ) {
01331 name = dirp->d_name;
01332 if (
01333 ((a_filter != ".") && (a_filter != ".."))
01334 &&
01335 ((name == ".") || (name == ".."))
01336 )
01337 continue;
01338 if (fnmatch(a_filter.c_str(), name.c_str(), 0) == 0) {
01339 TRY_nomem(type::push_back(name));
01340 }
01341 }
01342 if (closedir(dp) < 0) {
01343 TRY_nomem(es = "Error closing directory \"");
01344 TRY_nomem(es += a_path);
01345 TRY_nomem(es += "\"");
01346 throw(ERROR(errno,es));
01347 }
01348
01349 std::sort(begin(), end());
01350
01351 return(*this);
01352 }
01353
01354 subdirectory& subdirectory::operator=(const subdirectory& a_class)
01355 {
01356 assign(a_class);
01357
01358 return(*this);
01359 }
01360
01361
01362
01363
01364 void rm_recursive(const std::string a_path)
01365 {
01366 subdirectory d;
01367 subdirectory::const_iterator di;
01368 filestatus f;
01369 std::string pathstr;
01370 std::string es;
01371
01372 TRY_nomem(es = "Could not recursively delete: \"");
01373 TRY_nomem(es += a_path);
01374 TRY_nomem(es += "\"");
01375
01376 if (!exists(a_path)) {
01377 if (is_link(a_path)) {
01378 TRY(rm_file(a_path),es);
01379 }
01380 return;
01381 }
01382 TRY(f.path(a_path),es);
01383 if (f.is_directory()) {
01384 TRY(d.path(a_path),es);
01385 if (d.size() != 0) {
01386
01387 for (di = d.begin(); di != d.end(); ++di) {
01388 TRY_nomem(
01389 pathstr = std::string(a_path)
01390 + std::string("/")
01391 + std::string(*di)
01392 );
01393 TRY(f.path(pathstr),es);
01394 if (f.is_directory()) {
01395 TRY(rm_recursive(pathstr),es);
01396 }
01397 else {
01398 rm_file(pathstr);
01399 }
01400 }
01401 }
01402 rm_dir(a_path);
01403 }
01404 else {
01405 rm_file(a_path);
01406 }
01407 }
01408
01409
01410
01411
01412 directory::directory()
01413 {
01414 }
01415
01416
01417 directory::directory(const directory& a_class)
01418 {
01419
01420 }
01421
01422
01423 directory::directory(const std::string& a_str)
01424 {
01425 path(a_str);
01426 }
01427
01428
01429 directory::~directory()
01430 {
01431 }
01432
01433
01434 const directory::type& directory::path(const std::string& a_path)
01435 {
01436 std::string es;
01437 std::string::size_type idx;
01438 std::string path;
01439 std::string subdir_path;
01440 std::string new_subdir_path;
01441 subdirectory subdir;
01442 subdirectory::const_iterator sdi;
01443 filestatus filestat;
01444 const_iterator di;
01445 type list;
01446
01447 TRY_nomem(path = reform_path(a_path));
01448 if (path.size() == 0) {
01449 return(*this);
01450 }
01451
01452 idx = path.find('/');
01453 if (idx != std::string::npos) {
01454 TRY_nomem(subdir_path = path.substr(0,idx));
01455 path.erase(0,idx+1);
01456 }
01457 else {
01458 TRY_nomem(subdir_path = path);
01459 path.erase();
01460 }
01461 if (subdir_path.size() == 0)
01462 TRY_nomem(subdir_path = "/");
01463
01464 if (!exists(subdir_path)) {
01465 return(*this);
01466 }
01467 TRY_nomem(push_back(subdir_path));
01468
01469 while (path.size() != 0) {
01470 idx = path.find('/');
01471 if (idx != std::string::npos) {
01472 TRY_nomem(subdir_path = path.substr(0,idx));
01473 path.erase(0,idx+1);
01474 }
01475 else {
01476 TRY_nomem(subdir_path = path);
01477 path.erase();
01478 }
01479 list.clear();
01480 for (di = begin(); di != end(); di++) {
01481 TRY_nomem(list.push_back(*di));
01482 }
01483 clear();
01484 for (di = list.begin(); di != list.end(); di++) {
01485 filestat.path(*di);
01486 if (!filestat.is_directory())
01487 continue;
01488 subdir.path(*di, subdir_path);
01489 for (sdi = subdir.begin(); sdi != subdir.end(); sdi++) {
01490 TRY_nomem(new_subdir_path = *di);
01491 TRY_nomem(new_subdir_path += "/");
01492 TRY_nomem(new_subdir_path += *sdi);
01493 TRY_nomem(new_subdir_path = reform_path(new_subdir_path));
01494 TRY_nomem(push_back(new_subdir_path));
01495 }
01496 }
01497 }
01498 return(*this);
01499 }
01500
01501
01502
01503
01504 filesystem::filesystem()
01505 {
01506 clear();
01507 }
01508
01509
01510 filesystem::filesystem(const std::string& a_path)
01511 {
01512 clear();
01513 path(a_path);
01514 }
01515
01516
01517 void filesystem::clear(void)
01518 {
01519 TRY_nomem(m_path = "");
01520 memset(&m_statfs, 0, sizeof(m_statfs));
01521 }
01522
01523
01524 void filesystem::path(const std::string& a_path)
01525 {
01526 std::string es;
01527
01528 TRY_nomem(m_path = reform_path(a_path));
01529 if (STATFS(a_path.c_str(), &m_statfs) != 0) {
01530 TRY_nomem(es = "Could not stat filesystem: \"");
01531 TRY_nomem(es += a_path);
01532 TRY_nomem(es += "\"");
01533 throw(ERROR(errno,es));
01534 }
01535 }
01536
01537
01538 const std::string filesystem::path(void) const
01539 {
01540 return(m_path);
01541 }
01542
01543
01544 const filesystem::size_type filesystem::blocksize(void) const
01545 {
01546 size_type value;
01547
01548 value = static_cast<uint64>(m_statfs.f_bsize);
01549
01550 return(value);
01551 }
01552
01553
01554 const filesystem::size_type filesystem::total_blocks(void) const
01555 {
01556 size_type value;
01557
01558 value = static_cast<uint64>(m_statfs.f_blocks);
01559
01560 return(value);
01561 }
01562
01563
01564 const filesystem::size_type filesystem::free_blocks(void) const
01565 {
01566 size_type value;
01567
01568 value = static_cast<uint64>(m_statfs.f_bfree);
01569
01570 return(value);
01571 }
01572
01573
01574 const filesystem::size_type filesystem::used_blocks(void) const
01575 {
01576 size_type value;
01577
01578 value = total_blocks() - free_blocks();
01579
01580 return(value);
01581 }
01582
01583
01584
01585
01586 const filesystem::size_type filesystem::total_inodes(void) const
01587 {
01588 size_type value;
01589
01590 value = static_cast<uint64>(m_statfs.f_files);
01591
01592 return(value);
01593 }
01594
01595
01596
01597
01598 const filesystem::size_type filesystem::free_inodes(void) const
01599 {
01600 size_type value;
01601
01602 value = static_cast<uint64>(m_statfs.f_ffree);
01603
01604 return(value);
01605 }
01606
01607
01608 const filesystem::size_type filesystem::used_inodes(void) const
01609 {
01610 size_type value;
01611
01612 value = total_inodes() - free_inodes();
01613
01614 return(value);
01615 }
01616
01617
01618 filesystem& filesystem::operator=(const filesystem& a_class)
01619 {
01620 TRY_nomem(m_path = a_class.m_path);
01621 memcpy(&m_statfs, &a_class.m_statfs, sizeof(m_statfs));
01622
01623 return(*this);
01624 }
01625
01626
01627