xref: /csrg-svn/bin/pax/gen_subs.c (revision 57195)
1*57195Smuller /*-
2*57195Smuller  * Copyright (c) 1992 Keith Muller.
3*57195Smuller  * Copyright (c) 1992 The Regents of the University of California.
4*57195Smuller  * All rights reserved.
5*57195Smuller  *
6*57195Smuller  * This code is derived from software contributed to Berkeley by
7*57195Smuller  * Keith Muller of the University of California, San Diego.
8*57195Smuller  *
9*57195Smuller  * %sccs.include.redist.c%
10*57195Smuller  */
11*57195Smuller 
12*57195Smuller #ifndef lint
13*57195Smuller static char sccsid[] = "@(#)gen_subs.c	1.1 (Berkeley) 12/17/92";
14*57195Smuller #endif /* not lint */
15*57195Smuller 
16*57195Smuller #include <sys/types.h>
17*57195Smuller #include <sys/time.h>
18*57195Smuller #include <sys/stat.h>
19*57195Smuller #include <sys/param.h>
20*57195Smuller #include <stdio.h>
21*57195Smuller #include <ctype.h>
22*57195Smuller #include <tzfile.h>
23*57195Smuller #include <utmp.h>
24*57195Smuller #include <unistd.h>
25*57195Smuller #include <stdlib.h>
26*57195Smuller #include <string.h>
27*57195Smuller #include "pax.h"
28*57195Smuller #include "extern.h"
29*57195Smuller 
30*57195Smuller /*
31*57195Smuller  * a collection of general purpose subroutines used by pax
32*57195Smuller  */
33*57195Smuller 
34*57195Smuller /*
35*57195Smuller  * constants used by ls_list() when printing out archive members
36*57195Smuller  */
37*57195Smuller #define MODELEN 20
38*57195Smuller #define DATELEN 64
39*57195Smuller #define SIXMONTHS	 ((DAYSPERNYEAR / 2) * SECSPERDAY)
40*57195Smuller #define CURFRMT		"%b %e %H:%M"
41*57195Smuller #define OLDFRMT		"%b %e  %Y"
42*57195Smuller #ifndef UT_NAMESIZE
43*57195Smuller #define UT_NAMESIZE	8
44*57195Smuller #endif
45*57195Smuller #define UT_GRPSIZE	6
46*57195Smuller 
47*57195Smuller /*
48*57195Smuller  * ls_list()
49*57195Smuller  *	list the members of an archive in ls format
50*57195Smuller  */
51*57195Smuller 
52*57195Smuller #if __STDC__
53*57195Smuller void
54*57195Smuller ls_list(register ARCHD *arcn, time_t now)
55*57195Smuller #else
56*57195Smuller void
57*57195Smuller ls_list(arcn, now)
58*57195Smuller 	register ARCHD *arcn;
59*57195Smuller 	time_t now;
60*57195Smuller #endif
61*57195Smuller {
62*57195Smuller 	register struct stat *sbp;
63*57195Smuller 	char f_mode[MODELEN];
64*57195Smuller 	char f_date[DATELEN];
65*57195Smuller 	char *timefrmt;
66*57195Smuller 
67*57195Smuller 	/*
68*57195Smuller 	 * if not verbose, just print the file name
69*57195Smuller 	 */
70*57195Smuller 	if (!vflag) {
71*57195Smuller 		(void)printf("%s\n", arcn->name);
72*57195Smuller 		(void)fflush(stdout);
73*57195Smuller 		return;
74*57195Smuller 	}
75*57195Smuller 
76*57195Smuller 	/*
77*57195Smuller 	 * user wants long mode
78*57195Smuller 	 */
79*57195Smuller 	sbp = &(arcn->sb);
80*57195Smuller 	strmode(sbp->st_mode, f_mode);
81*57195Smuller 
82*57195Smuller 	if (ltmfrmt == NULL) {
83*57195Smuller 		/*
84*57195Smuller 		 * no locale specified format. time format based on age
85*57195Smuller 		 * compared to the time pax was started.
86*57195Smuller 		 */
87*57195Smuller 		if ((sbp->st_mtime + SIXMONTHS) <= now)
88*57195Smuller 			timefrmt = OLDFRMT;
89*57195Smuller 		else
90*57195Smuller 			timefrmt = CURFRMT;
91*57195Smuller 	} else
92*57195Smuller 		timefrmt = ltmfrmt;
93*57195Smuller 
94*57195Smuller 	/*
95*57195Smuller 	 * print file mode, link count, uid, gid and time
96*57195Smuller 	 */
97*57195Smuller 	if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
98*57195Smuller 		f_date[0] = '\0';
99*57195Smuller 	(void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE,
100*57195Smuller 		name_uid(sbp->st_uid, 1), UT_GRPSIZE,
101*57195Smuller 		name_gid(sbp->st_gid, 1));
102*57195Smuller 
103*57195Smuller 	/*
104*57195Smuller 	 * print device id's for devices, or sizes for other nodes
105*57195Smuller 	 */
106*57195Smuller 	if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
107*57195Smuller #		ifdef NET2_STAT
108*57195Smuller 		(void)printf("%4u,%4u ", MAJOR(sbp->st_rdev),
109*57195Smuller #		else
110*57195Smuller 		(void)printf("%4lu,%4lu ", MAJOR(sbp->st_rdev),
111*57195Smuller #		endif
112*57195Smuller 		    MINOR(sbp->st_rdev));
113*57195Smuller 	else {
114*57195Smuller #		ifdef NET2_STAT
115*57195Smuller 		(void)printf("%9lu ", sbp->st_size);
116*57195Smuller #		else
117*57195Smuller 		(void)printf("%9qu ", sbp->st_size);
118*57195Smuller #		endif
119*57195Smuller 	}
120*57195Smuller 
121*57195Smuller 	/*
122*57195Smuller 	 * print name and link info for hard and soft links
123*57195Smuller 	 */
124*57195Smuller 	(void)printf("%s %s", f_date, arcn->name);
125*57195Smuller 	if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
126*57195Smuller 		(void)printf(" == %s\n", arcn->ln_name);
127*57195Smuller 	else if (arcn->type == PAX_SLK)
128*57195Smuller 		(void)printf(" => %s\n", arcn->ln_name);
129*57195Smuller 	else
130*57195Smuller 		(void)putchar('\n');
131*57195Smuller 	(void)fflush(stdout);
132*57195Smuller 	return;
133*57195Smuller }
134*57195Smuller 
135*57195Smuller /*
136*57195Smuller  * tty_ls()
137*57195Smuller  * 	print a short summary of file to tty.
138*57195Smuller  */
139*57195Smuller 
140*57195Smuller #if __STDC__
141*57195Smuller void
142*57195Smuller ls_tty(register ARCHD *arcn)
143*57195Smuller #else
144*57195Smuller void
145*57195Smuller ls_tty(arcn)
146*57195Smuller 	register ARCHD *arcn;
147*57195Smuller #endif
148*57195Smuller {
149*57195Smuller 	char f_date[DATELEN];
150*57195Smuller 	char f_mode[MODELEN];
151*57195Smuller 	char *timefrmt;
152*57195Smuller 
153*57195Smuller 	if (ltmfrmt == NULL) {
154*57195Smuller 		/*
155*57195Smuller 		 * no locale specified format
156*57195Smuller 		 */
157*57195Smuller 		if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL))
158*57195Smuller 			timefrmt = OLDFRMT;
159*57195Smuller 		else
160*57195Smuller 			timefrmt = CURFRMT;
161*57195Smuller 	} else
162*57195Smuller 		timefrmt = ltmfrmt;
163*57195Smuller 
164*57195Smuller 	/*
165*57195Smuller 	 * convert time to string, and print
166*57195Smuller 	 */
167*57195Smuller 	if (strftime(f_date, DATELEN, timefrmt,
168*57195Smuller 	    localtime(&(arcn->sb.st_mtime))) == 0)
169*57195Smuller 		f_date[0] = '\0';
170*57195Smuller 	strmode(arcn->sb.st_mode, f_mode);
171*57195Smuller 	tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
172*57195Smuller 	return;
173*57195Smuller }
174*57195Smuller 
175*57195Smuller /*
176*57195Smuller  * zf_strncpy()
177*57195Smuller  *	copy src to dest up to len chars (stopping at first '\0'), when src is
178*57195Smuller  *	shorter than len, pads to len with '\0'. big performance win (and
179*57195Smuller  *	a lot easier to code) over strncpy(), then a strlen() then a
180*57195Smuller  *	bzero(). (or doing the bzero() first).
181*57195Smuller  */
182*57195Smuller 
183*57195Smuller #if __STDC__
184*57195Smuller void
185*57195Smuller zf_strncpy(register char *dest, register char *src, int len)
186*57195Smuller #else
187*57195Smuller void
188*57195Smuller zf_strncpy(dest, src, len)
189*57195Smuller 	register char *dest;
190*57195Smuller 	register char *src;
191*57195Smuller 	int len;
192*57195Smuller #endif
193*57195Smuller {
194*57195Smuller 	register char *stop;
195*57195Smuller 
196*57195Smuller 	stop = dest + len;
197*57195Smuller 	while ((dest < stop) && (*src != '\0'))
198*57195Smuller 		*dest++ = *src++;
199*57195Smuller 	while (dest < stop)
200*57195Smuller 		*dest++ = '\0';
201*57195Smuller 	return;
202*57195Smuller }
203*57195Smuller 
204*57195Smuller /*
205*57195Smuller  * l_strncpy()
206*57195Smuller  *	copy src to dest up to len chars (stopping at first '\0')
207*57195Smuller  * Return:
208*57195Smuller  *	number of chars copied. (Note this is a real performance win over
209*57195Smuller  *	doing a strncpy() then a strlen()
210*57195Smuller  */
211*57195Smuller 
212*57195Smuller #if __STDC__
213*57195Smuller int
214*57195Smuller l_strncpy(register char *dest, register char *src, int len)
215*57195Smuller #else
216*57195Smuller int
217*57195Smuller l_strncpy(dest, src, len)
218*57195Smuller 	register char *dest;
219*57195Smuller 	register char *src;
220*57195Smuller 	int len;
221*57195Smuller #endif
222*57195Smuller {
223*57195Smuller 	register char *stop;
224*57195Smuller 	register char *start;
225*57195Smuller 
226*57195Smuller 	stop = dest + len;
227*57195Smuller 	start = dest;
228*57195Smuller 	while ((dest < stop) && (*src != '\0'))
229*57195Smuller 		*dest++ = *src++;
230*57195Smuller 	if (dest < stop)
231*57195Smuller 		*dest = '\0';
232*57195Smuller 	return(dest - start);
233*57195Smuller }
234*57195Smuller 
235*57195Smuller /*
236*57195Smuller  * asc_ul()
237*57195Smuller  *	convert hex/octal character string into a u_long. We do not have to
238*57195Smuller  *	check for overflow! (the headers in all supported formats are not large
239*57195Smuller  *	enough to create an overflow).
240*57195Smuller  *	NOTE: strings passed to us are NOT TERMINATED.
241*57195Smuller  * Return:
242*57195Smuller  *	unsigned long value
243*57195Smuller  */
244*57195Smuller 
245*57195Smuller #if __STDC__
246*57195Smuller u_long
247*57195Smuller asc_ul(register char *str, int len, register int base)
248*57195Smuller #else
249*57195Smuller u_long
250*57195Smuller asc_ul(str, len, base)
251*57195Smuller 	register char *str;
252*57195Smuller 	int len;
253*57195Smuller 	register int base;
254*57195Smuller #endif
255*57195Smuller {
256*57195Smuller 	register char *stop;
257*57195Smuller 	u_long tval = 0;
258*57195Smuller 
259*57195Smuller 	stop = str + len;
260*57195Smuller 
261*57195Smuller 	/*
262*57195Smuller 	 * skip over leading blanks and zeros
263*57195Smuller 	 */
264*57195Smuller 	while ((str < stop) && ((*str == ' ') || (*str == '0')))
265*57195Smuller 		++str;
266*57195Smuller 
267*57195Smuller 	/*
268*57195Smuller 	 * for each valid digit, shift running value (tval) over to next digit
269*57195Smuller 	 * and add next digit
270*57195Smuller 	 */
271*57195Smuller 	if (base == HEX) {
272*57195Smuller 		while (str < stop) {
273*57195Smuller 			if ((*str >= '0') && (*str <= '9'))
274*57195Smuller 				tval = (tval << 4) + (*str++ - '0');
275*57195Smuller 			else if ((*str >= 'A') && (*str <= 'F'))
276*57195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'A');
277*57195Smuller 			else if ((*str >= 'a') && (*str <= 'f'))
278*57195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'a');
279*57195Smuller 			else
280*57195Smuller 				break;
281*57195Smuller 		}
282*57195Smuller 	} else {
283*57195Smuller  		while ((str < stop) && (*str >= '0') && (*str <= '7'))
284*57195Smuller 			tval = (tval << 3) + (*str++ - '0');
285*57195Smuller 	}
286*57195Smuller 	return(tval);
287*57195Smuller }
288*57195Smuller 
289*57195Smuller /*
290*57195Smuller  * ul_asc()
291*57195Smuller  *	convert an unsigned long into an hex/oct ascii string. pads with LEADING
292*57195Smuller  *	ascii 0's to fill string completely
293*57195Smuller  *	NOTE: the string created is NOT TERMINATED.
294*57195Smuller  */
295*57195Smuller 
296*57195Smuller #if __STDC__
297*57195Smuller int
298*57195Smuller ul_asc(u_long val, register char *str, register int len, register int base)
299*57195Smuller #else
300*57195Smuller int
301*57195Smuller ul_asc(val, str, len, base)
302*57195Smuller 	u_long val;
303*57195Smuller 	register char *str;
304*57195Smuller 	register int len;
305*57195Smuller 	register int base;
306*57195Smuller #endif
307*57195Smuller {
308*57195Smuller 	register char *pt;
309*57195Smuller 	u_long digit;
310*57195Smuller 
311*57195Smuller 	/*
312*57195Smuller 	 * WARNING str is not '\0' terminated by this routine
313*57195Smuller 	 */
314*57195Smuller 	pt = str + len - 1;
315*57195Smuller 
316*57195Smuller 	/*
317*57195Smuller 	 * do a tailwise conversion (start at right most end of string to place
318*57195Smuller 	 * least significant digit). Keep shifting until conversion value goes
319*57195Smuller 	 * to zero (all digits were converted)
320*57195Smuller 	 */
321*57195Smuller 	if (base == HEX) {
322*57195Smuller 		while (pt >= str) {
323*57195Smuller 			if ((digit = (val & 0xf)) < 10)
324*57195Smuller 				*pt-- = '0' + (char)digit;
325*57195Smuller 			else
326*57195Smuller 				*pt-- = 'a' + (char)(digit - 10);
327*57195Smuller 			if ((val = (val >> 4)) == (u_long)0)
328*57195Smuller 				break;
329*57195Smuller 		}
330*57195Smuller 	} else {
331*57195Smuller 		while (pt >= str) {
332*57195Smuller 			*pt-- = '0' + (char)(val & 0x7);
333*57195Smuller 			if ((val = (val >> 3)) == (u_long)0)
334*57195Smuller 				break;
335*57195Smuller 		}
336*57195Smuller 	}
337*57195Smuller 
338*57195Smuller 	/*
339*57195Smuller 	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
340*57195Smuller 	 */
341*57195Smuller 	while (pt >= str)
342*57195Smuller 		*pt-- = '0';
343*57195Smuller 	if (val != (u_long)0)
344*57195Smuller 		return(-1);
345*57195Smuller 	return(0);
346*57195Smuller }
347*57195Smuller 
348*57195Smuller #ifndef NET2_STAT
349*57195Smuller /*
350*57195Smuller  * asc_uqd()
351*57195Smuller  *	convert hex/octal character string into a u_quad_t. We do not have to
352*57195Smuller  *	check for overflow! (the headers in all supported formats are not large
353*57195Smuller  *	enough to create an overflow).
354*57195Smuller  *	NOTE: strings passed to us are NOT TERMINATED.
355*57195Smuller  * Return:
356*57195Smuller  *	u_quad_t value
357*57195Smuller  */
358*57195Smuller 
359*57195Smuller #if __STDC__
360*57195Smuller u_quad_t
361*57195Smuller asc_uqd(register char *str, int len, register int base)
362*57195Smuller #else
363*57195Smuller u_quad_t
364*57195Smuller asc_uqd(str, len, base)
365*57195Smuller 	register char *str;
366*57195Smuller 	int len;
367*57195Smuller 	register int base;
368*57195Smuller #endif
369*57195Smuller {
370*57195Smuller 	register char *stop;
371*57195Smuller 	u_quad_t tval = 0;
372*57195Smuller 
373*57195Smuller 	stop = str + len;
374*57195Smuller 
375*57195Smuller 	/*
376*57195Smuller 	 * skip over leading blanks and zeros
377*57195Smuller 	 */
378*57195Smuller 	while ((str < stop) && ((*str == ' ') || (*str == '0')))
379*57195Smuller 		++str;
380*57195Smuller 
381*57195Smuller 	/*
382*57195Smuller 	 * for each valid digit, shift running value (tval) over to next digit
383*57195Smuller 	 * and add next digit
384*57195Smuller 	 */
385*57195Smuller 	if (base == HEX) {
386*57195Smuller 		while (str < stop) {
387*57195Smuller 			if ((*str >= '0') && (*str <= '9'))
388*57195Smuller 				tval = (tval << 4) + (*str++ - '0');
389*57195Smuller 			else if ((*str >= 'A') && (*str <= 'F'))
390*57195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'A');
391*57195Smuller 			else if ((*str >= 'a') && (*str <= 'f'))
392*57195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'a');
393*57195Smuller 			else
394*57195Smuller 				break;
395*57195Smuller 		}
396*57195Smuller 	} else {
397*57195Smuller  		while ((str < stop) && (*str >= '0') && (*str <= '7'))
398*57195Smuller 			tval = (tval << 3) + (*str++ - '0');
399*57195Smuller 	}
400*57195Smuller 	return(tval);
401*57195Smuller }
402*57195Smuller 
403*57195Smuller /*
404*57195Smuller  * uqd_asc()
405*57195Smuller  *	convert an u_quad_t into a hex/oct ascii string. pads with LEADING
406*57195Smuller  *	ascii 0's to fill string completely
407*57195Smuller  *	NOTE: the string created is NOT TERMINATED.
408*57195Smuller  */
409*57195Smuller 
410*57195Smuller #if __STDC__
411*57195Smuller int
412*57195Smuller uqd_asc(u_quad_t val, register char *str, register int len, register int base)
413*57195Smuller #else
414*57195Smuller int
415*57195Smuller uqd_asc(val, str, len, base)
416*57195Smuller 	u_quad_t val;
417*57195Smuller 	register char *str;
418*57195Smuller 	register int len;
419*57195Smuller 	register int base;
420*57195Smuller #endif
421*57195Smuller {
422*57195Smuller 	register char *pt;
423*57195Smuller 	u_quad_t digit;
424*57195Smuller 
425*57195Smuller 	/*
426*57195Smuller 	 * WARNING str is not '\0' terminated by this routine
427*57195Smuller 	 */
428*57195Smuller 	pt = str + len - 1;
429*57195Smuller 
430*57195Smuller 	/*
431*57195Smuller 	 * do a tailwise conversion (start at right most end of string to place
432*57195Smuller 	 * least significant digit). Keep shifting until conversion value goes
433*57195Smuller 	 * to zero (all digits were converted)
434*57195Smuller 	 */
435*57195Smuller 	if (base == HEX) {
436*57195Smuller 		while (pt >= str) {
437*57195Smuller 			if ((digit = (val & 0xf)) < 10)
438*57195Smuller 				*pt-- = '0' + (char)digit;
439*57195Smuller 			else
440*57195Smuller 				*pt-- = 'a' + (char)(digit - 10);
441*57195Smuller 			if ((val = (val >> 4)) == (u_quad_t)0)
442*57195Smuller 				break;
443*57195Smuller 		}
444*57195Smuller 	} else {
445*57195Smuller 		while (pt >= str) {
446*57195Smuller 			*pt-- = '0' + (char)(val & 0x7);
447*57195Smuller 			if ((val = (val >> 3)) == (u_quad_t)0)
448*57195Smuller 				break;
449*57195Smuller 		}
450*57195Smuller 	}
451*57195Smuller 
452*57195Smuller 	/*
453*57195Smuller 	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
454*57195Smuller 	 */
455*57195Smuller 	while (pt >= str)
456*57195Smuller 		*pt-- = '0';
457*57195Smuller 	if (val != (u_quad_t)0)
458*57195Smuller 		return(-1);
459*57195Smuller 	return(0);
460*57195Smuller }
461*57195Smuller #endif
462