/* * UNG's Not GNU * * Copyright (c) 2022, Jakob Kaivo * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #define UINT16_BIT (16) #define BLOCK_SIZE (512) enum algorithm { UNSPECIFIED, ALTERNATIVE }; struct sum { uintmax_t size; uintmax_t sum; }; static struct sum sum_obsolete(FILE *f, int alt) { struct sum sum = { 0 }; int c; while ((c = fgetc(f)) != EOF) { sum.size++; if (alt) { sum.sum = (sum.sum >> 1) + ((sum.sum & 1) << (UINT16_BIT - 1)); } sum.sum += c; if (alt) { sum.sum &= UINT16_MAX; } } sum.sum = (sum.sum & UINT16_MAX) + (sum.sum >> UINT16_BIT); /* obsolete sum program prints number of 512 byte blocks */ if (sum.size % BLOCK_SIZE != 0) { sum.size += BLOCK_SIZE; } sum.size /= BLOCK_SIZE; return sum; } static struct sum sum_unspecified(FILE *f) { return sum_obsolete(f, 0); } static struct sum sum_alternative(FILE *f) { return sum_obsolete(f, 1); } int cksum(const char *path, enum algorithm alg) { FILE *f = stdin; if (path && strcmp(path, "-")) { f = fopen(path, "rb"); } if (f == NULL) { fprintf(stderr, "sum: %s: %s\n", path, strerror(errno)); return 1; } struct sum sum; switch (alg) { case UNSPECIFIED: sum = sum_unspecified(f); break; case ALTERNATIVE: sum = sum_alternative(f); break; default: break; } printf("%"PRIuMAX" %"PRIuMAX"", sum.sum, sum.size); if (f != stdin) { printf(" %s", path); fclose(f); } putchar('\n'); return 0; } int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); fprintf(stderr, "sum: utility is obsolete; use cksum\n"); enum algorithm alg = UNSPECIFIED; int c; while ((c = getopt(argc, argv, "r")) != -1) { switch (c) { case 'r': alg = ALTERNATIVE; break; default: return 1; } } int r = 0; do { r |= cksum(argv[optind++], alg); } while (optind < argc); return r; }