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