GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: gen_subs.c,v 1.32 2016/08/26 05:06:14 guenther Exp $ */ |
||
2 |
/* $NetBSD: gen_subs.c,v 1.5 1995/03/21 09:07:26 cgd Exp $ */ |
||
3 |
|||
4 |
/*- |
||
5 |
* Copyright (c) 1992 Keith Muller. |
||
6 |
* Copyright (c) 1992, 1993 |
||
7 |
* The Regents of the University of California. All rights reserved. |
||
8 |
* |
||
9 |
* This code is derived from software contributed to Berkeley by |
||
10 |
* Keith Muller of the University of California, San Diego. |
||
11 |
* |
||
12 |
* Redistribution and use in source and binary forms, with or without |
||
13 |
* modification, are permitted provided that the following conditions |
||
14 |
* are met: |
||
15 |
* 1. Redistributions of source code must retain the above copyright |
||
16 |
* notice, this list of conditions and the following disclaimer. |
||
17 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
18 |
* notice, this list of conditions and the following disclaimer in the |
||
19 |
* documentation and/or other materials provided with the distribution. |
||
20 |
* 3. Neither the name of the University nor the names of its contributors |
||
21 |
* may be used to endorse or promote products derived from this software |
||
22 |
* without specific prior written permission. |
||
23 |
* |
||
24 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
25 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
26 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
27 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
28 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
29 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
30 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
31 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
32 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
33 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
34 |
* SUCH DAMAGE. |
||
35 |
*/ |
||
36 |
|||
37 |
#include <sys/types.h> |
||
38 |
#include <sys/stat.h> |
||
39 |
#include <grp.h> |
||
40 |
#include <pwd.h> |
||
41 |
#include <stdio.h> |
||
42 |
#include <stdlib.h> |
||
43 |
#include <string.h> |
||
44 |
#include <time.h> |
||
45 |
#include <unistd.h> |
||
46 |
#include <utmp.h> |
||
47 |
#include <vis.h> |
||
48 |
|||
49 |
#include "pax.h" |
||
50 |
#include "extern.h" |
||
51 |
|||
52 |
/* |
||
53 |
* a collection of general purpose subroutines used by pax |
||
54 |
*/ |
||
55 |
|||
56 |
/* |
||
57 |
* constants used by ls_list() when printing out archive members |
||
58 |
*/ |
||
59 |
#define MODELEN 20 |
||
60 |
#define DATELEN 64 |
||
61 |
#define SECSPERDAY (24 * 60 * 60) |
||
62 |
#define SIXMONTHS (SECSPERDAY * 365 / 2) |
||
63 |
#define CURFRMT "%b %e %H:%M" |
||
64 |
#define OLDFRMT "%b %e %Y" |
||
65 |
#define NAME_WIDTH 8 |
||
66 |
#define TIMEFMT(t, now) \ |
||
67 |
(((t) + SIXMONTHS <= (now) || (t) > (now)) ? OLDFRMT : CURFRMT) |
||
68 |
|||
69 |
/* |
||
70 |
* ls_list() |
||
71 |
* list the members of an archive in ls format |
||
72 |
*/ |
||
73 |
|||
74 |
void |
||
75 |
ls_list(ARCHD *arcn, time_t now, FILE *fp) |
||
76 |
{ |
||
77 |
struct stat *sbp; |
||
78 |
1700 |
char f_mode[MODELEN]; |
|
79 |
850 |
char f_date[DATELEN]; |
|
80 |
int term; |
||
81 |
|||
82 |
850 |
term = zeroflag ? '\0' : '\n'; /* path termination character */ |
|
83 |
|||
84 |
/* |
||
85 |
* if not verbose, just print the file name |
||
86 |
*/ |
||
87 |
✓✗ | 850 |
if (!vflag) { |
88 |
✗✓ | 850 |
if (zeroflag) |
89 |
(void)fputs(arcn->name, fp); |
||
90 |
else |
||
91 |
850 |
safe_print(arcn->name, fp); |
|
92 |
✓✗ | 1700 |
(void)putc(term, fp); |
93 |
850 |
(void)fflush(fp); |
|
94 |
850 |
return; |
|
95 |
} |
||
96 |
|||
97 |
/* |
||
98 |
* user wants long mode |
||
99 |
*/ |
||
100 |
sbp = &(arcn->sb); |
||
101 |
strmode(sbp->st_mode, f_mode); |
||
102 |
|||
103 |
/* |
||
104 |
* print file mode, link count, uid, gid and time |
||
105 |
*/ |
||
106 |
if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now), |
||
107 |
localtime(&(sbp->st_mtime))) == 0) |
||
108 |
f_date[0] = '\0'; |
||
109 |
(void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink, |
||
110 |
NAME_WIDTH, UT_NAMESIZE, user_from_uid(sbp->st_uid, 0), |
||
111 |
NAME_WIDTH, UT_NAMESIZE, group_from_gid(sbp->st_gid, 0)); |
||
112 |
|||
113 |
/* |
||
114 |
* print device id's for devices, or sizes for other nodes |
||
115 |
*/ |
||
116 |
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK)) |
||
117 |
(void)fprintf(fp, "%4lu, %4lu ", |
||
118 |
(unsigned long)MAJOR(sbp->st_rdev), |
||
119 |
(unsigned long)MINOR(sbp->st_rdev)); |
||
120 |
else { |
||
121 |
(void)fprintf(fp, "%9llu ", sbp->st_size); |
||
122 |
} |
||
123 |
|||
124 |
/* |
||
125 |
* print name and link info for hard and soft links |
||
126 |
*/ |
||
127 |
(void)fputs(f_date, fp); |
||
128 |
(void)putc(' ', fp); |
||
129 |
safe_print(arcn->name, fp); |
||
130 |
if (PAX_IS_HARDLINK(arcn->type)) { |
||
131 |
fputs(" == ", fp); |
||
132 |
safe_print(arcn->ln_name, fp); |
||
133 |
} else if (arcn->type == PAX_SLK) { |
||
134 |
fputs(" -> ", fp); |
||
135 |
safe_print(arcn->ln_name, fp); |
||
136 |
} |
||
137 |
(void)putc(term, fp); |
||
138 |
(void)fflush(fp); |
||
139 |
850 |
} |
|
140 |
|||
141 |
/* |
||
142 |
* tty_ls() |
||
143 |
* print a short summary of file to tty. |
||
144 |
*/ |
||
145 |
|||
146 |
void |
||
147 |
ls_tty(ARCHD *arcn) |
||
148 |
{ |
||
149 |
char f_date[DATELEN]; |
||
150 |
char f_mode[MODELEN]; |
||
151 |
time_t now = time(NULL); |
||
152 |
|||
153 |
/* |
||
154 |
* convert time to string, and print |
||
155 |
*/ |
||
156 |
if (strftime(f_date, DATELEN, TIMEFMT(arcn->sb.st_mtime, now), |
||
157 |
localtime(&(arcn->sb.st_mtime))) == 0) |
||
158 |
f_date[0] = '\0'; |
||
159 |
strmode(arcn->sb.st_mode, f_mode); |
||
160 |
tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name); |
||
161 |
} |
||
162 |
|||
163 |
void |
||
164 |
safe_print(const char *str, FILE *fp) |
||
165 |
{ |
||
166 |
19056 |
char visbuf[5]; |
|
167 |
const char *cp; |
||
168 |
|||
169 |
/* |
||
170 |
* if printing to a tty, use vis(3) to print special characters. |
||
171 |
*/ |
||
172 |
✓✗✓✓ |
28584 |
if (isatty(fileno(fp))) { |
173 |
✓✓ | 502918 |
for (cp = str; *cp; cp++) { |
174 |
242781 |
(void)vis(visbuf, cp[0], VIS_CSTYLE, cp[1]); |
|
175 |
242781 |
(void)fputs(visbuf, fp); |
|
176 |
} |
||
177 |
} else { |
||
178 |
850 |
(void)fputs(str, fp); |
|
179 |
} |
||
180 |
9528 |
} |
|
181 |
|||
182 |
/* |
||
183 |
* asc_ul() |
||
184 |
* convert hex/octal character string into a u_long. We do not have to |
||
185 |
* check for overflow! (the headers in all supported formats are not large |
||
186 |
* enough to create an overflow). |
||
187 |
* NOTE: strings passed to us are NOT TERMINATED. |
||
188 |
* Return: |
||
189 |
* unsigned long value |
||
190 |
*/ |
||
191 |
|||
192 |
u_long |
||
193 |
asc_ul(char *str, int len, int base) |
||
194 |
{ |
||
195 |
char *stop; |
||
196 |
u_long tval = 0; |
||
197 |
|||
198 |
77348 |
stop = str + len; |
|
199 |
|||
200 |
/* |
||
201 |
* skip over leading blanks and zeros |
||
202 |
*/ |
||
203 |
✓✗✓✓ ✓✓ |
515356 |
while ((str < stop) && ((*str == ' ') || (*str == '0'))) |
204 |
90250 |
++str; |
|
205 |
|||
206 |
/* |
||
207 |
* for each valid digit, shift running value (tval) over to next digit |
||
208 |
* and add next digit |
||
209 |
*/ |
||
210 |
✗✓ | 38674 |
if (base == HEX) { |
211 |
while (str < stop) { |
||
212 |
if ((*str >= '0') && (*str <= '9')) |
||
213 |
tval = (tval << 4) + (*str++ - '0'); |
||
214 |
else if ((*str >= 'A') && (*str <= 'F')) |
||
215 |
tval = (tval << 4) + 10 + (*str++ - 'A'); |
||
216 |
else if ((*str >= 'a') && (*str <= 'f')) |
||
217 |
tval = (tval << 4) + 10 + (*str++ - 'a'); |
||
218 |
else |
||
219 |
break; |
||
220 |
} |
||
221 |
} else { |
||
222 |
✓✗✓✓ ✓✗ |
795140 |
while ((str < stop) && (*str >= '0') && (*str <= '7')) |
223 |
179448 |
tval = (tval << 3) + (*str++ - '0'); |
|
224 |
} |
||
225 |
38674 |
return(tval); |
|
226 |
} |
||
227 |
|||
228 |
/* |
||
229 |
* ul_asc() |
||
230 |
* convert an unsigned long into an hex/oct ascii string. pads with LEADING |
||
231 |
* ascii 0's to fill string completely |
||
232 |
* NOTE: the string created is NOT TERMINATED. |
||
233 |
*/ |
||
234 |
|||
235 |
int |
||
236 |
ul_asc(u_long val, char *str, int len, int base) |
||
237 |
{ |
||
238 |
char *pt; |
||
239 |
u_long digit; |
||
240 |
|||
241 |
/* |
||
242 |
* WARNING str is not '\0' terminated by this routine |
||
243 |
*/ |
||
244 |
pt = str + len - 1; |
||
245 |
|||
246 |
/* |
||
247 |
* do a tailwise conversion (start at right most end of string to place |
||
248 |
* least significant digit). Keep shifting until conversion value goes |
||
249 |
* to zero (all digits were converted) |
||
250 |
*/ |
||
251 |
if (base == HEX) { |
||
252 |
while (pt >= str) { |
||
253 |
if ((digit = (val & 0xf)) < 10) |
||
254 |
*pt-- = '0' + (char)digit; |
||
255 |
else |
||
256 |
*pt-- = 'a' + (char)(digit - 10); |
||
257 |
val >>= 4; |
||
258 |
if (val == 0) |
||
259 |
break; |
||
260 |
} |
||
261 |
} else { |
||
262 |
while (pt >= str) { |
||
263 |
*pt-- = '0' + (char)(val & 0x7); |
||
264 |
val >>= 3; |
||
265 |
if (val == 0) |
||
266 |
break; |
||
267 |
} |
||
268 |
} |
||
269 |
|||
270 |
/* |
||
271 |
* pad with leading ascii ZEROS. We return -1 if we ran out of space. |
||
272 |
*/ |
||
273 |
while (pt >= str) |
||
274 |
*pt-- = '0'; |
||
275 |
if (val != 0) |
||
276 |
return(-1); |
||
277 |
return(0); |
||
278 |
} |
||
279 |
|||
280 |
/* |
||
281 |
* asc_ull() |
||
282 |
* Convert hex/octal character string into a unsigned long long. |
||
283 |
* We do not have to check for overflow! (The headers in all |
||
284 |
* supported formats are not large enough to create an overflow). |
||
285 |
* NOTE: strings passed to us are NOT TERMINATED. |
||
286 |
* Return: |
||
287 |
* unsigned long long value |
||
288 |
*/ |
||
289 |
|||
290 |
unsigned long long |
||
291 |
asc_ull(char *str, int len, int base) |
||
292 |
{ |
||
293 |
char *stop; |
||
294 |
unsigned long long tval = 0; |
||
295 |
|||
296 |
38792 |
stop = str + len; |
|
297 |
|||
298 |
/* |
||
299 |
* skip over leading blanks and zeros |
||
300 |
*/ |
||
301 |
✓✓✓✓ ✓✓ |
376959 |
while ((str < stop) && ((*str == ' ') || (*str == '0'))) |
302 |
75018 |
++str; |
|
303 |
|||
304 |
/* |
||
305 |
* for each valid digit, shift running value (tval) over to next digit |
||
306 |
* and add next digit |
||
307 |
*/ |
||
308 |
✗✓ | 19396 |
if (base == HEX) { |
309 |
while (str < stop) { |
||
310 |
if ((*str >= '0') && (*str <= '9')) |
||
311 |
tval = (tval << 4) + (*str++ - '0'); |
||
312 |
else if ((*str >= 'A') && (*str <= 'F')) |
||
313 |
tval = (tval << 4) + 10 + (*str++ - 'A'); |
||
314 |
else if ((*str >= 'a') && (*str <= 'f')) |
||
315 |
tval = (tval << 4) + 10 + (*str++ - 'a'); |
||
316 |
else |
||
317 |
break; |
||
318 |
} |
||
319 |
} else { |
||
320 |
✓✓✓✓ ✓✗ |
592501 |
while ((str < stop) && (*str >= '0') && (*str <= '7')) |
321 |
138457 |
tval = (tval << 3) + (*str++ - '0'); |
|
322 |
} |
||
323 |
19396 |
return(tval); |
|
324 |
} |
||
325 |
|||
326 |
/* |
||
327 |
* ull_asc() |
||
328 |
* Convert an unsigned long long into a hex/oct ascii string. |
||
329 |
* Pads with LEADING ascii 0's to fill string completely |
||
330 |
* NOTE: the string created is NOT TERMINATED. |
||
331 |
*/ |
||
332 |
|||
333 |
int |
||
334 |
ull_asc(unsigned long long val, char *str, int len, int base) |
||
335 |
{ |
||
336 |
char *pt; |
||
337 |
unsigned long long digit; |
||
338 |
|||
339 |
/* |
||
340 |
* WARNING str is not '\0' terminated by this routine |
||
341 |
*/ |
||
342 |
pt = str + len - 1; |
||
343 |
|||
344 |
/* |
||
345 |
* do a tailwise conversion (start at right most end of string to place |
||
346 |
* least significant digit). Keep shifting until conversion value goes |
||
347 |
* to zero (all digits were converted) |
||
348 |
*/ |
||
349 |
if (base == HEX) { |
||
350 |
while (pt >= str) { |
||
351 |
if ((digit = (val & 0xf)) < 10) |
||
352 |
*pt-- = '0' + (char)digit; |
||
353 |
else |
||
354 |
*pt-- = 'a' + (char)(digit - 10); |
||
355 |
val >>= 4; |
||
356 |
if (val == 0) |
||
357 |
break; |
||
358 |
} |
||
359 |
} else { |
||
360 |
while (pt >= str) { |
||
361 |
*pt-- = '0' + (char)(val & 0x7); |
||
362 |
val >>= 3; |
||
363 |
if (val == 0) |
||
364 |
break; |
||
365 |
} |
||
366 |
} |
||
367 |
|||
368 |
/* |
||
369 |
* pad with leading ascii ZEROS. We return -1 if we ran out of space. |
||
370 |
*/ |
||
371 |
while (pt >= str) |
||
372 |
*pt-- = '0'; |
||
373 |
if (val != 0) |
||
374 |
return(-1); |
||
375 |
return(0); |
||
376 |
} |
||
377 |
|||
378 |
/* |
||
379 |
* Copy at max min(bufz, fieldsz) chars from field to buf, stopping |
||
380 |
* at the first NUL char. NUL terminate buf if there is room left. |
||
381 |
*/ |
||
382 |
size_t |
||
383 |
fieldcpy(char *buf, size_t bufsz, const char *field, size_t fieldsz) |
||
384 |
{ |
||
385 |
char *p = buf; |
||
386 |
const char *q = field; |
||
387 |
size_t i = 0; |
||
388 |
|||
389 |
✓✓ | 40344 |
if (fieldsz > bufsz) |
390 |
266 |
fieldsz = bufsz; |
|
391 |
✓✓✓✓ |
1079645 |
while (i < fieldsz && *q != '\0') { |
392 |
346530 |
*p++ = *q++; |
|
393 |
346530 |
i++; |
|
394 |
} |
||
395 |
✓✓ | 20172 |
if (i < bufsz) |
396 |
20121 |
*p = '\0'; |
|
397 |
20172 |
return(i); |
|
398 |
} |
Generated by: GCOVR (Version 3.3) |