WvStreams
unifilesystemgen.cc
1 #include "unifilesystemgen.h"
2 #include "wvfile.h"
3 #include "wvdiriter.h"
4 #include "wvfileutils.h"
5 #include "wvmoniker.h"
6 #include "wvlinkerhack.h"
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 
12 WV_LINK(UniFileSystemGen);
13 
14 
15 static IUniConfGen *creator(WvStringParm s, IObject *)
16 {
17  return new UniFileSystemGen(s, 0777);
18 }
19 
20 WvMoniker<IUniConfGen> UniFileSystemGenMoniker("fs", creator);
21 
22 
23 UniFileSystemGen::UniFileSystemGen(WvStringParm _dir, mode_t _mode)
24  : dir(_dir), mode(_mode)
25 {
26 }
27 
28 
29 static bool key_safe(const UniConfKey &key)
30 {
31  UniConfKey::Iter i(key);
32  for (i.rewind(); i.next(); )
33  {
34  if (*i == "." || *i == ".." || *i == "")
35  return false; // unsafe key segments
36  }
37 
38  // otherwise a safe filename
39  return true;
40 }
41 
42 
44 {
45  WvString null;
46 
47  if (!key_safe(key))
48  return null;
49 
50  WvString path("%s/%s", dir, key);
51 
52  // WARNING: this code depends on the ability to open() a directory
53  // as long as we don't read it, because we want to fstat() it after.
54  WvFile file(path, O_RDONLY);
55  if (!file.isok())
56  return null; // unreadable; pretend it doesn't exist
57 
58  struct stat st;
59  if (fstat(file.getrfd(), &st) < 0)
60  return null; // openable but can't stat? That's odd.
61 
62  if (S_ISREG(st.st_mode))
63  {
64  WvDynBuf buf;
65  while (file.isok())
66  file.read(buf, 4096);
67  if (file.geterr())
68  return null;
69  else
70  return buf.getstr();
71  }
72  else
73  return ""; // exists, but pretend it's an empty file
74 }
75 
76 
77 void UniFileSystemGen::set(const UniConfKey &key, WvStringParm value)
78 {
79  if (!key_safe(key))
80  return;
81 
82  WvString base("%s/%s", dir, key.removelast(1));
83  WvString path("%s/%s", dir, key);
84 
85  mkdirp(base, mode);
86 
87  if (value.isnull())
88  rm_rf(path);
89  else
90  {
91  WvFile file(path, O_WRONLY|O_CREAT|O_TRUNC, mode & 0666);
92  file.write(value);
93  }
94 }
95 
96 
97 void UniFileSystemGen::setv(const UniConfPairList &pairs)
98 {
99  setv_naive(pairs);
100 }
101 
102 
104 {
105 private:
106  UniFileSystemGen *gen;
107  WvDirIter i;
108  UniConfKey rel;
109 
110 public:
111  UniFileSystemGenIter(UniFileSystemGen *_gen, WvStringParm path,
112  const UniConfKey &_rel)
113  : gen(_gen), i(path, false), rel(_rel)
114  { }
115 
117  { }
118 
119  void rewind()
120  { i.rewind(); }
121 
122  bool next()
123  { return i.next(); }
124 
125  UniConfKey key() const
126  { return i->relname; }
127 
128  WvString value() const
129  { return gen->get(WvString("%s/%s", rel, i->relname)); }
130 };
131 
132 
134 {
135  if (!key_safe(key))
136  return NULL;
137 
138  return new UniFileSystemGenIter(this, WvString("%s/%s", dir, key), key);
139 }
UniFileSystemGenIter::next
bool next()
Seeks to the next element in the sequence.
Definition: unifilesystemgen.cc:122
UniFileSystemGenIter
Definition: unifilesystemgen.cc:103
WvStream::write
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
Definition: wvstream.cc:532
WvErrorBase::geterr
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
Definition: wverror.h:48
WvFdStream::isok
virtual bool isok() const
return true if the stream is actually usable right now
Definition: wvfdstream.cc:134
UniConfKey::removelast
UniConfKey removelast(int n=1) const
Returns the path formed by removing the last n segments of this path.
Definition: uniconfkey.h:346
WvFile
WvFile implements a stream connected to a file or Unix device.
Definition: wvfile.h:28
WvBufBase< unsigned char >::getstr
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
Definition: wvbuffer.cc:17
WvFdStream::getrfd
int getrfd() const
Returns the Unix file descriptor for reading from this stream.
Definition: wvfdstream.h:63
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
IUniConfGen
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:39
UniFileSystemGen::set
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
Definition: unifilesystemgen.cc:77
WvDirIter
Definition: wvdiriter.h:31
UniConfKey::Iter
An iterator over the segments of a key.
Definition: uniconfkey.h:463
UniFileSystemGen::setv
virtual void setv(const UniConfPairList &pairs)
Stores multiple key-value pairs into the registry.
Definition: unifilesystemgen.cc:97
UniConfKey
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:38
WvMoniker
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:61
WvStream::read
virtual size_t read(void *buf, size_t count)
read a data block on the stream.
Definition: wvstream.cc:490
UniFileSystemGen::get
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unifilesystemgen.cc:43
IObject
Definition: IObject.h:65
UniFileSystemGen::iterator
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
Definition: unifilesystemgen.cc:133
UniFileSystemGenIter::rewind
void rewind()
Rewinds the iterator.
Definition: unifilesystemgen.cc:119
UniFileSystemGenIter::key
UniConfKey key() const
Returns the current key.
Definition: unifilesystemgen.cc:125
WvDynBufBase< unsigned char >
UniFileSystemGenIter::value
WvString value() const
Returns the value of the current key.
Definition: unifilesystemgen.cc:128
UniFileSystemGen
Creates a UniConf tree that mirrors some point in the Linux filesystem, with restrictions.
Definition: unifilesystemgen.h:41
UniConfGen::Iter
An abstract iterator over keys and values in a generator.
Definition: uniconfgen.h:323