]> Dogcows Code - chaz/tar/commitdiff
GNU tar 1.12
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 24 Apr 1997 02:25:57 +0000 (02:25 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 24 Apr 1997 02:25:57 +0000 (02:25 +0000)
src/arith.c [new file with mode: 0644]

diff --git a/src/arith.c b/src/arith.c
new file mode 100644 (file)
index 0000000..62c7638
--- /dev/null
@@ -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 */
This page took 0.027483 seconds and 4 git commands to generate.