Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/sum.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/sum.c
r821 r1770 11 11 * Taken from coreutils and turned into a busybox applet by Mike Frysinger 12 12 * 13 * Licensed under the GPL v2 , see the file LICENSE in this tarball.13 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 14 14 */ 15 15 16 #include <stdio.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <fcntl.h> 20 #include <unistd.h> 16 #include "libbb.h" 21 17 22 #include "busybox.h" 18 enum { SUM_BSD, PRINT_NAME, SUM_SYSV }; 23 19 24 /* 1 if any of the files read were the standard input */ 25 static int have_read_stdin; 26 27 /* make a little more readable and avoid using strcmp for just 2 bytes */ 28 #define IS_STDIN(s) (s[0] == '-' && s[1] == '\0') 29 30 /* Calculate and print the rotated checksum and the size in 1K blocks 31 of file FILE, or of the standard input if FILE is "-". 32 If PRINT_NAME is >1, print FILE next to the checksum and size. 33 The checksum varies depending on sizeof (int). 34 Return 1 if successful. */ 35 static int bsd_sum_file(const char *file, int print_name) 20 /* BSD: calculate and print the rotated checksum and the size in 1K blocks 21 The checksum varies depending on sizeof (int). */ 22 /* SYSV: calculate and print the checksum and the size in 512-byte blocks */ 23 /* Return 1 if successful. */ 24 static unsigned sum_file(const char *file, const unsigned type) 36 25 { 37 FILE *fp; 38 int checksum = 0; /* The checksum mod 2^16. */ 39 uintmax_t total_bytes = 0; /* The number of bytes. */ 40 int ch; /* Each character read. */ 41 42 if (IS_STDIN(file)) { 43 fp = stdin; 44 have_read_stdin = 1; 45 } else { 46 fp = bb_wfopen(file, "r"); 47 if (fp == NULL) 48 return 0; 49 } 50 51 while ((ch = getc(fp)) != EOF) { 52 ++total_bytes; 53 checksum = (checksum >> 1) + ((checksum & 1) << 15); 54 checksum += ch; 55 checksum &= 0xffff; /* Keep it within bounds. */ 56 } 57 58 if (ferror(fp)) { 59 bb_perror_msg(file); 60 bb_fclose_nonstdin(fp); 61 return 0; 62 } 63 64 if (bb_fclose_nonstdin(fp) == EOF) { 65 bb_perror_msg(file); 66 return 0; 67 } 68 69 printf("%05d %5ju ", checksum, (total_bytes+1023)/1024); 70 if (print_name > 1) 71 puts(file); 72 else 73 printf("\n"); 74 75 return 1; 76 } 77 78 /* Calculate and print the checksum and the size in 512-byte blocks 79 of file FILE, or of the standard input if FILE is "-". 80 If PRINT_NAME is >0, print FILE next to the checksum and size. 81 Return 1 if successful. */ 82 #define MY_BUF_SIZE 8192 83 static int sysv_sum_file(const char *file, int print_name) 84 { 85 RESERVE_CONFIG_BUFFER(buf, MY_BUF_SIZE); 86 int fd; 26 #define buf bb_common_bufsiz1 87 27 uintmax_t total_bytes = 0; 28 int fd = 0, r; 88 29 89 30 /* The sum of all the input bytes, modulo (UINT_MAX + 1). */ 90 unsigned ints = 0;31 unsigned s = 0; 91 32 92 if (IS_STDIN(file)) { 93 fd = 0; 94 have_read_stdin = 1; 95 } else { 33 if (NOT_LONE_DASH(file)) { 96 34 fd = open(file, O_RDONLY); 97 35 if (fd == -1) 98 goto re lease_and_ret;36 goto ret_bad; 99 37 } 100 38 101 39 while (1) { 102 size_t bytes_read = safe_read(fd, buf, MY_BUF_SIZE);40 size_t bytes_read = safe_read(fd, buf, BUFSIZ); 103 41 104 if (bytes_read == 0) 105 break; 106 107 if (bytes_read == -1) { 108 release_and_ret: 42 if ((ssize_t)bytes_read <= 0) { 43 r = (fd && close(fd) != 0); 44 if (!bytes_read && !r) 45 /* no error */ 46 break; 47 ret_bad: 109 48 bb_perror_msg(file); 110 RELEASE_CONFIG_BUFFER(buf);111 if (!IS_STDIN(file))112 close(fd);113 49 return 0; 114 50 } 115 51 116 52 total_bytes += bytes_read; 117 while (bytes_read--) 118 s += buf[bytes_read]; 53 if (type >= SUM_SYSV) { 54 do s += buf[--bytes_read]; while (bytes_read); 55 } else { 56 r = 0; 57 do { 58 s = (s >> 1) + ((s & 1) << 15); 59 s += buf[r++]; 60 s &= 0xffff; /* Keep it within bounds. */ 61 } while (--bytes_read); 62 } 119 63 } 120 64 121 if (!IS_STDIN(file) && close(fd) == -1) 122 goto release_and_ret; 123 else 124 RELEASE_CONFIG_BUFFER(buf); 125 126 { 127 int r = (s & 0xffff) + ((s & 0xffffffff) >> 16); 65 if (type < PRINT_NAME) 66 file = ""; 67 if (type >= SUM_SYSV) { 68 r = (s & 0xffff) + ((s & 0xffffffff) >> 16); 128 69 s = (r & 0xffff) + (r >> 16); 129 130 printf("%d %ju ", s, (total_bytes+511)/512); 131 } 132 puts(print_name ? file : ""); 133 70 printf("%d %ju %s\n", s, (total_bytes+511)/512, file); 71 } else 72 printf("%05d %5ju %s\n", s, (total_bytes+1023)/1024, file); 134 73 return 1; 74 #undef buf 135 75 } 136 76 77 int sum_main(int argc, char **argv); 137 78 int sum_main(int argc, char **argv) 138 79 { 139 int flags; 140 int ok; 141 int (*sum_func)(const char *, int) = bsd_sum_file; 80 unsigned n; 81 unsigned type = SUM_BSD; 142 82 143 /* give the bsd func priority over sysv func */ 144 flags = bb_getopt_ulflags(argc, argv, "sr"); 145 if (flags & 1) 146 sum_func = sysv_sum_file; 147 if (flags & 2) 148 sum_func = bsd_sum_file; 83 n = getopt32(argv, "sr"); 84 if (n & 1) type = SUM_SYSV; 85 /* give the bsd priority over sysv func */ 86 if (n & 2) type = SUM_BSD; 149 87 150 have_read_stdin = 0; 151 if ((argc - optind) == 0) 152 ok = sum_func("-", 0); 153 else 154 for (ok = 1; optind < argc; optind++) 155 ok &= sum_func(argv[optind], 1); 156 157 if (have_read_stdin && fclose(stdin) == EOF) 158 bb_perror_msg_and_die("-"); 159 160 exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); 88 if (argc == optind) { 89 /* Do not print the name */ 90 n = sum_file("-", type); 91 } else { 92 /* Need to print the name if either 93 - more than one file given 94 - doing sysv */ 95 type += argc - 1 > optind || type == SUM_SYSV; 96 for (n = 1; optind < argc; optind++) 97 n &= sum_file(argv[optind], type); 98 } 99 return !n; 161 100 }
Note:
See TracChangeset
for help on using the changeset viewer.