home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / CPIO11AS.ZIP / COPYIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-22  |  18.3 KB  |  680 lines

  1. /* copyin.c - cpio copy in sub-function.
  2.    Copyright (C) 1988, 1989, 1990 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 1, 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. /* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
  19.    This port is also distributed under the terms of the
  20.    GNU General Public License as published by the
  21.    Free Software Foundation.
  22.  
  23.    Please note that this file is not identical to the
  24.    original GNU release, you should have received this
  25.    code as patch to the official release.
  26.  
  27.    $Header: e:/gnu/cpio/RCS/copyin.c 1.1.0.2 90/09/23 23:10:58 tho Exp $
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #ifndef S_IFLNK
  34. #define lstat stat
  35. #endif
  36. #include <errno.h>
  37. #ifndef MSDOS            /* sigh, it's `volatile' !!! */
  38. extern int errno;
  39. #endif
  40. #include <fcntl.h>
  41. #ifndef MSDOS
  42. #include <sys/file.h>
  43. #endif
  44. #ifdef USG
  45. #include <time.h>
  46. #include <string.h>
  47. #ifndef MSDOS
  48. #include <sys/sysmacros.h>
  49. #endif
  50. #else
  51. #include <sys/time.h>
  52. #include <strings.h>
  53. #endif
  54. #include "cpio.h"
  55. #include "dstring.h"
  56. #include "extern.h"
  57.  
  58. #ifdef MSDOS
  59. extern int mkdir (char *, int);    /* we're cheating! */
  60. #define major(dev)  (((dev) >> 8) & 0xff)
  61. #define minor(dev)  ((dev) & 0xff)
  62. extern int glob_match (char *pattern, char *text, int dot_special);
  63. extern void read_in_header (struct cpio_header *file_hdr, int in_des);
  64. static void read_in_ascii (struct cpio_header *file_hdr, int in_des);
  65. static void read_in_binary (struct cpio_header *file_hdr, int in_des);
  66. extern void swab_array (short *ptr, int count);
  67. extern void mode_string (unsigned short mode, char *str);
  68. extern void print_name_with_quoting (char *p);
  69. #endif /* MSDOS */
  70.  
  71.  
  72. #ifdef MSDOS
  73. #define bcopy(s, d, n) memmove ((d), (s), (n))    /* more efficient */
  74. #else
  75. void bcopy ();
  76. #endif
  77.  
  78. void read_in_ascii ();
  79. void read_in_binary ();
  80. void mode_string ();
  81. void print_name_with_quoting ();
  82. void swab_array ();
  83.  
  84. /* Return 16-bit integer I with the bytes swapped. */
  85. #define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
  86.  
  87. /* Read header, including the name of the file, from file
  88.    descriptor IN_DES into FILE_HDR.  */
  89.  
  90. void
  91. read_in_header (file_hdr, in_des)
  92.      struct cpio_header *file_hdr;
  93.      int in_des;
  94. {
  95.   long bytes_skipped = 0;    /* Bytes of junk found before magic number. */
  96.  
  97.   /* Search for valid magic number. */
  98.   copy_in_buf ((char *) file_hdr, in_des, 6);
  99.   while (1)
  100.   {
  101.     if (portability_flag && !strncmp ((char *) file_hdr, "070707", 6))
  102.       {
  103.     if (bytes_skipped > 0)
  104.       error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
  105.     read_in_ascii (file_hdr, in_des);
  106.     break;
  107.       }
  108.     if (binary_flag
  109.     && (file_hdr->h_magic == 070707
  110.         || file_hdr->h_magic == swab_short ((unsigned short) 070707)))
  111.       {
  112.     /* Having to skip 1 byte because of word alignment is normal. */
  113.     if (bytes_skipped > 1)
  114.       error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
  115.     read_in_binary (file_hdr, in_des);
  116.     break;
  117.       }
  118.     bytes_skipped++;
  119.     bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
  120.     copy_in_buf ((char *) file_hdr + 5, in_des, 1);
  121.   }
  122. }
  123.  
  124. /* Fill in FILE_HDR by reading an ASCII format cpio header from
  125.    file descriptor IN_DES, except for the magic number, which is
  126.    already filled in. */
  127.  
  128. void
  129. read_in_ascii (file_hdr, in_des)
  130.      struct cpio_header *file_hdr;
  131.      int in_des;
  132. {
  133.   char ascii_header[78];
  134.  
  135.   copy_in_buf (ascii_header, in_des, 70);
  136.   ascii_header[70] = '\0';
  137.   sscanf (ascii_header,
  138.       "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
  139.       &file_hdr->h_dev, &file_hdr->h_ino,
  140.       &file_hdr->h_mode, &file_hdr->h_uid, &file_hdr->h_gid,
  141.       &file_hdr->h_nlink, &file_hdr->h_rdev, &file_hdr->h_mtime,
  142.       &file_hdr->h_namesize, &file_hdr->h_filesize);
  143.  
  144.   /* Read file name from input.  */
  145.   if (file_hdr->h_name != NULL)
  146.     free (file_hdr->h_name);
  147.   file_hdr->h_name = (char *) xmalloc (file_hdr->h_namesize);
  148.   copy_in_buf (file_hdr->h_name, in_des, file_hdr->h_namesize);
  149. }
  150.  
  151. /* Fill in FILE_HDR by reading a binary format cpio header from
  152.    file descriptor IN_DES, except for the first 6 bytes, which are
  153.    already filled in. */
  154.  
  155. void
  156. read_in_binary (file_hdr, in_des)
  157.      struct cpio_header *file_hdr;
  158.      int in_des;
  159. {
  160.   copy_in_buf ((char *) file_hdr + 6, in_des, 20);
  161.  
  162.   /* If correct magic number but byte swapped, fix the header. */
  163.   if (file_hdr->h_magic == swab_short ((unsigned short) 070707))
  164.     {
  165.       static int warned = 0;
  166.       
  167.       /* Alert the user that they might have to do byte swapping on
  168.      the file contents. */
  169.       if (warned == 0)
  170.     {
  171.       error (0, 0, "warning: archive header has reverse byte-order");
  172.       warned = 1;
  173.     }
  174.       swab_array ((short *) file_hdr, 13);
  175.     }
  176.  
  177. #ifdef MSDOS
  178.   file_hdr->h_mtime = (long) file_hdr->h_mtimes[0] << 16
  179.               | file_hdr->h_mtimes[1];
  180.  
  181.   file_hdr->h_filesize = (long) file_hdr->h_filesizes[0] << 16
  182.              | file_hdr->h_filesizes[1];
  183. #else /* not MSDOS */
  184.   file_hdr->h_mtime = file_hdr->h_mtimes[0] << 16 | file_hdr->h_mtimes[1];
  185.  
  186.   file_hdr->h_filesize = file_hdr->h_filesizes[0] << 16
  187.     | file_hdr->h_filesizes[1];
  188. #endif /* not MSDOS */
  189.  
  190.   /* Read file name from input.  */
  191.   if (file_hdr->h_name != NULL)
  192.     free (file_hdr->h_name);
  193.   file_hdr->h_name = (char *) xmalloc (file_hdr->h_namesize);
  194.   copy_in_buf (file_hdr->h_name, in_des, file_hdr->h_namesize);
  195.  
  196.   /* In binary mode, the amount of space allocated in the header for
  197.      the filename is `h_namesize' rounded up to the next short-word,
  198.      so we might need to drop a byte. */
  199.   if (file_hdr->h_namesize % 2)
  200.     toss_input (in_des, 1);
  201. }
  202.  
  203. /* Exchange the bytes of each element of the array of COUNT shorts
  204.    starting at PTR. */
  205.  
  206. void
  207. swab_array (ptr, count)
  208.      short *ptr;
  209.      int count;
  210. {
  211.   while (count-- > 0)
  212.     {
  213.       *ptr = swab_short (*ptr);
  214.       ++ptr;
  215.     }
  216. }
  217.  
  218. /* Current time for verbose table. */
  219. static long current_time;
  220.  
  221. /* Read the collection from standard input and create files
  222.    in the file system.  */
  223.  
  224. void
  225. process_copy_in ()
  226. {
  227.   char done = FALSE;        /* True if trailer reached.  */
  228.   int res;            /* Result of various function calls.  */
  229.   dynamic_string new_name;    /* New file name for rename option.  */
  230.   FILE *tty_in;            /* Interactive file for rename option.  */
  231.   FILE *tty_out;        /* Interactive file for rename option.  */
  232.   char *str_res;        /* Result for string function.  */
  233.   long times[2];        /* For setting file times.  */
  234.   struct stat file_stat;    /* Output file stat record.  */
  235.   struct cpio_header file_hdr;    /* Output header information.  */
  236.   int out_file_des;        /* Output file descriptor.  */
  237.   int in_file_des;        /* Input file descriptor.  */
  238. #ifdef MSDOS
  239.   int skip_file;        /* Shut up the compiler.  */
  240. #else
  241.   char skip_file;        /* Flag for use with patterns.  */
  242. #endif
  243.   int i;            /* Loop index variable.  */
  244.   char *link_name = NULL;    /* Name of hard and symbolic links.  */
  245.  
  246. #ifdef MSDOS
  247.   setmode (fileno (stdin), O_BINARY);
  248. #endif
  249.  
  250.   /* Initialize copy in.  */
  251.   file_hdr.h_name = NULL;
  252.   ds_init (&new_name, 128);
  253.  
  254.   /* Open interactive file pair for rename operation.  */
  255.   if (rename_flag)
  256.     {
  257. #ifdef MSDOS
  258.       tty_in = fopen ("con", "r");
  259.       if (tty_in == NULL)
  260.     error (2, errno, "/dev/tty");
  261.       tty_out = fopen ("con", "w");
  262.       if (tty_out == NULL)
  263.     error (2, errno, "/dev/tty");
  264. #else /* not MSDOS */
  265.       tty_in = fopen ("/dev/tty", "r");
  266.       if (tty_in == NULL)
  267.     error (2, errno, "/dev/tty");
  268.       tty_out = fopen ("/dev/tty", "w");
  269.       if (tty_out == NULL)
  270.     error (2, errno, "/dev/tty");
  271. #endif /* not MSDOS */
  272.     }
  273.  
  274.   /* Get date and time if needed for processing the table option. */
  275.   if (table_flag && verbose_flag)
  276.     time (¤t_time);
  277.  
  278.   /* Check whether the input file might be a tape.  */
  279.   in_file_des = fileno (stdin);
  280.   if (fstat (in_file_des, &file_stat))
  281.     error (1, errno, "standard input is closed");
  282. #ifdef S_IFBLK
  283.   input_is_special = ((file_stat.st_mode & S_IFMT) == S_IFCHR
  284.               || (file_stat.st_mode & S_IFMT) == S_IFBLK);
  285. #else /* not S_IFBLK */
  286.   input_is_special = ((file_stat.st_mode & S_IFMT) == S_IFCHR);
  287. #endif /* not S_IFBLK */
  288.   input_is_seekable = ((file_stat.st_mode & S_IFMT) == S_IFREG);
  289.   output_is_seekable = TRUE;
  290.  
  291.   /* While there is more input in collection, process the input.  */
  292.   while (!done)
  293.     {
  294.       /* Start processing the next file by reading the header. */
  295.       read_in_header (&file_hdr, in_file_des);
  296.  
  297.       /* Is this the header for the TRAILER file?  */
  298.       if (strcmp ("TRAILER!!!", file_hdr.h_name) == 0)
  299.     {
  300.       done = TRUE;
  301.       break;
  302.     }
  303.  
  304.       /* Does the file name match one of the given patterns?  */
  305.       if (num_patterns <= 0)
  306.     skip_file = FALSE;
  307.       else
  308.     {
  309.       skip_file = copy_matching_files;
  310.       for (i = 0; i < num_patterns
  311.            && skip_file == copy_matching_files; i++)
  312.         {
  313.           if (glob_match (save_patterns[i], file_hdr.h_name, 0) == 1)
  314.         skip_file = !copy_matching_files;
  315.         }
  316.     }
  317.  
  318.       if (skip_file)
  319.     toss_input (in_file_des, file_hdr.h_filesize);
  320.       else if (table_flag)
  321.     {
  322.       if (verbose_flag)
  323.         {
  324. #ifdef S_IFLNK
  325.           if ((file_hdr.h_mode & S_IFMT) == S_IFLNK)
  326.         {
  327.           link_name = (char *) xmalloc (file_hdr.h_filesize + 1);
  328.           link_name[file_hdr.h_filesize] = '\0';
  329.           copy_in_buf (link_name, in_file_des, file_hdr.h_filesize);
  330.           long_format (&file_hdr, link_name);
  331.           free (link_name);
  332.           file_hdr.h_filesize = 0;
  333.         }
  334.           else
  335. #endif
  336.         long_format (&file_hdr, (char *) 0);
  337.         }
  338.       else
  339.         printf ("%s\n", file_hdr.h_name);
  340.       toss_input (in_file_des, file_hdr.h_filesize);
  341.     }
  342.       else
  343.     {
  344.       /* Copy the input file into the directory structure.  */
  345.  
  346.       /* Do we need to rename the file? */
  347.       if (rename_flag)
  348.         {
  349.           fprintf (tty_out, "rename %s -> ", file_hdr.h_name);
  350.           fflush (tty_out);
  351.           str_res = ds_fgets (tty_in, &new_name);
  352.           if (str_res == NULL || str_res[0] == 0)
  353.         {
  354.           toss_input (in_file_des, file_hdr.h_filesize);
  355.           continue;
  356.         }
  357.           else
  358.         file_hdr.h_name = copystring (new_name.ds_string);
  359.         }
  360.  
  361.       /* See if the file already exists. */
  362.       if (lstat (file_hdr.h_name, &file_stat) == 0)
  363.         {
  364.           if (!unconditional_flag
  365.           && file_hdr.h_mtime < file_stat.st_mtime)
  366.         {
  367.           error (0, 0, "%s not created: newer version exists",
  368.              file_hdr.h_name);
  369.           toss_input (in_file_des, file_hdr.h_filesize);
  370.           continue;    /* Go to the next file. */
  371.         }
  372.           else if ((file_stat.st_mode & S_IFMT) == S_IFDIR)
  373.         {
  374.           error (0, 0, "cannot remove current %s: Is a directory",
  375.              file_hdr.h_name);
  376.           toss_input (in_file_des, file_hdr.h_filesize);
  377.           continue;    /* Go to the next file. */
  378.         }
  379.           else if (unlink (file_hdr.h_name))
  380.         {
  381.           error (0, errno, "cannot remove current %s",
  382.              file_hdr.h_name);
  383.           toss_input (in_file_des, file_hdr.h_filesize);
  384.           continue;    /* Go to the next file. */
  385.         }          
  386.         }
  387.  
  388.       /* Do the real copy or link.  */
  389.       switch (file_hdr.h_mode & S_IFMT)
  390.         {
  391.         case S_IFREG:
  392.           /* Can the current file be linked to a previously copied file? */
  393. #ifdef MSDOS
  394.           link_name = NULL;
  395. #else /* not MSDOS */
  396.           if (file_hdr.h_nlink > 1)
  397.         {
  398.           link_name = find_inode_file (file_hdr.h_ino);
  399.           if (link_name == NULL)
  400.             add_inode (file_hdr.h_ino, file_hdr.h_name);
  401.           else
  402.             {
  403.               res = link (link_name, file_hdr.h_name);
  404.               if (res < 0 && create_dir_flag)
  405.             {
  406.               create_all_directories (file_hdr.h_name);
  407.               res = link (link_name, file_hdr.h_name);
  408.             }
  409.               if (res == 0)
  410.             {
  411.               if (verbose_flag)
  412.                 error (0, 0, "%s linked to %s",
  413.                    link_name, file_hdr.h_name);
  414.               toss_input (in_file_des, file_hdr.h_filesize);
  415.             }
  416.               else
  417.             link_name = NULL;
  418.             }
  419.         }
  420. #endif /* not MSDOS */
  421.  
  422.           /* If not linked, copy the contents of the file. */
  423.           if (link_name == NULL)
  424.         {
  425. #ifdef MSDOS
  426.           out_file_des = open (file_hdr.h_name,
  427.                        O_CREAT | O_WRONLY | O_BINARY, 0600);
  428. #else
  429.           out_file_des = open (file_hdr.h_name,
  430.                        O_CREAT | O_WRONLY, 0600);
  431. #endif
  432.           if (out_file_des < 0 && create_dir_flag)
  433.             {
  434.               create_all_directories (file_hdr.h_name);
  435. #ifdef MSDOS
  436.               out_file_des = open (file_hdr.h_name,
  437.                        O_CREAT | O_WRONLY | O_BINARY,
  438.                        0600);
  439. #else
  440.               out_file_des = open (file_hdr.h_name,
  441.                        O_CREAT | O_WRONLY, 0600);
  442. #endif
  443.             }
  444.           if (out_file_des < 0)
  445.             {
  446.               error (0, errno, "%s", file_hdr.h_name);
  447.               toss_input (in_file_des, file_hdr.h_filesize);
  448.               continue;
  449.             }
  450.  
  451.           copy_files (in_file_des, out_file_des, file_hdr.h_filesize);
  452.           empty_output_buffer (out_file_des);
  453.           finish_output_file (file_hdr.h_name, out_file_des);
  454.           close (out_file_des);
  455.  
  456.           /* File is now copied; set attributes.  */
  457.           if (chmod (file_hdr.h_name, file_hdr.h_mode) < 0)
  458.             error (0, errno, "%s", file_hdr.h_name);
  459. #ifndef MSDOS
  460.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  461.                  file_hdr.h_gid) < 0
  462.               && errno != EPERM)
  463.             error (0, errno, "%s", file_hdr.h_name);
  464. #endif /* not MSDOS */
  465.           if (retain_time_flag)
  466.             {
  467.               times[0] = times[1] = file_hdr.h_mtime;
  468.               if (utime (file_hdr.h_name, times) < 0)
  469.             error (0, errno, "%s", file_hdr.h_name);
  470.             }
  471.         }
  472.           break;
  473.  
  474.         case S_IFDIR:
  475.           res = mkdir (file_hdr.h_name, file_hdr.h_mode);
  476.           if (res < 0 && create_dir_flag)
  477.         {
  478.           create_all_directories (file_hdr.h_name);
  479.           res = mkdir (file_hdr.h_name, file_hdr.h_mode);
  480.         }
  481.           if (res < 0)
  482.         {
  483.           error (0, errno, "%s", file_hdr.h_name);
  484.           continue;
  485.         }
  486. #ifndef MSDOS
  487.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  488.              file_hdr.h_gid) < 0
  489.           && errno != EPERM)
  490.         error (0, errno, "%s", file_hdr.h_name);
  491. #endif /* not MSDOS */
  492.           break;
  493.  
  494.         case S_IFCHR:
  495. #ifdef S_IFBLK
  496.         case S_IFBLK:
  497. #endif
  498. #ifdef S_IFSOCK
  499.         case S_IFSOCK:
  500. #endif
  501. #ifdef S_IFIFO
  502.         case S_IFIFO:
  503. #endif
  504. #ifndef MSDOS
  505.           res = mknod (file_hdr.h_name, file_hdr.h_mode, file_hdr.h_rdev);
  506.           if (res < 0 && create_dir_flag)
  507.         {
  508.           create_all_directories (file_hdr.h_name);
  509.           res = mknod (file_hdr.h_name, file_hdr.h_mode,
  510.                    file_hdr.h_rdev);
  511.         }
  512.           if (res < 0)
  513.         {
  514.           error (0, errno, "%s", file_hdr.h_name);
  515.           continue;
  516.         }
  517.           if (chown (file_hdr.h_name, file_hdr.h_uid,
  518.              file_hdr.h_gid) < 0
  519.           && errno != EPERM)
  520.         error (0, errno, "%s", file_hdr.h_name);
  521. #endif /* not MSDOS */
  522.           break;
  523.  
  524. #ifdef S_IFLNK
  525.         case S_IFLNK:
  526.           {
  527.         link_name = (char *) xmalloc (file_hdr.h_filesize + 1);
  528.         link_name[file_hdr.h_filesize] = '\0';
  529.         copy_in_buf (link_name, in_file_des, file_hdr.h_filesize);
  530.  
  531.         res = symlink (link_name, file_hdr.h_name);
  532.         if (res < 0 && create_dir_flag)
  533.           {
  534.             create_all_directories (file_hdr.h_name);
  535.             res = symlink (link_name, file_hdr.h_name);
  536.           }
  537.         if (res < 0)
  538.           {
  539.             error (0, errno, "%s", file_hdr.h_name);
  540.             free (link_name);
  541.             continue;
  542.           }
  543.         free (link_name);
  544.           }
  545.           break;
  546. #endif
  547.  
  548.         default:
  549.           error (0, 0, "%s: unknown file type", file_hdr.h_name);
  550.           toss_input (in_file_des, file_hdr.h_filesize);
  551.         }
  552.  
  553.       if (verbose_flag)
  554.         fprintf (stderr, "%s\n", file_hdr.h_name);
  555.     }
  556.     }
  557. #ifdef MSDOS
  558.   res = (int) ((input_bytes + io_block_size - 1) / io_block_size);
  559. #else
  560.   res = (input_bytes + io_block_size - 1) / io_block_size;
  561. #endif
  562.   if (res == 1)
  563.     fprintf (stderr, "1 block\n");
  564.   else
  565.     fprintf (stderr, "%d blocks\n", res);
  566. }
  567.  
  568. /* Print the file described by FILE_HDR in long format.
  569.    If LINK_NAME is nonzero, it is the name of the file that
  570.    this file is a symbolic link to.  */
  571.  
  572. void
  573. long_format (file_hdr, link_name)
  574.      struct cpio_header *file_hdr;
  575.      char *link_name;
  576. {
  577.   char mbuf[11];
  578.   char tbuf[40];
  579.   long when;
  580.  
  581.   mode_string (file_hdr->h_mode, mbuf);
  582.   mbuf[10] = '\0';
  583.  
  584.   /* Get time values ready to print. */
  585.   when = file_hdr->h_mtime;
  586.   strcpy (tbuf, ctime (&when));
  587.   if (current_time - when > 6L * 30L * 24L * 60L * 60L
  588.       || current_time - when < 0L)
  589.     {
  590.       /* The file is older than 6 months, or in the future.
  591.      Show the year instead of the time of day.  */
  592.       strcpy (tbuf + 11, tbuf + 19);
  593.     }
  594.   tbuf[16] = '\0';
  595.  
  596.   printf ("%s %3u ", mbuf, file_hdr->h_nlink);
  597.  
  598.   if (numeric_uid)
  599.     printf ("%-8u %-8u ", file_hdr->h_uid, file_hdr->h_gid);
  600.   else
  601.     printf ("%-8.8s %-8.8s ", getuser (file_hdr->h_uid),
  602.         getgroup (file_hdr->h_gid));
  603.  
  604. #ifdef S_IFBLK
  605.   if ((file_hdr->h_mode & S_IFMT) == S_IFCHR
  606.       || (file_hdr->h_mode & S_IFMT) == S_IFBLK)
  607. #else /* not S_IFBLK */
  608.   if ((file_hdr->h_mode & S_IFMT) == S_IFCHR)
  609. #endif /* not S_IFBLK */
  610.     printf ("%3u, %3u ", major (file_hdr->h_rdev),
  611.         minor (file_hdr->h_rdev));
  612.   else
  613. #ifdef MSDOS
  614.     printf ("%8lu ", file_hdr->h_filesize);
  615. #else
  616.     printf ("%8u ", file_hdr->h_filesize);
  617. #endif
  618.  
  619.   printf ("%s ", tbuf + 4);
  620.  
  621.   print_name_with_quoting (file_hdr->h_name);
  622.   if (link_name)
  623.     {
  624.       printf (" -> ");
  625.       print_name_with_quoting (link_name);
  626.     }
  627.   putc ('\n', stdout);
  628. }
  629.  
  630. void
  631. print_name_with_quoting (p)
  632.      register char *p;
  633. {
  634.   register unsigned char c;
  635.  
  636.   while (c = *p++)
  637.     {
  638.       switch (c)
  639.     {
  640.     case '\\':
  641.       printf ("\\\\");
  642.       break;
  643.  
  644.     case '\n':
  645.       printf ("\\n");
  646.       break;
  647.  
  648.     case '\b':
  649.       printf ("\\b");
  650.       break;
  651.  
  652.     case '\r':
  653.       printf ("\\r");
  654.       break;
  655.  
  656.     case '\t':
  657.       printf ("\\t");
  658.       break;
  659.  
  660.     case '\f':
  661.       printf ("\\f");
  662.       break;
  663.  
  664.     case ' ':
  665.       printf ("\\ ");
  666.       break;
  667.  
  668.     case '"':
  669.       printf ("\\\"");
  670.       break;
  671.  
  672.     default:
  673.       if (c > 040 && c < 0177)
  674.         putchar (c);
  675.       else
  676.         printf ("\\%03o", (unsigned int) c);
  677.     }
  678.     }
  679. }
  680.