diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile index fd720a9..4e77487 100644 --- a/lib/libstand/Makefile +++ b/lib/libstand/Makefile @@ -38,7 +38,7 @@ CFLAGS+= -msoft-float -D_STANDALONE .endif # standalone components and stuff we have modified locally -SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \ +SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c crc.c environment.c getopt.c gets.c \ globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \ sbrk.c twiddle.c zalloc.c zalloc_malloc.c diff --git a/lib/libstand/crc.c b/lib/libstand/crc.c new file mode 100644 index 0000000..331d390 --- /dev/null +++ b/lib/libstand/crc.c @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2012 Boris Astardzhiev / Smartcom Bulgaria AD + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Simple CRC calculation of a file. + */ + +#include +#include "stand.h" +#include +#include "../libz/zlib.h" + +/* + * Display checksum. + */ + +int +crc32_file(const char *fname) +{ + unsigned long crc = 0UL; + char buf[80]; + size_t bytes; + int fd; + int res; + off_t end_off; + struct stat st; + + res = 0; + fd = open(fname, O_RDONLY); + if (fd == -1) { + printf("can't open '%s': %s\n", fname, strerror(errno)); + res = -1; + return (res); + } + + /* + * Check if it is a regular file. + */ + memset(&st, 0, sizeof(st)); + if (fstat(fd, &st) == -1) { + printf("can't get statistics of '%s': %s\n", fname, + strerror(errno)); + close(fd); + res = -1; + return (res); + } + + if (!(S_ISREG(st.st_mode))) { + printf("'%s' is not a regular file\n", fname); + close(fd); + res = -1; + return (res); + } + + /* + * Grab file size. + */ + end_off = lseek(fd, 0, SEEK_END); + if (end_off == -1) { + printf("can't get end of '%s': %s\n", fname, strerror(errno)); + close(fd); + res = -1; + return (res); + } + + if (lseek(fd, 0, SEEK_SET) == -1) { + printf("can't set offset to '%s': %s\n", fname, + strerror(errno)); + close(fd); + res = -1; + return (res); + } + + /* + * Calculate checksum. + */ + crc = crc32(crc, 0, 0); + for (;;) { + bytes = read(fd, buf, sizeof(buf)); + if (bytes < 0) { + res = -1; + break; + } + + if (!bytes) + break; + + crc = crc32(crc, buf, bytes); + } + + if (!res) { + printf("file: %s\n", fname); + printf("\t size: %llu\n", end_off); + printf("\tcrc32: 0x%08lx\n", crc); + } else + printf("can't calculate crc32 of '%s'\n", fname); + + close(fd); + + return (res); +} + diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h index 10bb829..ff75bed 100644 --- a/lib/libstand/stand.h +++ b/lib/libstand/stand.h @@ -265,6 +265,9 @@ extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt, optreset; extern int getopt(int, char * const [], const char *); +/* crc.c */ +extern int crc32_file(const char *fname); + /* pager.c */ extern void pager_open(void); extern void pager_close(void); diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c index 7fba019..c445d71 100644 --- a/sys/boot/common/commands.c +++ b/sys/boot/common/commands.c @@ -497,3 +497,20 @@ command_lsdev(int argc, char *argv[]) return(CMD_OK); } +/* + * Calculate CRC32 of a file. + */ +COMMAND_SET(crc32, "crc32", "calculate crc32 of a file", command_crc32); + +static int +command_crc32(int argc, char *argv[]) +{ + int i, res; + + res = 0; + for (i = 1; (i < argc) && !res; i++) + res |= crc32_file(argv[i]); + + return (!res ? (CMD_OK) : (CMD_ERROR)); +} + diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8 index 7386f72..8ec9143 100644 --- a/sys/boot/common/loader.8 +++ b/sys/boot/common/loader.8 @@ -174,6 +174,8 @@ The behavior of this builtin is changed if .Xr loader.4th 8 is loaded. .Pp +.It Ic crc32 +Calculate CRC32 of a specified file. .It Ic echo Xo .Op Fl n .Op Aq message