From 87c285e6b2d63bc1b237697bba8aa65776753bec Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 16 Apr 2011 00:44:07 -0400 Subject: [PATCH] File/Directory Enhancement - Migrated enhanced code out of taskd. --- src/Directory.cpp | 38 +++++++++- src/Directory.h | 1 + src/File.cpp | 176 +++++++++++++++++++++++++++++++++++++++++-- src/File.h | 27 ++++--- test/directory.t.cpp | 12 ++- 5 files changed, 234 insertions(+), 20 deletions(-) diff --git a/src/Directory.cpp b/src/Directory.cpp index 528d05d4c..41592e20f 100644 --- a/src/Directory.cpp +++ b/src/Directory.cpp @@ -30,7 +30,7 @@ #include #include #include -#include "Directory.h" +#include #include "../cmake.h" //////////////////////////////////////////////////////////////////////////////// @@ -87,7 +87,41 @@ bool Directory::create () //////////////////////////////////////////////////////////////////////////////// bool Directory::remove () { - return rmdir (data.c_str ()) == 0 ? true : false; + return remove_directory (data); +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::remove_directory (const std::string& dir) +{ + DIR* dp = opendir (dir.c_str ()); + if (dp != NULL) + { + struct dirent* de; + while ((de = readdir (dp)) != NULL) + { + if (!strcmp (de->d_name, ".") || + !strcmp (de->d_name, "..")) + continue; + +#if defined (SOLARIS) || defined (HAIKU) + struct stat s; + stat (de->d_name, &s); + if (s.st_mode & S_IFDIR) + remove_directory (dir + "/" + de->de_name); + else + unlink ((dir + "/" + de->d_name).c_str ()); +#else + if (de->d_type == DT_DIR) + remove_directory (dir + "/" + de->d_name); + else + unlink ((dir + "/" + de->d_name).c_str ()); +#endif + } + + closedir (dp); + } + + return rmdir (dir.c_str ()) ? false : true; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Directory.h b/src/Directory.h index fe33ec8e3..3e512f235 100644 --- a/src/Directory.h +++ b/src/Directory.h @@ -49,6 +49,7 @@ public: private: void list (const std::string&, std::vector &, bool); + bool remove_directory (const std::string&); }; #endif diff --git a/src/File.cpp b/src/File.cpp index 5699b1508..40c7de6ca 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -27,46 +27,56 @@ #include #include +#include #include #include -#include "File.h" +#include +#include //////////////////////////////////////////////////////////////////////////////// File::File () : Path::Path () +, fh (NULL) +, h (-1) { } //////////////////////////////////////////////////////////////////////////////// File::File (const Path& other) : Path::Path (other) +, fh (NULL) +, h (-1) { } //////////////////////////////////////////////////////////////////////////////// File::File (const File& other) : Path::Path (other) +, fh (NULL) +, h (-1) { } //////////////////////////////////////////////////////////////////////////////// File::File (const std::string& in) : Path::Path (in) +, fh (NULL) +, h (-1) { } //////////////////////////////////////////////////////////////////////////////// File::~File () { + if (fh) + close (); } //////////////////////////////////////////////////////////////////////////////// File& File::operator= (const File& other) { if (this != &other) - { Path::operator= (other); - } return *this; } @@ -74,10 +84,9 @@ File& File::operator= (const File& other) //////////////////////////////////////////////////////////////////////////////// bool File::create () { - std::ofstream out (data.c_str ()); - if (out.good ()) + if (open ()) { - out.close (); + close (); return true; } @@ -90,6 +99,161 @@ bool File::remove () return unlink (data.c_str ()) == 0 ? true : false; } +//////////////////////////////////////////////////////////////////////////////// +bool File::open () +{ + if (data != "" && fh == NULL) + { + bool already_exists = exists (); + if (already_exists) + if (!readable () || !writable ()) + throw std::string ("Task does not have the correct permissions for '") + + data + "'."; + + fh = fopen (data.c_str (), (already_exists ? "r+" : "w+")); + if (fh) + { + h = fileno (fh); + return true; + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::openAndLock () +{ + return open () && lock (); +} + +//////////////////////////////////////////////////////////////////////////////// +void File::close () +{ + if (fh) + { + fclose (fh); + fh = NULL; + h = -1; + } +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::lock () +{ + if (fh && h != -1) + { + // Try three times before failing. + int retry = 0; + while (flock (h, LOCK_NB | LOCK_EX) && ++retry <= 3) + ; + + if (retry <= 3) + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::waitForLock () +{ + if (fh && h != -1) + return flock (h, LOCK_EX) == 0 ? true : false; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::read (std::string& contents) +{ + contents = ""; + + std::ifstream in (data.c_str ()); + if (in.good ()) + { + std::string line; + while (getline (in, line)) + contents += line + "\n"; + + in.close (); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::read (std::vector & contents) +{ + contents.clear (); + + std::ifstream in (data.c_str ()); + if (in.good ()) + { + std::string line; + while (getline (in, line)) + contents.push_back (line); + + in.close (); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::write (const std::string& line) +{ + if (!fh) + open (); + + if (fh) + fputs (line.c_str (), fh); +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::write (const std::vector & lines) +{ + if (!fh) + open (); + + if (fh) + { + std::vector ::const_iterator it; + for (it = lines.begin (); it != lines.end (); ++it) + fputs (it->c_str (), fh); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::append (const std::string& line) +{ + if (!fh) + open (); + + if (fh) + { + fseek (fh, 0, SEEK_END); + fputs (line.c_str (), fh); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::append (const std::vector & lines) +{ + if (!fh) + open (); + + if (fh) + { + fseek (fh, 0, SEEK_END); + std::vector ::const_iterator it; + for (it = lines.begin (); it != lines.end (); ++it) + fputs (((*it) + "\n").c_str (), fh); + } +} + //////////////////////////////////////////////////////////////////////////////// // S_IFMT 0170000 type of file // S_IFIFO 0010000 named pipe (fifo) diff --git a/src/File.h b/src/File.h index d75901cc8..a7083b0f4 100644 --- a/src/File.h +++ b/src/File.h @@ -24,9 +24,11 @@ // USA // //////////////////////////////////////////////////////////////////////////////// + #ifndef INCLUDED_FILE #define INCLUDED_FILE +#include #include #include #include @@ -46,19 +48,21 @@ public: virtual bool create (); virtual bool remove (); -// bool open (); -// bool openAndLock (); -// void close (); + bool open (); + bool openAndLock (); + void close (); -// bool lock (); -// bool lockNoWait (); -// void unlock (); + bool lock (); + bool waitForLock (); -// void read (std::string&); -// void read (std::vector &); + void read (std::string&); + void read (std::vector &); -// void write (const std::string&); -// void write (const std::vector &); + void write (const std::string&); + void write (const std::vector &); + + void append (const std::string&); + void append (const std::vector &); virtual mode_t mode (); virtual size_t size () const; @@ -75,7 +79,8 @@ public: static bool remove (const std::string&); private: -// int handle; + FILE* fh; + int h; }; #endif diff --git a/test/directory.t.cpp b/test/directory.t.cpp index 023c6d4aa..3b8f955a7 100644 --- a/test/directory.t.cpp +++ b/test/directory.t.cpp @@ -34,7 +34,7 @@ Context context; int main (int argc, char** argv) { - UnitTest t (21); + UnitTest t (25); // Directory (const File&); // Directory (const Path&); @@ -93,6 +93,16 @@ int main (int argc, char** argv) t.ok (d5.remove (), "Directory::remove /tmp/test_directory"); t.notok (d5.exists (), "Directory::exists /tmp/test_directory - no"); + // bool remove (const std::string&); + Directory d7 ("/tmp/to_be_removed"); + t.ok (d7.create (), "Directory::create /tmp/to_be_removed"); + File::create (d7.data + "/f0"); + Directory d8 (d7.data + "/another"); + t.ok (d8.create (), "Directory::create /tmp/to_be_removed/another"); + File::create (d8.data + "/f1"); + t.ok (d7.remove (), "Directory::remove /tmp/to_be_removed"); + t.notok (d7.exists (), "Directory /tmp/to_be_removed gone"); + return 0; }