// sum.c, version 1.0.1 // OMKOV coreutils sum // Copyright (C) 2020, Jakob Wakeling // MIT Licence #include "util/error.h" #include "util/optget.h" #include #include #include #define VERSION "1.0.1" static struct lop lops[] = { { "help", ARG_NUL, 256 }, { "version", ARG_NUL, 257 }, { NULL, 0, 0 } }; static inline int sum(const char *file); static inline uint32_t bsd(FILE *fi, size_t *fl); static inline uint32_t sysv(FILE *fi, size_t *fl); static uint32_t (*fn)(FILE *, size_t *) = bsd; static void hlp(void); static void ver(void); int main(int ac, char *av[]) { struct opt opt = OPTGET_INIT; opt.str = "rs"; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { case 'r': { fn = bsd; break; } case 's': { fn = sysv; break; } case 256: { hlp(); return 0; } case 257: { ver(); return 0; } default: { return 1; } } bool warned = false; if (opt.ind == ac) { sum(NULL); } else for (char **p = &av[opt.ind]; *p; ++p) if (sum(*p)) { warn("%s: %s", *p, serr()); warned = true; } return warned; } static inline int sum(const char *file) { FILE *fi; size_t bl = 0; register uint32_t sum; if (!file || (file[0] == '-' && file[1] == 0)) { fi = stdin; } else if (!(fi = fopen(file, "r"))) { return 1; } sum = fn(fi, &bl); printf("%u %zu", sum, bl); if (file) { printf(" %s", file); } fputc('\n', stdout); if (fi != stdin) { fclose(fi); } return 0; } static inline uint32_t bsd(FILE *fi, size_t *bl) { uint8_t buf[BUFSIZ * 16]; register uint16_t sum = 0; for (size_t c; (c = fread(buf, 1, sizeof (buf), fi)); *bl += c) { for (register size_t i = 0; i != c; ++i) { sum = (sum >> 1) + ((sum & 1) << 15); sum += buf[i]; sum &= 0xFFFF; } } *bl = *bl / 1024 + 1; return sum; } static inline uint32_t sysv(FILE *fi, size_t *bl) { uint8_t buf[BUFSIZ * 16]; register uint32_t sum = 0; for (size_t c; (c = fread(buf, 1, sizeof (buf), fi)); *bl += c) { for (register size_t i = 0; i != c; ++i) { sum += buf[i]; } } sum = (sum & 0xFFFF) + ((sum & 0xFFFFFFFF) >> 16); sum = (sum & 0xFFFF) + (sum >> 16); *bl = *bl / 512 + 1; return sum; } static void hlp(void) { puts("sum - write file checksums and block counts\n"); puts("usage: sum [-rs] [file...]\n"); puts("options:"); puts(" -r Use BSD algorithm and 1024 byte blocks"); puts(" -s Use System V algorithm and 512 byte blocks"); puts(" --help Display help information"); puts(" --version Display version information"); } static void ver(void) { puts("OMKOV coreutils sum, version " VERSION); puts("Copyright (C) 2020, Jakob Wakeling"); puts("MIT Licence (https://opensource.org/licenses/MIT)"); }