#include "global.h" #include "clog.h" int Verbose; extern char compiled[], compiledby[], compilehost[]; static void Usage() { printf( "cLOG is tool for managment syslogd operation with circular logs\n" "=== %s === %s@%s ===\n\n" " Syntax: clog [options] \n\n" "\t-v\t\tVerbose, more -vv more verbosity\n" "\t-i\t\tInit file.log, create and prepare for use\n" "\t-s \tUse with init for set needed file.log size\n" "\t-m \tUse permissions with init for set file.log\n" "\t-f\t\tRead and follow log file.log\n" "\n", compiled, compiledby, compilehost); } static int initlog(const char *csLog, size_t size, int mode) { int f, ret = -1, fill = size; struct clogFooter cf = { 0 }; char buffer[BUFLEN] = { 0 }; memcpy(&cf.cf_magic, MAGIC, sizeof cf.cf_magic); cf.cf_max = size - sizeof cf; f = open(csLog, O_WRONLY | O_CREAT | O_TRUNC, mode); if (f == -1) { printf("Error:: in open log %s #%d - %s\n", csLog, errno, strerror(errno)); return -1; } else VERB(1) printf("Verbose:: Create log %s\n", csLog); while (fill > BUFLEN) if (write(f, buffer, BUFLEN) == -1) { printf("Error:: in fill log %s #%d - %s\n", csLog, errno, strerror(errno)); goto end; } else fill -= BUFLEN; if (fill > BUFLEN) { printf("Error:: in fill log %s uninspected result!!!\n", csLog); goto end; } else if (fill && write(f, buffer, fill) == -1) { printf("Error:: in last fill log %s #%d - %s\n", csLog, errno, strerror(errno)); goto end; } // return to write cfooter if (lseek(f, -(off_t)(sizeof cf), SEEK_END) == -1) { printf("Error:: can`t set position for write footer #%d - %s\n", errno, strerror(errno)); goto end; } if (write(f, &cf, sizeof cf) == -1) { printf("Error:: in footer log %s #%d - %s\n", csLog, errno, strerror(errno)); goto end; } ret = 0; VERB(1) printf("Verbose:: Init done.\n"); end: close(f); return ret; } static int readlog(const char *csLog, char m) { int f, cx; size_t end; struct clogFooter *cf; char *buffer = NULL; uint32_t next, start = 0; struct iovec iov[2]; struct pollfd pfd = { 0 }; f = open(csLog, O_RDONLY); if (f == -1) { printf("Error:: in open read %s #%d - %s\n", csLog, errno, strerror(errno)); return -1; } else VERB(1) printf("Verbose:: Opened log %s\n", csLog); end = lseek(f, 0, SEEK_END); if (end == -1) { printf("Error:: in get size %s #%d - %s\n", csLog, errno, strerror(errno)); close(f); return -1; } else lseek(f, 0, SEEK_SET); VERB(2) printf("Verbose(2):: Get file size %lu\n", (u_long) end); buffer = mmap(NULL, end, PROT_READ, MAP_SHARED, f, 0); if (!buffer) { printf("Error:: in map %s #%d - %s\n", csLog, errno, strerror(errno)); close(f); return -1; } else { close(f); cf = (struct clogFooter*) (buffer + end - sizeof(struct clogFooter)); VERB(3) printf("Verbose(3):: Map file to address %p and footer %p\n", buffer, cf); } if (cf->cf_wrap == 1) start = cf->cf_next + 1; VERB(3) printf("Verbose(3):: wrapped log? %d\n", cf->cf_wrap); do { cx = 0; while (cf->cf_lock == 1) sched_yield(); next = cf->cf_next; if (start > next) { iov[cx].iov_base = buffer + start; iov[cx++].iov_len = cf->cf_max - start; start = 0; } iov[cx].iov_base = buffer + start; iov[cx++].iov_len = next - start; start = next; writev(1, iov, cx); if (!(m & 2)) break; if (poll(&pfd, 1, 50) == -1) { printf("Error:: in poll %s #%d - %s\n", csLog, errno, strerror(errno)); munmap(buffer, end); return -1; } } while (42); munmap(buffer, end); VERB(1) printf("Verbose:: Read done.\n"); return 0; } int main(int argc, char **argv) { char ch, m = 0, szLog[MAXPATHLEN]; size_t siz = 0; int mode = 0644; while ((ch = getopt(argc, argv, "hm:vfis:")) != -1) switch (ch) { case 'm': mode = strtol(optarg, NULL, 0); break; case 'v': Verbose++; break; case 'i': m |= 1; break; case 'f': m |= 2; break; case 's': siz = strtol(optarg, NULL, 0); if (siz < 1) { printf("Error:: size is invalid %lu!\n", (u_long) siz); Usage(); return 1; } break; case 'h': default: Usage(); return 1; } argc -= optind; argv += optind; if (m & 1 && !siz) { printf("Error:: not specified size when use with init log!\n"); Usage(); return 1; } if (m == 3) { printf("Error:: can`t in same time init and force!\n"); Usage(); return 1; } if (!argc) { printf("Error:: not specified log file!\n"); Usage(); return 1; } else strlcpy(szLog, *argv, MAXPATHLEN); if (m & 1 && initlog(szLog, siz, mode) == -1) return 2; if (readlog(szLog, m) == -1) return 3; return 0; }