Rob Landley | 856489b | 2006-04-18 20:57:28 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* |
| 3 | * cksum - calculate the CRC32 checksum of a file |
| 4 | * |
| 5 | * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 6 | * |
Denys Vlasenko | 0ef64bd | 2010-08-16 20:14:46 +0200 | [diff] [blame] | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
Denys Vlasenko | 5b6fe34 | 2009-11-26 05:43:16 +0100 | [diff] [blame] | 8 | */ |
Denys Vlasenko | af3f420 | 2016-11-23 14:46:56 +0100 | [diff] [blame] | 9 | //config:config CKSUM |
Denys Vlasenko | b097a84 | 2018-12-28 03:20:17 +0100 | [diff] [blame] | 10 | //config: bool "cksum (4.1 kb)" |
Denys Vlasenko | af3f420 | 2016-11-23 14:46:56 +0100 | [diff] [blame] | 11 | //config: default y |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 12 | //config: |
| 13 | //config:config CRC32 |
| 14 | //config: bool "crc32 (4.1 kb)" |
| 15 | //config: default y |
Denys Vlasenko | af3f420 | 2016-11-23 14:46:56 +0100 | [diff] [blame] | 16 | |
Denys Vlasenko | 836580a | 2021-06-22 09:23:54 +0200 | [diff] [blame] | 17 | // APPLET_NOEXEC:name main location suid_type help |
Denys Vlasenko | af3f420 | 2016-11-23 14:46:56 +0100 | [diff] [blame] | 18 | //applet:IF_CKSUM(APPLET_NOEXEC(cksum, cksum, BB_DIR_USR_BIN, BB_SUID_DROP, cksum)) |
Denys Vlasenko | 836580a | 2021-06-22 09:23:54 +0200 | [diff] [blame] | 19 | //applet:IF_CRC32(APPLET_NOEXEC(crc32, cksum, BB_DIR_USR_BIN, BB_SUID_DROP, cksum)) |
Denys Vlasenko | b9be780 | 2017-08-06 21:23:03 +0200 | [diff] [blame] | 20 | /* bb_common_bufsiz1 usage here is safe wrt NOEXEC: not expecting it to be zeroed. */ |
Denys Vlasenko | af3f420 | 2016-11-23 14:46:56 +0100 | [diff] [blame] | 21 | |
| 22 | //kbuild:lib-$(CONFIG_CKSUM) += cksum.o |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 23 | //kbuild:lib-$(CONFIG_CRC32) += cksum.o |
Pere Orga | 3442538 | 2011-03-31 14:43:25 +0200 | [diff] [blame] | 24 | |
| 25 | //usage:#define cksum_trivial_usage |
Denys Vlasenko | 2f59bf3 | 2017-04-07 20:45:08 +0200 | [diff] [blame] | 26 | //usage: "FILE..." |
Pere Orga | 3442538 | 2011-03-31 14:43:25 +0200 | [diff] [blame] | 27 | //usage:#define cksum_full_usage "\n\n" |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 28 | //usage: "Calculate CRC32 checksum of FILEs" |
Pere Orga | 3442538 | 2011-03-31 14:43:25 +0200 | [diff] [blame] | 29 | |
Denis Vlasenko | b6adbf1 | 2007-05-26 19:00:18 +0000 | [diff] [blame] | 30 | #include "libbb.h" |
Denys Vlasenko | e6a2f4c | 2016-04-21 16:26:30 +0200 | [diff] [blame] | 31 | #include "common_bufsiz.h" |
Rob Landley | 856489b | 2006-04-18 20:57:28 +0000 | [diff] [blame] | 32 | |
Dan Fandrich | 2d1a78b | 2010-09-30 14:31:12 -0700 | [diff] [blame] | 33 | /* This is a NOEXEC applet. Be very careful! */ |
| 34 | |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 35 | #define IS_CKSUM (ENABLE_CKSUM && (!ENABLE_CRC32 || applet_name[1] == 'k')) |
Denys Vlasenko | 836580a | 2021-06-22 09:23:54 +0200 | [diff] [blame] | 36 | #define IS_CRC32 (ENABLE_CRC32 && (!ENABLE_CKSUM || applet_name[1] == 'r')) |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 37 | |
Denis Vlasenko | 9b49a5e | 2007-10-11 10:05:36 +0000 | [diff] [blame] | 38 | int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Denis Vlasenko | a60f84e | 2008-07-05 09:18:54 +0000 | [diff] [blame] | 39 | int cksum_main(int argc UNUSED_PARAM, char **argv) |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 40 | { |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 41 | uint32_t *crc32_table = crc32_filltable(NULL, IS_CKSUM); |
Denis Vlasenko | f91f14d | 2008-11-11 22:59:41 +0000 | [diff] [blame] | 42 | int exit_code = EXIT_SUCCESS; |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 43 | |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 44 | #if ENABLE_DESKTOP |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 45 | getopt32(argv, ""); /* cksum coreutils 6.9 compat */ |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 46 | argv += optind; |
| 47 | #else |
| 48 | argv++; |
| 49 | #endif |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 50 | |
Denys Vlasenko | 9de2e5a | 2016-04-21 18:38:51 +0200 | [diff] [blame] | 51 | setup_common_bufsiz(); |
Rob Landley | 856489b | 2006-04-18 20:57:28 +0000 | [diff] [blame] | 52 | do { |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 53 | uint32_t crc; |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 54 | IF_CKSUM(off_t filesize;) |
Denys Vlasenko | 836580a | 2021-06-22 09:23:54 +0200 | [diff] [blame] | 55 | const char *fname = *argv ? *argv : bb_msg_standard_input; |
| 56 | int fd = open_or_warn_stdin(fname); |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 57 | |
Denis Vlasenko | f91f14d | 2008-11-11 22:59:41 +0000 | [diff] [blame] | 58 | if (fd < 0) { |
| 59 | exit_code = EXIT_FAILURE; |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 60 | continue; |
Denis Vlasenko | f91f14d | 2008-11-11 22:59:41 +0000 | [diff] [blame] | 61 | } |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 62 | |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 63 | crc = IS_CKSUM ? 0 : 0xffffffff; |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 64 | IF_CKSUM(filesize = 0;) |
Denys Vlasenko | 9de2e5a | 2016-04-21 18:38:51 +0200 | [diff] [blame] | 65 | #define read_buf bb_common_bufsiz1 |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 66 | for (;;) { |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 67 | int bytes_read = safe_read(fd, read_buf, COMMON_BUFSIZE); |
Denys Vlasenko | 836580a | 2021-06-22 09:23:54 +0200 | [diff] [blame] | 68 | if (bytes_read < 0) |
| 69 | bb_simple_perror_msg_and_die(fname); |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 70 | if (bytes_read > 0) { |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 71 | IF_CKSUM(filesize += bytes_read;) |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 72 | } else { |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 73 | IF_CKSUM(uoff_t t;) |
| 74 | |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 75 | close(fd); |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 76 | if (IS_CRC32) |
| 77 | break; |
| 78 | #if ENABLE_CKSUM |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 79 | fd = -1; /* break flag */ |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 80 | /* Checksum filesize bytes, LSB first */ |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 81 | t = filesize; |
| 82 | /*bytes_read = 0; - already is */ |
| 83 | while (t != 0) { |
| 84 | read_buf[bytes_read++] = (uint8_t)t; |
| 85 | t >>= 8; |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 86 | } |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 87 | #endif |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 88 | } |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 89 | crc = (IS_CKSUM ? crc32_block_endian1 : crc32_block_endian0)(crc, read_buf, bytes_read, crc32_table); |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 90 | if (ENABLE_CKSUM && fd < 0) |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 91 | break; |
Rob Landley | 856489b | 2006-04-18 20:57:28 +0000 | [diff] [blame] | 92 | } |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 93 | |
Denis Vlasenko | 8f0e342 | 2008-08-27 21:31:23 +0000 | [diff] [blame] | 94 | crc = ~crc; |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 95 | #if ENABLE_CKSUM |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 96 | if (IS_CKSUM) |
| 97 | printf((*argv ? "%u %"OFF_FMT"u %s\n" : "%u %"OFF_FMT"u\n"), |
Denys Vlasenko | da49e70 | 2018-02-01 11:44:52 +0100 | [diff] [blame] | 98 | (unsigned)crc, filesize, *argv); |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 99 | else |
Denys Vlasenko | 91b9549 | 2021-06-22 10:21:47 +0200 | [diff] [blame] | 100 | #endif |
Denys Vlasenko | ea9b96e | 2021-06-22 01:07:54 +0200 | [diff] [blame] | 101 | printf((*argv ? "%08x %s\n" : "%08x\n"), |
| 102 | (unsigned)crc, *argv); |
Denis Vlasenko | 62a90cd | 2008-03-17 09:07:36 +0000 | [diff] [blame] | 103 | } while (*argv && *++argv); |
Bernhard Reutner-Fischer | 73561cc | 2006-08-28 23:31:54 +0000 | [diff] [blame] | 104 | |
Denis Vlasenko | f91f14d | 2008-11-11 22:59:41 +0000 | [diff] [blame] | 105 | fflush_stdout_and_exit(exit_code); |
Rob Landley | 856489b | 2006-04-18 20:57:28 +0000 | [diff] [blame] | 106 | } |