mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
File/Directory Enhancement
- Migrated enhanced code out of taskd.
This commit is contained in:
parent
e9273cd6c3
commit
87c285e6b2
5 changed files with 234 additions and 20 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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
|
||||||
|
|
176
src/File.cpp
176
src/File.cpp
|
@ -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)
|
||||||
|
|
27
src/File.h
27
src/File.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue