00001 #include "unifilesystemgen.h"
00002 #include "wvfile.h"
00003 #include "wvdiriter.h"
00004 #include "wvfileutils.h"
00005 #include "wvmoniker.h"
00006 #include "wvlinkerhack.h"
00007 #include <sys/types.h>
00008 #include <sys/stat.h>
00009 #include <unistd.h>
00010 #include <fcntl.h>
00011
00012 WV_LINK(UniFileSystemGen);
00013
00014
00015 static IUniConfGen *creator(WvStringParm s)
00016 {
00017 return new UniFileSystemGen(s, 0777);
00018 }
00019
00020 WvMoniker<IUniConfGen> UniFileSystemGenMoniker("fs", creator);
00021
00022
00023 UniFileSystemGen::UniFileSystemGen(WvStringParm _dir, mode_t _mode)
00024 : dir(_dir), mode(_mode)
00025 {
00026 }
00027
00028
00029 static bool key_safe(const UniConfKey &key)
00030 {
00031 UniConfKey::Iter i(key);
00032 for (i.rewind(); i.next(); )
00033 {
00034 if (*i == "." || *i == ".." || *i == "")
00035 return false;
00036 }
00037
00038
00039 return true;
00040 }
00041
00042
00043 WvString UniFileSystemGen::get(const UniConfKey &key)
00044 {
00045 WvString null;
00046
00047 if (!key_safe(key))
00048 return null;
00049
00050 WvString path("%s/%s", dir, key);
00051
00052
00053
00054 WvFile file(path, O_RDONLY);
00055 if (!file.isok())
00056 return null;
00057
00058 struct stat st;
00059 if (fstat(file.getrfd(), &st) < 0)
00060 return null;
00061
00062 if (S_ISREG(st.st_mode))
00063 {
00064 WvDynBuf buf;
00065 while (file.isok())
00066 file.read(buf, 4096);
00067 if (file.geterr())
00068 return null;
00069 else
00070 return buf.getstr();
00071 }
00072 else
00073 return "";
00074 }
00075
00076
00077 void UniFileSystemGen::set(const UniConfKey &key, WvStringParm value)
00078 {
00079 if (!key_safe(key))
00080 return;
00081
00082 WvString base("%s/%s", dir, key.removelast(1));
00083 WvString path("%s/%s", dir, key);
00084
00085 mkdirp(base, mode);
00086
00087 if (value.isnull())
00088 rm_rf(path);
00089 else
00090 {
00091 WvFile file(path, O_WRONLY|O_CREAT|O_TRUNC, mode & 0666);
00092 file.write(value);
00093 }
00094 }
00095
00096
00097 void UniFileSystemGen::setv(const UniConfPairList &pairs)
00098 {
00099 setv_naive(pairs);
00100 }
00101
00102
00103 class UniFileSystemGenIter : public UniConfGen::Iter
00104 {
00105 private:
00106 UniFileSystemGen *gen;
00107 WvDirIter i;
00108 UniConfKey rel;
00109
00110 public:
00111 UniFileSystemGenIter(UniFileSystemGen *_gen, WvStringParm path,
00112 const UniConfKey &_rel)
00113 : gen(_gen), i(path, false), rel(_rel)
00114 { }
00115
00116 ~UniFileSystemGenIter()
00117 { }
00118
00119 void rewind()
00120 { i.rewind(); }
00121
00122 bool next()
00123 { return i.next(); }
00124
00125 UniConfKey key() const
00126 { return i->relname; }
00127
00128 WvString value() const
00129 { return gen->get(WvString("%s/%s", rel, i->relname)); }
00130 };
00131
00132
00133 UniConfGen::Iter *UniFileSystemGen::iterator(const UniConfKey &key)
00134 {
00135 if (!key_safe(key))
00136 return NULL;
00137
00138 return new UniFileSystemGenIter(this, WvString("%s/%s", dir, key), key);
00139 }