Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/bin/pax/gen_subs.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1992 Keith Muller.
5
* Copyright (c) 1992, 1993
6
* The Regents of the University of California. All rights reserved.
7
*
8
* This code is derived from software contributed to Berkeley by
9
* Keith Muller of the University of California, San Diego.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
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.
22
*
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
33
* SUCH DAMAGE.
34
*/
35
36
#include <sys/types.h>
37
#include <sys/time.h>
38
#include <sys/stat.h>
39
#include <langinfo.h>
40
#include <stdint.h>
41
#include <stdio.h>
42
#include <string.h>
43
#include "pax.h"
44
#include "extern.h"
45
46
/*
47
* a collection of general purpose subroutines used by pax
48
*/
49
50
/*
51
* constants used by ls_list() when printing out archive members
52
*/
53
#define MODELEN 20
54
#define DATELEN 64
55
#define SIXMONTHS ((365 / 2) * 86400)
56
#define CURFRMTM "%b %e %H:%M"
57
#define OLDFRMTM "%b %e %Y"
58
#define CURFRMTD "%e %b %H:%M"
59
#define OLDFRMTD "%e %b %Y"
60
61
static int d_first = -1;
62
63
/*
64
* ls_list()
65
* list the members of an archive in ls format
66
*/
67
68
void
69
ls_list(ARCHD *arcn, time_t now, FILE *fp)
70
{
71
struct stat *sbp;
72
char f_mode[MODELEN];
73
char f_date[DATELEN];
74
const char *timefrmt;
75
76
/*
77
* if not verbose, just print the file name
78
*/
79
if (!vflag) {
80
(void)fprintf(fp, "%s\n", arcn->name);
81
(void)fflush(fp);
82
return;
83
}
84
85
if (d_first < 0)
86
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
87
/*
88
* user wants long mode
89
*/
90
sbp = &(arcn->sb);
91
strmode(sbp->st_mode, f_mode);
92
93
/*
94
* time format based on age compared to the time pax was started.
95
*/
96
if ((sbp->st_mtime + SIXMONTHS) <= now)
97
timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
98
else
99
timefrmt = d_first ? CURFRMTD : CURFRMTM;
100
101
/*
102
* print file mode, link count, uid, gid and time
103
*/
104
if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
105
f_date[0] = '\0';
106
(void)fprintf(fp, "%s%2ju %-12s %-12s ", f_mode,
107
(uintmax_t)sbp->st_nlink,
108
name_uid(sbp->st_uid, 1), name_gid(sbp->st_gid, 1));
109
110
/*
111
* print device id's for devices, or sizes for other nodes
112
*/
113
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
114
(void)fprintf(fp, "%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
115
(unsigned long)MINOR(sbp->st_rdev));
116
else {
117
(void)fprintf(fp, "%9ju ", (uintmax_t)sbp->st_size);
118
}
119
120
/*
121
* print name and link info for hard and soft links
122
*/
123
(void)fprintf(fp, "%s %s", f_date, arcn->name);
124
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
125
(void)fprintf(fp, " == %s\n", arcn->ln_name);
126
else if (arcn->type == PAX_SLK)
127
(void)fprintf(fp, " => %s\n", arcn->ln_name);
128
else
129
(void)putc('\n', fp);
130
(void)fflush(fp);
131
return;
132
}
133
134
/*
135
* tty_ls()
136
* print a short summary of file to tty.
137
*/
138
139
void
140
ls_tty(ARCHD *arcn)
141
{
142
char f_date[DATELEN];
143
char f_mode[MODELEN];
144
const char *timefrmt;
145
146
if (d_first < 0)
147
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
148
149
if ((arcn->sb.st_mtime + SIXMONTHS) <= time(NULL))
150
timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
151
else
152
timefrmt = d_first ? CURFRMTD : CURFRMTM;
153
154
/*
155
* convert time to string, and print
156
*/
157
if (strftime(f_date, DATELEN, timefrmt,
158
localtime(&(arcn->sb.st_mtime))) == 0)
159
f_date[0] = '\0';
160
strmode(arcn->sb.st_mode, f_mode);
161
tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
162
return;
163
}
164
165
/*
166
* l_strncpy()
167
* copy src to dest up to len chars (stopping at first '\0').
168
* when src is shorter than len, pads to len with '\0'.
169
* Return:
170
* number of chars copied. (Note this is a real performance win over
171
* doing a strncpy(), a strlen(), and then a possible memset())
172
*/
173
174
int
175
l_strncpy(char *dest, const char *src, int len)
176
{
177
char *stop;
178
char *start;
179
180
stop = dest + len;
181
start = dest;
182
while ((dest < stop) && (*src != '\0'))
183
*dest++ = *src++;
184
len = dest - start;
185
while (dest < stop)
186
*dest++ = '\0';
187
return(len);
188
}
189
190
/*
191
* asc_ul()
192
* convert hex/octal character string into a u_long. We do not have to
193
* check for overflow! (the headers in all supported formats are not large
194
* enough to create an overflow).
195
* NOTE: strings passed to us are NOT TERMINATED.
196
* Return:
197
* unsigned long value
198
*/
199
200
u_long
201
asc_ul(char *str, int len, int base)
202
{
203
char *stop;
204
u_long tval = 0;
205
206
stop = str + len;
207
208
/*
209
* skip over leading blanks and zeros
210
*/
211
while ((str < stop) && ((*str == ' ') || (*str == '0')))
212
++str;
213
214
/*
215
* for each valid digit, shift running value (tval) over to next digit
216
* and add next digit
217
*/
218
if (base == HEX) {
219
while (str < stop) {
220
if ((*str >= '0') && (*str <= '9'))
221
tval = (tval << 4) + (*str++ - '0');
222
else if ((*str >= 'A') && (*str <= 'F'))
223
tval = (tval << 4) + 10 + (*str++ - 'A');
224
else if ((*str >= 'a') && (*str <= 'f'))
225
tval = (tval << 4) + 10 + (*str++ - 'a');
226
else
227
break;
228
}
229
} else {
230
while ((str < stop) && (*str >= '0') && (*str <= '7'))
231
tval = (tval << 3) + (*str++ - '0');
232
}
233
return(tval);
234
}
235
236
/*
237
* ul_asc()
238
* convert an unsigned long into an hex/oct ascii string. pads with LEADING
239
* ascii 0's to fill string completely
240
* NOTE: the string created is NOT TERMINATED.
241
*/
242
243
int
244
ul_asc(u_long val, char *str, int len, int base)
245
{
246
char *pt;
247
u_long digit;
248
249
/*
250
* WARNING str is not '\0' terminated by this routine
251
*/
252
pt = str + len - 1;
253
254
/*
255
* do a tailwise conversion (start at right most end of string to place
256
* least significant digit). Keep shifting until conversion value goes
257
* to zero (all digits were converted)
258
*/
259
if (base == HEX) {
260
while (pt >= str) {
261
if ((digit = (val & 0xf)) < 10)
262
*pt-- = '0' + (char)digit;
263
else
264
*pt-- = 'a' + (char)(digit - 10);
265
if ((val = (val >> 4)) == (u_long)0)
266
break;
267
}
268
} else {
269
while (pt >= str) {
270
*pt-- = '0' + (char)(val & 0x7);
271
if ((val = (val >> 3)) == (u_long)0)
272
break;
273
}
274
}
275
276
/*
277
* pad with leading ascii ZEROS. We return -1 if we ran out of space.
278
*/
279
while (pt >= str)
280
*pt-- = '0';
281
if (val != (u_long)0)
282
return(-1);
283
return(0);
284
}
285
286
/*
287
* asc_uqd()
288
* convert hex/octal character string into a u_quad_t. We do not have to
289
* check for overflow! (the headers in all supported formats are not large
290
* enough to create an overflow).
291
* NOTE: strings passed to us are NOT TERMINATED.
292
* Return:
293
* u_quad_t value
294
*/
295
296
u_quad_t
297
asc_uqd(char *str, int len, int base)
298
{
299
char *stop;
300
u_quad_t tval = 0;
301
302
stop = str + len;
303
304
/*
305
* skip over leading blanks and zeros
306
*/
307
while ((str < stop) && ((*str == ' ') || (*str == '0')))
308
++str;
309
310
/*
311
* for each valid digit, shift running value (tval) over to next digit
312
* and add next digit
313
*/
314
if (base == HEX) {
315
while (str < stop) {
316
if ((*str >= '0') && (*str <= '9'))
317
tval = (tval << 4) + (*str++ - '0');
318
else if ((*str >= 'A') && (*str <= 'F'))
319
tval = (tval << 4) + 10 + (*str++ - 'A');
320
else if ((*str >= 'a') && (*str <= 'f'))
321
tval = (tval << 4) + 10 + (*str++ - 'a');
322
else
323
break;
324
}
325
} else {
326
while ((str < stop) && (*str >= '0') && (*str <= '7'))
327
tval = (tval << 3) + (*str++ - '0');
328
}
329
return(tval);
330
}
331
332
/*
333
* uqd_asc()
334
* convert an u_quad_t into a hex/oct ascii string. pads with LEADING
335
* ascii 0's to fill string completely
336
* NOTE: the string created is NOT TERMINATED.
337
*/
338
339
int
340
uqd_asc(u_quad_t val, char *str, int len, int base)
341
{
342
char *pt;
343
u_quad_t digit;
344
345
/*
346
* WARNING str is not '\0' terminated by this routine
347
*/
348
pt = str + len - 1;
349
350
/*
351
* do a tailwise conversion (start at right most end of string to place
352
* least significant digit). Keep shifting until conversion value goes
353
* to zero (all digits were converted)
354
*/
355
if (base == HEX) {
356
while (pt >= str) {
357
if ((digit = (val & 0xf)) < 10)
358
*pt-- = '0' + (char)digit;
359
else
360
*pt-- = 'a' + (char)(digit - 10);
361
if ((val = (val >> 4)) == (u_quad_t)0)
362
break;
363
}
364
} else {
365
while (pt >= str) {
366
*pt-- = '0' + (char)(val & 0x7);
367
if ((val = (val >> 3)) == (u_quad_t)0)
368
break;
369
}
370
}
371
372
/*
373
* pad with leading ascii ZEROS. We return -1 if we ran out of space.
374
*/
375
while (pt >= str)
376
*pt-- = '0';
377
if (val != (u_quad_t)0)
378
return(-1);
379
return(0);
380
}
381
382