xref: /csrg-svn/bin/pax/gen_subs.c (revision 60676)
157195Smuller /*-
257195Smuller  * Copyright (c) 1992 Keith Muller.
3*60676Sbostic  * Copyright (c) 1992, 1993
4*60676Sbostic  *	The Regents of the University of California.  All rights reserved.
557195Smuller  *
657195Smuller  * This code is derived from software contributed to Berkeley by
757195Smuller  * Keith Muller of the University of California, San Diego.
857195Smuller  *
957195Smuller  * %sccs.include.redist.c%
1057195Smuller  */
1157195Smuller 
1257195Smuller #ifndef lint
13*60676Sbostic static char sccsid[] = "@(#)gen_subs.c	8.1 (Berkeley) 05/31/93";
1457195Smuller #endif /* not lint */
1557195Smuller 
1657195Smuller #include <sys/types.h>
1757195Smuller #include <sys/time.h>
1857195Smuller #include <sys/stat.h>
1957195Smuller #include <sys/param.h>
2057195Smuller #include <stdio.h>
2157195Smuller #include <ctype.h>
2257195Smuller #include <tzfile.h>
2357195Smuller #include <utmp.h>
2457195Smuller #include <unistd.h>
2557195Smuller #include <stdlib.h>
2657195Smuller #include <string.h>
2757195Smuller #include "pax.h"
2857195Smuller #include "extern.h"
2957195Smuller 
3057195Smuller /*
3157195Smuller  * a collection of general purpose subroutines used by pax
3257195Smuller  */
3357195Smuller 
3457195Smuller /*
3557195Smuller  * constants used by ls_list() when printing out archive members
3657195Smuller  */
3757195Smuller #define MODELEN 20
3857195Smuller #define DATELEN 64
3957195Smuller #define SIXMONTHS	 ((DAYSPERNYEAR / 2) * SECSPERDAY)
4057195Smuller #define CURFRMT		"%b %e %H:%M"
4157195Smuller #define OLDFRMT		"%b %e  %Y"
4257195Smuller #ifndef UT_NAMESIZE
4357195Smuller #define UT_NAMESIZE	8
4457195Smuller #endif
4557195Smuller #define UT_GRPSIZE	6
4657195Smuller 
4757195Smuller /*
4857195Smuller  * ls_list()
4957195Smuller  *	list the members of an archive in ls format
5057195Smuller  */
5157195Smuller 
5257195Smuller #if __STDC__
5357195Smuller void
ls_list(register ARCHD * arcn,time_t now)5457195Smuller ls_list(register ARCHD *arcn, time_t now)
5557195Smuller #else
5657195Smuller void
5757195Smuller ls_list(arcn, now)
5857195Smuller 	register ARCHD *arcn;
5957195Smuller 	time_t now;
6057195Smuller #endif
6157195Smuller {
6257195Smuller 	register struct stat *sbp;
6357195Smuller 	char f_mode[MODELEN];
6457195Smuller 	char f_date[DATELEN];
6557195Smuller 	char *timefrmt;
6657195Smuller 
6757195Smuller 	/*
6857195Smuller 	 * if not verbose, just print the file name
6957195Smuller 	 */
7057195Smuller 	if (!vflag) {
7157195Smuller 		(void)printf("%s\n", arcn->name);
7257195Smuller 		(void)fflush(stdout);
7357195Smuller 		return;
7457195Smuller 	}
7557195Smuller 
7657195Smuller 	/*
7757195Smuller 	 * user wants long mode
7857195Smuller 	 */
7957195Smuller 	sbp = &(arcn->sb);
8057195Smuller 	strmode(sbp->st_mode, f_mode);
8157195Smuller 
8257195Smuller 	if (ltmfrmt == NULL) {
8357195Smuller 		/*
8457195Smuller 		 * no locale specified format. time format based on age
8557195Smuller 		 * compared to the time pax was started.
8657195Smuller 		 */
8757195Smuller 		if ((sbp->st_mtime + SIXMONTHS) <= now)
8857195Smuller 			timefrmt = OLDFRMT;
8957195Smuller 		else
9057195Smuller 			timefrmt = CURFRMT;
9157195Smuller 	} else
9257195Smuller 		timefrmt = ltmfrmt;
9357195Smuller 
9457195Smuller 	/*
9557195Smuller 	 * print file mode, link count, uid, gid and time
9657195Smuller 	 */
9757195Smuller 	if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
9857195Smuller 		f_date[0] = '\0';
9957195Smuller 	(void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE,
10057195Smuller 		name_uid(sbp->st_uid, 1), UT_GRPSIZE,
10157195Smuller 		name_gid(sbp->st_gid, 1));
10257195Smuller 
10357195Smuller 	/*
10457195Smuller 	 * print device id's for devices, or sizes for other nodes
10557195Smuller 	 */
10657195Smuller 	if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
10757195Smuller #		ifdef NET2_STAT
10857195Smuller 		(void)printf("%4u,%4u ", MAJOR(sbp->st_rdev),
10957195Smuller #		else
11057195Smuller 		(void)printf("%4lu,%4lu ", MAJOR(sbp->st_rdev),
11157195Smuller #		endif
11257195Smuller 		    MINOR(sbp->st_rdev));
11357195Smuller 	else {
11457195Smuller #		ifdef NET2_STAT
11557195Smuller 		(void)printf("%9lu ", sbp->st_size);
11657195Smuller #		else
11757195Smuller 		(void)printf("%9qu ", sbp->st_size);
11857195Smuller #		endif
11957195Smuller 	}
12057195Smuller 
12157195Smuller 	/*
12257195Smuller 	 * print name and link info for hard and soft links
12357195Smuller 	 */
12457195Smuller 	(void)printf("%s %s", f_date, arcn->name);
12557195Smuller 	if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
12657195Smuller 		(void)printf(" == %s\n", arcn->ln_name);
12757195Smuller 	else if (arcn->type == PAX_SLK)
12857195Smuller 		(void)printf(" => %s\n", arcn->ln_name);
12957195Smuller 	else
13057195Smuller 		(void)putchar('\n');
13157195Smuller 	(void)fflush(stdout);
13257195Smuller 	return;
13357195Smuller }
13457195Smuller 
13557195Smuller /*
13657195Smuller  * tty_ls()
13757195Smuller  * 	print a short summary of file to tty.
13857195Smuller  */
13957195Smuller 
14057195Smuller #if __STDC__
14157195Smuller void
ls_tty(register ARCHD * arcn)14257195Smuller ls_tty(register ARCHD *arcn)
14357195Smuller #else
14457195Smuller void
14557195Smuller ls_tty(arcn)
14657195Smuller 	register ARCHD *arcn;
14757195Smuller #endif
14857195Smuller {
14957195Smuller 	char f_date[DATELEN];
15057195Smuller 	char f_mode[MODELEN];
15157195Smuller 	char *timefrmt;
15257195Smuller 
15357195Smuller 	if (ltmfrmt == NULL) {
15457195Smuller 		/*
15557195Smuller 		 * no locale specified format
15657195Smuller 		 */
15757195Smuller 		if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL))
15857195Smuller 			timefrmt = OLDFRMT;
15957195Smuller 		else
16057195Smuller 			timefrmt = CURFRMT;
16157195Smuller 	} else
16257195Smuller 		timefrmt = ltmfrmt;
16357195Smuller 
16457195Smuller 	/*
16557195Smuller 	 * convert time to string, and print
16657195Smuller 	 */
16757195Smuller 	if (strftime(f_date, DATELEN, timefrmt,
16857195Smuller 	    localtime(&(arcn->sb.st_mtime))) == 0)
16957195Smuller 		f_date[0] = '\0';
17057195Smuller 	strmode(arcn->sb.st_mode, f_mode);
17157195Smuller 	tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
17257195Smuller 	return;
17357195Smuller }
17457195Smuller 
17557195Smuller /*
17657195Smuller  * zf_strncpy()
17757195Smuller  *	copy src to dest up to len chars (stopping at first '\0'), when src is
17857195Smuller  *	shorter than len, pads to len with '\0'. big performance win (and
17957195Smuller  *	a lot easier to code) over strncpy(), then a strlen() then a
18057195Smuller  *	bzero(). (or doing the bzero() first).
18157195Smuller  */
18257195Smuller 
18357195Smuller #if __STDC__
18457195Smuller void
zf_strncpy(register char * dest,register char * src,int len)18557195Smuller zf_strncpy(register char *dest, register char *src, int len)
18657195Smuller #else
18757195Smuller void
18857195Smuller zf_strncpy(dest, src, len)
18957195Smuller 	register char *dest;
19057195Smuller 	register char *src;
19157195Smuller 	int len;
19257195Smuller #endif
19357195Smuller {
19457195Smuller 	register char *stop;
19557195Smuller 
19657195Smuller 	stop = dest + len;
19757195Smuller 	while ((dest < stop) && (*src != '\0'))
19857195Smuller 		*dest++ = *src++;
19957195Smuller 	while (dest < stop)
20057195Smuller 		*dest++ = '\0';
20157195Smuller 	return;
20257195Smuller }
20357195Smuller 
20457195Smuller /*
20557195Smuller  * l_strncpy()
20657195Smuller  *	copy src to dest up to len chars (stopping at first '\0')
20757195Smuller  * Return:
20857195Smuller  *	number of chars copied. (Note this is a real performance win over
20957195Smuller  *	doing a strncpy() then a strlen()
21057195Smuller  */
21157195Smuller 
21257195Smuller #if __STDC__
21357195Smuller int
l_strncpy(register char * dest,register char * src,int len)21457195Smuller l_strncpy(register char *dest, register char *src, int len)
21557195Smuller #else
21657195Smuller int
21757195Smuller l_strncpy(dest, src, len)
21857195Smuller 	register char *dest;
21957195Smuller 	register char *src;
22057195Smuller 	int len;
22157195Smuller #endif
22257195Smuller {
22357195Smuller 	register char *stop;
22457195Smuller 	register char *start;
22557195Smuller 
22657195Smuller 	stop = dest + len;
22757195Smuller 	start = dest;
22857195Smuller 	while ((dest < stop) && (*src != '\0'))
22957195Smuller 		*dest++ = *src++;
23057195Smuller 	if (dest < stop)
23157195Smuller 		*dest = '\0';
23257195Smuller 	return(dest - start);
23357195Smuller }
23457195Smuller 
23557195Smuller /*
23657195Smuller  * asc_ul()
23757195Smuller  *	convert hex/octal character string into a u_long. We do not have to
23857195Smuller  *	check for overflow! (the headers in all supported formats are not large
23957195Smuller  *	enough to create an overflow).
24057195Smuller  *	NOTE: strings passed to us are NOT TERMINATED.
24157195Smuller  * Return:
24257195Smuller  *	unsigned long value
24357195Smuller  */
24457195Smuller 
24557195Smuller #if __STDC__
24657195Smuller u_long
asc_ul(register char * str,int len,register int base)24757195Smuller asc_ul(register char *str, int len, register int base)
24857195Smuller #else
24957195Smuller u_long
25057195Smuller asc_ul(str, len, base)
25157195Smuller 	register char *str;
25257195Smuller 	int len;
25357195Smuller 	register int base;
25457195Smuller #endif
25557195Smuller {
25657195Smuller 	register char *stop;
25757195Smuller 	u_long tval = 0;
25857195Smuller 
25957195Smuller 	stop = str + len;
26057195Smuller 
26157195Smuller 	/*
26257195Smuller 	 * skip over leading blanks and zeros
26357195Smuller 	 */
26457195Smuller 	while ((str < stop) && ((*str == ' ') || (*str == '0')))
26557195Smuller 		++str;
26657195Smuller 
26757195Smuller 	/*
26857195Smuller 	 * for each valid digit, shift running value (tval) over to next digit
26957195Smuller 	 * and add next digit
27057195Smuller 	 */
27157195Smuller 	if (base == HEX) {
27257195Smuller 		while (str < stop) {
27357195Smuller 			if ((*str >= '0') && (*str <= '9'))
27457195Smuller 				tval = (tval << 4) + (*str++ - '0');
27557195Smuller 			else if ((*str >= 'A') && (*str <= 'F'))
27657195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'A');
27757195Smuller 			else if ((*str >= 'a') && (*str <= 'f'))
27857195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'a');
27957195Smuller 			else
28057195Smuller 				break;
28157195Smuller 		}
28257195Smuller 	} else {
28357195Smuller  		while ((str < stop) && (*str >= '0') && (*str <= '7'))
28457195Smuller 			tval = (tval << 3) + (*str++ - '0');
28557195Smuller 	}
28657195Smuller 	return(tval);
28757195Smuller }
28857195Smuller 
28957195Smuller /*
29057195Smuller  * ul_asc()
29157195Smuller  *	convert an unsigned long into an hex/oct ascii string. pads with LEADING
29257195Smuller  *	ascii 0's to fill string completely
29357195Smuller  *	NOTE: the string created is NOT TERMINATED.
29457195Smuller  */
29557195Smuller 
29657195Smuller #if __STDC__
29757195Smuller int
ul_asc(u_long val,register char * str,register int len,register int base)29857195Smuller ul_asc(u_long val, register char *str, register int len, register int base)
29957195Smuller #else
30057195Smuller int
30157195Smuller ul_asc(val, str, len, base)
30257195Smuller 	u_long val;
30357195Smuller 	register char *str;
30457195Smuller 	register int len;
30557195Smuller 	register int base;
30657195Smuller #endif
30757195Smuller {
30857195Smuller 	register char *pt;
30957195Smuller 	u_long digit;
31057195Smuller 
31157195Smuller 	/*
31257195Smuller 	 * WARNING str is not '\0' terminated by this routine
31357195Smuller 	 */
31457195Smuller 	pt = str + len - 1;
31557195Smuller 
31657195Smuller 	/*
31757195Smuller 	 * do a tailwise conversion (start at right most end of string to place
31857195Smuller 	 * least significant digit). Keep shifting until conversion value goes
31957195Smuller 	 * to zero (all digits were converted)
32057195Smuller 	 */
32157195Smuller 	if (base == HEX) {
32257195Smuller 		while (pt >= str) {
32357195Smuller 			if ((digit = (val & 0xf)) < 10)
32457195Smuller 				*pt-- = '0' + (char)digit;
32557195Smuller 			else
32657195Smuller 				*pt-- = 'a' + (char)(digit - 10);
32757195Smuller 			if ((val = (val >> 4)) == (u_long)0)
32857195Smuller 				break;
32957195Smuller 		}
33057195Smuller 	} else {
33157195Smuller 		while (pt >= str) {
33257195Smuller 			*pt-- = '0' + (char)(val & 0x7);
33357195Smuller 			if ((val = (val >> 3)) == (u_long)0)
33457195Smuller 				break;
33557195Smuller 		}
33657195Smuller 	}
33757195Smuller 
33857195Smuller 	/*
33957195Smuller 	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
34057195Smuller 	 */
34157195Smuller 	while (pt >= str)
34257195Smuller 		*pt-- = '0';
34357195Smuller 	if (val != (u_long)0)
34457195Smuller 		return(-1);
34557195Smuller 	return(0);
34657195Smuller }
34757195Smuller 
34857195Smuller #ifndef NET2_STAT
34957195Smuller /*
35057195Smuller  * asc_uqd()
35157195Smuller  *	convert hex/octal character string into a u_quad_t. We do not have to
35257195Smuller  *	check for overflow! (the headers in all supported formats are not large
35357195Smuller  *	enough to create an overflow).
35457195Smuller  *	NOTE: strings passed to us are NOT TERMINATED.
35557195Smuller  * Return:
35657195Smuller  *	u_quad_t value
35757195Smuller  */
35857195Smuller 
35957195Smuller #if __STDC__
36057195Smuller u_quad_t
asc_uqd(register char * str,int len,register int base)36157195Smuller asc_uqd(register char *str, int len, register int base)
36257195Smuller #else
36357195Smuller u_quad_t
36457195Smuller asc_uqd(str, len, base)
36557195Smuller 	register char *str;
36657195Smuller 	int len;
36757195Smuller 	register int base;
36857195Smuller #endif
36957195Smuller {
37057195Smuller 	register char *stop;
37157195Smuller 	u_quad_t tval = 0;
37257195Smuller 
37357195Smuller 	stop = str + len;
37457195Smuller 
37557195Smuller 	/*
37657195Smuller 	 * skip over leading blanks and zeros
37757195Smuller 	 */
37857195Smuller 	while ((str < stop) && ((*str == ' ') || (*str == '0')))
37957195Smuller 		++str;
38057195Smuller 
38157195Smuller 	/*
38257195Smuller 	 * for each valid digit, shift running value (tval) over to next digit
38357195Smuller 	 * and add next digit
38457195Smuller 	 */
38557195Smuller 	if (base == HEX) {
38657195Smuller 		while (str < stop) {
38757195Smuller 			if ((*str >= '0') && (*str <= '9'))
38857195Smuller 				tval = (tval << 4) + (*str++ - '0');
38957195Smuller 			else if ((*str >= 'A') && (*str <= 'F'))
39057195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'A');
39157195Smuller 			else if ((*str >= 'a') && (*str <= 'f'))
39257195Smuller 				tval = (tval << 4) + 10 + (*str++ - 'a');
39357195Smuller 			else
39457195Smuller 				break;
39557195Smuller 		}
39657195Smuller 	} else {
39757195Smuller  		while ((str < stop) && (*str >= '0') && (*str <= '7'))
39857195Smuller 			tval = (tval << 3) + (*str++ - '0');
39957195Smuller 	}
40057195Smuller 	return(tval);
40157195Smuller }
40257195Smuller 
40357195Smuller /*
40457195Smuller  * uqd_asc()
40557195Smuller  *	convert an u_quad_t into a hex/oct ascii string. pads with LEADING
40657195Smuller  *	ascii 0's to fill string completely
40757195Smuller  *	NOTE: the string created is NOT TERMINATED.
40857195Smuller  */
40957195Smuller 
41057195Smuller #if __STDC__
41157195Smuller int
uqd_asc(u_quad_t val,register char * str,register int len,register int base)41257195Smuller uqd_asc(u_quad_t val, register char *str, register int len, register int base)
41357195Smuller #else
41457195Smuller int
41557195Smuller uqd_asc(val, str, len, base)
41657195Smuller 	u_quad_t val;
41757195Smuller 	register char *str;
41857195Smuller 	register int len;
41957195Smuller 	register int base;
42057195Smuller #endif
42157195Smuller {
42257195Smuller 	register char *pt;
42357195Smuller 	u_quad_t digit;
42457195Smuller 
42557195Smuller 	/*
42657195Smuller 	 * WARNING str is not '\0' terminated by this routine
42757195Smuller 	 */
42857195Smuller 	pt = str + len - 1;
42957195Smuller 
43057195Smuller 	/*
43157195Smuller 	 * do a tailwise conversion (start at right most end of string to place
43257195Smuller 	 * least significant digit). Keep shifting until conversion value goes
43357195Smuller 	 * to zero (all digits were converted)
43457195Smuller 	 */
43557195Smuller 	if (base == HEX) {
43657195Smuller 		while (pt >= str) {
43757195Smuller 			if ((digit = (val & 0xf)) < 10)
43857195Smuller 				*pt-- = '0' + (char)digit;
43957195Smuller 			else
44057195Smuller 				*pt-- = 'a' + (char)(digit - 10);
44157195Smuller 			if ((val = (val >> 4)) == (u_quad_t)0)
44257195Smuller 				break;
44357195Smuller 		}
44457195Smuller 	} else {
44557195Smuller 		while (pt >= str) {
44657195Smuller 			*pt-- = '0' + (char)(val & 0x7);
44757195Smuller 			if ((val = (val >> 3)) == (u_quad_t)0)
44857195Smuller 				break;
44957195Smuller 		}
45057195Smuller 	}
45157195Smuller 
45257195Smuller 	/*
45357195Smuller 	 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
45457195Smuller 	 */
45557195Smuller 	while (pt >= str)
45657195Smuller 		*pt-- = '0';
45757195Smuller 	if (val != (u_quad_t)0)
45857195Smuller 		return(-1);
45957195Smuller 	return(0);
46057195Smuller }
46157195Smuller #endif
462