aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-04-21 23:24:46 +0000
committerMike Frysinger <vapier@gentoo.org>2005-04-21 23:24:46 +0000
commit4a2117027f12c43b93e4221f636074c881206a2d (patch)
tree3e83cfb5f5d0370be31c459bd6859cedd31e3a3f
parent6d1d2e59bff295c5876430a6289425118f02e0ee (diff)
downloadbusybox-w32-4a2117027f12c43b93e4221f636074c881206a2d.tar.gz
busybox-w32-4a2117027f12c43b93e4221f636074c881206a2d.tar.bz2
busybox-w32-4a2117027f12c43b93e4221f636074c881206a2d.zip
grab sum from coreutils, clean it up, and make it busybox happy
-rw-r--r--coreutils/Config.in6
-rw-r--r--coreutils/Makefile.in1
-rw-r--r--coreutils/sum.c182
3 files changed, 189 insertions, 0 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 466e8b880..677970d1f 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -428,6 +428,12 @@ config CONFIG_STTY
428 help 428 help
429 stty is used to change and print terminal line settings. 429 stty is used to change and print terminal line settings.
430 430
431config CONFIG_SUM
432 bool "sum"
433 default n
434 help
435 checksum and count the blocks in a file
436
431config CONFIG_SYNC 437config CONFIG_SYNC
432 bool "sync" 438 bool "sync"
433 default n 439 default n
diff --git a/coreutils/Makefile.in b/coreutils/Makefile.in
index 130bdf48b..c9c42e091 100644
--- a/coreutils/Makefile.in
+++ b/coreutils/Makefile.in
@@ -71,6 +71,7 @@ COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o
71COREUTILS-$(CONFIG_SLEEP) += sleep.o 71COREUTILS-$(CONFIG_SLEEP) += sleep.o
72COREUTILS-$(CONFIG_SORT) += sort.o 72COREUTILS-$(CONFIG_SORT) += sort.o
73COREUTILS-$(CONFIG_STTY) += stty.o 73COREUTILS-$(CONFIG_STTY) += stty.o
74COREUTILS-$(CONFIG_SUM) += sum.o
74COREUTILS-$(CONFIG_SYNC) += sync.o 75COREUTILS-$(CONFIG_SYNC) += sync.o
75COREUTILS-$(CONFIG_TAIL) += tail.o 76COREUTILS-$(CONFIG_TAIL) += tail.o
76COREUTILS-$(CONFIG_TEE) += tee.o 77COREUTILS-$(CONFIG_TEE) += tee.o
diff --git a/coreutils/sum.c b/coreutils/sum.c
new file mode 100644
index 000000000..2618648b2
--- /dev/null
+++ b/coreutils/sum.c
@@ -0,0 +1,182 @@
1/*
2 * sum -- checksum and count the blocks in a file
3 * Like BSD sum or SysV sum -r, except like SysV sum if -s option is given.
4 *
5 * Copyright (C) 86, 89, 91, 1995-2002, 2004 Free Software Foundation, Inc.
6 * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
7 * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
8 *
9 * Written by Kayvan Aghaiepour and David MacKenzie
10 * Taken from coreutils and turned into a busybox applet by Mike Frysinger
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#include <stdio.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <unistd.h>
33#include <getopt.h>
34
35#include "libbb.h"
36
37/* 1 if any of the files read were the standard input */
38static int have_read_stdin;
39
40/* make a little more readable and avoid using strcmp for just 2 bytes */
41#define IS_STDIN(s) (s[0] == '-' && s[1] == '\0')
42
43/* Calculate and print the rotated checksum and the size in 1K blocks
44 of file FILE, or of the standard input if FILE is "-".
45 If PRINT_NAME is >1, print FILE next to the checksum and size.
46 The checksum varies depending on sizeof (int).
47 Return 1 if successful. */
48static int bsd_sum_file(const char *file, int print_name)
49{
50 register FILE *fp;
51 register int checksum = 0; /* The checksum mod 2^16. */
52 register uintmax_t total_bytes = 0; /* The number of bytes. */
53 register int ch; /* Each character read. */
54
55 if (IS_STDIN(file)) {
56 fp = stdin;
57 have_read_stdin = 1;
58 } else {
59 fp = fopen(file, "r");
60 if (fp == NULL) {
61 bb_perror_msg("%s", file);
62 return 0;
63 }
64 }
65
66 while ((ch = getc(fp)) != EOF) {
67 ++total_bytes;
68 checksum = (checksum >> 1) + ((checksum & 1) << 15);
69 checksum += ch;
70 checksum &= 0xffff; /* Keep it within bounds. */
71 }
72
73 if (ferror(fp)) {
74 bb_perror_msg("%s", file);
75 if (!IS_STDIN(file))
76 fclose(fp);
77 return 0;
78 }
79
80 if (!IS_STDIN(file) && fclose(fp) == EOF) {
81 bb_perror_msg("%s", file);
82 return 0;
83 }
84
85 printf("%05d %5s", checksum,
86 make_human_readable_str(total_bytes, 1, 1024));
87 if (print_name > 1)
88 printf(" %s", file);
89 putchar('\n');
90
91 return 1;
92}
93
94/* Calculate and print the checksum and the size in 512-byte blocks
95 of file FILE, or of the standard input if FILE is "-".
96 If PRINT_NAME is >0, print FILE next to the checksum and size.
97 Return 1 if successful. */
98static int sysv_sum_file(const char *file, int print_name)
99{
100 int fd;
101 unsigned char buf[8192];
102 uintmax_t total_bytes = 0;
103 int r;
104 int checksum;
105
106 /* The sum of all the input bytes, modulo (UINT_MAX + 1). */
107 unsigned int s = 0;
108
109 if (IS_STDIN(file)) {
110 fd = 0;
111 have_read_stdin = 1;
112 } else {
113 fd = open(file, O_RDONLY);
114 if (fd == -1) {
115 bb_perror_msg("%s", file);
116 return 0;
117 }
118 }
119
120 while (1) {
121 size_t i;
122 size_t bytes_read = safe_read(fd, buf, sizeof(buf));
123
124 if (bytes_read == 0)
125 break;
126
127 if (bytes_read == -1) {
128 bb_perror_msg("%s", file);
129 if (!IS_STDIN(file))
130 close(fd);
131 return 0;
132 }
133
134 for (i = 0; i < bytes_read; i++)
135 s += buf[i];
136 total_bytes += bytes_read;
137 }
138
139 if (!IS_STDIN(file) && close(fd) == -1) {
140 bb_perror_msg("%s", file);
141 return 0;
142 }
143
144 r = (s & 0xffff) + ((s & 0xffffffff) >> 16);
145 checksum = (r & 0xffff) + (r >> 16);
146
147 printf("%d %s", checksum,
148 make_human_readable_str(total_bytes, 1, 512));
149 if (print_name)
150 printf(" %s", file);
151 putchar('\n');
152
153 return 1;
154}
155
156int sum_main(int argc, char **argv)
157{
158 int flags;
159 int ok;
160 int files_given;
161 int (*sum_func)(const char *, int) = bsd_sum_file;
162
163 /* give the bsd func priority over sysv func */
164 flags = bb_getopt_ulflags(argc, argv, "sr");
165 if (flags & 1)
166 sum_func = sysv_sum_file;
167 if (flags & 2)
168 sum_func = bsd_sum_file;
169
170 have_read_stdin = 0;
171 files_given = argc - optind;
172 if (files_given <= 0)
173 ok = sum_func("-", files_given);
174 else
175 for (ok = 1; optind < argc; optind++)
176 ok &= sum_func(argv[optind], files_given);
177
178 if (have_read_stdin && fclose(stdin) == EOF)
179 bb_perror_msg_and_die("-");
180
181 exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
182}