home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 May / W2KPRK.iso / apps / posix / source / PAX / LIST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-17  |  20.6 KB  |  801 lines

  1. /* $Source: /u/mark/src/pax/RCS/list.c,v $
  2.  *
  3.  * $Revision: 1.2 $
  4.  *
  5.  * list.c - List all files on an archive
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  *    These function are needed to support archive table of contents and
  10.  *    verbose mode during extraction and creation of achives.
  11.  *
  12.  * AUTHOR
  13.  *
  14.  *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  15.  *
  16.  * Sponsored by The USENIX Association for public distribution. 
  17.  *
  18.  * Copyright (c) 1989 Mark H. Colburn.
  19.  * All rights reserved.
  20.  *
  21.  * Redistribution and use in source and binary forms are permitted
  22.  * provided that the above copyright notice is duplicated in all such 
  23.  * forms and that any documentation, advertising materials, and other 
  24.  * materials related to such distribution and use acknowledge that the 
  25.  * software was developed * by Mark H. Colburn and sponsored by The 
  26.  * USENIX Association. 
  27.  *
  28.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  29.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  30.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31.  *
  32.  * $Log:    list.c,v $
  33.  * Revision 1.2  89/02/12  10:04:43  mark
  34.  * 1.2 release fixes
  35.  * 
  36.  * Revision 1.1  88/12/23  18:02:14  mark
  37.  * Initial revision
  38.  * 
  39.  */
  40.  
  41. #ifndef lint
  42. static char *ident = "$Id: list.c,v 1.2 89/02/12 10:04:43 mark Exp $";
  43. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  44. #endif /* ! lint */
  45.  
  46.  
  47. /* Headers */
  48.  
  49. #include "pax.h"
  50.  
  51.  
  52. /* Defines */
  53.  
  54. /*
  55.  * isodigit returns non zero iff argument is an octal digit, zero otherwise
  56.  */
  57. #define    ISODIGIT(c)    (((c) >= '0') && ((c) <= '7'))
  58.  
  59.  
  60. /* Function Prototypes */
  61.  
  62. #ifdef __STDC__
  63.  
  64. static void cpio_entry(char *, Stat *);
  65. static void tar_entry(char *, Stat *);
  66. static void pax_entry(char *, Stat *);
  67. #ifdef _POSIX_SOURCE  /* Xn */
  68. static void print_mode(mode_t);  /* Xn */
  69. #else  /* Xn */
  70. static void print_mode(ushort);
  71. #endif  /* Xn */
  72. static long from_oct(int digs, char *where);
  73.  
  74. #else /* !__STDC__ */
  75.  
  76. static void cpio_entry();
  77. static void tar_entry();
  78. static void pax_entry();
  79. static void print_mode();
  80. static long from_oct();
  81.  
  82. #endif /* __STDC__ */
  83.  
  84.  
  85. /* Internal Identifiers */
  86.  
  87. static char       *monnames[] = {
  88.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  89.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  90. };
  91.  
  92.  
  93. /* read_header - read a header record
  94.  *
  95.  * DESCRIPTION
  96.  *
  97.  *     Read a record that's supposed to be a header record. Return its 
  98.  *    address in "head", and if it is good, the file's size in 
  99.  *    asb->sb_size.  Decode things from a file header record into a "Stat". 
  100.  *    Also set "head_standard" to !=0 or ==0 depending whether header record 
  101.  *    is "Unix Standard" tar format or regular old tar format. 
  102.  *
  103.  * PARAMETERS
  104.  *
  105.  *    char   *name        - pointer which will contain name of file
  106.  *    Stat   *asb        - pointer which will contain stat info
  107.  *
  108.  * RETURNS
  109.  *
  110.  *     Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a 
  111.  *     record full of zeros (EOF marker). 
  112.  */
  113.  
  114. #ifdef __STDC__
  115.  
  116. int read_header(char *name, Stat *asb)
  117.  
  118. #else
  119.     
  120. int read_header(name, asb)
  121. char           *name;
  122. Stat           *asb;
  123.  
  124. #endif
  125. {
  126.     int             i;
  127.     long            sum;
  128.     long        recsum;
  129. #if 0  /* Xn */
  130.     Link           *link;
  131. #endif  /* Xn */
  132.     char           *p;
  133.     char            hdrbuf[BLOCKSIZE];
  134.  
  135. #ifdef DF_TRACE_DEBUG
  136. printf("DF_TRACE_DEBUG: int read_header() in list.c\n");
  137. #endif
  138.     memset((char *)asb, 0, sizeof(Stat));
  139.     /* read the header from the buffer */
  140. #if 0
  141.     (void) fprintf(stderr, "list.c/read_header - before buf_read\n");
  142.     (void) fflush(stderr);
  143. #endif /* Xn 1993-06-22 */
  144.     if (buf_read(hdrbuf, BLOCKSIZE) != 0) {
  145.     return (EOF);
  146.     }
  147. #if 0
  148.     (void) fprintf(stderr, "list.c/read_header - after buf_read\n");
  149.     (void) fflush(stderr);
  150. #endif /* Xn 1993-06-22 */
  151.  
  152. #if 0 && WIN_NT
  153. /*
  154.     XXX.mjb: this code doesn't seem to handle filename which are
  155.     not null-terminated.
  156. */
  157. #endif
  158.  
  159.     if ('\0' == hdrbuf[345]) {
  160.      strcpy(name, &hdrbuf[0]);
  161.     } else {
  162.     strcpy(name, &hdrbuf[345]);
  163.     strcat(name, "/");
  164.     strcat(name, &hdrbuf[0]);
  165.     }
  166.  
  167.  
  168.     recsum = from_oct(8, &hdrbuf[148]);
  169.     sum = 0;
  170.     p = hdrbuf;
  171.     for (i = 0 ; i < 500; i++) {
  172.  
  173.     /*
  174.      * We can't use unsigned char here because of old compilers, e.g. V7. 
  175.      */
  176.     sum += 0xFF & *p++;
  177.     }
  178.  
  179.     /* Adjust checksum to count the "chksum" field as blanks. */
  180.     for (i = 0; i < 8; i++) {
  181.     sum -= 0xFF & hdrbuf[148 + i];
  182.     }
  183.     sum += ' ' * 8;
  184.  
  185.     if (sum == 8 * ' ') {
  186.  
  187.     /*
  188.      * This is a zeroed record...whole record is 0's except for the 8
  189.      * blanks we faked for the checksum field. 
  190.      */
  191. #if 0
  192.     (void) fprintf(stderr, "list.c/read_header - returning 2\n");
  193.     (void) fflush(stderr);
  194. #endif /* Xn 1993-06-22 */
  195.     return (2);
  196.     }
  197.     if (sum == recsum) {
  198.     /*
  199.      * Good record.  Decode file size and return. 
  200.      */
  201. #if 0
  202.     (void) fprintf(stderr, "list.c/read_header - entering sum == recsum\n");
  203.     (void) fflush(stderr);
  204. #endif /* Xn 1993-06-22 */
  205.     if (hdrbuf[156] != LNKTYPE) {
  206.         asb->sb_size = from_oct(1 + 12, &hdrbuf[124]);
  207.     }
  208.     asb->sb_mtime = from_oct(1 + 12, &hdrbuf[136]);
  209.     asb->sb_mode = (from_oct(8, &hdrbuf[100]) & 0777);
  210.  
  211. #if 0
  212.     (void) fprintf(stderr, "list.c/read_header - before TMAGIC\n");
  213.     (void) fflush(stderr);
  214. #endif /* Xn 1993-06-22 */
  215.     if (strcmp(&hdrbuf[257], TMAGIC) == 0) {
  216.         /* Unix Standard tar archive */
  217. #if 0
  218.         (void) fprintf(stderr, "list.c/read_header - strcmp match\n");
  219.         (void) fflush(stderr);
  220. #endif /* Xn 1993-06-22 */
  221.         head_standard = 1;
  222. #ifdef NONAMES
  223.         asb->sb_uid = from_oct(8, &hdrbuf[108]);
  224.         asb->sb_gid = from_oct(8, &hdrbuf[116]);
  225. #else
  226. #if 0
  227.         (void) fprintf(stderr, "list.c/read_header - before finduid\n");
  228.         (void) fflush(stderr);
  229. #endif /* Xn 1993-06-22 */
  230.         asb->sb_uid = finduid(&hdrbuf[265]);
  231. #if 0
  232.         (void) fprintf(stderr, "list.c/read_header - after finduid; before findgid\n");
  233.         (void) fflush(stderr);
  234. #endif /* Xn 1993-06-22 */
  235.         asb->sb_gid = findgid(&hdrbuf[297]);
  236. #if 0
  237.         (void) fprintf(stderr, "list.c/read_header - after findgid\n");
  238.         (void) fflush(stderr);
  239. #endif /* Xn 1993-06-22 */
  240. #endif
  241. #if 0
  242.         (void) fprintf(stderr, "list.c/read_header - before subswitch; hdrbuf[156]: '%c'\n", hdrbuf[156]);
  243.         (void) fflush(stderr);
  244. #endif /* Xn 1993-06-22 */
  245.         switch (hdrbuf[156]) {
  246.         case BLKTYPE:
  247.         case CHRTYPE:
  248. #ifndef _POSIX_SOURCE
  249.         asb->sb_rdev = makedev(from_oct(8, &hdrbuf[329]),
  250.                       from_oct(8, &hdrbuf[337]));
  251. #endif
  252.         break;
  253.         default:
  254.         /* do nothing... */
  255.         break;
  256.         }
  257. #if 0
  258.         (void) fprintf(stderr, "list.c/read_header - after subswitch\n");
  259.         (void) fflush(stderr);
  260. #endif /* Xn 1993-06-22 */
  261.     } else {
  262.         /* Old fashioned tar archive */
  263. #if 0
  264.         (void) fprintf(stderr, "list.c/read_header - strcmp mismatch\n");
  265.         (void) fflush(stderr);
  266. #endif /* Xn 1993-06-22 */
  267.         head_standard = 0;
  268.         asb->sb_uid = from_oct(8, &hdrbuf[108]);
  269.         asb->sb_gid = from_oct(8, &hdrbuf[116]);
  270.     }
  271. #if 0
  272.     (void) fprintf(stderr, "list.c/read_header - after TMAGIC; before switch\n");
  273.     (void) fflush(stderr);
  274. #endif /* Xn 1993-06-22 */
  275.  
  276.     switch (hdrbuf[156]) {
  277.     case REGTYPE:
  278.     case AREGTYPE:
  279.         /*
  280.          * Berkeley tar stores directories as regular files with a
  281.          * trailing /
  282.          */
  283.         if (name[strlen(name) - 1] == '/') {
  284.         name[strlen(name) - 1] = '\0';
  285.         asb->sb_mode |= S_IFDIR;
  286.         } else {
  287.         asb->sb_mode |= S_IFREG;
  288.         }
  289.         break;
  290.     case LNKTYPE:
  291.         asb->sb_nlink = 2;
  292.         linkto(&hdrbuf[157], asb);
  293.         linkto(name, asb);
  294.         asb->sb_mode |= S_IFREG;
  295.         break;
  296.     case BLKTYPE:
  297.         asb->sb_mode |= S_IFBLK;
  298.         break;
  299.     case CHRTYPE:
  300.         asb->sb_mode |= S_IFCHR;
  301.         break;
  302.     case DIRTYPE:
  303.         asb->sb_mode |= S_IFDIR;
  304.         break;
  305. #ifdef S_IFLNK
  306.     case SYMTYPE:
  307.         asb->sb_mode |= S_IFLNK;
  308.         strcpy(asb->sb_link, &hdrbuf[157]);
  309.         break;
  310. #endif
  311. #ifdef S_IFIFO
  312.     case FIFOTYPE:
  313.         asb->sb_mode |= S_IFIFO;
  314.         break;
  315. #endif
  316. #ifdef S_IFCTG
  317.     case CONTTYPE:
  318.         asb->sb_mode |= S_IFCTG;
  319.         break;
  320. #endif
  321. #ifdef S_IFSOCK  /* Xn */
  322.     case SOCKTYPE:  /* Xn */
  323.         asb->sb_mode |= S_IFSOCK;  /* Xn */
  324.         break;  /* Xn */
  325. #endif  /* Xn */
  326.     }
  327. #if 0
  328.     (void) fprintf(stderr, "list.c/read_header - exiting sum == recsum\n");
  329.     (void) fflush(stderr);
  330. #endif /* Xn 1993-06-22 */
  331.     return (1);
  332.     }
  333. #if 0
  334.     (void) fprintf(stderr, "list.c/read_header - sum != recsum\n");
  335.     (void) fflush(stderr);
  336. #endif /* Xn 1993-06-22 */
  337.     return (0);
  338. }
  339.  
  340.  
  341. /* print_entry - print a single table-of-contents entry
  342.  *
  343.  * DESCRIPTION
  344.  * 
  345.  *    Print_entry prints a single line of file information.  The format
  346.  *    of the line is the same as that used by the LS command.  For some
  347.  *    archive formats, various fields may not make any sense, such as
  348.  *    the link count on tar archives.  No error checking is done for bad
  349.  *    or invalid data.
  350.  *
  351.  * PARAMETERS
  352.  *
  353.  *    char   *name        - pointer to name to print an entry for
  354.  *    Stat   *asb        - pointer to the stat structure for the file
  355.  */
  356.  
  357. #ifdef __STDC__
  358.  
  359. void print_entry(char *name, Stat *asb)
  360.  
  361. #else
  362.     
  363. void print_entry(name, asb)
  364. char        *name;
  365. Stat            *asb;
  366.  
  367. #endif
  368. {
  369. #ifdef DF_TRACE_DEBUG
  370. printf("DF_TRACE_DEBUG: void print_entry() in list.c\n");
  371. #endif
  372.     switch (ar_interface) {
  373.     case TAR:
  374.     tar_entry(name, asb);
  375.     break;
  376.     case CPIO:
  377.     cpio_entry(name, asb);
  378.     break;
  379.     case PAX:
  380.     pax_entry(name, asb);
  381.     break;
  382.     }
  383. }
  384.  
  385.  
  386. /* cpio_entry - print a verbose cpio-style entry
  387.  *
  388.  * DESCRIPTION
  389.  *
  390.  *    Print_entry prints a single line of file information.  The format
  391.  *    of the line is the same as that used by the traditional cpio 
  392.  *    command.  No error checking is done for bad or invalid data.
  393.  *
  394.  * PARAMETERS
  395.  *
  396.  *    char   *name        - pointer to name to print an entry for
  397.  *    Stat   *asb        - pointer to the stat structure for the file
  398.  */
  399.  
  400. #ifdef __STDC__
  401.  
  402. static void cpio_entry(char *name, Stat *asb)
  403.  
  404. #else
  405.     
  406. static void cpio_entry(name, asb)
  407. char           *name;
  408. Stat           *asb;
  409.  
  410. #endif
  411. {
  412.     struct tm           *atm;
  413.     Link           *from;
  414.     struct passwd      *pwp;
  415. #if 0  /* Xn */
  416.     struct group       *grp;
  417. #endif  /* Xn */
  418.  
  419. #ifdef DF_TRACE_DEBUG
  420. printf("DF_TRACE_DEBUG: static void cpio_entry() in list.c\n");
  421. #endif
  422.     if (f_list && f_verbose) {
  423.     fprintf(msgfile, "%-7o", asb->sb_mode);
  424.     atm = localtime(&asb->sb_mtime);
  425.     if ((pwp = getpwuid((int) USH(asb->sb_uid))) != NULL) {  /* Xn */
  426.         fprintf(msgfile, "%-6s", pwp->pw_name);
  427.     } else {
  428.         fprintf(msgfile, "%-6u", USH(asb->sb_uid));
  429.     }
  430.     fprintf(msgfile,"%7ld  %3s %2d %02d:%02d:%02d %4d  ",
  431.                    asb->sb_size, monnames[atm->tm_mon], 
  432.                atm->tm_mday, atm->tm_hour, atm->tm_min, 
  433.                atm->tm_sec, atm->tm_year + 1900);
  434.     }
  435.     fprintf(msgfile, "%s", name);
  436.     if ((asb->sb_nlink > 1) && ((from = islink(name, asb))) != NULL) {  /* Xn */
  437.     fprintf(msgfile, " linked to %s", from->l_name);
  438.     }
  439. #ifdef    S_IFLNK
  440.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  441.     fprintf(msgfile, " symbolic link to %s", asb->sb_link);
  442.     }
  443. #endif    /* S_IFLNK */
  444.     putc('\n', msgfile);
  445. }
  446.  
  447.  
  448. /* tar_entry - print a tar verbose mode entry
  449.  *
  450.  * DESCRIPTION
  451.  *
  452.  *    Print_entry prints a single line of tar file information.  The format
  453.  *    of the line is the same as that produced by the traditional tar 
  454.  *    command.  No error checking is done for bad or invalid data.
  455.  *
  456.  * PARAMETERS
  457.  *
  458.  *    char   *name        - pointer to name to print an entry for
  459.  *    Stat   *asb        - pointer to the stat structure for the file
  460.  */
  461.  
  462. #ifdef __STDC__
  463.  
  464. static void tar_entry(char *name, Stat *asb)
  465.  
  466. #else
  467.     
  468. static void tar_entry(name, asb)
  469. char        *name;
  470. Stat            *asb;
  471.  
  472. #endif
  473. {
  474.     struct tm             *atm;
  475. #ifdef S_IFLNK  /* Xn */
  476.     int            i;
  477. #endif  /* Xn */
  478. #ifdef _POSIX_SOURCE  /* Xn */
  479.     mode_t        mode;  /* Xn */
  480. #else  /* Xn */
  481.     int            mode;
  482. #endif  /* Xn */
  483.     char               *symnam = "NULL";
  484.     Link               *link;
  485.  
  486. #ifdef DF_TRACE_DEBUG
  487. printf("DF_TRACE_DEBUG: static void tar_entry() in list.c\n");
  488. #endif
  489.     if ((mode = asb->sb_mode & S_IFMT) == S_IFDIR) {
  490.     return;            /* don't print directories */
  491.     }
  492.     if (f_extract) {
  493.     switch (mode) {
  494. #ifdef S_IFLNK
  495.     case S_IFLNK:     /* This file is a symbolic link */
  496.         i = readlink(name, symnam, PATH_MAX - 1);
  497.         if (i < 0) {        /* Could not find symbolic link */
  498.         warn("can't read symbolic link", strerror(errno));  /* Xn */
  499.         } else {         /* Found symbolic link filename */
  500.         symnam[i] = '\0';
  501.         fprintf(msgfile, "x %s symbolic link to %s\n", name, symnam);
  502.         }
  503.         break;
  504. #endif
  505.     case S_IFREG:     /* It is a link or a file */
  506.         if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) {  /* Xn */
  507.         fprintf(msgfile, "%s linked to %s\n", name, link->l_name); 
  508.         } else {
  509.         fprintf(msgfile, "x %s, %ld bytes, %d tape blocks\n", 
  510.             name, asb->sb_size, ROUNDUP(asb->sb_size, 
  511.             BLOCKSIZE) / BLOCKSIZE);
  512.         }
  513.     }
  514.     } else if (f_append || f_create) {
  515.     switch (mode) {
  516. #ifdef S_IFLNK
  517.     case S_IFLNK:     /* This file is a symbolic link */
  518.         i = readlink(name, symnam, PATH_MAX - 1);
  519.         if (i < 0) {        /* Could not find symbolic link */
  520.         warn("can't read symbolic link", strerror(errno));  /* Xn */
  521.         } else {         /* Found symbolic link filename */
  522.         symnam[i] = '\0';
  523.         fprintf(msgfile, "a %s symbolic link to %s\n", name, symnam);
  524.         }
  525.         break;
  526. #endif
  527.     case S_IFREG:     /* It is a link or a file */
  528.         fprintf(msgfile, "a %s ", name);
  529.         if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) {  /* Xn */
  530.         fprintf(msgfile, "link to %s\n", link->l_name); 
  531.         } else {
  532.         fprintf(msgfile, "%ld Blocks\n", 
  533.             ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
  534.         }
  535.         break;
  536.     }
  537.     } else if (f_list) {
  538.     if (f_verbose) {
  539.         atm = localtime(&asb->sb_mtime);
  540.         print_mode(asb->sb_mode);
  541.         fprintf(msgfile," %d/%d %6d %3s %2d %02d:%02d %4d %s",
  542.             asb->sb_uid, asb->sb_gid, asb->sb_size,
  543.             monnames[atm->tm_mon], atm->tm_mday, atm->tm_hour, 
  544.             atm->tm_min, atm->tm_year + 1900, name);
  545.     } else {
  546.         fprintf(msgfile, "%s", name);
  547.     }
  548.     switch (mode) {
  549. #ifdef S_IFLNK
  550.     case S_IFLNK:     /* This file is a symbolic link */
  551.         i = readlink(name, symnam, PATH_MAX - 1);
  552.         if (i < 0) {        /* Could not find symbolic link */
  553.         warn("can't read symbolic link", strerror(errno));  /* Xn */
  554.         } else {         /* Found symbolic link filename */
  555.         symnam[i] = '\0';
  556.         fprintf(msgfile, " symbolic link to %s", symnam);
  557.         }
  558.         break;
  559. #endif
  560.     case S_IFREG:     /* It is a link or a file */
  561.         if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) {  /* Xn */
  562.         fprintf(msgfile, " linked to %s", link->l_name);
  563.         }
  564.         break;        /* Do not print out directories */
  565.     }
  566.     fputc('\n', msgfile);
  567.     } else {
  568.     fprintf(msgfile, "? %s %ld blocks\n", name,
  569.         ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
  570.     }
  571. }
  572.  
  573.  
  574. /* pax_entry - print a verbose cpio-style entry
  575.  *
  576.  * DESCRIPTION
  577.  *
  578.  *    Print_entry prints a single line of file information.  The format
  579.  *    of the line is the same as that used by the LS command.  
  580.  *    No error checking is done for bad or invalid data.
  581.  *
  582.  * PARAMETERS
  583.  *
  584.  *    char   *name        - pointer to name to print an entry for
  585.  *    Stat   *asb        - pointer to the stat structure for the file
  586.  */
  587.  
  588. #ifdef __STDC__
  589.  
  590. static void pax_entry(char *name, Stat *asb)
  591.  
  592. #else
  593.     
  594. static void pax_entry(name, asb)
  595. char           *name;
  596. Stat           *asb;
  597.  
  598. #endif
  599. {
  600.     struct tm           *atm;
  601.     Link           *from;
  602.     struct passwd      *pwp;
  603.     struct group       *grp;
  604.  
  605. #ifdef DF_TRACE_DEBUG
  606. printf("DF_TRACE_DEBUG: static void pax_entry() in list.c\n");
  607. #endif
  608.     if (f_list && f_verbose) {
  609.     print_mode(asb->sb_mode);
  610.     fprintf(msgfile, " %2d", asb->sb_nlink);
  611.     atm = localtime(&asb->sb_mtime);
  612.     if ((pwp = getpwuid((int) USH(asb->sb_uid))) != NULL) {  /* Xn */
  613.         fprintf(msgfile, " %-8s", pwp->pw_name);
  614.     } else {
  615.         fprintf(msgfile, " %-8u", USH(asb->sb_uid));
  616.     }
  617.     if ((grp = getgrgid((int) USH(asb->sb_gid))) != NULL) {  /* Xn */
  618. #if 0
  619.         (void) fprintf(stderr, "list.c/pax_entry - asb->sb_gid: %lu; grp->gr_name: \"%s\"\n",
  620.         (unsigned long) asb->sb_gid, grp->gr_name);
  621.         (void) fflush(stderr);
  622. #endif /* Xn 1993-06-23 */
  623.         fprintf(msgfile, " %-8s", grp->gr_name);
  624.     } else {
  625. #if 0
  626.         (void) fprintf(stderr, "list.c/pax_entry - asb->sb_gid: %lu\n", (unsigned long) asb->sb_gid);
  627.         (void) fflush(stderr);
  628. #endif /* Xn 1993-06-23 */
  629.         fprintf(msgfile, " %-8u", USH(asb->sb_gid));
  630.     }
  631.     switch (asb->sb_mode & S_IFMT) {
  632.     case S_IFBLK:
  633.     case S_IFCHR:
  634. #ifndef _POSIX_SOURCE
  635.         fprintf(msgfile, "\t%3d, %3d",
  636.                    major(asb->sb_rdev), minor(asb->sb_rdev));
  637. #endif
  638.         break;
  639.     case S_IFREG:
  640.         fprintf(msgfile, "\t%8ld", asb->sb_size);
  641.         break;
  642.     default:
  643.         fprintf(msgfile, "\t        ");
  644.     }
  645.     fprintf(msgfile," %3s %2d %02d:%02d ",
  646.             monnames[atm->tm_mon], atm->tm_mday, 
  647.         atm->tm_hour, atm->tm_min);
  648.     }
  649.     fprintf(msgfile, "%s", name);
  650.     if ((asb->sb_nlink > 1) && ((from = islink(name, asb)) != NULL)) {  /* Xn */
  651.     fprintf(msgfile, " == %s", from->l_name);
  652.     }
  653. #ifdef    S_IFLNK
  654.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  655.     fprintf(msgfile, " -> %s", asb->sb_link);
  656.     }
  657. #endif    /* S_IFLNK */
  658.     putc('\n', msgfile);
  659. }
  660.  
  661.  
  662. /* print_mode - fancy file mode display
  663.  *
  664.  * DESCRIPTION
  665.  *
  666.  *    Print_mode displays a numeric file mode in the standard unix
  667.  *    representation, ala ls (-rwxrwxrwx).  No error checking is done
  668.  *    for bad mode combinations.  FIFOS, sybmbolic links, sticky bits,
  669.  *    block- and character-special devices are supported if supported
  670.  *    by the hosting implementation.
  671.  *
  672.  * PARAMETERS
  673.  *
  674.  *    ushort    mode    - The integer representation of the mode to print.
  675.  */
  676.  
  677. #ifdef __STDC__
  678.  
  679. #ifdef _POSIX_SOURCE  /* Xn */
  680. static void print_mode(mode_t mode)  /* Xn */
  681. #else  /* Xn */
  682. static void print_mode(ushort mode)
  683. #endif  /* Xn */
  684.  
  685. #else
  686.     
  687. static void print_mode(mode)
  688. ushort    mode;
  689.  
  690. #endif
  691. {
  692.     /* Tar does not print the leading identifier... */
  693. #ifdef DF_TRACE_DEBUG
  694. printf("DF_TRACE_DEBUG: static void print_mode() in list.c\n");
  695. #endif
  696.     if (ar_interface != TAR) {
  697.     switch (mode & S_IFMT) {
  698.     case S_IFDIR: 
  699.         putc('d', msgfile); 
  700.         break;
  701. #ifdef    S_IFLNK
  702.     case S_IFLNK: 
  703.         putc('l', msgfile); 
  704.         break;
  705. #endif    /* S_IFLNK */
  706.     case S_IFBLK: 
  707.         putc('b', msgfile); 
  708.         break;
  709.     case S_IFCHR: 
  710.         putc('c', msgfile); 
  711.         break;
  712. #ifdef    S_IFIFO
  713.     case S_IFIFO: 
  714.         putc('p', msgfile); 
  715.         break; 
  716. #endif    /* S_IFIFO */ 
  717.     case S_IFREG: 
  718.     default:
  719.         putc('-', msgfile); 
  720.         break;
  721.     }
  722.     }
  723.     putc(mode & 0400 ? 'r' : '-', msgfile);
  724.     putc(mode & 0200 ? 'w' : '-', msgfile);
  725.     putc(mode & 0100
  726.      ? mode & 04000 ? 's' : 'x'
  727.      : mode & 04000 ? 'S' : '-', msgfile);
  728.     putc(mode & 0040 ? 'r' : '-', msgfile);
  729.     putc(mode & 0020 ? 'w' : '-', msgfile);
  730.     putc(mode & 0010
  731.      ? mode & 02000 ? 's' : 'x'
  732.      : mode & 02000 ? 'S' : '-', msgfile);
  733.     putc(mode & 0004 ? 'r' : '-', msgfile);
  734.     putc(mode & 0002 ? 'w' : '-', msgfile);
  735.     putc(mode & 0001
  736.      ? mode & 01000 ? 't' : 'x'
  737.      : mode & 01000 ? 'T' : '-', msgfile);
  738. }
  739.  
  740.  
  741. /* from_oct - quick and dirty octal conversion
  742.  *
  743.  * DESCRIPTION
  744.  *
  745.  *    From_oct will convert an ASCII representation of an octal number
  746.  *    to the numeric representation.  The number of characters to convert
  747.  *    is given by the parameter "digs".  If there are less numbers than
  748.  *    specified by "digs", then the routine returns -1.
  749.  *
  750.  * PARAMETERS
  751.  *
  752.  *    int digs    - Number to of digits to convert 
  753.  *    char *where    - Character representation of octal number
  754.  *
  755.  * RETURNS
  756.  *
  757.  *    The value of the octal number represented by the first digs
  758.  *    characters of the string where.  Result is -1 if the field 
  759.  *    is invalid (all blank, or nonoctal). 
  760.  *
  761.  * ERRORS
  762.  *
  763.  *    If the field is all blank, then the value returned is -1.
  764.  *
  765.  */
  766.  
  767. #ifdef __STDC__
  768.  
  769. static long from_oct(int digs, char *where)
  770.  
  771. #else
  772.  
  773. static long from_oct(digs, where)
  774. int             digs;        /* number of characters to convert */
  775. char           *where;        /* character representation of octal number */
  776.  
  777. #endif
  778. {
  779.     long            value;
  780.  
  781. #ifdef DF_TRACE_DEBUG
  782. printf("DF_TRACE_DEBUG: static long from_oct() in list.c\n");
  783. #endif
  784.     while (isspace(*where)) {    /* Skip spaces */
  785.     where++;
  786.     if (--digs <= 0) {
  787.         return(-1);        /* All blank field */
  788.     }
  789.     }
  790.     value = 0;
  791.     while (digs > 0 && ISODIGIT(*where)) {    /* Scan til nonoctal */
  792.     value = (value << 3) | (*where++ - '0');
  793.     --digs;
  794.     }
  795.  
  796.     if (digs > 0 && *where && !isspace(*where)) {
  797.     return(-1);        /* Ended on non-space/nul */
  798.     }
  799.     return(value);
  800. }
  801.