1 /* sum -- checksum and count the blocks in a file
2 Copyright (C) 86, 89, 91, 1995-2001 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Like BSD sum or SysV sum -r, except like SysV sum if -s option is given. */
20 /* Written by Kayvan Aghaiepour and David MacKenzie. */
25 #include <sys/types.h>
31 #include "safe-read.h"
33 /* The official name of this program (e.g., no `g' prefix). */
34 #define PROGRAM_NAME "sum"
36 #define AUTHORS N_ ("Kayvan Aghaiepour and David MacKenzie")
38 /* The name this program was run with. */
41 /* Nonzero if any of the files read were the standard input. */
42 static int have_read_stdin
;
44 static struct option
const longopts
[] =
46 {"sysv", no_argument
, NULL
, 's'},
47 {GETOPT_HELP_OPTION_DECL
},
48 {GETOPT_VERSION_OPTION_DECL
},
56 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
61 Usage: %s [OPTION]... [FILE]...\n\
65 Print checksum and block counts for each FILE.\n\
67 -r defeat -s, use BSD sum algorithm, use 1K blocks\n\
68 -s, --sysv use System V sum algorithm, use 512 bytes blocks\n\
70 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
71 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
74 With no FILE, or when FILE is -, read standard input.\n\
76 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
78 exit (status
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
);
81 /* Calculate and print the rotated checksum and the size in 1K blocks
82 of file FILE, or of the standard input if FILE is "-".
83 If PRINT_NAME is >1, print FILE next to the checksum and size.
84 The checksum varies depending on sizeof(int).
85 Return 0 if successful, -1 if an error occurs. */
88 bsd_sum_file (const char *file
, int print_name
)
91 register int checksum
= 0; /* The checksum mod 2^16. */
92 register uintmax_t total_bytes
= 0; /* The number of bytes. */
93 register int ch
; /* Each character read. */
94 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
96 if (STREQ (file
, "-"))
103 fp
= fopen (file
, "r");
106 error (0, errno
, "%s", file
);
110 /* Need binary I/O, or else byte counts and checksums are incorrect. */
111 SET_BINARY (fileno(fp
));
113 while ((ch
= getc (fp
)) != EOF
)
116 checksum
= (checksum
>> 1) + ((checksum
& 1) << 15);
118 checksum
&= 0xffff; /* Keep it within bounds. */
123 error (0, errno
, "%s", file
);
124 if (!STREQ (file
, "-"))
129 if (!STREQ (file
, "-") && fclose (fp
) == EOF
)
131 error (0, errno
, "%s", file
);
135 printf ("%05d %5s", checksum
,
136 human_readable_inexact (total_bytes
, hbuf
, 1, 1024, human_ceiling
));
138 printf (" %s", file
);
144 /* Calculate and print the checksum and the size in 512-byte blocks
145 of file FILE, or of the standard input if FILE is "-".
146 If PRINT_NAME is >0, print FILE next to the checksum and size.
147 Return 0 if successful, -1 if an error occurs. */
150 sysv_sum_file (const char *file
, int print_name
)
153 unsigned char buf
[8192];
154 register int bytes_read
;
155 uintmax_t total_bytes
= 0;
156 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
160 /* The sum of all the input bytes, modulo (UINT_MAX + 1). */
161 register unsigned int s
= 0;
163 if (STREQ (file
, "-"))
170 fd
= open (file
, O_RDONLY
);
173 error (0, errno
, "%s", file
);
177 /* Need binary I/O, or else byte counts and checksums are incorrect. */
180 while ((bytes_read
= safe_read (fd
, buf
, sizeof buf
)) > 0)
184 for (i
= 0; i
< bytes_read
; i
++)
186 total_bytes
+= bytes_read
;
191 error (0, errno
, "%s", file
);
192 if (!STREQ (file
, "-"))
197 if (!STREQ (file
, "-") && close (fd
) == -1)
199 error (0, errno
, "%s", file
);
203 r
= (s
& 0xffff) + ((s
& 0xffffffff) >> 16);
204 checksum
= (r
& 0xffff) + (r
>> 16);
206 printf ("%d %s", checksum
,
207 human_readable_inexact (total_bytes
, hbuf
, 1, 512, human_ceiling
));
209 printf (" %s", file
);
216 main (int argc
, char **argv
)
221 int (*sum_func
) PARAMS ((const char *, int)) = bsd_sum_file
;
223 program_name
= argv
[0];
224 setlocale (LC_ALL
, "");
225 bindtextdomain (PACKAGE
, LOCALEDIR
);
226 textdomain (PACKAGE
);
228 atexit (close_stdout
);
232 while ((optc
= getopt_long (argc
, argv
, "rs", longopts
, NULL
)) != -1)
239 case 'r': /* For SysV compatibility. */
240 sum_func
= bsd_sum_file
;
244 sum_func
= sysv_sum_file
;
247 case_GETOPT_HELP_CHAR
;
249 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
256 files_given
= argc
- optind
;
257 if (files_given
== 0)
259 if ((*sum_func
) ("-", files_given
) < 0)
263 for (; optind
< argc
; optind
++)
264 if ((*sum_func
) (argv
[optind
], files_given
) < 0)
267 if (have_read_stdin
&& fclose (stdin
) == EOF
)
268 error (EXIT_FAILURE
, errno
, "-");
269 exit (errors
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
);