Rizin
unix-like reverse engineering framework and cli tools
gzlog.c File Reference
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "zlib.h"
#include "gzlog.h"

Go to the source code of this file.

Classes

struct  log
 

Macros

#define local   static
 
#define BAIL(n)
 
#define PATIENCE   300
 
#define MAX_STORE   16
 
#define TRIGGER   1024
 
#define DICT   32768U
 
#define NO_OP   0
 
#define APPEND_OP   1
 
#define COMPRESS_OP   2
 
#define REPLACE_OP   3
 
#define PULL2(p)   ((p)[0]+((uint)((p)[1])<<8))
 
#define PULL4(p)   (PULL2(p)+((ulong)PULL2(p+2)<<16))
 
#define PULL8(p)   (PULL4(p)+((off_t)PULL4(p+4)<<32))
 
#define PUT2(p, a)   do {(p)[0]=a;(p)[1]=(a)>>8;} while(0)
 
#define PUT4(p, a)   do {PUT2(p,a);PUT2(p+2,a>>16);} while(0)
 
#define PUT8(p, a)   do {PUT4(p,a);PUT4(p+4,a>>32);} while(0)
 
#define LOGID   "\106\035\172" /* should be three non-zero characters */
 
#define HEAD   sizeof(log_gzhead) /* should be 16 */
 
#define EXTRA   sizeof(log_gzext) /* should be 35 */
 
#define BODY   sizeof(log_gzbody)
 

Typedefs

typedef unsigned int uint
 
typedef unsigned long ulong
 

Functions

int log_lock (struct log *log)
 
void log_touch (struct log *log)
 
int log_check (struct log *log)
 
void log_unlock (struct log *log)
 
int log_head (struct log *log)
 
int log_mark (struct log *log, int op)
 
int log_last (struct log *log, int last)
 
int log_append (struct log *log, unsigned char *data, size_t len)
 
int log_replace (struct log *log)
 
int log_compress (struct log *log, unsigned char *data, size_t len)
 
void log_log (struct log *log, int op, char *record)
 
int log_recover (struct log *log, int op)
 
void log_close (struct log *log)
 
int log_open (struct log *log)
 
gzloggzlog_open (char *path)
 
int gzlog_compress (gzlog *logd)
 
int gzlog_write (gzlog *logd, void *data, size_t len)
 
int gzlog_close (gzlog *logd)
 

Variables

unsigned char log_gzhead []
 
unsigned char log_gzext []
 
unsigned char log_gzbody []
 

Macro Definition Documentation

◆ APPEND_OP

#define APPEND_OP   1

Definition at line 273 of file gzlog.c.

◆ BAIL

#define BAIL (   n)

Definition at line 254 of file gzlog.c.

◆ BODY

#define BODY   sizeof(log_gzbody)

Definition at line 337 of file gzlog.c.

◆ COMPRESS_OP

#define COMPRESS_OP   2

Definition at line 274 of file gzlog.c.

◆ DICT

#define DICT   32768U

Definition at line 269 of file gzlog.c.

◆ EXTRA

#define EXTRA   sizeof(log_gzext) /* should be 35 */

Definition at line 328 of file gzlog.c.

◆ HEAD

#define HEAD   sizeof(log_gzhead) /* should be 16 */

Definition at line 316 of file gzlog.c.

◆ local

#define local   static

Definition at line 241 of file gzlog.c.

◆ LOGID

#define LOGID   "\106\035\172" /* should be three non-zero characters */

Definition at line 288 of file gzlog.c.

◆ MAX_STORE

#define MAX_STORE   16

Definition at line 261 of file gzlog.c.

◆ NO_OP

#define NO_OP   0

Definition at line 272 of file gzlog.c.

◆ PATIENCE

#define PATIENCE   300

Definition at line 258 of file gzlog.c.

◆ PULL2

#define PULL2 (   p)    ((p)[0]+((uint)((p)[1])<<8))

Definition at line 278 of file gzlog.c.

◆ PULL4

#define PULL4 (   p)    (PULL2(p)+((ulong)PULL2(p+2)<<16))

Definition at line 279 of file gzlog.c.

◆ PULL8

#define PULL8 (   p)    (PULL4(p)+((off_t)PULL4(p+4)<<32))

Definition at line 280 of file gzlog.c.

◆ PUT2

#define PUT2 (   p,
  a 
)    do {(p)[0]=a;(p)[1]=(a)>>8;} while(0)

Definition at line 283 of file gzlog.c.

◆ PUT4

#define PUT4 (   p,
  a 
)    do {PUT2(p,a);PUT2(p+2,a>>16);} while(0)

Definition at line 284 of file gzlog.c.

◆ PUT8

#define PUT8 (   p,
  a 
)    do {PUT4(p,a);PUT4(p+4,a>>32);} while(0)

Definition at line 285 of file gzlog.c.

◆ REPLACE_OP

#define REPLACE_OP   3

Definition at line 275 of file gzlog.c.

◆ TRIGGER

#define TRIGGER   1024

Definition at line 266 of file gzlog.c.

Typedef Documentation

◆ uint

typedef unsigned int uint

Definition at line 242 of file gzlog.c.

◆ ulong

typedef unsigned long ulong

Definition at line 243 of file gzlog.c.

Function Documentation

◆ gzlog_close()

int gzlog_close ( gzlog logd)

Definition at line 1044 of file gzlog.c.

1045 {
1046  struct log *log = logd;
1047 
1048  /* check arguments */
1049  if (log == NULL || strcmp(log->id, LOGID))
1050  return -3;
1051 
1052  /* close the log file and release the lock */
1053  log_close(log);
1054 
1055  /* free structure and return */
1056  if (log->path != NULL)
1057  free(log->path);
1058  strcpy(log->id, "bad");
1059  free(log);
1060  return 0;
1061 }
#define NULL
Definition: cris-opc.c:27
void log_close(struct log *log)
Definition: gzlog.c:798
#define LOGID
Definition: gzlog.c:288
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
Definition: gzlog.c:289
char * path
Definition: gzlog.c:292
char id[4]
Definition: gzlog.c:290

References free(), log::id, log_close(), LOGID, NULL, and log::path.

◆ gzlog_compress()

int gzlog_compress ( gzlog logd)

Definition at line 910 of file gzlog.c.

911 {
912  int fd, ret;
913  uint block;
914  size_t len, next;
915  unsigned char *data, buf[5];
916  struct log *log = logd;
917 
918  /* check arguments */
919  if (log == NULL || strcmp(log->id, LOGID))
920  return -3;
921 
922  /* see if we lost the lock -- if so get it again and reload the extra
923  field information (it probably changed), recover last operation if
924  necessary */
925  if (log_check(log) && log_open(log))
926  return -1;
927 
928  /* create space for uncompressed data */
929  len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) +
930  log->stored;
931  if ((data = malloc(len)) == NULL)
932  return -2;
933 
934  /* do statement here is just a cheap trick for error handling */
935  do {
936  /* read in the uncompressed data */
937  if (lseek(log->fd, log->first - 1, SEEK_SET) < 0)
938  break;
939  next = 0;
940  while (next < len) {
941  if (read(log->fd, buf, 5) != 5)
942  break;
943  block = PULL2(buf + 1);
944  if (next + block > len ||
945  read(log->fd, (char *)data + next, block) != block)
946  break;
947  next += block;
948  }
949  if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored)
950  break;
951  log_touch(log);
952 
953  /* write the uncompressed data to the .add file */
954  strcpy(log->end, ".add");
955  fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
956  if (fd < 0)
957  break;
958  ret = (size_t)write(fd, data, len) != len;
959  if (ret | close(fd))
960  break;
961  log_touch(log);
962 
963  /* write the dictionary for the next compress to the .temp file */
964  strcpy(log->end, ".temp");
965  fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
966  if (fd < 0)
967  break;
968  next = DICT > len ? len : DICT;
969  ret = (size_t)write(fd, (char *)data + len - next, next) != next;
970  if (ret | close(fd))
971  break;
972  log_touch(log);
973 
974  /* roll back to compressed data, mark the compress in progress */
975  log->last = log->first;
976  log->stored = 0;
977  if (log_mark(log, COMPRESS_OP))
978  break;
979  BAIL(7);
980 
981  /* compress and append the data (clears mark) */
982  ret = log_compress(log, data, len);
983  free(data);
984  return ret;
985  } while (0);
986 
987  /* broke out of do above on i/o error */
988  free(data);
989  return -1;
990 }
size_t len
Definition: 6502dis.c:15
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep lseek
Definition: sflib.h:113
int log_mark(struct log *log, int op)
Definition: gzlog.c:437
#define BAIL(n)
Definition: gzlog.c:254
unsigned int uint
Definition: gzlog.c:242
int log_check(struct log *log)
Definition: gzlog.c:384
void log_touch(struct log *log)
Definition: gzlog.c:372
#define PULL2(p)
Definition: gzlog.c:278
#define COMPRESS_OP
Definition: gzlog.c:274
int log_open(struct log *log)
Definition: gzlog.c:815
int log_compress(struct log *log, unsigned char *data, size_t len)
Definition: gzlog.c:608
#define DICT
Definition: gzlog.c:269
voidpf void * buf
Definition: ioapi.h:138
void * malloc(size_t size)
Definition: malloc.c:123
#define O_WRONLY
Definition: sftypes.h:487
#define O_CREAT
Definition: sftypes.h:489
int size_t
Definition: sftypes.h:40
#define O_TRUNC
Definition: sftypes.h:492
uint stored
Definition: gzlog.c:296
off_t first
Definition: gzlog.c:294
off_t last
Definition: gzlog.c:297
int fd
Definition: gzlog.c:291
char * end
Definition: gzlog.c:293
static const z80_opcode fd[]
Definition: z80_tab.h:997
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References BAIL, close, COMPRESS_OP, DICT, log::end, fd, log::fd, log::first, free(), log::id, log::last, len, log_check(), log_compress(), log_mark(), log_open(), log_touch(), LOGID, lseek, malloc(), NULL, O_CREAT, O_TRUNC, O_WRONLY, log::path, PULL2, read(), SEEK_CUR, SEEK_SET, log::stored, and write.

Referenced by gzlog_write().

◆ gzlog_open()

gzlog* gzlog_open ( char *  path)

Definition at line 867 of file gzlog.c.

868 {
869  size_t n;
870  struct log *log;
871 
872  /* check arguments */
873  if (path == NULL || *path == 0)
874  return NULL;
875 
876  /* allocate and initialize log structure */
877  log = malloc(sizeof(struct log));
878  if (log == NULL)
879  return NULL;
880  strcpy(log->id, LOGID);
881  log->fd = -1;
882 
883  /* save path and end of path for name construction */
884  n = strlen(path);
885  log->path = malloc(n + 9); /* allow for ".repairs" */
886  if (log->path == NULL) {
887  free(log);
888  return NULL;
889  }
890  strcpy(log->path, path);
891  log->end = log->path + n;
892 
893  /* gain exclusive access and verify log file -- may perform a
894  recovery operation if needed */
895  if (log_open(log)) {
896  free(log->path);
897  free(log);
898  return NULL;
899  }
900 
901  /* return pointer to log structure */
902  return log;
903 }
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
int n
Definition: mipsasm.c:19
def log(text)

References log::end, log::fd, free(), log::id, test-lz4-list::log(), log_open(), LOGID, malloc(), n, NULL, path, and log::path.

◆ gzlog_write()

int gzlog_write ( gzlog logd,
void *  data,
size_t  len 
)

Definition at line 997 of file gzlog.c.

998 {
999  int fd, ret;
1000  struct log *log = logd;
1001 
1002  /* check arguments */
1003  if (log == NULL || strcmp(log->id, LOGID))
1004  return -3;
1005  if (data == NULL || len <= 0)
1006  return 0;
1007 
1008  /* see if we lost the lock -- if so get it again and reload the extra
1009  field information (it probably changed), recover last operation if
1010  necessary */
1011  if (log_check(log) && log_open(log))
1012  return -1;
1013 
1014  /* create and write .add file */
1015  strcpy(log->end, ".add");
1016  fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1017  if (fd < 0)
1018  return -1;
1019  ret = (size_t)write(fd, data, len) != len;
1020  if (ret | close(fd))
1021  return -1;
1022  log_touch(log);
1023 
1024  /* mark log file with append in progress */
1025  if (log_mark(log, APPEND_OP))
1026  return -1;
1027  BAIL(8);
1028 
1029  /* append data (clears mark) */
1030  if (log_append(log, data, len))
1031  return -1;
1032 
1033  /* check to see if it's time to compress -- if not, then done */
1034  if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER)
1035  return 0;
1036 
1037  /* time to compress */
1038  return gzlog_compress(log);
1039 }
int gzlog_compress(gzlog *logd)
Definition: gzlog.c:910
int log_append(struct log *log, unsigned char *data, size_t len)
Definition: gzlog.c:501
#define APPEND_OP
Definition: gzlog.c:273
#define TRIGGER
Definition: gzlog.c:266

References APPEND_OP, BAIL, close, log::end, fd, log::first, gzlog_compress(), log::id, log::last, len, log_append(), log_check(), log_mark(), log_open(), log_touch(), LOGID, NULL, O_CREAT, O_TRUNC, O_WRONLY, log::path, log::stored, TRIGGER, and write.

◆ log_append()

int log_append ( struct log log,
unsigned char *  data,
size_t  len 
)

Definition at line 501 of file gzlog.c.

502 {
503  uint put;
504  off_t end;
505  unsigned char buf[8];
506 
507  /* set the last block last-bit and length, in case recovering an
508  interrupted append, then position the file pointer to append to the
509  block */
510  if (log_last(log, 1))
511  return -1;
512 
513  /* append, adding stored blocks and updating the offset of the last stored
514  block as needed, and update the total crc and length */
515  while (len) {
516  /* append as much as we can to the last block */
517  put = (MAX_STORE << 10) - log->stored;
518  if (put > len)
519  put = (uint)len;
520  if (put) {
521  if (write(log->fd, data, put) != put)
522  return -1;
523  BAIL(1);
524  log->tcrc = crc32(log->tcrc, data, put);
525  log->tlen += put;
526  log->stored += put;
527  data += put;
528  len -= put;
529  }
530 
531  /* if we need to, add a new empty stored block */
532  if (len) {
533  /* mark current block as not last */
534  if (log_last(log, 0))
535  return -1;
536 
537  /* point to new, empty stored block */
538  log->last += 4 + log->stored + 1;
539  log->stored = 0;
540  }
541 
542  /* mark last block as last, update its length */
543  if (log_last(log, 1))
544  return -1;
545  BAIL(2);
546  }
547 
548  /* write the new crc and length trailer, and truncate just in case (could
549  be recovering from partial append with a missing foo.add file) */
550  PUT4(buf, log->tcrc);
551  PUT4(buf + 4, log->tlen);
552  if (write(log->fd, buf, 8) != 8 ||
553  (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
554  return -1;
555 
556  /* write the extra field, marking the log file as done, delete .add file */
557  if (log_mark(log, NO_OP))
558  return -1;
559  strcpy(log->end, ".add");
560  unlink(log->path); /* ignore error, since may not exist */
561  return 0;
562 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence ftruncate
Definition: sflib.h:113
int log_last(struct log *log, int last)
Definition: gzlog.c:462
#define MAX_STORE
Definition: gzlog.c:261
#define NO_OP
Definition: gzlog.c:272
#define PUT4(p, a)
Definition: gzlog.c:284
static static fork const void static count static fd const char static mode unlink
Definition: sflib.h:41
int off_t
Definition: sftypes.h:41
ulong tlen
Definition: gzlog.c:301
ulong tcrc
Definition: gzlog.c:300
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:1063

References BAIL, crc32(), test_evm::end, log::end, log::fd, ftruncate, if(), log::last, len, log_last(), log_mark(), lseek, MAX_STORE, NO_OP, log::path, PUT4, SEEK_CUR, log::stored, log::tcrc, log::tlen, unlink, and write.

Referenced by gzlog_write(), and log_recover().

◆ log_check()

int log_check ( struct log log)

Definition at line 384 of file gzlog.c.

385 {
386  struct stat st;
387 
388  strcpy(log->end, ".lock");
389  if (stat(log->path, &st) || st.st_mtime != log->lock)
390  return 1;
391  log_touch(log);
392  return 0;
393 }
static stat
Definition: sflib.h:131
time_t lock
Definition: gzlog.c:302
Definition: sftypes.h:80

References log::end, log::lock, log_touch(), log::path, and stat.

Referenced by gzlog_compress(), gzlog_write(), and log_unlock().

◆ log_close()

void log_close ( struct log log)

Definition at line 798 of file gzlog.c.

799 {
800  if (log->fd >= 0)
801  close(log->fd);
802  log->fd = -1;
803  log_unlock(log);
804 }
void log_unlock(struct log *log)
Definition: gzlog.c:396

References close, log::fd, and log_unlock().

Referenced by gzlog_close(), and log_open().

◆ log_compress()

int log_compress ( struct log log,
unsigned char *  data,
size_t  len 
)

Definition at line 608 of file gzlog.c.

609 {
610  int fd;
611  uint got, max;
612  ssize_t dict;
613  off_t end;
614  z_stream strm;
615  unsigned char buf[DICT];
616 
617  /* compress and append compressed data */
618  if (len) {
619  /* set up for deflate, allocating memory */
620  strm.zalloc = Z_NULL;
621  strm.zfree = Z_NULL;
622  strm.opaque = Z_NULL;
625  return -2;
626 
627  /* read in dictionary (last 32K of data that was compressed) */
628  strcpy(log->end, ".dict");
629  fd = open(log->path, O_RDONLY, 0);
630  if (fd >= 0) {
631  dict = read(fd, buf, DICT);
632  close(fd);
633  if (dict < 0) {
634  deflateEnd(&strm);
635  return -1;
636  }
637  if (dict)
638  deflateSetDictionary(&strm, buf, (uint)dict);
639  }
640  log_touch(log);
641 
642  /* prime deflate with last bits of previous block, position write
643  pointer to write those bits and overwrite what follows */
644  if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1),
645  SEEK_SET) < 0 ||
646  read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) {
647  deflateEnd(&strm);
648  return -1;
649  }
650  deflatePrime(&strm, (8 - log->back) & 7, *buf);
651 
652  /* compress, finishing with a partial non-last empty static block */
653  strm.next_in = data;
654  max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */
655  do {
656  strm.avail_in = len > max ? max : (uint)len;
657  len -= strm.avail_in;
658  do {
659  strm.avail_out = DICT;
660  strm.next_out = buf;
662  got = DICT - strm.avail_out;
663  if (got && write(log->fd, buf, got) != got) {
664  deflateEnd(&strm);
665  return -1;
666  }
667  log_touch(log);
668  } while (strm.avail_out == 0);
669  } while (len);
670  deflateEnd(&strm);
671  BAIL(5);
672 
673  /* find start of empty static block -- scanning backwards the first one
674  bit is the second bit of the block, if the last byte is zero, then
675  we know the byte before that has a one in the top bit, since an
676  empty static block is ten bits long */
677  if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 ||
678  read(log->fd, buf, 1) != 1)
679  return -1;
680  log->first++;
681  if (*buf) {
682  log->back = 1;
683  while ((*buf & ((uint)1 << (8 - log->back++))) == 0)
684  ; /* guaranteed to terminate, since *buf != 0 */
685  }
686  else
687  log->back = 10;
688 
689  /* update compressed crc and length */
690  log->ccrc = log->tcrc;
691  log->clen = log->tlen;
692  }
693  else {
694  /* no data to compress -- fix up existing gzip stream */
695  log->tcrc = log->ccrc;
696  log->tlen = log->clen;
697  }
698 
699  /* complete and truncate gzip stream */
700  log->last = log->first;
701  log->stored = 0;
702  PUT4(buf, log->tcrc);
703  PUT4(buf + 4, log->tlen);
704  if (log_last(log, 1) || write(log->fd, buf, 8) != 8 ||
705  (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
706  return -1;
707  BAIL(6);
708 
709  /* mark as being in the replace operation */
710  if (log_mark(log, REPLACE_OP))
711  return -1;
712 
713  /* execute the replace operation and mark the file as done */
714  return log_replace(log);
715 }
int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
Definition: deflate.c:416
int ZEXPORT deflatePrime(z_streamp strm, int bits, int value)
Definition: deflate.c:582
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:1119
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:804
int max
Definition: enough.c:225
static lzma_stream strm
Definition: full_flush.c:20
#define REPLACE_OP
Definition: gzlog.c:275
int log_replace(struct log *log)
Definition: gzlog.c:571
#define O_RDONLY
Definition: sftypes.h:486
int ssize_t
Definition: sftypes.h:39
int back
Definition: gzlog.c:295
ulong ccrc
Definition: gzlog.c:298
ulong clen
Definition: gzlog.c:299
uint8_t * next_out
Definition: base.h:490
size_t avail_out
Definition: base.h:491
const uint8_t * next_in
Definition: base.h:486
size_t avail_in
Definition: base.h:487
#define Z_DEFLATED
Definition: zlib.h:209
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1814
#define Z_OK
Definition: zlib.h:177
#define Z_NO_FLUSH
Definition: zlib.h:168
#define Z_NULL
Definition: zlib.h:212
#define Z_PARTIAL_FLUSH
Definition: zlib.h:169
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:193

References lzma_stream::avail_in, lzma_stream::avail_out, log::back, BAIL, log::ccrc, log::clen, close, deflate(), deflateEnd(), deflateInit2, deflatePrime(), deflateSetDictionary(), DICT, test_evm::end, log::end, fd, log::fd, log::first, ftruncate, log::last, len, log_last(), log_mark(), log_replace(), log_touch(), lseek, max, lzma_stream::next_in, lzma_stream::next_out, O_RDONLY, log::path, PUT4, read(), REPLACE_OP, SEEK_CUR, SEEK_SET, log::stored, strm, log::tcrc, log::tlen, write, Z_DEFAULT_COMPRESSION, Z_DEFAULT_STRATEGY, Z_DEFLATED, Z_NO_FLUSH, Z_NULL, Z_OK, and Z_PARTIAL_FLUSH.

Referenced by gzlog_compress(), and log_recover().

◆ log_head()

int log_head ( struct log log)

Definition at line 410 of file gzlog.c.

411 {
412  int op;
413  unsigned char buf[HEAD + EXTRA];
414 
415  if (lseek(log->fd, 0, SEEK_SET) < 0 ||
416  read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA ||
417  memcmp(buf, log_gzhead, HEAD)) {
418  return -1;
419  }
420  log->first = PULL8(buf + HEAD);
421  log->last = PULL8(buf + HEAD + 8);
422  log->ccrc = PULL4(buf + HEAD + 16);
423  log->clen = PULL4(buf + HEAD + 20);
424  log->tcrc = PULL4(buf + HEAD + 24);
425  log->tlen = PULL4(buf + HEAD + 28);
426  log->stored = PULL2(buf + HEAD + 32);
427  log->back = 3 + (buf[HEAD + 34] & 7);
428  op = (buf[HEAD + 34] >> 3) & 3;
429  return op;
430 }
ut8 op
Definition: 6502dis.c:13
#define HEAD
Definition: gzlog.c:316
#define PULL8(p)
Definition: gzlog.c:280
unsigned char log_gzhead[]
Definition: gzlog.c:306
#define PULL4(p)
Definition: gzlog.c:279
#define EXTRA
Definition: gzlog.c:328
Definition: dis.c:32

References log::back, log::ccrc, log::clen, EXTRA, log::fd, log::first, HEAD, log::last, log_gzhead, lseek, op, PULL2, PULL4, PULL8, read(), SEEK_SET, log::stored, log::tcrc, and log::tlen.

Referenced by log_open().

◆ log_last()

int log_last ( struct log log,
int  last 
)

Definition at line 462 of file gzlog.c.

463 {
464  int back, len, mask;
465  unsigned char buf[6];
466 
467  /* determine the locations of the bytes and bits to modify */
468  back = log->last == log->first ? log->back : 8;
469  len = back > 8 ? 2 : 1; /* bytes back from log->last */
470  mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */
471 
472  /* get the byte to modify (one or two back) into buf[0] -- don't need to
473  read the byte if the last-bit is eight bits back, since in that case
474  the entire byte will be modified */
475  buf[0] = 0;
476  if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
477  read(log->fd, buf, 1) != 1))
478  return -1;
479 
480  /* change the last-bit of the last stored block as requested -- note
481  that all bits above the last-bit are set to zero, per the type bits
482  of a stored block being 00 and per the convention that the bits to
483  bring the stream to a byte boundary are also zeros */
484  buf[1] = 0;
485  buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0);
486 
487  /* write the modified stored block header and lengths, move the file
488  pointer to after the last stored block data */
489  PUT2(buf + 2, log->stored);
490  PUT2(buf + 4, log->stored ^ 0xffff);
491  return lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
492  write(log->fd, buf + 2 - len, len + 4) != len + 4 ||
493  lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0;
494 }
#define mask()
#define PUT2(p, a)
Definition: gzlog.c:283

References log::back, log::fd, log::first, log::last, len, lseek, mask, PUT2, read(), SEEK_CUR, SEEK_SET, log::stored, and write.

Referenced by log_append(), and log_compress().

◆ log_lock()

int log_lock ( struct log log)

Definition at line 348 of file gzlog.c.

349 {
350  int fd;
351  struct stat st;
352 
353  strcpy(log->end, ".lock");
354  while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) {
355  if (errno != EEXIST)
356  return -1;
357  if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) {
358  unlink(log->path);
359  continue;
360  }
361  sleep(2); /* relinquish the CPU for two seconds while waiting */
362  }
363  close(fd);
364  if (stat(log->path, &st) == 0)
365  log->lock = st.st_mtime;
366  return 0;
367 }
#define PATIENCE
Definition: gzlog.c:258
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
#define EEXIST
Definition: sftypes.h:127
#define O_EXCL
Definition: sftypes.h:490

References close, EEXIST, log::end, fd, log::lock, NULL, O_CREAT, O_EXCL, log::path, PATIENCE, stat, time, and unlink.

Referenced by log_open().

◆ log_log()

void log_log ( struct log log,
int  op,
char *  record 
)

Definition at line 718 of file gzlog.c.

719 {
720  time_t now;
721  FILE *rec;
722 
723  now = time(NULL);
724  strcpy(log->end, ".repairs");
725  rec = fopen(log->path, "a");
726  if (rec == NULL)
727  return;
728  fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ?
729  "append" : (op == COMPRESS_OP ? "compress" : "replace"), record);
730  fclose(rec);
731  return;
732 }
string FILE
Definition: benchmark.py:21
int time_t
Definition: sftypes.h:66
Definition: tar.h:52

References APPEND_OP, COMPRESS_OP, log::end, benchmark::FILE, NULL, log::path, and time.

Referenced by log_recover().

◆ log_mark()

int log_mark ( struct log log,
int  op 
)

Definition at line 437 of file gzlog.c.

438 {
439  int ret;
440  unsigned char ext[EXTRA];
441 
442  PUT8(ext, log->first);
443  PUT8(ext + 8, log->last);
444  PUT4(ext + 16, log->ccrc);
445  PUT4(ext + 20, log->clen);
446  PUT4(ext + 24, log->tcrc);
447  PUT4(ext + 28, log->tlen);
448  PUT2(ext + 32, log->stored);
449  ext[34] = log->back - 3 + (op << 3);
450  fsync(log->fd);
451  ret = lseek(log->fd, HEAD, SEEK_SET) < 0 ||
452  write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0;
453  fsync(log->fd);
454  return ret;
455 }
static const char ext[]
Definition: apprentice.c:1981
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg fsync
Definition: sflib.h:79
#define PUT8(p, a)
Definition: gzlog.c:285

References log::back, log::ccrc, log::clen, ext, EXTRA, log::fd, log::first, fsync, HEAD, log::last, lseek, PUT2, PUT4, PUT8, SEEK_SET, log::stored, log::tcrc, log::tlen, and write.

Referenced by gzlog_compress(), gzlog_write(), log_append(), log_compress(), and log_replace().

◆ log_open()

int log_open ( struct log log)

Definition at line 815 of file gzlog.c.

816 {
817  int op;
818 
819  /* release open file resource if left over -- can occur if lock lost
820  between gzlog_open() and gzlog_write() */
821  if (log->fd >= 0)
822  close(log->fd);
823  log->fd = -1;
824 
825  /* negotiate exclusive access */
826  if (log_lock(log) < 0)
827  return -1;
828 
829  /* open the log file, foo.gz */
830  strcpy(log->end, ".gz");
831  log->fd = open(log->path, O_RDWR | O_CREAT, 0644);
832  if (log->fd < 0) {
833  log_close(log);
834  return -1;
835  }
836 
837  /* if new, initialize foo.gz with an empty log, delete old dictionary */
838  if (lseek(log->fd, 0, SEEK_END) == 0) {
839  if (write(log->fd, log_gzhead, HEAD) != HEAD ||
840  write(log->fd, log_gzext, EXTRA) != EXTRA ||
841  write(log->fd, log_gzbody, BODY) != BODY) {
842  log_close(log);
843  return -1;
844  }
845  strcpy(log->end, ".dict");
846  unlink(log->path);
847  }
848 
849  /* verify log file and load extra field information */
850  if ((op = log_head(log)) < 0) {
851  log_close(log);
852  return -1;
853  }
854 
855  /* check for interrupted process and if so, recover */
856  if (op != NO_OP && log_recover(log, op)) {
857  log_close(log);
858  return -1;
859  }
860 
861  /* touch the lock file to prevent another process from grabbing it */
862  log_touch(log);
863  return 0;
864 }
int log_head(struct log *log)
Definition: gzlog.c:410
unsigned char log_gzbody[]
Definition: gzlog.c:331
#define BODY
Definition: gzlog.c:337
unsigned char log_gzext[]
Definition: gzlog.c:319
int log_recover(struct log *log, int op)
Definition: gzlog.c:738
int log_lock(struct log *log)
Definition: gzlog.c:348
#define O_RDWR
Definition: sftypes.h:488
#define SEEK_END
Definition: zip.c:84

References BODY, close, log::end, EXTRA, log::fd, HEAD, log_close(), log_gzbody, log_gzext, log_gzhead, log_head(), log_lock(), log_recover(), log_touch(), lseek, NO_OP, O_CREAT, O_RDWR, op, log::path, SEEK_END, unlink, and write.

Referenced by gzlog_compress(), gzlog_open(), and gzlog_write().

◆ log_recover()

int log_recover ( struct log log,
int  op 
)

Definition at line 738 of file gzlog.c.

739 {
740  int fd, ret = 0;
741  unsigned char *data = NULL;
742  size_t len = 0;
743  struct stat st;
744 
745  /* log recovery */
746  log_log(log, op, "start");
747 
748  /* load foo.add file if expected and present */
749  if (op == APPEND_OP || op == COMPRESS_OP) {
750  strcpy(log->end, ".add");
751  if (stat(log->path, &st) == 0 && st.st_size) {
752  len = (size_t)(st.st_size);
753  if ((off_t)len != st.st_size ||
754  (data = malloc(st.st_size)) == NULL) {
755  log_log(log, op, "allocation failure");
756  return -2;
757  }
758  if ((fd = open(log->path, O_RDONLY, 0)) < 0) {
759  free(data);
760  log_log(log, op, ".add file read failure");
761  return -1;
762  }
763  ret = (size_t)read(fd, data, len) != len;
764  close(fd);
765  if (ret) {
766  free(data);
767  log_log(log, op, ".add file read failure");
768  return -1;
769  }
770  log_log(log, op, "loaded .add file");
771  }
772  else
773  log_log(log, op, "missing .add file!");
774  }
775 
776  /* recover the interrupted operation */
777  switch (op) {
778  case APPEND_OP:
779  ret = log_append(log, data, len);
780  break;
781  case COMPRESS_OP:
782  ret = log_compress(log, data, len);
783  break;
784  case REPLACE_OP:
785  ret = log_replace(log);
786  }
787 
788  /* log status */
789  log_log(log, op, ret ? "failure" : "complete");
790 
791  /* clean up */
792  if (data != NULL)
793  free(data);
794  return ret;
795 }
void log_log(struct log *log, int op, char *record)
Definition: gzlog.c:718

References APPEND_OP, close, COMPRESS_OP, log::end, fd, free(), len, log_append(), log_compress(), log_log(), log_replace(), malloc(), NULL, O_RDONLY, log::path, read(), REPLACE_OP, and stat.

Referenced by log_open().

◆ log_replace()

int log_replace ( struct log log)

Definition at line 571 of file gzlog.c.

572 {
573  int ret;
574  char *dest;
575 
576  /* delete foo.add file */
577  strcpy(log->end, ".add");
578  unlink(log->path); /* ignore error, since may not exist */
579  BAIL(3);
580 
581  /* rename foo.name to foo.dict, replacing foo.dict if it exists */
582  strcpy(log->end, ".dict");
583  dest = malloc(strlen(log->path) + 1);
584  if (dest == NULL)
585  return -2;
586  strcpy(dest, log->path);
587  strcpy(log->end, ".temp");
588  ret = rename(log->path, dest);
589  free(dest);
590  if (ret && errno != ENOENT)
591  return -1;
592  BAIL(4);
593 
594  /* mark the foo.gz file as done */
595  return log_mark(log, NO_OP);
596 }
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync rename
Definition: sflib.h:69
char * dest
Definition: lz4.h:697
#define ENOENT
Definition: sftypes.h:112

References BAIL, dest, log::end, ENOENT, free(), log_mark(), malloc(), NO_OP, NULL, log::path, rename, and unlink.

Referenced by log_compress(), and log_recover().

◆ log_touch()

void log_touch ( struct log log)

Definition at line 372 of file gzlog.c.

373 {
374  struct stat st;
375 
376  strcpy(log->end, ".lock");
377  utimes(log->path, NULL);
378  if (stat(log->path, &st) == 0)
379  log->lock = st.st_mtime;
380 }

References log::end, log::lock, NULL, log::path, and stat.

Referenced by gzlog_compress(), gzlog_write(), log_check(), log_compress(), and log_open().

◆ log_unlock()

void log_unlock ( struct log log)

Definition at line 396 of file gzlog.c.

397 {
398  if (log_check(log))
399  return;
400  strcpy(log->end, ".lock");
401  unlink(log->path);
402  log->lock = 0;
403 }

References log::end, log::lock, log_check(), log::path, and unlink.

Referenced by log_close().

Variable Documentation

◆ log_gzbody

unsigned char log_gzbody[]
Initial value:
= {
1, 0, 0, 0xff, 0xff,
0, 0, 0, 0,
0, 0, 0, 0
}

Definition at line 331 of file gzlog.c.

Referenced by log_open().

◆ log_gzext

unsigned char log_gzext[]
Initial value:
= {
52, 0, 0, 0, 0, 0, 0, 0,
52, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
5
}

Definition at line 319 of file gzlog.c.

Referenced by log_open().

◆ log_gzhead

unsigned char log_gzhead[]
Initial value:
= {
0x1f, 0x8b,
8,
4,
0, 0, 0, 0,
0, 0xff,
39, 0, 'a', 'p', 35, 0
}

Definition at line 306 of file gzlog.c.

Referenced by log_head(), and log_open().