#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include "zpm.h" void usage(void) { fprintf(stderr, "zpm-note [-I] [-s ...] [-S ] [package]\n"); } void show_note(struct zpm_note *n) { printf("Note %" PRId64 " %s\n", n->id, n->ts); if (n->pkgid) { printf("Package: %s\n", n->pkgid); } if (n->path) { printf("Path: %s\n", n->pkgid); } if (n->file) { printf("Hash: %s\n", n->file); } printf("%s\n", n->note); } void jstring(char *field, char *value, int indent, int final) { while (indent--) { putchar('\t'); } printf("\"%s\": ", field); if (value) { while (*value) { if (strchr("\"\\\b\f\n\r\t", *value)) { putchar('\\'); } putchar(*value++); } } else { printf("null"); } if (!final) { printf(","); } putchar('\n'); } void show_json(struct zpm_note *n) { size_t len = 0; if (n->pkgid) { len = strcspn(n->note, "\n\r"); } printf("{\n\t\"id\": %" PRId64 ",\n", n->id); jstring("package", n->pkgid, 1, 0); jstring("hash", n->file, 1, 0); jstring("path", n->path, 1, 0); if (len) { printf("\t\"subject\": \"%.*s\",\n", (int)len, n->note); } else { printf("\t\"subject\": null,\n"); } jstring("note", n->note, 1, 1); printf("}\n"); } void print_note(struct zpm_note *n) { size_t len; size_t space = 66; uint64_t id = n->id; if (n->pkgid) { space -= strlen(n->pkgid); } else { space -= 1; } do { space--; } while (id /= 10); len = strcspn(n->note, "\n\r"); if (len > space) { len = space; } printf("%" PRId64 " %.10s %s %.*s\n", n->id, n->ts, n->pkgid ? n->pkgid : "-", (int)len, n->note); } int main(int ac, char **av){ int opt; struct zpm pkg; char *dbfile; int fail, echo = 0; int64_t start = 0, end = INT64_MAX; char *range = 0; int select = 1; struct zpm_note n = { 0 }; n.pkgid = 0; n.hash = 0; n.path = 0; n.ts = 0; dbfile = getenv("ZPMDB"); if (!dbfile) { dbfile = "/var/lib/zpm/local.db"; } /* -l list * -p packageid * -A ack * -n note id * -D delete * -H hash * -m note message, otherwise EDITOR/vi to edit a text file * -e echo note after creating * zpm note -p pkgid -P path -H hash -m 'foo' * zpm note -l * zpm note -D * zpm note -A */ int list = 0, delete = 0, ack = 0, show = 0, json = 0; char *notefrom = 0; while ((opt = getopt(ac, av, "f:p:P:H:m:n:lDAauesjF:")) != -1) { switch (opt) { case 'f': dbfile = optarg; break; case 'p': n.pkgid = optarg; break; case 'P': n.path = optarg; break; case 'H': n.hash = optarg; break; case 'm': n.note = optarg; break; case 'F': notefrom = optarg; break; case 'n': range = optarg; break; case 'l': list = 1; break; case 'j': json = 1; break; case 's': show = 1; break; case 'e': echo = 1; break; case 'D': delete = 1; break; case 'A': ack = 1; break; case 'a': select |= 2; break; case 'u': select |= 6; break; default: usage(); exit(EXIT_FAILURE); break; } } /* 0x1 = next note, * 0x2 = include acked * 0x4 = suppress unack, implies 0x2 */ if (range) { if (*range == '-') { start = 0; end = strtoll(range+1, NULL, 10); } else if (isdigit(*range)) { char *next; start = strtoll(range, &next, 10); if (next && *next == '-') { end = -1; next++; if (isdigit(*next)) { end = strtoll(next, NULL, 10); } } else { end = start; } } } if (!dbfile) { fprintf(stderr, "must specify db\n"); return 1; } /* given a package name, get the packages */ /* no package name, get all */ char *filenote = 0; if (notefrom) { size_t in = 0; ssize_t cread = 0; FILE *input; if (strcmp(notefrom, "-")) { input = fopen(notefrom, "r"); } else { input = stdin; } if (!input) { perror("can't read input file"); exit(EXIT_FAILURE); } cread = getdelim(&filenote, &in, 0, input); if (cread == -1) { perror("error reading file"); exit(EXIT_FAILURE); } n.note = filenote; } if (zpm_open(&pkg, dbfile)) { if (list || show || delete || ack) { n.id = start ? start - 1 : start; while (zpm_note(&pkg, &n, select)) { if (n.id > end) { break; } if (delete) { zpm_note_del(&pkg, n.id); } else if (ack) { zpm_note_ack(&pkg, n.id); } else if (show) { if (json) { show_json(&n); } else { show_note(&n); } } else { print_note(&n); } zpm_note_free(&n); } zpm_note_free(&n); } else if (n.note) { n.id = zpm_note_add(&pkg, n.pkgid, n.path, n.hash, "%s", n.note); zpm_note(&pkg, &n, 2); if (n.id) { if (echo) { print_note(&n); } else { printf("%" PRId64 "\n", n.id); } } else { fprintf(stderr, "unable to create note\n"); pkg.error = 1; } } } else { fprintf(stderr, "unable to open %s\n", dbfile); } fail = pkg.error; zpm_close(&pkg); free(filenote); return fail ? EXIT_FAILURE : EXIT_SUCCESS; }