diff options
Diffstat (limited to 'coreutils/sum.c')
-rw-r--r-- | coreutils/sum.c | 155 |
1 files changed, 48 insertions, 107 deletions
diff --git a/coreutils/sum.c b/coreutils/sum.c index 68a857816..df5804899 100644 --- a/coreutils/sum.c +++ b/coreutils/sum.c @@ -15,139 +15,80 @@ #include "busybox.h" -/* 1 if any of the files read were the standard input */ -static int have_read_stdin; +enum { sysv_sum, bsd_sum }; -/* Calculate and print the rotated checksum and the size in 1K blocks - of file FILE, or of the standard input if FILE is "-". - If PRINT_NAME is >1, print FILE next to the checksum and size. - The checksum varies depending on sizeof (int). - Return 1 if successful. */ -static int bsd_sum_file(const char *file, int print_name) +/* BSD: calculate and print the rotated checksum and the size in 1K blocks + The checksum varies depending on sizeof (int). */ +/* SYSV: calculate and print the checksum and the size in 512-byte blocks */ +/* Return 1 if successful. */ +static int sum_file(const char *file, int type, int print_name) { - FILE *fp; - int checksum = 0; /* The checksum mod 2^16. */ - uintmax_t total_bytes = 0; /* The number of bytes. */ - int ch; /* Each character read. */ - int ret = 0; - - if (LONE_DASH(file)) { - fp = stdin; - have_read_stdin++; - } else { - fp = fopen_or_warn(file, "r"); - if (fp == NULL) - goto out; - } - - while ((ch = getc(fp)) != EOF) { - ++total_bytes; - checksum = (checksum >> 1) + ((checksum & 1) << 15); - checksum += ch; - checksum &= 0xffff; /* Keep it within bounds. */ - } - - if (ferror(fp)) { - bb_perror_msg(file); - fclose_if_not_stdin(fp); - goto out; - } - - if (fclose_if_not_stdin(fp) == EOF) { - bb_perror_msg(file); - goto out; - } - ret++; - printf("%05d %5ju ", checksum, (total_bytes+1023)/1024); - if (print_name > 1) - puts(file); - else - puts(""); -out: - return ret; -} - -/* Calculate and print the checksum and the size in 512-byte blocks - of file FILE, or of the standard input if FILE is "-". - If PRINT_NAME is >0, print FILE next to the checksum and size. - Return 1 if successful. */ -#define MY_BUF_SIZE 8192 -static int sysv_sum_file(const char *file, int print_name) -{ - RESERVE_CONFIG_BUFFER(buf, MY_BUF_SIZE); - int fd; +#define buf bb_common_bufsiz1 + int r, fd; uintmax_t total_bytes = 0; /* The sum of all the input bytes, modulo (UINT_MAX + 1). */ - unsigned int s = 0; + unsigned s = 0; - if (LONE_DASH(file)) { - fd = 0; - have_read_stdin = 1; - } else { + fd = 0; + if (NOT_LONE_DASH(file)) { fd = open(file, O_RDONLY); if (fd == -1) - goto release_and_ret; + goto ret_bad; } while (1) { - size_t bytes_read = safe_read(fd, buf, MY_BUF_SIZE); - - if (bytes_read == 0) - break; - - if (bytes_read == -1) { -release_and_ret: + size_t bytes_read = safe_read(fd, buf, BUFSIZ); + + if ((ssize_t)bytes_read <= 0) { + r = (fd && close(fd) != 0); + if (!bytes_read && !r) + /* no error */ + break; + ret_bad: bb_perror_msg(file); - RELEASE_CONFIG_BUFFER(buf); - if (NOT_LONE_DASH(file)) - close(fd); return 0; } total_bytes += bytes_read; - while (bytes_read--) - s += buf[bytes_read]; + if (type == sysv_sum) { + do s += buf[--bytes_read]; while (bytes_read); + } else { + r = 0; + do { + s = (s >> 1) + ((s & 1) << 15); + s += buf[r++]; + s &= 0xffff; /* Keep it within bounds. */ + } while (--bytes_read); + } } - if (NOT_LONE_DASH(file) && close(fd) == -1) - goto release_and_ret; - else - RELEASE_CONFIG_BUFFER(buf); - - { - int r = (s & 0xffff) + ((s & 0xffffffff) >> 16); + if (!print_name) file = ""; + if (type == sysv_sum) { + r = (s & 0xffff) + ((s & 0xffffffff) >> 16); s = (r & 0xffff) + (r >> 16); - - printf("%d %ju ", s, (total_bytes+511)/512); - } - puts(print_name ? file : ""); - + printf("%d %ju %s\n", s, (total_bytes+511)/512, file); + } else + printf("%05d %5ju %s\n", s, (total_bytes+1023)/1024, file); return 1; +#undef buf } int sum_main(int argc, char **argv) { - int flags; - int ok; - int (*sum_func)(const char *, int) = bsd_sum_file; + int n; + int type = bsd_sum; - /* give the bsd func priority over sysv func */ - flags = getopt32(argc, argv, "sr"); - if (flags & 1) - sum_func = sysv_sum_file; - if (flags & 2) - sum_func = bsd_sum_file; + n = getopt32(argc, argv, "sr"); + if (n & 1) type = sysv_sum; + /* give the bsd priority over sysv func */ + if (n & 2) type = bsd_sum; - have_read_stdin = 0; - if ((argc - optind) == 0) - ok = sum_func("-", 0); + if (argc == optind) + n = sum_file("-", type, 0); else - for (ok = 1; optind < argc; optind++) - ok &= sum_func(argv[optind], 1); - - if (have_read_stdin && fclose(stdin) == EOF) - bb_perror_msg_and_die("-"); + for (n = 1; optind < argc; optind++) + n &= sum_file(argv[optind], type, 1); - exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); + return !n; } |