source: freewrt/tools/paxmirabilis/src/gen_subs.c@ 9b4fa61

freewrt_2_0
Last change on this file since 9b4fa61 was 9b4fa61, checked in by Waldemar Brodkorb <wbx@…>, 4 months ago

include missing sysmacros.h

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