From: Paul Eggert Date: Thu, 24 Apr 1997 02:25:57 +0000 (+0000) Subject: GNU tar 1.12 X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=76dce03c2e9751933ea8dd23038a064204dbf00f;p=chaz%2Ftar GNU tar 1.12 --- diff --git a/src/arith.c b/src/arith.c new file mode 100644 index 0000000..62c7638 --- /dev/null +++ b/src/arith.c @@ -0,0 +1,163 @@ +/* Arithmetic for numbers greater than a long int, for GNU tar. + Copyright (C) 1996, 1997 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 Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "system.h" + +/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */ +#include "common.h" + +/* GNU tar needs handling numbers exceeding 32 bits, which is the size of + unsigned long ints for many C compilers. This module should provide + machinery for handling at least BITS_PER_TARLONG bits per number. If + `long long' ints are available and are sufficient for the task, they will + be used preferrably. + + Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on + Ampex drives), so requiring 38 bits for the tape length in bytes. He + also reports breaking the terabyte limit with a single file (using SGI + xFS file system over 37 28GB disk arrays attached to a Power Challenge + XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a + little more than 40 bits for the file size in bytes. The POSIX header + structure allows for 12 octal digits to represent file lengths, that is, + up to 36 bits for the byte size of files. + + If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be + set to zero by configure. In this case, or if `long long' ints does not + have enough bits, then huge numbers are rather represented by an array of + longs, with the least significant super-digit at position 0. For making + multiplication and decimal input/output easy, the base of a super-digit + is an exact exponent of 10, and is such that base*base fits in a long. */ + +#if SUPERDIGIT + +/*-------------------------------. +| Check if ACCUMULATOR is zero. | +`-------------------------------*/ + +int +zerop_tarlong_helper (unsigned long *accumulator) +{ + int counter; + + for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--) + if (accumulator[counter]) + return 0; + + return 1; +} + +/*----------------------------------------------. +| Check if FIRST is strictly less than SECOND. | +`----------------------------------------------*/ + +int +lessp_tarlong_helper (unsigned long *first, unsigned long *second) +{ + int counter; + + for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--) + if (first[counter] != second[counter]) + return first[counter] < second[counter]; + + return 0; +} + +/*----------------------------. +| Reset ACCUMULATOR to zero. | +`----------------------------*/ + +void +clear_tarlong_helper (unsigned long *accumulator) +{ + int counter; + + for (counter = 0; counter < LONGS_PER_TARLONG; counter++) + accumulator[counter] = 0; +} + +/*----------------------------. +| To ACCUMULATOR, add VALUE. | +`----------------------------*/ + +void +add_to_tarlong_helper (unsigned long *accumulator, int value) +{ + int counter; + + if (value < 0) + for (counter = 0; counter < LONGS_PER_TARLONG; counter++) + { + if (accumulator[counter] >= -value) + { + accumulator[counter] += value; + return; + } + accumulator[counter] += value + SUPERDIGIT; + value = -1; + } + else + for (counter = 0; counter < LONGS_PER_TARLONG; counter++) + { + if (accumulator[counter] + value < SUPERDIGIT) + { + accumulator[counter] += value; + return; + } + accumulator[counter] += value - SUPERDIGIT; + value = 1; + } + FATAL_ERROR ((0, 0, _("Arithmetic overflow"))); +} + +/*--------------------------------. +| Multiply ACCUMULATOR by VALUE. | +`--------------------------------*/ + +void +mult_tarlong_helper (unsigned long *accumulator, int value) +{ + int carry = 0; + int counter; + + for (counter = 0; counter < LONGS_PER_TARLONG; counter++) + { + carry += accumulator[counter] * value; + accumulator[counter] = carry % SUPERDIGIT; + carry /= SUPERDIGIT; + } + if (carry) + FATAL_ERROR ((0, 0, _("Arithmetic overflow"))); +} + +/*----------------------------------------------------------. +| Print the decimal representation of ACCUMULATOR on FILE. | +`----------------------------------------------------------*/ + +void +print_tarlong_helper (unsigned long *accumulator, FILE *file) +{ + int counter = LONGS_PER_TARLONG - 1; + + while (counter > 0 && accumulator[counter] == 0) + counter--; + + fprintf (file, "%uld", accumulator[counter]); + while (counter > 0) + fprintf (file, TARLONG_FORMAT, accumulator[--counter]); +} + +#endif /* SUPERDIGIT */