Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/ape/cmd/pax/list.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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