00001 #ifndef FILE_HEADER_INCLUDED
00002 #define FILE_HEADER_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <string>
00030 #include <string.h>
00031 #include <memory>
00032 #include <sys/types.h>
00033 #include <time.h>
00034 #include <sys/stat.h>
00035 #include <iostream>
00036 #include <list>
00037 #include <set>
00038 #include <memory>
00039 #include <cxxtls/strtool.h>
00040
00041 namespace cxxtls
00042 {
00043
00049
00050
00051
00052
00053
00054 struct FileTime
00062 {
00063 int year;
00064 int month;
00065 int day;
00066 int hour;
00067 int minute;
00068 int second;
00069
00070 friend bool operator<(FileTime const &l, FileTime const &r)
00071 {
00072 if(l.year < r.year)
00073 return true;
00074 else
00075 if(l.year > r.year)
00076 return false;
00077
00078
00079 if(l.month < r.month)
00080 return true;
00081 else
00082 if(l.month > r.month)
00083 return false;
00084
00085
00086 if(l.day < r.day)
00087 return true;
00088 else
00089 if(l.day > r.day)
00090 return false;
00091
00092
00093 if(l.hour < r.hour)
00094 return true;
00095 else
00096 if(l.hour > r.hour)
00097 return false;
00098
00099
00100 if(l.minute < r.minute)
00101 return true;
00102 else
00103 if(l.minute > r.minute)
00104 return false;
00105
00106
00107 if(l.second < r.second)
00108 return true;
00109 else
00110 if(l.second > r.year)
00111 return false;
00112
00113
00114 return false;
00115 }
00116
00117
00118 operator std::string() const;
00120
00121 friend std::ostream& operator<< (std::ostream& o, FileTime const &r)
00123 {
00124 return o << std::string(r);
00125 }
00126
00127 FileTime()
00128 : year(0),
00129 month(0),
00130 day(0),
00131 hour(0),
00132 minute(0),
00133 second(0)
00134 {
00135 }
00136
00137 FileTime(struct tm const *);
00138
00139 FileTime(std::string s)
00140 : year(0),
00141 month(0),
00142 day(0),
00143 hour(0),
00144 minute(0),
00145 second(0)
00146 {
00147 construct_from_string(s);
00148 }
00149
00150 bool construct_from_string(std::string s);
00176
00177 std::string short_string() const;
00181 };
00182
00183
00184
00185
00186
00187 struct FileMode
00213 {
00214 int mode;
00215
00216
00217
00218 int os_mode() const;
00219
00220
00221
00222
00223 operator std::string() const;
00224
00225 friend std::ostream& operator<< (std::ostream& o, FileMode const &r)
00229 {
00230 return o << std::string(r);
00231 }
00232
00233 FileMode(): mode(0) {}
00234
00235 FileMode(int m);
00241
00242 FileMode(char const*s)
00250 {
00251 construct_from_string(s);
00252 }
00253
00254 FileMode(std::string s)
00258 {
00259 construct_from_string(s.c_str());
00260 }
00261
00262 void construct_from_string(char const *string);
00267
00268 void construct_from_string(std::string const& s)
00273 {
00274 construct_from_string(s.c_str());
00275 }
00276
00277
00278 enum bit_name
00280 {
00281 link = 010000,
00282 directory= 004000,
00283 set_uid = 002000,
00284 set_gid = 001000,
00285
00286 user_readable = 000400,
00287 user_writeable = 000200,
00288 user_executable = 000100,
00289
00290 group_readable = 000040,
00291 group_writeable = 000020,
00292 group_executable= 000010,
00293
00294 world_readable = 000004,
00295 world_writeable = 000002,
00296 world_executable = 0000001
00297 };
00298
00299 bool is_dir() const { return mode & directory; }
00307
00308 bool is_link() const { return mode & link; }
00322
00323
00324 void unpackPermissions(std::string &userMode, std::string &groupMode, std::string &worldMode);
00327
00328 void packPermissions(std::string const &userMode, std::string const &groupMode, std::string const &worldMode);
00333
00334 bool permStringValid(std::string const &string);
00340 };
00341
00342
00343
00344
00345
00346 struct FileStatus
00350 {
00351 typedef off_t file_size_t;
00352
00353 FileMode mode;
00354 file_size_t size;
00355 FileTime time;
00356 int owner_id;
00357 int group_id;
00358
00359 FileStatus()
00360 : mode(),
00361 size(0),
00362 time(),
00363 owner_id(0),
00364 group_id(0)
00365 {
00366
00367
00368 }
00369
00370 std::string convert_to_string(bool resolve_id_names=false) const;
00377
00378 operator std::string() const
00381 {
00382 return convert_to_string();
00383 }
00384
00385 friend std::ostream& operator<< (std::ostream& o, FileStatus const &r)
00389 {
00390 return o << std::string(r);
00391 }
00392
00393 static std::string id2string(int id);
00399
00400 static std::string group2string(int id);
00406
00407 };
00408
00409
00410
00411
00412
00413 class FileContents
00419 {
00420 private:
00421
00422 char *begin_;
00423 char *end_;
00424 char const *error_;
00425
00426 public:
00427
00428 FileContents()
00429 : begin_(0),
00430 end_(0),
00431 error_("not read yet")
00432 {
00433 }
00434
00435 ~FileContents()
00436 {
00437 delete [] begin_;
00438 }
00439
00440 typedef char *iterator;
00441 typedef char const *const_iterator;
00442
00443 const_iterator begin() const { return begin_; }
00447
00448 const_iterator end() const { return end_; }
00452
00453 iterator begin() { return begin_; }
00454 iterator end() { return end_; }
00455
00456 void reserve(long bytes) { delete [] begin_; begin_ = new char[bytes]; end_ = begin_ + bytes; }
00460
00461 long size() const { return end_ - begin_; }
00462
00463 char const *error() const { return error_; }
00467
00468 void set_error(char const *msg) { error_ = msg ; }
00472
00473 void clear_error() { error_ = 0; }
00476
00477 bool ok() const { return error_ == 0; }
00480
00481
00482 };
00483
00484
00485
00486
00487
00488
00489
00490 class FileName
00515 {
00516 public:
00517
00518 struct FileNameSorter
00519 {
00520 bool operator()(FileName const &a, FileName const &b) const
00521 { return 0 > StrTool:: compareInsensitive(a,b); }
00522 };
00523
00524 typedef std::set<FileName, FileNameSorter> sorted_names_t;
00525
00526 typedef std::string rep_t;
00527 typedef FileStatus::file_size_t off_t;
00528 typedef rep_t::const_iterator const_iterator;
00529 typedef rep_t::iterator iterator;
00530
00531 private:
00532 rep_t impl_;
00533
00534 public:
00535
00536 operator std::string &() { return impl_; }
00537 operator std::string const &() const { return impl_; }
00538 const_iterator begin() const { return impl_.begin(); }
00539 const_iterator end() const { return impl_.end(); }
00540 size_t size() const { return impl_.size(); }
00541 iterator begin() { return impl_.begin(); }
00542 iterator end() { return impl_.end(); }
00543 char const * c_str() const { return impl_.c_str(); }
00544 char const * data() const { return impl_.data(); }
00545
00546 char operator[](size_t i) const { return impl_[i]; }
00547
00548
00549 char &operator[](size_t i) { return impl_[i]; }
00550
00551
00552 void erase(iterator a) { impl_.erase(a); }
00553 void erase(iterator a, iterator b) { impl_.erase(a,b); }
00554 void erase(size_t o, size_t l) { impl_.erase(o,l); }
00555 void erase(size_t o) { impl_.erase(o); }
00556 void insert(iterator a, char c) { impl_.insert(a,c); }
00557 void insert(size_t o, char const *s) { impl_.insert(o,s); }
00558 void insert(size_t o, rep_t const &s) { impl_.insert(o,s); }
00559 bool empty() const { return impl_.empty(); }
00560
00561 bool operator<( std::string const &rhs ) const
00563 {
00564 return impl_ < rhs;
00565 }
00566
00567 rep_t substr(size_t s, size_t l) const
00569 {
00570 return impl_.substr(s,l);
00571 }
00572
00573 FileName &operator+= (char const *p)
00574 {
00575 std::string *me = &impl_;
00576
00577 *me += p;
00578
00579 return *this;
00580
00581 }
00582
00583 FileName &operator+= (char c)
00584 {
00585 std::string *me = &impl_;
00586
00587 *me += c;
00588
00589 return *this;
00590
00591 }
00592
00593
00594 FileName &operator+= (std::string const &r)
00595 {
00596 std::string *me = &impl_;
00597
00598 *me += r;
00599
00600 return *this;
00601
00602 }
00603
00604
00605 FileName()
00606 {
00607 }
00608
00609 FileName(char const *r)
00610 : impl_(r)
00611 {
00612 }
00613
00614 FileName(std::string const &r)
00615 : impl_(r)
00616 {
00617 }
00618
00619 FileName(FileName const &r)
00620 : impl_(r)
00621 {
00622 }
00623
00624
00625 FileName expand_tildes() const;
00642
00643 rep_t basename(bool remove_extension=false) const;
00646
00647 rep_t extension() const;
00650
00651 rep_t dirname() const;
00654
00655 void convert_to_absolute_path();
00658
00659 bool is_syntactically_valid() const;
00661
00662 bool exists() const;
00664
00665 bool is_dir() const;
00666 bool is_executable() const;
00667 bool is_writeable() const;
00668 bool is_readable() const;
00669 bool is_createable() const;
00670 bool is_absolute_path() const;
00671 bool is_root_dir() const;
00672
00673 FileMode file_mode() const;
00674 off_t file_size() const;
00675
00676 bool file_time(FileTime *t) const;
00682
00683 bool file_stat(FileStatus* s, bool l=false) const;
00684
00700
00701 bool matches(char const *pattern) const;
00707
00708 bool matches(rep_t pattern) const
00710 {
00711 return matches(pattern.c_str());
00712 }
00713
00714
00715 FileName readlink(int *returnedMode=0) const;
00733
00734
00735 bool remove() const;
00737
00738 bool chmod(FileMode) const;
00742
00743
00744 bool copy(FileName const &destination) const;
00754
00755 bool rename(FileName const &destination) const;
00762
00763 bool mkdir(FileMode m=FileMode(" drwxrwxrwx") ) const;
00769
00770 bool rmdir() const;
00773
00774 void convertToDirectorySearchPattern(std::string const &pattern)
00785 {
00786 convertToDirectorySearchPattern(pattern.c_str());
00787 }
00788
00789 void convertToDirectorySearchPattern(char const *pattern="*");
00791
00792
00793 static int find_matching(char const *pattern,
00794 sorted_names_t *matches,
00795 int options=0
00796 );
00828
00829
00830 static int find_matching(rep_t pattern,
00831 sorted_names_t* l,
00832 int options=0
00833 )
00835 {
00836 return find_matching(pattern.c_str(), l, options);
00837 }
00838
00839 void slurp(FileContents *f) const ;
00843
00844 bool write(std::string const &file_contents, bool binary_mode=true);
00860
00861 bool write(char const *begin, char const *end, bool binary_mode=true);
00872
00874
00875 size_t slurp(std::list<std::string> *lines) const;
00882
00883 struct accumulate_lines
00895 {
00896 virtual ~accumulate_lines(){}
00900
00901 virtual void push_back(std::string const &new_line) = 0;
00905
00906 virtual std::string &back() = 0;
00911
00912 virtual void setBackHasCR(bool flag){ }
00919
00920 };
00921
00922 std::string read_lines(accumulate_lines &accum, size_t *line_count_ptr=0, bool removeCR=false);
00962
00963 template<class Container>
00964 struct Accum
00965 : public accumulate_lines
00976 {
00977 Container& container_;
00978
00979 Accum(Container& container)
00980 : container_(container)
00981 {
00982 }
00983
00984 void push_back(std::string const &s) { container_.push_back(s); }
00985 std::string & back() { return container_.back();}
00986
00987 };
00988
00989 template<class Container>
00990 std::string read_file(Container &container, size_t* line_count_ptr=0)
01015 {
01016
01017 Accum<Container> accum(container);
01018
01019 return read_lines( accum, line_count_ptr );
01020
01021 }
01022
01023
01024 static FileName mktemp(FileName dir="./");
01048
01049
01050 static char PATH_separator;
01051
01052
01053
01054
01055 struct is_separator
01062 {
01063 bool operator() (char c) const
01064 {
01065 return c == FileName::PATH_separator;
01066 }
01067 };
01068
01069 static FileName find_executable(std::string progname, std::string path="");
01089
01090 static FileName find_file_in_path(std::string filename, std::string path="");
01100
01101 std::string shorten(int max_chars) const;
01107
01108 FileName operator+(FileName const &r ) const
01109 {
01110 std::string const &me = *this;
01111 std::string const &other = r;
01112
01113
01114 return FileName(me + other);
01115 }
01116
01117 FileName operator+(char const* r) const
01119 {
01120 std::string const &me = *this;
01121
01122
01123 return FileName(me + r);
01124 }
01125
01126 FileName operator+(std::string const &r) const
01128 {
01129 std::string const &me = *this;
01130
01131
01132 return FileName(me + r);
01133 }
01134
01135 template<class T>
01136 FileName &operator=(T const &rhs)
01138 {
01139 impl_ = rhs;
01140
01141 return *this;
01142 }
01143
01144
01145
01146 friend std::string operator+(std::string const &lhs, FileName const&rhs)
01149 {
01150 return lhs + (std::string const &)(rhs);
01151 }
01152
01153 friend std::string operator+(char const *lhs, FileName const&rhs)
01156 {
01157 return lhs + (std::string const &)(rhs);
01158 }
01159
01160 static int compareIgnoringPathSeparatorDifferences(char const *l,
01161 char const *r,
01162 size_t lsize,
01163 size_t rsize
01164 )
01169 {
01170
01171
01172 size_t smaller = lsize < rsize ? lsize : rsize;
01173
01174 for(size_t i = 0; i < smaller; ++i)
01175 {
01176 char lc = l[i];
01177 char rc = r[i];
01178
01179 if(lc == '\\')
01180 lc = '/';
01181
01182 if(rc == '\\')
01183 rc = '/';
01184
01185 if(lc < rc)
01186 return -1;
01187
01188 if(lc > rc)
01189 return 1;
01190
01191
01192
01193
01194 }
01195
01196
01197
01198
01199 if(lsize < rsize)
01200 return -1;
01201 else
01202 if(lsize > rsize)
01203 return 1;
01204
01205 return 0;
01206
01207
01208 }
01209
01210 static int compareIgnoringPathSeparatorDifferences(std::string const &l,
01211 std::string const &r
01212 )
01217 {
01218 return compareIgnoringPathSeparatorDifferences(l.data(), r.data(), l.size(), r.size());
01219
01220 }
01221
01222
01223
01224 bool operator==(FileName const rhs) const
01226 {
01227 int cmp = compareIgnoringPathSeparatorDifferences(*this, rhs);
01228
01229 if(cmp != 0)
01230 return false;
01231
01232 return true;
01233
01234
01235
01236 }
01237
01238 bool operator==(std::string const rhs) const
01240 {
01241
01242 int cmp = compareIgnoringPathSeparatorDifferences(this->data(), rhs.data(), this->size(), rhs.size());
01243
01244 if(cmp != 0)
01245 return false;
01246
01247 return true;
01248
01249
01250 }
01251
01252 bool operator==(char const *rhs) const
01254 {
01255 int cmp = compareIgnoringPathSeparatorDifferences(this->data(), rhs, this->size(), strlen(rhs));
01256
01257 if(cmp != 0)
01258 return false;
01259
01260 return true;
01261
01262
01263 return ((std::string const &)(*this)) == rhs;
01264 }
01265
01266
01267 friend bool operator==(std::string const &lhs, FileName const& rhs)
01269 {
01270
01271 int cmp = compareIgnoringPathSeparatorDifferences(lhs, rhs);
01272
01273 if(cmp != 0)
01274 return false;
01275
01276 return true;
01277
01278
01279 }
01280
01281 friend bool operator==(char const*lhs, FileName const& rhs)
01283 {
01284
01285 int cmp = compareIgnoringPathSeparatorDifferences(lhs, rhs.data(), strlen(lhs), rhs.size());
01286
01287 if(cmp != 0)
01288 return false;
01289
01290 return true;
01291
01292
01293 }
01294
01295 static FileName getcwd();
01296
01297 class Tree
01304 {
01305 public:
01306 typedef std::list<Tree*> children_t;
01307
01308 friend class FileName;
01309
01310 private:
01311
01312 FileStatus status_;
01313 std::string name_;
01314 children_t children_;
01315
01316 Tree* parent_;
01317
01318 int depth_;
01319
01320 public:
01321
01322 Tree(Tree* parent=0)
01323 : parent_(parent),
01324 depth_(0)
01325 {
01327 }
01328
01329 ~Tree();
01330 Tree(Tree const &r);
01331
01332 Tree(std::string const &name, FileStatus const &status, Tree* parent=0, int depth=0)
01333 : status_(status),
01334 name_(name),
01335 parent_(parent),
01336 depth_(0)
01337 {
01340 }
01341
01342 Tree &operator=(Tree const &r)
01343 {
01344 this->~Tree();
01345 new (this) Tree(r);
01346 return *this;
01347 }
01348
01349
01350 FileStatus const& status() const { return status_; }
01352
01353 FileName name() const { return name_; }
01355
01356 FileName path() const;
01361
01362 int depth() const { return depth_; }
01366
01367 children_t const& children() const { return children_; }
01369
01370 void add_child(FileName const &name, FileStatus const &status)
01372 {
01373 children_.push_back(new Tree(name,status,this,this->depth_+1));
01374 }
01375
01376 void add_child(Tree *tree)
01378 {
01379 tree->parent_ = this;
01380 tree->depth_ = depth_+1;
01381 children_.push_back(tree);
01382 }
01383
01384 void remove_child(FileName const &name);
01386
01387 };
01388
01389 std::auto_ptr<Tree> tree(bool only_dirs=false) const;
01400
01401 private:
01402 std::auto_ptr<Tree>
01403 tree_helper(std::string const &path, bool only_dirs=false, int depth=0) const;
01405 };
01406
01407
01408
01409
01410
01411 inline std::ostream &operator<< (std::ostream &s, FileName const &rhs)
01412 {
01413 std::string const &data = rhs;
01414
01415 return s << data;
01416 }
01417
01418
01419
01420
01421 template<class T>
01422 inline bool operator!= (FileName const &lhs, T const &rhs)
01423 {
01424 std::string const &data = lhs;
01425
01426 return data != rhs;
01427
01428 }
01429
01430
01431
01432
01433 template<class T>
01434 inline bool operator!= (T const &lhs, FileName const &rhs)
01435 {
01436 std::string const &data = rhs;
01437
01438 return data != rhs;
01439
01440 }
01441
01442
01443
01444 }
01445
01446 #endif