9 #include "unitempgen.h" 11 #include "wvmoniker.h" 12 #include "wvstringmask.h" 15 #include "wvlinkerhack.h" 31 : filename(_filename), create_mode(_create_mode), log(_filename), save_cb(_save_cb)
35 memset(&old_st, 0,
sizeof(old_st));
50 UniIniGen::~UniIniGen()
57 WvFile file(filename, O_RDONLY);
61 if (file.
isok() && fstat(file.
getrfd(), &statbuf) == -1)
63 log(WvLog::Warning,
"Can't stat '%s': %s\n",
64 filename, strerror(errno));
68 if (file.
isok() && (statbuf.st_mode & S_ISVTX))
75 && statbuf.st_ctime == old_st.st_ctime
76 && statbuf.st_dev == old_st.st_dev
77 && statbuf.st_ino == old_st.st_ino
78 && statbuf.st_blocks == old_st.st_blocks
79 && statbuf.st_size == old_st.st_size)
81 log(WvLog::Debug3,
"refresh: file hasn't changed; do nothing.\n");
84 memcpy(&old_st, &statbuf,
sizeof(statbuf));
90 "Can't open '%s' for reading: %s\n" 91 "...starting with blank configuration.\n",
92 filename, file.errstr());
116 WVTCL_NASTY_NEWLINES,
122 int len = strlen(str);
123 if (len == 0)
continue;
132 if (str[0] ==
'[' && str[len - 1] ==
']')
156 assert(*value ==
'=');
168 "Ignoring malformed input line: \"%s\"\n", word);
175 size_t offset = buf.
strchr(
'\n');
180 "XXX Ignoring malformed input line: \"%s\"\n", line1);
187 "Error reading from config file: %s\n", file.errstr());
199 oldtree->
compare(newtree, wv::bind(&UniIniGen::refreshcomparator,
this,
232 a->
visit(wv::bind(&UniIniGen::notify_deleted,
this, _1, _2),
248 bool UniIniGen::commit_atomic(
WvStringParm real_filename)
252 if (lstat(real_filename, &statbuf) == -1)
258 if (!S_ISREG(statbuf.st_mode))
261 WvString tmp_filename(
"%s.tmp%s", real_filename, getpid());
262 WvFile file(tmp_filename, O_WRONLY|O_TRUNC|O_CREAT, 0000);
266 log(WvLog::Warning,
"Can't write '%s': %s\n",
267 tmp_filename, strerror(errno));
268 unlink(tmp_filename);
275 mode_t theumask = umask(0);
277 fchmod(file.
getwfd(), create_mode & ~theumask);
281 if (file.
geterr() || rename(tmp_filename, real_filename) == -1)
283 log(WvLog::Warning,
"Can't write '%s': %s\n",
284 filename, strerror(errno));
285 unlink(tmp_filename);
304 WvFile file(filename, O_WRONLY|O_TRUNC|O_CREAT, create_mode);
309 log(WvLog::Warning,
"Can't write '%s': %s\n",
310 filename, file.errstr());
315 char resolved_path[PATH_MAX];
317 if (realpath(filename, resolved_path) != NULL)
318 real_filename = resolved_path;
320 if (!commit_atomic(real_filename))
322 WvFile file(real_filename, O_WRONLY|O_TRUNC|O_CREAT, create_mode);
325 if (fstat(file.
getwfd(), &statbuf) == -1)
327 log(WvLog::Warning,
"Can't write '%s' ('%s'): %s\n",
328 filename, real_filename, strerror(errno));
332 fchmod(file.
getwfd(), (statbuf.st_mode & 07777) | S_ISVTX);
340 statbuf.st_mode = statbuf.st_mode & ~S_ISVTX;
341 fchmod(file.
getwfd(), statbuf.st_mode & 07777);
344 log(WvLog::Warning,
"Error writing '%s' ('%s'): %s\n",
345 filename, real_filename, file.errstr());
357 static bool absolutely_needs_escape(
WvStringParm s,
const char *sepchars)
361 bool inescape =
false, inspace =
false;
363 if (isspace((
unsigned char)*s))
366 for (cptr = s; *cptr; cptr++)
370 else if (!numbraces && strchr(sepchars, *cptr))
372 else if (*cptr ==
'\\')
374 else if (*cptr ==
'{')
376 else if (*cptr ==
'}')
379 inspace = isspace((
unsigned char)*cptr);
385 if (inescape || inspace)
396 static void printsection(
WvStream &file,
const UniConfKey &key, UniIniGen::SaveCallback save_cb)
401 if (absolutely_needs_escape(key,
"\r\n[]"))
422 if (absolutely_needs_escape(_key,
"\r\n[]=#\""))
431 if (absolutely_needs_escape(_value,
"\r\n"))
452 bool recursive, UniIniGen::SaveCallback save_cb)
455 for (it.rewind(); it.next(); )
472 printsection(file, toplevel.
fullkey(), save_cb);
473 printedsection =
true;
475 printkey(file, node.
fullkey(&toplevel), node.
value(), save_cb);
480 save_sect(file, toplevel, node, printedsection, recursive, save_cb);
489 if (!&parent)
return;
496 if (!!parent.
value())
497 printkey(file, parent.
key(), parent.
value(), save_cb);
500 bool printedsection =
false;
502 save_sect(file, parent, parent, printedsection,
false, save_cb);
505 for (it.rewind(); it.next(); )
509 printedsection =
false;
510 save_sect(file, node, node, printedsection,
true, save_cb);
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
bool isempty() const
Returns true if this path has zero segments (also known as root).
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
A raw memory read-only buffer backed by a constant WvString.
Functions to handle "tcl-style" strings and lists.
The basic interface which is included by all other XPLC interfaces and objects.
int getrfd() const
Returns the Unix file descriptor for reading from this stream.
void delta(const UniConfKey &key, WvStringParm value)
Call this when a key's value or children have possibly changed.
A UniConf generator that stores keys in memory.
const WvString & value() const
Returns the value field.
An abstract data container that backs a UniConf tree.
WvString & unique()
make the buf and str pointers owned only by this WvString.
WvFile implements a stream connected to a file or Unix device.
bool compare(const Sub *other, const Comparator &comparator)
Compares this tree with another using the specified comparator function.
bool isnull() const
returns true if this string is null
A plain UniConfTree that holds keys and values.
const UniConfKey & key() const
Returns the key field.
A class used to provide a masked lookup for characters in a string.
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
virtual void commit()
Commits any changes.
char * blocking_getline(time_t wait_msec, int separator='\n', int readahead=1024)
This is a version of getline() that allows you to block for more data to arrive.
int getwfd() const
Returns the Unix file descriptor for writing to this stream.
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
UniIniGen(WvStringParm filename, int _create_mode=0666, SaveCallback _save_cb=SaveCallback())
Creates a generator which can load/modify/save a .ini file.
virtual bool refresh()
Refreshes information about a key recursively.
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
Loads and saves ".ini"-style files similar to those used by Windows, but adapted to represent keys an...
char * edit()
make the string editable, and return a non-const (char*)
void visit(const Visitor &visitor, void *userdata, bool preorder=true, bool postorder=false) const
Performs a traversal on this tree using the specified visitor function and traversal type(s)...
WvString wvtcl_getword(WvBuf &buf, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
Get a single tcl word from an input buffer, and return the rest of the buffer untouched.
void hold_delta()
Pauses notifications until matched with a call to unhold_delta().
virtual bool isok() const
return true if the stream is actually usable right now
virtual void close()
Closes the file descriptors.
size_t used() const
Returns the number of elements in the buffer currently available for reading.
void prepend(const UniConfKey &other)
Prepends a path to this path.
WvString wvtcl_escape(WvStringParm s, const WvStringMask &nasties=WVTCL_NASTY_SPACES)
tcl-escape a string.
size_t strchr(int ch)
Returns the number of characters that would have to be read to find the first instance of the charact...
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
void unhold_delta()
Resumes notifications when each hold_delta() has been matched.
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
WvString is an implementation of a simple and efficient printable-string class.
UniConfKey fullkey(const Sub *ancestor=NULL) const
Returns full path of this node relative to an ancestor.
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
virtual bool refresh()
Refreshes information about a key recursively.
WvString wvtcl_unescape(WvStringParm s)
tcl-unescape a string.
virtual void commit()
Commits any changes.
bool haschildren() const
Returns true if the node has children.