ocarina/libsaria/fs.cpp

212 lines
4.0 KiB
C++

// Copyright (c) 2012 Bryan Schumaker.
#include <fs.h>
#include <idle.h>
#include <print.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
static string appdir;
static mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
static bool pipe_opened = false;
static void make_dir(const string &path)
{
println("Making directory: " + path);
mkdir(path.c_str(), dirmode);
}
static void handle_entry(string &dir, list<string> &file_list, struct dirent *dirp)
{
struct stat stat;
string name = dirp->d_name;
if (name == "." || name == "..")
return;
name = dir + "/" + name;
if (lstat(name.c_str(), &stat) == 0) {
if (S_ISDIR(stat.st_mode))
libsaria::list_dir(name, file_list);
else
file_list.push_back(name);
}
}
static bool compare_files(string &one, string &two)
{
unsigned int a = atoi(one.c_str());
unsigned int b = atoi(two.c_str());
return a < b;
}
struct ReadData
{
string filepath;
void (*func)(ifstream &);
};
static void read_cb(void *d)
{
ifstream stream;
struct ReadData *data = (struct ReadData *)d;
stream.open(data->filepath.c_str());
data->func(stream);
stream.close();
delete data;
}
struct WriteData
{
string filepath;
void (*func)(ofstream &, void *);
void *data;
};
static void write_cb(void *d)
{
ofstream stream;
struct WriteData *data = (struct WriteData *)d;
stream.open(data->filepath.c_str());
data->func(stream, data->data);
stream.close();
delete data;
}
namespace libsaria
{
bool exists(const string &filepath)
{
struct stat stat;
return lstat(filepath.c_str(), &stat) == 0;
}
void list_dir(string &dir, list<string> &file_list)
{
DIR *dp;
struct dirent *dirp;
dp = opendir(dir.c_str());
if (dp == NULL)
return;
do {
dirp = readdir(dp);
if (dirp)
handle_entry(dir, file_list, dirp);
} while (dirp != NULL);
closedir(dp);
}
void app::list_dir(const string &dir, list<string> &file_list)
{
list<string> files;
list<string>::iterator it;
string d = appdir + "/" + dir;
libsaria::list_dir(d, files);
/* Strip out appdir information */
for (it = files.begin(); it != files.end(); it++)
file_list.push_back( (*it).substr(d.size() + 1) );
}
unsigned int app::read_numdir(const string &dir, void (*func)(ifstream &))
{
list<string> files;
list<string>::iterator it;
list_dir(dir, files);
if (files.size() == 0)
return 0;
files.sort(compare_files);
for (it = files.begin(); it != files.end(); it++) {
println("Reading path: " + dir + "/" + (*it));
read(dir + "/" + (*it), func);
}
return atoi(files.back().c_str()) + 1;
}
void app::mkdir(const string &dir)
{
string d = appdir + "/" + dir;
make_dir(d.c_str());
}
void app::rm(const string &file)
{
string f = appdir + "/" + file;
remove(f.c_str());
}
void app::init()
{
string home = getenv("HOME");
appdir = home + "/.ocarina";
#ifdef DEBUG
appdir += "-debug";
#endif
make_dir(appdir.c_str());
}
void app::save(string file, void (*func)(ofstream &, void *), void *d)
{
struct WriteData *data = new struct WriteData;
data->filepath = appdir + "/" + file;
data->func = func;
data->data = d;
idle::schedule(write_cb, data);
}
void app::read(string file, void (*func)(ifstream &))
{
struct ReadData *data = new struct ReadData;
data->filepath = appdir + "/" + file;
data->func = func;
idle::schedule(read_cb, data);
}
void app::read_now(string file, void (*func)(ifstream &))
{
ifstream stream;
stream.open((appdir + "/" + file).c_str());
func(stream);
stream.close();
}
void app::open_pipe()
{
string file = appdir + "/pipe";
if (!exists(file)) {
mkfifo(file.c_str(), 0644);
pipe_opened = true;
} else {
println("Pipe file: %s already exists, pipe not opened!",
file.c_str());
}
}
void app::close_pipe()
{
string file = appdir + "/pipe";
if (pipe_opened && exists(file))
rm("pipe");
}
string app::pipe_file()
{
if (pipe_opened)
return appdir + "/pipe";
return "";
}
} /* Namespace: libsaria */