home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / cpio-2.3-src.lha / GNU / src / amiga / cpio-2.3 / util.c < prev    next >
C/C++ Source or Header  |  1993-04-28  |  31KB  |  1,103 lines

  1. /* util.c - Several utility routines for cpio.
  2.    Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #ifdef HPUX_CDF
  21. #include <sys/stat.h>
  22. #endif
  23. #include "system.h"
  24. #include "cpiohdr.h"
  25. #include "dstring.h"
  26. #include "extern.h"
  27. #include "rmt.h"
  28.  
  29. #ifndef __MSDOS__
  30. #include <sys/ioctl.h>
  31. #else
  32. #include <io.h>
  33. #endif
  34.  
  35. #ifdef HAVE_SYS_MTIO_H
  36. #ifdef HAVE_SYS_IO_TRIOCTL_H
  37. #include <sys/io/trioctl.h>
  38. #endif
  39. #include <sys/mtio.h>
  40. #endif
  41.  
  42. static void empty_output_buffer_swap ();
  43. static void hash_insert ();
  44.  
  45. /* Write `output_size' bytes of `output_buffer' to file
  46.    descriptor OUT_DES and reset `output_size' and `out_buff'.  */
  47.  
  48. void
  49. empty_output_buffer (out_des)
  50.      int out_des;
  51. {
  52.   int bytes_written;
  53.  
  54. #ifdef BROKEN_LONG_TAPE_DRIVER
  55.   static long output_bytes_before_lseek = 0;
  56. #endif
  57.  
  58.   if (swapping_halfwords || swapping_bytes)
  59.     {
  60.       empty_output_buffer_swap (out_des);
  61.       return;
  62.     }
  63.  
  64. #ifdef BROKEN_LONG_TAPE_DRIVER
  65.   /* Some tape drivers seem to have a signed internal seek pointer and
  66.      they lose if it overflows and becomes negative (e.g. when writing 
  67.      tapes > 2Gb).  Doing an lseek (des, 0, SEEK_SET) seems to reset the 
  68.      seek pointer and prevent it from overflowing.  */
  69.   if (output_is_special
  70.      && (output_bytes_before_lseek += output_size) < 0L)
  71.     {
  72.       lseek(out_des, 0L, SEEK_SET);
  73.       output_bytes_before_lseek = 0;
  74.     }
  75. #endif
  76.  
  77.   bytes_written = rmtwrite (out_des, output_buffer, output_size);
  78.   if (bytes_written != output_size)
  79.     {
  80.       int rest_bytes_written;
  81.       int rest_output_size;
  82.  
  83.       if (output_is_special
  84.       && (bytes_written >= 0
  85.           || (bytes_written < 0
  86.           && (errno == ENOSPC || errno == EIO || errno == ENXIO))))
  87.     {
  88.       get_next_reel (out_des);
  89.       if (bytes_written > 0)
  90.         rest_output_size = output_size - bytes_written;
  91.       else
  92.         rest_output_size = output_size;
  93.       rest_bytes_written = rmtwrite (out_des, output_buffer,
  94.                      rest_output_size);
  95.       if (rest_bytes_written != rest_output_size)
  96.         error (1, errno, "write error");
  97.     }
  98.       else
  99.     error (1, errno, "write error");
  100.     }
  101.   output_bytes += output_size;
  102.   out_buff = output_buffer;
  103.   output_size = 0;
  104. }
  105.  
  106. /* Write `output_size' bytes of `output_buffer' to file
  107.    descriptor OUT_DES with byte and/or halfword swapping and reset
  108.    `output_size' and `out_buff'.  This routine should not be called
  109.    with `swapping_bytes' set unless the caller knows that the
  110.    file being written has an even number of bytes, and it should not be
  111.    called with `swapping_halfwords' set unless the caller knows
  112.    that the file being written has a length divisible by 4.  If either
  113.    of those restrictions are not met, bytes may be lost in the output
  114.    file.  OUT_DES must refer to a file that we are creating during
  115.    a process_copy_in, so we don't have to check for end of media
  116.    errors or be careful about only writing in blocks of `output_size'
  117.    bytes.  */
  118.  
  119. static void
  120. empty_output_buffer_swap (out_des)
  121.      int out_des;
  122. {
  123.   /* Since `output_size' might not be divisible by 4 or 2, we might
  124.      not be able to be able to swap all the bytes and halfwords in
  125.      `output_buffer' (e.g., if `output_size' is odd), so we might not be
  126.      able to write them all.  We will swap and write as many bytes as
  127.      we can, and save the rest in `left_overs' for the next time we are
  128.      called.  */
  129.   static char left_overs[4];
  130.   static int left_over_bytes = 0;
  131.  
  132.   int bytes_written;
  133.   int complete_halfwords;
  134.   int complete_words;
  135.   int extra_bytes;
  136.  
  137.   output_bytes += output_size;
  138.  
  139.   out_buff = output_buffer;
  140.  
  141.   if (swapping_halfwords)
  142.     {
  143.       if (left_over_bytes != 0)
  144.     {
  145.       while (output_size > 0 && left_over_bytes < 4)
  146.         {
  147.           left_overs[left_over_bytes++] = *out_buff++;
  148.           --output_size;
  149.         }
  150.       if (left_over_bytes < 4)
  151.         {
  152.           out_buff = output_buffer;
  153.           output_size = 0;
  154.           return;
  155.         }
  156.       swahw_array (left_overs, 1);
  157.       if (swapping_bytes)
  158.         swab_array (left_overs, 2);
  159.       bytes_written = rmtwrite (out_des, left_overs, 4);
  160.       if (bytes_written != 4)
  161.         error (1, errno, "write error");
  162.       left_over_bytes = 0;
  163.     }
  164.       complete_words = output_size / 4;
  165.       if (complete_words > 0)
  166.     {
  167.       swahw_array (out_buff, complete_words);
  168.       if (swapping_bytes)
  169.         swab_array (out_buff, 2 * complete_words);
  170.       bytes_written = rmtwrite (out_des, out_buff, 4 * complete_words);
  171.       if (bytes_written != (4 * complete_words))
  172.         error (1, errno, "write error");
  173.     }
  174.       out_buff += (4 * complete_words);
  175.       extra_bytes = output_size % 4;
  176.       while (extra_bytes > 0)
  177.     {
  178.       left_overs[left_over_bytes++] = *out_buff++;
  179.       --extra_bytes;
  180.     }
  181.  
  182.     }
  183.   else
  184.     {
  185.       if (left_over_bytes != 0)
  186.     {
  187.       while (output_size > 0 && left_over_bytes < 2)
  188.         {
  189.           left_overs[left_over_bytes++] = *out_buff++;
  190.           --output_size;
  191.         }
  192.       if (left_over_bytes < 2)
  193.         {
  194.           out_buff = output_buffer;
  195.           output_size = 0;
  196.           return;
  197.         }
  198.       swab_array (left_overs, 1);
  199.       bytes_written = rmtwrite (out_des, left_overs, 2);
  200.       if (bytes_written != 2)
  201.         error (1, errno, "write error");
  202.       left_over_bytes = 0;
  203.     }
  204.       complete_halfwords = output_size / 2;
  205.       if (complete_halfwords > 0)
  206.     {
  207.       swab_array (out_buff, complete_halfwords);
  208.       bytes_written = rmtwrite (out_des, out_buff, 2 * complete_halfwords);
  209.       if (bytes_written != (2 * complete_halfwords))
  210.         error (1, errno, "write error");
  211.     }
  212.       out_buff += (2 * complete_halfwords);
  213.       extra_bytes = output_size % 2;
  214.       while (extra_bytes > 0)
  215.     {
  216.       left_overs[left_over_bytes++] = *out_buff++;
  217.       --extra_bytes;
  218.     }
  219.     }
  220.  
  221.   out_buff = output_buffer;
  222.   output_size = 0;
  223. }
  224.  
  225. /* Exchange the halfwords of each element of the array of COUNT longs
  226.    starting at PTR.  PTR does not have to be aligned at a word
  227.    boundary.  */
  228.  
  229. void
  230. swahw_array (ptr, count)
  231.      char *ptr;
  232.      int count;
  233. {
  234.   char tmp;
  235.  
  236.   for (; count > 0; --count)
  237.     {
  238.       tmp = *ptr;
  239.       *ptr = *(ptr + 2);
  240.       *(ptr + 2) = tmp;
  241.       ++ptr;
  242.       tmp = *ptr;
  243.       *ptr = *(ptr + 2);
  244.       *(ptr + 2) = tmp;
  245.       ptr += 3;
  246.     }
  247. }
  248.  
  249. /* Read at most NUM_BYTES or `io_block_size' bytes, whichever is smaller,
  250.    into the start of `input_buffer' from file descriptor IN_DES.
  251.    Set `input_size' to the number of bytes read and reset `in_buff'.
  252.    Exit with an error if end of file is reached.  */
  253.  
  254. #ifdef BROKEN_LONG_TAPE_DRIVER
  255. static long input_bytes_before_lseek = 0;
  256. #endif
  257.  
  258. void
  259. fill_input_buffer (in_des, num_bytes)
  260.      int in_des;
  261.      int num_bytes;
  262. {
  263. #ifdef BROKEN_LONG_TAPE_DRIVER
  264.   /* Some tape drivers seem to have a signed internal seek pointer and
  265.      they lose if it overflows and becomes negative (e.g. when writing 
  266.      tapes > 4Gb).  Doing an lseek (des, 0, SEEK_SET) seems to reset the 
  267.      seek pointer and prevent it from overflowing.  */
  268.   if (input_is_special
  269.       && (input_bytes_before_lseek += num_bytes) < 0L)
  270.     {
  271.       lseek(in_des, 0L, SEEK_SET);
  272.       input_bytes_before_lseek = 0;
  273.     }
  274. #endif
  275.   in_buff = input_buffer;
  276.   num_bytes = (num_bytes < io_block_size) ? num_bytes : io_block_size;
  277.   input_size = rmtread (in_des, input_buffer, num_bytes);
  278.   if (input_size == 0 && input_is_special)
  279.     {
  280.       get_next_reel (in_des);
  281.       input_size = rmtread (in_des, input_buffer, num_bytes);
  282.     }
  283.   if (input_size < 0)
  284.     error (1, errno, "read error");
  285.   if (input_size == 0)
  286.     {
  287.       error (0, 0, "premature end of file");
  288.       exit (1);
  289.     }
  290.   input_bytes += input_size;
  291. }
  292.  
  293. /*