Business-KontoCheck
view release on metacpan or search on metacpan
zlib/examples/gzlog.c view on Meta::CPAN
point in the process. Return -1 if the write to foo.gz failed. */
local int log_mark(struct log *log, int op)
{
int ret;
unsigned char ext[EXTRA];
PUT8(ext, log->first);
PUT8(ext + 8, log->last);
PUT4(ext + 16, log->ccrc);
PUT4(ext + 20, log->clen);
PUT4(ext + 24, log->tcrc);
PUT4(ext + 28, log->tlen);
PUT2(ext + 32, log->stored);
ext[34] = log->back - 3 + (op << 3);
fsync(log->fd);
ret = lseek(log->fd, HEAD, SEEK_SET) < 0 ||
write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0;
fsync(log->fd);
return ret;
}
/* Rewrite the last block header bits and subsequent zero bits to get to a byte
boundary, setting the last block bit if last is true, and then write the
remainder of the stored block header (length and one's complement). Leave
the file pointer after the end of the last stored block data. Return -1 if
there is a read or write failure on the foo.gz file */
local int log_last(struct log *log, int last)
{
int back, len, mask;
unsigned char buf[6];
/* determine the locations of the bytes and bits to modify */
back = log->last == log->first ? log->back : 8;
len = back > 8 ? 2 : 1; /* bytes back from log->last */
mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */
/* get the byte to modify (one or two back) into buf[0] -- don't need to
read the byte if the last-bit is eight bits back, since in that case
the entire byte will be modified */
buf[0] = 0;
if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
read(log->fd, buf, 1) != 1))
return -1;
/* change the last-bit of the last stored block as requested -- note
that all bits above the last-bit are set to zero, per the type bits
of a stored block being 00 and per the convention that the bits to
bring the stream to a byte boundary are also zeros */
buf[1] = 0;
buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0);
/* write the modified stored block header and lengths, move the file
pointer to after the last stored block data */
PUT2(buf + 2, log->stored);
PUT2(buf + 4, log->stored ^ 0xffff);
return lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
write(log->fd, buf + 2 - len, len + 4) != len + 4 ||
lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0;
}
/* Append len bytes from data to the locked and open log file. len may be zero
if recovering and no .add file was found. In that case, the previous state
of the foo.gz file is restored. The data is appended uncompressed in
deflate stored blocks. Return -1 if there was an error reading or writing
the foo.gz file. */
local int log_append(struct log *log, unsigned char *data, size_t len)
{
uint put;
off_t end;
unsigned char buf[8];
/* set the last block last-bit and length, in case recovering an
interrupted append, then position the file pointer to append to the
block */
if (log_last(log, 1))
return -1;
/* append, adding stored blocks and updating the offset of the last stored
block as needed, and update the total crc and length */
while (len) {
/* append as much as we can to the last block */
put = (MAX_STORE << 10) - log->stored;
if (put > len)
put = (uint)len;
if (put) {
if (write(log->fd, data, put) != put)
return -1;
BAIL(1);
log->tcrc = crc32(log->tcrc, data, put);
log->tlen += put;
log->stored += put;
data += put;
len -= put;
}
/* if we need to, add a new empty stored block */
if (len) {
/* mark current block as not last */
if (log_last(log, 0))
return -1;
/* point to new, empty stored block */
log->last += 4 + log->stored + 1;
log->stored = 0;
}
/* mark last block as last, update its length */
if (log_last(log, 1))
return -1;
BAIL(2);
}
/* write the new crc and length trailer, and truncate just in case (could
be recovering from partial append with a missing foo.add file) */
PUT4(buf, log->tcrc);
PUT4(buf + 4, log->tlen);
if (write(log->fd, buf, 8) != 8 ||
(end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
return -1;
/* write the extra field, marking the log file as done, delete .add file */
( run in 2.672 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )