1 #include "unifilesystemgen.h"
4 #include "wvfileutils.h"
6 #include "wvlinkerhack.h"
12 WV_LINK(UniFileSystemGen
);
15 static IUniConfGen
*creator(WvStringParm s
, IObject
*)
17 return new UniFileSystemGen(s
, 0777);
20 WvMoniker
<IUniConfGen
> UniFileSystemGenMoniker("fs", creator
);
23 UniFileSystemGen::UniFileSystemGen(WvStringParm _dir
, mode_t _mode
)
24 : dir(_dir
), mode(_mode
)
29 static bool key_safe(const UniConfKey
&key
)
31 UniConfKey::Iter
i(key
);
32 for (i
.rewind(); i
.next(); )
34 if (*i
== "." || *i
== ".." || *i
== "")
35 return false; // unsafe key segments
38 // otherwise a safe filename
43 WvString
UniFileSystemGen::get(const UniConfKey
&key
)
50 WvString
path("%s/%s", dir
, key
);
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
);
56 return null
; // unreadable; pretend it doesn't exist
59 if (fstat(file
.getrfd(), &st
) < 0)
60 return null
; // openable but can't stat? That's odd.
62 if (S_ISREG(st
.st_mode
))
73 return ""; // exists, but pretend it's an empty file
77 void UniFileSystemGen::set(const UniConfKey
&key
, WvStringParm value
)
82 WvString
base("%s/%s", dir
, key
.removelast(1));
83 WvString
path("%s/%s", dir
, key
);
91 WvFile
file(path
, O_WRONLY
|O_CREAT
|O_TRUNC
, mode
& 0666);
97 void UniFileSystemGen::setv(const UniConfPairList
&pairs
)
103 class UniFileSystemGenIter
: public UniConfGen::Iter
106 UniFileSystemGen
*gen
;
111 UniFileSystemGenIter(UniFileSystemGen
*_gen
, WvStringParm path
,
112 const UniConfKey
&_rel
)
113 : gen(_gen
), i(path
, false), rel(_rel
)
116 ~UniFileSystemGenIter()
125 UniConfKey
key() const
126 { return i
->relname
; }
128 WvString
value() const
129 { return gen
->get(WvString("%s/%s", rel
, i
->relname
)); }
133 UniConfGen::Iter
*UniFileSystemGen::iterator(const UniConfKey
&key
)
138 return new UniFileSystemGenIter(this, WvString("%s/%s", dir
, key
), key
);