1 /* $NetBSD: gen_subs.c,v 1.33 2006/02/11 10:43:18 dsl Exp $ */
4 * Copyright (c) 1992 Keith Muller.
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Keith Muller of the University of California, San Diego.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #if HAVE_NBTOOL_CONFIG_H
37 #include "nbtool_config.h"
40 #include <sys/cdefs.h>
43 static char sccsid
[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
45 __RCSID("$NetBSD: gen_subs.c,v 1.33 2006/02/11 10:43:18 dsl Exp $");
49 #include <sys/types.h>
52 #include <sys/param.h>
69 * a collection of general purpose subroutines used by pax
73 * constants used by ls_list() when printing out archive members
77 #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
78 #define CURFRMT "%b %e %H:%M"
79 #define OLDFRMT "%b %e %Y"
87 * list the members of an archive in ls format
91 ls_list(ARCHD
*arcn
, time_t now
, FILE *fp
)
96 const char *timefrmt
, *user
, *group
;
99 * if not verbose, just print the file name
102 (void)fprintf(fp
, "%s\n", arcn
->name
);
108 * user wants long mode
111 strmode(sbp
->st_mode
, f_mode
);
114 * time format based on age compared to the time pax was started.
116 if ((sbp
->st_mtime
+ SIXMONTHS
) <= now
)
122 * print file mode, link count, uid, gid and time
124 if (strftime(f_date
,DATELEN
,timefrmt
,localtime(&(sbp
->st_mtime
))) == 0)
126 user
= user_from_uid(sbp
->st_uid
, 0);
127 group
= group_from_gid(sbp
->st_gid
, 0);
128 (void)fprintf(fp
, "%s%2lu %-*s %-*s ", f_mode
,
129 (unsigned long)sbp
->st_nlink
,
130 UT_NAMESIZE
, user
? user
: "", UT_GRPSIZE
, group
? group
: "");
133 * print device id's for devices, or sizes for other nodes
135 if ((arcn
->type
== PAX_CHR
) || (arcn
->type
== PAX_BLK
))
136 (void)fprintf(fp
, "%4lu,%4lu ", (long) MAJOR(sbp
->st_rdev
),
137 (long) MINOR(sbp
->st_rdev
));
139 (void)fprintf(fp
, OFFT_FP("9") " ", (OFFT_T
)sbp
->st_size
);
143 * print name and link info for hard and soft links
145 (void)fprintf(fp
, "%s %s", f_date
, arcn
->name
);
146 if ((arcn
->type
== PAX_HLK
) || (arcn
->type
== PAX_HRG
))
147 (void)fprintf(fp
, " == %s\n", arcn
->ln_name
);
148 else if (arcn
->type
== PAX_SLK
)
149 (void)fprintf(fp
, " -> %s\n", arcn
->ln_name
);
151 (void)fputc('\n', fp
);
157 * print a short summary of file to tty.
163 char f_date
[DATELEN
];
164 char f_mode
[MODELEN
];
165 const char *timefrmt
;
167 if ((arcn
->sb
.st_mtime
+ SIXMONTHS
) <= time((time_t *)NULL
))
173 * convert time to string, and print
175 if (strftime(f_date
, DATELEN
, timefrmt
,
176 localtime(&(arcn
->sb
.st_mtime
))) == 0)
178 strmode(arcn
->sb
.st_mode
, f_mode
);
179 tty_prnt("%s%s %s\n", f_mode
, f_date
, arcn
->name
);
184 safe_print(const char *str
, FILE *fp
)
190 * if printing to a tty, use vis(3) to print special characters.
192 if (isatty(fileno(fp
))) {
193 for (cp
= str
; *cp
; cp
++) {
194 (void)vis(visbuf
, cp
[0], VIS_CSTYLE
, cp
[1]);
195 (void)fputs(visbuf
, fp
);
198 (void)fputs(str
, fp
);
204 * convert hex/octal character string into a u_long. We do not have to
205 * check for overflow! (the headers in all supported formats are not large
206 * enough to create an overflow).
207 * NOTE: strings passed to us are NOT TERMINATED.
209 * unsigned long value
213 asc_ul(char *str
, int len
, int base
)
221 * skip over leading blanks and zeros
223 while ((str
< stop
) && ((*str
== ' ') || (*str
== '0')))
227 * for each valid digit, shift running value (tval) over to next digit
232 if ((*str
>= '0') && (*str
<= '9'))
233 tval
= (tval
<< 4) + (*str
++ - '0');
234 else if ((*str
>= 'A') && (*str
<= 'F'))
235 tval
= (tval
<< 4) + 10 + (*str
++ - 'A');
236 else if ((*str
>= 'a') && (*str
<= 'f'))
237 tval
= (tval
<< 4) + 10 + (*str
++ - 'a');
242 while ((str
< stop
) && (*str
>= '0') && (*str
<= '7'))
243 tval
= (tval
<< 3) + (*str
++ - '0');
250 * convert an unsigned long into an hex/oct ascii string. pads with LEADING
251 * ascii 0's to fill string completely
252 * NOTE: the string created is NOT TERMINATED.
256 ul_asc(u_long val
, char *str
, int len
, int base
)
262 * WARNING str is not '\0' terminated by this routine
267 * do a tailwise conversion (start at right most end of string to place
268 * least significant digit). Keep shifting until conversion value goes
269 * to zero (all digits were converted)
273 if ((digit
= (val
& 0xf)) < 10)
274 *pt
-- = '0' + (char)digit
;
276 *pt
-- = 'a' + (char)(digit
- 10);
277 if ((val
= (val
>> 4)) == (u_long
)0)
282 *pt
-- = '0' + (char)(val
& 0x7);
283 if ((val
= (val
>> 3)) == (u_long
)0)
289 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
293 if (val
!= (u_long
)0)
301 * convert hex/octal character string into a unsigned long long. We do
302 * not have to to check for overflow! (the headers in all supported
303 * formats are not large enough to create an overflow).
304 * NOTE: strings passed to us are NOT TERMINATED.
306 * unsigned long long value
310 asc_ull(char *str
, int len
, int base
)
313 unsigned long long tval
= 0;
318 * skip over leading blanks and zeros
320 while ((str
< stop
) && ((*str
== ' ') || (*str
== '0')))
324 * for each valid digit, shift running value (tval) over to next digit
329 if ((*str
>= '0') && (*str
<= '9'))
330 tval
= (tval
<< 4) + (*str
++ - '0');
331 else if ((*str
>= 'A') && (*str
<= 'F'))
332 tval
= (tval
<< 4) + 10 + (*str
++ - 'A');
333 else if ((*str
>= 'a') && (*str
<= 'f'))
334 tval
= (tval
<< 4) + 10 + (*str
++ - 'a');
339 while ((str
< stop
) && (*str
>= '0') && (*str
<= '7'))
340 tval
= (tval
<< 3) + (*str
++ - '0');
347 * convert an unsigned long long into a hex/oct ascii string. pads with
348 * LEADING ascii 0's to fill string completely
349 * NOTE: the string created is NOT TERMINATED.
353 ull_asc(unsigned long long val
, char *str
, int len
, int base
)
356 unsigned long long digit
;
359 * WARNING str is not '\0' terminated by this routine
364 * do a tailwise conversion (start at right most end of string to place
365 * least significant digit). Keep shifting until conversion value goes
366 * to zero (all digits were converted)
370 if ((digit
= (val
& 0xf)) < 10)
371 *pt
-- = '0' + (char)digit
;
373 *pt
-- = 'a' + (char)(digit
- 10);
374 if ((val
= (val
>> 4)) == (unsigned long long)0)
379 *pt
-- = '0' + (char)(val
& 0x7);
380 if ((val
= (val
>> 3)) == (unsigned long long)0)
386 * pad with leading ascii ZEROS. We return -1 if we ran out of space.
390 if (val
!= (unsigned long long)0)
405 "Removing leading / from absolute path names in the archive");