File/Directory Enhancement

- Migrated enhanced code out of taskd.
This commit is contained in:
Paul Beckingham 2011-04-16 00:44:07 -04:00
parent e9273cd6c3
commit 87c285e6b2
5 changed files with 234 additions and 20 deletions

View file

@ -30,7 +30,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <string.h> #include <string.h>
#include "Directory.h" #include <Directory.h>
#include "../cmake.h" #include "../cmake.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -87,7 +87,41 @@ bool Directory::create ()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool Directory::remove () 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;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -49,6 +49,7 @@ public:
private: private:
void list (const std::string&, std::vector <std::string>&, bool); void list (const std::string&, std::vector <std::string>&, bool);
bool remove_directory (const std::string&);
}; };
#endif #endif

View file

@ -27,46 +27,56 @@
#include <fstream> #include <fstream>
#include <sys/types.h> #include <sys/types.h>
#include <sys/file.h>
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include "File.h" #include <File.h>
#include <util.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File::File () File::File ()
: Path::Path () : Path::Path ()
, fh (NULL)
, h (-1)
{ {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File::File (const Path& other) File::File (const Path& other)
: Path::Path (other) : Path::Path (other)
, fh (NULL)
, h (-1)
{ {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File::File (const File& other) File::File (const File& other)
: Path::Path (other) : Path::Path (other)
, fh (NULL)
, h (-1)
{ {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File::File (const std::string& in) File::File (const std::string& in)
: Path::Path (in) : Path::Path (in)
, fh (NULL)
, h (-1)
{ {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File::~File () File::~File ()
{ {
if (fh)
close ();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
File& File::operator= (const File& other) File& File::operator= (const File& other)
{ {
if (this != &other) if (this != &other)
{
Path::operator= (other); Path::operator= (other);
}
return *this; return *this;
} }
@ -74,10 +84,9 @@ File& File::operator= (const File& other)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool File::create () bool File::create ()
{ {
std::ofstream out (data.c_str ()); if (open ())
if (out.good ())
{ {
out.close (); close ();
return true; return true;
} }
@ -90,6 +99,161 @@ bool File::remove ()
return unlink (data.c_str ()) == 0 ? true : false; 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 <std::string>& 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 <std::string>& lines)
{
if (!fh)
open ();
if (fh)
{
std::vector <std::string>::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 <std::string>& lines)
{
if (!fh)
open ();
if (fh)
{
fseek (fh, 0, SEEK_END);
std::vector <std::string>::const_iterator it;
for (it = lines.begin (); it != lines.end (); ++it)
fputs (((*it) + "\n").c_str (), fh);
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// S_IFMT 0170000 type of file // S_IFMT 0170000 type of file
// S_IFIFO 0010000 named pipe (fifo) // S_IFIFO 0010000 named pipe (fifo)

View file

@ -24,9 +24,11 @@
// USA // USA
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_FILE #ifndef INCLUDED_FILE
#define INCLUDED_FILE #define INCLUDED_FILE
#include <stdio.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <sys/stat.h> #include <sys/stat.h>
@ -46,19 +48,21 @@ public:
virtual bool create (); virtual bool create ();
virtual bool remove (); virtual bool remove ();
// bool open (); bool open ();
// bool openAndLock (); bool openAndLock ();
// void close (); void close ();
// bool lock (); bool lock ();
// bool lockNoWait (); bool waitForLock ();
// void unlock ();
// void read (std::string&); void read (std::string&);
// void read (std::vector <std::string>&); void read (std::vector <std::string>&);
// void write (const std::string&); void write (const std::string&);
// void write (const std::vector <std::string>&); void write (const std::vector <std::string>&);
void append (const std::string&);
void append (const std::vector <std::string>&);
virtual mode_t mode (); virtual mode_t mode ();
virtual size_t size () const; virtual size_t size () const;
@ -75,7 +79,8 @@ public:
static bool remove (const std::string&); static bool remove (const std::string&);
private: private:
// int handle; FILE* fh;
int h;
}; };
#endif #endif

View file

@ -34,7 +34,7 @@ Context context;
int main (int argc, char** argv) int main (int argc, char** argv)
{ {
UnitTest t (21); UnitTest t (25);
// Directory (const File&); // Directory (const File&);
// Directory (const Path&); // Directory (const Path&);
@ -93,6 +93,16 @@ int main (int argc, char** argv)
t.ok (d5.remove (), "Directory::remove /tmp/test_directory"); t.ok (d5.remove (), "Directory::remove /tmp/test_directory");
t.notok (d5.exists (), "Directory::exists /tmp/test_directory - no"); 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; return 0;
} }