/* sum -- checksum and count the blocks in a file Copyright (C) 86, 89, 91, 1995-1999 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Like BSD sum or SysV sum -r, except like SysV sum if -s option is given. */ /* Written by Kayvan Aghaiepour and David MacKenzie. */ /* Optimized for fchksum by Matthew Mueller */ #include "fchksum.h" #include #include #define AUTHORS "Kayvan Aghaiepour and David MacKenzie" /* Right-rotate 32-bit integer variable C. */ #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x8000; else (c) >>= 1; /* Calculate and print the rotated checksum and the size in 1K blocks of file FILE, or of the standard input if FILE is "-". If PRINT_NAME is >1, print FILE next to the checksum and size. The checksum varies depending on sizeof(int). Return 0 if successful, -1 if an error occurs. */ int bsd_sum_stream (int fd, unsigned long *res, chksum_size_t *size, CallbackInfo *cbinfo) { unsigned char buf[FCHKSUMBLOCKSIZE]; int bytes_read; unsigned long checksum = 0; /* The checksum mod 2^16. */ chksum_size_reset(*size); while ((bytes_read = read (fd, buf, sizeof buf)) > 0) { register int i; for (i = 0; i < bytes_read; i++) { ROTATE_RIGHT (checksum); checksum += buf[i]; checksum &= 0xffff; /* Keep it within bounds. */ } chksum_size_add(*size, bytes_read); if (do_callback(cbinfo, *size)) return CHKSUM_EXCEPT; } if (bytes_read < 0) return CHKSUM_FERROR; *res = checksum; return CHKSUM_OK; } /* Calculate and print the checksum and the size in 512-byte blocks of file FILE, or of the standard input if FILE is "-". If PRINT_NAME is >0, print FILE next to the checksum and size. Return 0 if successful, -1 if an error occurs. */ int sysv_sum_stream (int fd, unsigned long *res, chksum_size_t *size, CallbackInfo *cbinfo) { unsigned char buf[FCHKSUMBLOCKSIZE]; int bytes_read; unsigned long checksum = 0; chksum_size_reset(*size); while ((bytes_read = read (fd, buf, sizeof buf)) > 0) { register int i; for (i = 0; i < bytes_read; i++) checksum += buf[i]; chksum_size_add(*size, bytes_read); if (do_callback(cbinfo, *size)) return CHKSUM_EXCEPT; } if (bytes_read < 0) return CHKSUM_FERROR; *res = checksum % 0xffff; return CHKSUM_OK; }