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