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) 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00802 filestatus::filestatus()
00803 {
00804 }
00805
00806
00807 filestatus::filestatus(const std::string a_path)
00808 {
00809 path(a_path);
00810 }
00811
00812
00813 filestatus::~filestatus()
00814 {
00815 }
00816
00817
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
00882 const std::string filestatus::path(void) const
00883 {
00884 return(m_path);
00885 }
00886
00887
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
00934 const std::string filestatus::link(void) const
00935 {
00936 return(m_link);
00937 }
00938
00939
00940 const filestatus::mode_type filestatus::mode(void) const
00941 {
00942 return(m_stat.st_mode);
00943 }
00944
00945
00946 const filestatus::inode_type filestatus::inode(void) const
00947 {
00948 return(m_stat.st_ino);
00949 }
00950
00951
00952 const filestatus::device_type filestatus::dev(void) const
00953 {
00954 return(m_stat.st_dev);
00955 }
00956
00957
00958 const filestatus::device_type filestatus::rdev(void) const
00959 {
00960 return(m_stat.st_rdev);
00961 }
00962
00963
00964 const filestatus::major_type filestatus::get_major(void) const
00965 {
00966 return(m_major);
00967 }
00968
00969
00970 const filestatus::minor_type filestatus::get_minor(void) const
00971 {
00972 return(m_minor);
00973 }
00974
00975
00976 const filestatus::num_links_type filestatus::num_links(void) const
00977 {
00978 return(m_stat.st_nlink);
00979 }
00980
00981
00982 const filestatus::uid_type filestatus::uid(void) const
00983 {
00984 return(m_stat.st_uid);
00985 }
00986
00987
00988 const filestatus::gid_type filestatus::gid(void) const
00989 {
00990 return(m_stat.st_gid);
00991 }
00992
00993
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
01004 const filestatus::time_type filestatus::last_access_time(void) const
01005 {
01006 return(m_stat.st_atime);
01007 }
01008
01009
01010 const filestatus::time_type filestatus::last_modification_time(void) const
01011 {
01012 return(m_stat.st_mtime);
01013 }
01014
01015
01016 const filestatus::time_type filestatus::last_status_change_time(void) const
01017 {
01018 return(m_stat.st_ctime);
01019 }
01020
01021
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
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
01042 const bool filestatus::uid_is_found(void) const
01043 {
01044 return(m_uidfound);
01045 }
01046
01047
01048 const bool filestatus::gid_is_found(void) const
01049 {
01050 return(m_gidfound);
01051 }
01052
01053
01054 const std::string filestatus::uid_name(void) const
01055 {
01056 return(m_uname);
01057 }
01058
01059
01060 const std::string filestatus::gid_name(void) const
01061 {
01062 return(m_gname);
01063 }
01064
01065 #ifdef S_ISFIFO
01066
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01321 subdirectory::subdirectory()
01322 {
01323 }
01324
01325
01326 subdirectory::subdirectory(const subdirectory& a_class)
01327 {
01328 assign(a_class);
01329 }
01330
01331
01332 subdirectory::subdirectory(
01333 const std::string a_path, const std::string a_filter)
01334 {
01335 path(a_path, a_filter);
01336 }
01337
01338
01339 subdirectory::~subdirectory()
01340 {
01341 }
01342
01343
01344 void subdirectory::assign(const subdirectory& a_class)
01345 {
01346 type::assign(a_class.begin(), a_class.end());
01347 }
01348
01349
01350
01351
01352
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
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
01456 directory::directory()
01457 {
01458 }
01459
01460
01461 directory::directory(const directory& a_class)
01462 {
01463
01464 }
01465
01466
01467 directory::directory(const std::string& a_str)
01468 {
01469 path(a_str);
01470 }
01471
01472
01473 directory::~directory()
01474 {
01475 }
01476
01477
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
01548 filesystem::filesystem()
01549 {
01550 clear();
01551 }
01552
01553
01554 filesystem::filesystem(const std::string& a_path)
01555 {
01556 clear();
01557 path(a_path);
01558 }
01559
01560
01561 void filesystem::clear(void)
01562 {
01563 TRY_nomem(m_path = "");
01564 memset(&m_statfs, 0, sizeof(m_statfs));
01565 }
01566
01567
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
01582 const std::string filesystem::path(void) const
01583 {
01584 return(m_path);
01585 }
01586
01587
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
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
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
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
01628
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
01640
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
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
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
01673 simple_lock::simple_lock()
01674 {
01675 clear();
01676 }
01677
01678
01679 simple_lock::simple_lock(const std::string& a_lockfile)
01680 {
01681 clear();
01682 lockfile(a_lockfile);
01683 }
01684
01685
01686 simple_lock::~simple_lock()
01687 {
01688 clear();
01689 }
01690
01691
01692 void simple_lock::clear(void)
01693 {
01694 if (is_locked() && (locked_by() == getpid())) {
01695 unlock();
01696 }
01697 m_lockfile.clear();
01698 }
01699
01700
01701 void simple_lock::lockfile(const std::string& a_lockfile)
01702 {
01703 clear();
01704 m_lockfile = a_lockfile;
01705 }
01706
01707
01708 const std::string simple_lock::lockfile(void) const
01709 {
01710 return(m_lockfile);
01711 }
01712
01713
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
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
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
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