Clean-up in TLSRecvLine().

Unable to track down an uninintialized memory read in its helper
function, I simplified the code.  The old code was also rescanning all
old input, each time it appended new, looking for a '\n' that could
only be in the new; let's not waste time doing that !  If the UMR is
still there, it should be easier to find now ...

Also changed its return type to ssize_t (if there's any sense in the
buffer size being size_t, the return could overflow int) and fix its
garbled documentation.  (The @return refers to a parameter #line that
didn't exist, while talking about things other than the return value
and being wrong about whether the return count included terminating
'\0'; and the actual parameters weren't documented.)
Check return from TLSRecvLine() before comparing the text returned.

Not sure how these turned into the uninitialized memory reads that
valgrind reports, but TLSRecvLine() can't have given us the expected
OK messages if what it's given us is shorter than that message.  So
check for that (and maybe this'll avoid the UMRs - but I suspect
SSL_Read()'s return is actually the value that depends on
uninitialised data).
Don't just assume sscanf() succeeds - check it !

An uninitialized memory read reported by valgrind appears to stem from
sscanf() not filling a buffer for its second format specifier;
presumably it got text that didn't match its format.  Checking its
return is The Right Thing To Do anyway, so do that and log an error if
it didn't do what we expected.
LogRaw: const-ify buf (and tidy up a bit).

Since LogRaw() only reads buf, make clear that this is the case by
declaring it const.  Its loop body had a conditional lacking braces
required by our coding style; rather than doubling the number of lines
involved, I reduced it to one.  Hopefully the ?: involved isn't too
hard to read.
Clean-up in RecvSocketStream().

Its documentation was inadequate and the little it said was wrong.  It
was duplicating a test against got == -1.  If some perversity had lead
to recv returning more than the available space, its check against
data read being equal to space available would never have been met.

Its declaration didn't match its definition (used a char* where a char
[CF_BUFSIZE] should be); nor did that of its Send brother.
Fix ReceiveTransaction()'s call to LogRaw().

It read up to the buffer's size, but could end up with less than that
in the buffer; yet told LogRaw() to read the full size.  Since
LogRaw() takes the asserted size literally, it'll actually replace any
'\0' with a '.' and keep going to the end of the buffer; this leads
to reading uninitialized memory if the read didn't fill the buffer.
Specify the actual size of data in the buffer, not the space available.
UMR-fix: '\0'-terminate data from read().

Calling strrchr() involves looking for the first '\0' byte and then
coming back looking for the sought byte; which only works well if the
string being searched is '\0'-terminated.  Since read() doesn't do
that, we have to do it ourselves.

Tidied up a comment while I was there.
Reworked RlistFromSplitString for clarity and correctness.

The prior code was confused about what SubStrnCopyChr()'s returned
count was: the number of bytes of from[] consumed or the number
written in to[].  The documentation claimed, and the caller assumed,
the former; the implementation did the latter, comparing count against
the length constraint and only incrementing it once round the loop,
even when consuming an escape sequence (two bytes).

The caller would have reused the tail of any item that included more
than one escaped separator (and seen an empty entry after an item with
just one); and its unconditional increment of sp ensured that it
stepped over the final '\0' if the last item didn't include an escaped
separator.  It had consequently grown several kludges that only mostly
fixed these problems.

The implementation, further, exited the loop only if count got to be
more than len - 1, i.e. len or more; so it would happily have written
to[len-1], leaving no space at the end for the terminator: no number
of (wantonly expensive) calls to memset(to,0,len) beforehand would
leave a '\0' at the end in that case.  It also contained code to
handle bad calls that can never happen; asserting they don't happen
makes more sense.

Somewhere in all of that, valgrind caught us reading the byte after
the end of a string.

Reworked to return the bytes consumed, as expected by the caller,
which thus no longer needs its kludges.  It only increments sp if it
should, so won't skip off the end, and asserts each item ends
sensibly.  The implementation now terminates with one '\0' byte in the
one place it's needed, instead of firehosing the buffer with them
(twice); it checks the amount written, correctly leaving space for
this one terminator; and it asserts the things that have to be true
(and are).  Added a few simple unit tests.
Add 2 functions to DB API
- WriteNoCommit : write to DB without commiting the last transaction
- CloseCommit   : commit current transaction before closing DB conn

These two functions will allow us to solve one specific performance problem when we need to open a DB, batch insert a set of records and close the DB afterwords
Redmine#4482: introduce cf-promises -T option to tag a release directory
Merge pull request #1419 from tzz/feature/redmine4482-cf-promises-tag-release

Redmine#4482: introduce cf-promises -T option to tag a release directory
Revert "Redmine#4482: introduce cf-promises -T option to tag a release directory"

This reverts commit 70cc8ad9df45ca10d23f179d75611ab067ccafd2.

It breaks masterfiles/tests/acceptance/promises/promises.cf test on
certain platforms, like RHEL4.
Revert "Revert "Redmine#4482: introduce cf-promises -T option to tag a release directory""

This reverts commit 1607f7babde7ff693def73f42bf8e7314c7ae607.

Could not duplicate the parsing problem in RHEL testing, and the test logs don't show it.
Merge pull request #1414 from ediosyncratic/leak-fixes

Memory abuse fixes
Make backups of the lock database after a cf-agent run.

This is in anticipation of turning on NOSYNC for the lock database, in
order to improve performance. But this leaves the database open to
corruption in case of system crash. To deal with that, while still
maintaining performance, we make a complete backup of the database
file at the end of an agent run, which is fsync'ed to disk in order to
survive a crash.

Later, if we detect that the database timestamp is older than the boot
time, we assume that there has been a crash, and restore the database
from the backup to avoid potential corruption.
Implement fsync() and GetUptimeSeconds() on Windows.
Add dbid arg to the DBPrivOpen function and make sure that the locks DB is open in NOSYNC mode
variable ip_len breaks build on aix so switched it to len_ip
Redmine#4482: clear config->tag_release_dir explicitly
Merge pull request #1416 from kacfengine/lock_db_backup

Make backups of the lock database after a cf-agent run.