|
|
| version 1.1.2.1, 2010/09/28 15:02:55 | version 1.1.2.8, 2010/09/30 11:39:08 |
|---|---|
| Line 2 | Line 2 |
| #include "clog.h" | #include "clog.h" |
| int Verbose; | |
| extern char compiled[], compiledby[], compilehost[]; | extern char compiled[], compiledby[], compilehost[]; |
| Line 12 Usage() | Line 13 Usage() |
| printf( "cLOG is tool for managment syslogd operation with circular logs\n" | printf( "cLOG is tool for managment syslogd operation with circular logs\n" |
| "=== %s === %s@%s ===\n\n" | "=== %s === %s@%s ===\n\n" |
| " Syntax: clog [options] <file.log>\n\n" | " Syntax: clog [options] <file.log>\n\n" |
| "\t-v\t\tVerbose, more -vv more verbosity\n" | |
| "\t-i\t\tInit file.log, create and prepare for use\n" | "\t-i\t\tInit file.log, create and prepare for use\n" |
| "\t-s <size>\tUse with init for set needed file.log size\n" | "\t-s <size>\tUse with init for set needed file.log size\n" |
| "\t-f\t\tForce command\n" | "\t-m <perm>\tUse permissions with init for set file.log\n" |
| "\t-f\t\tRead and follow log file.log\n" | |
| "\n", compiled, compiledby, compilehost); | "\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 %u\n", 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 | int |
| main(int argc, char **argv) | main(int argc, char **argv) |
| { | { |
| char ch; | char ch, m = 0, szLog[MAXPATHLEN]; |
| size_t siz = 0; | |
| int mode = 0644; | |
| while ((ch = getopt(argc, argv, "hfis:")) != -1) | while ((ch = getopt(argc, argv, "hm:vfis:")) != -1) |
| switch (ch) { | 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 %u!\n", siz); | |
| Usage(); | |
| return 1; | |
| } | |
| break; | |
| case 'h': | case 'h': |
| default: | default: |
| Usage(); | Usage(); |
| Line 33 main(int argc, char **argv) | Line 173 main(int argc, char **argv) |
| } | } |
| argc -= optind; | argc -= optind; |
| argv += 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; | return 0; |
| } | } |