hexdump: accept hex numbers in -n, closes 16195
[busybox-git.git] / coreutils / cksum.c
blob1fb6ef2d02b9f3527d957a94004a4f4f854e9bbc
1 /* vi: set sw=4 ts=4: */
2 /*
3 * cksum - calculate the CRC32 checksum of a file
5 * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9 //config:config CKSUM
10 //config: bool "cksum (4.3 kb)"
11 //config: default y
12 //config:
13 //config:config CRC32
14 //config: bool "crc32 (4.2 kb)"
15 //config: default y
17 // APPLET_NOEXEC:name main location suid_type help
18 //applet:IF_CKSUM(APPLET_NOEXEC(cksum, cksum, BB_DIR_USR_BIN, BB_SUID_DROP, cksum))
19 //applet:IF_CRC32(APPLET_NOEXEC(crc32, cksum, BB_DIR_USR_BIN, BB_SUID_DROP, cksum))
20 /* bb_common_bufsiz1 usage here is safe wrt NOEXEC: not expecting it to be zeroed. */
22 //kbuild:lib-$(CONFIG_CKSUM) += cksum.o
23 //kbuild:lib-$(CONFIG_CRC32) += cksum.o
25 //usage:#define cksum_trivial_usage
26 //usage: "FILE..."
27 //usage:#define cksum_full_usage "\n\n"
28 //usage: "Calculate CRC32 checksum of FILEs"
30 #include "libbb.h"
31 #include "common_bufsiz.h"
33 /* This is a NOEXEC applet. Be very careful! */
35 #define IS_CKSUM (ENABLE_CKSUM && (!ENABLE_CRC32 || applet_name[1] == 'k'))
36 #define IS_CRC32 (ENABLE_CRC32 && (!ENABLE_CKSUM || applet_name[1] == 'r'))
38 int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
39 int cksum_main(int argc UNUSED_PARAM, char **argv)
41 uint32_t *crc32_table = crc32_filltable(NULL, IS_CKSUM);
42 exitcode_t exit_code = EXIT_SUCCESS;
44 #if ENABLE_DESKTOP
45 getopt32(argv, ""); /* cksum coreutils 6.9 compat */
46 argv += optind;
47 #else
48 argv++;
49 #endif
51 setup_common_bufsiz();
52 do {
53 uint32_t crc;
54 IF_CKSUM(off_t filesize;)
55 const char *fname = *argv ? *argv : bb_msg_standard_input;
56 int fd = open_or_warn_stdin(fname);
58 if (fd < 0) {
59 exit_code = EXIT_FAILURE;
60 continue;
63 crc = IS_CKSUM ? 0 : 0xffffffff;
64 IF_CKSUM(filesize = 0;)
65 #define read_buf bb_common_bufsiz1
66 for (;;) {
67 int bytes_read = safe_read(fd, read_buf, COMMON_BUFSIZE);
68 if (bytes_read < 0)
69 bb_simple_perror_msg_and_die(fname);
70 if (bytes_read > 0) {
71 IF_CKSUM(filesize += bytes_read;)
72 } else {
73 IF_CKSUM(uoff_t t;)
75 close(fd);
76 if (IS_CRC32)
77 break;
78 #if ENABLE_CKSUM
79 fd = -1; /* break flag */
80 /* Checksum filesize bytes, LSB first */
81 t = filesize;
82 /*bytes_read = 0; - already is */
83 while (t != 0) {
84 read_buf[bytes_read++] = (uint8_t)t;
85 t >>= 8;
87 #endif
89 crc = (IS_CKSUM ? crc32_block_endian1 : crc32_block_endian0)(crc, read_buf, bytes_read, crc32_table);
90 if (ENABLE_CKSUM && fd < 0)
91 break;
94 crc = ~crc;
95 #if ENABLE_CKSUM
96 if (IS_CKSUM)
97 printf((*argv ? "%u %"OFF_FMT"u %s\n" : "%u %"OFF_FMT"u\n"),
98 (unsigned)crc, filesize, *argv);
99 else
100 #endif
101 printf((*argv ? "%08x %s\n" : "%08x\n"),
102 (unsigned)crc, *argv);
103 } while (*argv && *++argv);
105 fflush_stdout_and_exit(exit_code);