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