Module Name: src Committed By: christos Date: Thu Aug 9 08:09:22 UTC 2012
Modified Files: src/bin/pax: cpio.c extern.h gen_subs.c pax.h tar.c Log Message: PR/46786: Simon Burge: After conversion to 64 bit time_t, tar/pax/cpio erroneously think that negative time_t's never fit in 32 bits. Rework conversion code to always use uintmax_t, and detect negative values. XXX[1]: Perhaps we should do the same (use a signed conversion) for all fields not just for time_t XXX[2]: pullup for 6 To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/bin/pax/cpio.c cvs rdiff -u -r1.58 -r1.59 src/bin/pax/extern.h cvs rdiff -u -r1.35 -r1.36 src/bin/pax/gen_subs.c cvs rdiff -u -r1.30 -r1.31 src/bin/pax/pax.h cvs rdiff -u -r1.69 -r1.70 src/bin/pax/tar.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/pax/cpio.c diff -u src/bin/pax/cpio.c:1.21 src/bin/pax/cpio.c:1.22 --- src/bin/pax/cpio.c:1.21 Sat Mar 26 08:01:06 2011 +++ src/bin/pax/cpio.c Thu Aug 9 04:09:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: cpio.c,v 1.21 2011/03/26 12:01:06 martin Exp $ */ +/* $NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: cpio.c,v 1.21 2011/03/26 12:01:06 martin Exp $"); +__RCSID("$NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $"); #endif #endif /* not lint */ @@ -297,15 +297,15 @@ cpio_rd(ARCHD *arcn, char *buf) * ascii fields from the header */ arcn->pad = 0L; - arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); - arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); - arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); - arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); - arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); - arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), + arcn->sb.st_dev = (dev_t)asc_u32(hd->c_dev, sizeof(hd->c_dev), OCT); + arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), OCT); + arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), OCT); + arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), OCT); + arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), OCT); + arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink), OCT); - arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); - arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), + arcn->sb.st_rdev = (dev_t)asc_u32(hd->c_rdev, sizeof(hd->c_rdev), OCT); + arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime, sizeof(hd->c_mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize, @@ -315,7 +315,7 @@ cpio_rd(ARCHD *arcn, char *buf) * check name size and if valid, read in the name of this entry (name * follows header in the archive) */ - if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) + if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) return -1; arcn->nlen = nsz - 1; if (rd_nm(arcn, nsz) < 0) @@ -415,7 +415,7 @@ cpio_wr(ARCHD *arcn) /* * set data size to hold link name */ - if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, + if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize, sizeof(hd->c_filesize), OCT)) goto out; break; @@ -423,7 +423,7 @@ cpio_wr(ARCHD *arcn) /* * all other file types have no file data */ - if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), + if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize), OCT)) goto out; break; @@ -432,24 +432,24 @@ cpio_wr(ARCHD *arcn) /* * copy the values to the header using octal ascii */ - if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || - ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), + if (u32_asc((uintmax_t)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || + u32_asc((uintmax_t)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), OCT) || - ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), + u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), OCT) || - ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), + u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), OCT) || - ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), + u32_asc((uintmax_t)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), OCT) || - ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), + u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), OCT) || - ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), + u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), OCT) || - ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), + u32_asc((uintmax_t)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), OCT) || - ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), + u32_asc((uintmax_t)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), OCT) || - ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) + u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) goto out; /* @@ -578,29 +578,29 @@ vcpio_rd(ARCHD *arcn, char *buf) /* * extract the hex ascii fields from the header */ - arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); - arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); - arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); - arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); - arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); + arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), HEX); + arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), HEX); + arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), HEX); + arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), HEX); + arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime,sizeof(hd->c_mtime),HEX); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize, sizeof(hd->c_filesize), HEX); - arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), + arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink), HEX); - devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); - devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); + devmajor = (dev_t)asc_u32(hd->c_maj, sizeof(hd->c_maj), HEX); + devminor = (dev_t)asc_u32(hd->c_min, sizeof(hd->c_min), HEX); arcn->sb.st_dev = TODEV(devmajor, devminor); - devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX); - devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX); + devmajor = (dev_t)asc_u32(hd->c_rmaj, sizeof(hd->c_maj), HEX); + devminor = (dev_t)asc_u32(hd->c_rmin, sizeof(hd->c_min), HEX); arcn->sb.st_rdev = TODEV(devmajor, devminor); - arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); + arcn->crc = asc_u32(hd->c_chksum, sizeof(hd->c_chksum), HEX); /* * check the length of the file name, if ok read it in, return -1 if * bogus */ - if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) + if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) return -1; arcn->nlen = nsz - 1; if (rd_nm(arcn, nsz) < 0) @@ -699,15 +699,15 @@ vcpio_wr(ARCHD *arcn) * file data crc's, and the crc if needed. */ if (docrc) { - if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), + if (u32_asc((uintmax_t)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || - ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), + u32_asc((uintmax_t)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), HEX)) goto out; } else { - if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), + if (u32_asc((uintmax_t)VMAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || - ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) + u32_asc((uintmax_t)0, hd->c_chksum, sizeof(hd->c_chksum),HEX)) goto out; } @@ -733,7 +733,7 @@ vcpio_wr(ARCHD *arcn) * the size of the link */ arcn->pad = 0L; - if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, + if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize, sizeof(hd->c_filesize), HEX)) goto out; break; @@ -742,7 +742,7 @@ vcpio_wr(ARCHD *arcn) * no file data for the caller to process */ arcn->pad = 0L; - if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), + if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize), HEX)) goto out; break; @@ -751,27 +751,27 @@ vcpio_wr(ARCHD *arcn) /* * set the other fields in the header */ - if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), + if (u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), HEX) || - ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), + u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), HEX) || - ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), + u32_asc((uintmax_t)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), HEX) || - ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), + u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), HEX) || - ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), + u32_asc((uintmax_t)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), HEX) || - ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), + u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), HEX) || - ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), + u32_asc((uintmax_t)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), HEX) || - ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), + u32_asc((uintmax_t)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), HEX) || - ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), + u32_asc((uintmax_t)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), HEX) || - ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), + u32_asc((uintmax_t)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), HEX) || - ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) + u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) goto out; /* Index: src/bin/pax/extern.h diff -u src/bin/pax/extern.h:1.58 src/bin/pax/extern.h:1.59 --- src/bin/pax/extern.h:1.58 Mon Aug 29 10:47:47 2011 +++ src/bin/pax/extern.h Thu Aug 9 04:09:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.58 2011/08/29 14:47:47 joerg Exp $ */ +/* $NetBSD: extern.h,v 1.59 2012/08/09 08:09:21 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -181,12 +181,10 @@ int next_file(ARCHD *); void ls_list(ARCHD *, time_t, FILE *); void ls_tty(ARCHD *); void safe_print(const char *, FILE *); -u_long asc_ul(char *, int, int); -int ul_asc(u_long, char *, int, int); -#if !defined(_LP64) -unsigned long long asc_ull(char *, int, int); -int ull_asc(unsigned long long, char *, int, int); -#endif +uint32_t asc_u32(char *, int, int); +int u32_asc(uintmax_t, char *, int, int); +uintmax_t asc_umax(char *, int, int); +int umax_asc(uintmax_t, char *, int, int); int check_Aflag(void); /* Index: src/bin/pax/gen_subs.c diff -u src/bin/pax/gen_subs.c:1.35 src/bin/pax/gen_subs.c:1.36 --- src/bin/pax/gen_subs.c:1.35 Sun Aug 14 06:49:58 2011 +++ src/bin/pax/gen_subs.c Thu Aug 9 04:09:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: gen_subs.c,v 1.35 2011/08/14 10:49:58 christos Exp $ */ +/* $NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: gen_subs.c,v 1.35 2011/08/14 10:49:58 christos Exp $"); +__RCSID("$NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $"); #endif #endif /* not lint */ @@ -202,20 +202,20 @@ safe_print(const char *str, FILE *fp) } /* - * asc_ul() - * convert hex/octal character string into a u_long. We do not have to + * asc_u32() + * convert hex/octal character string into a uint32_t. We do not have to * check for overflow! (the headers in all supported formats are not large * enough to create an overflow). * NOTE: strings passed to us are NOT TERMINATED. * Return: - * unsigned long value + * uint32_t value */ -u_long -asc_ul(char *str, int len, int base) +uint32_t +asc_u32(char *str, int len, int base) { char *stop; - u_long tval = 0; + uint32_t tval = 0; stop = str + len; @@ -248,17 +248,24 @@ asc_ul(char *str, int len, int base) } /* - * ul_asc() - * convert an unsigned long into an hex/oct ascii string. pads with LEADING + * u32_asc() + * convert an uintmax_t into an hex/oct ascii string. pads with LEADING * ascii 0's to fill string completely * NOTE: the string created is NOT TERMINATED. */ int -ul_asc(u_long val, char *str, int len, int base) +u32_asc(uintmax_t val, char *str, int len, int base) { char *pt; - u_long digit; + uint32_t digit; + uintmax_t p; + + p = val & TOP_HALF; + if (p && p != TOP_HALF) + return -1; + + val &= BOTTOM_HALF; /* * WARNING str is not '\0' terminated by this routine @@ -282,7 +289,7 @@ ul_asc(u_long val, char *str, int len, i } else { while (pt >= str) { *pt-- = '0' + (char)(val & 0x7); - if ((val = (val >> 3)) == (u_long)0) + if ((val = (val >> 3)) == 0) break; } } @@ -292,27 +299,26 @@ ul_asc(u_long val, char *str, int len, i */ while (pt >= str) *pt-- = '0'; - if (val != (u_long)0) + if (val != 0) return -1; return 0; } -#if !defined(_LP64) /* - * asc_ull() - * convert hex/octal character string into a unsigned long long. We do + * asc_umax() + * convert hex/octal character string into a uintmax. We do * not have to to check for overflow! (the headers in all supported * formats are not large enough to create an overflow). * NOTE: strings passed to us are NOT TERMINATED. * Return: - * unsigned long long value + * uintmax_t value */ -unsigned long long -asc_ull(char *str, int len, int base) +uintmax_t +asc_umax(char *str, int len, int base) { char *stop; - unsigned long long tval = 0; + uintmax_t tval = 0; stop = str + len; @@ -345,17 +351,17 @@ asc_ull(char *str, int len, int base) } /* - * ull_asc() - * convert an unsigned long long into a hex/oct ascii string. pads with + * umax_asc() + * convert an uintmax_t into a hex/oct ascii string. pads with * LEADING ascii 0's to fill string completely * NOTE: the string created is NOT TERMINATED. */ int -ull_asc(unsigned long long val, char *str, int len, int base) +umax_asc(uintmax_t val, char *str, int len, int base) { char *pt; - unsigned long long digit; + uintmax_t digit; /* * WARNING str is not '\0' terminated by this routine @@ -373,13 +379,13 @@ ull_asc(unsigned long long val, char *st *pt-- = '0' + (char)digit; else *pt-- = 'a' + (char)(digit - 10); - if ((val = (val >> 4)) == (unsigned long long)0) + if ((val = (val >> 4)) == 0) break; } } else { while (pt >= str) { *pt-- = '0' + (char)(val & 0x7); - if ((val = (val >> 3)) == (unsigned long long)0) + if ((val = (val >> 3)) == 0) break; } } @@ -389,11 +395,10 @@ ull_asc(unsigned long long val, char *st */ while (pt >= str) *pt-- = '0'; - if (val != (unsigned long long)0) + if (val != 0) return -1; return 0; } -#endif int check_Aflag(void) Index: src/bin/pax/pax.h diff -u src/bin/pax/pax.h:1.30 src/bin/pax/pax.h:1.31 --- src/bin/pax/pax.h:1.30 Tue Apr 7 15:52:35 2009 +++ src/bin/pax/pax.h Thu Aug 9 04:09:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: pax.h,v 1.30 2009/04/07 19:52:35 perry Exp $ */ +/* $NetBSD: pax.h,v 1.31 2012/08/09 08:09:21 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -267,24 +267,17 @@ typedef struct oplist { #define _TFILE_BASE "paxXXXXXXXXXX" /* - * Macros to manipulate off_t as a unsigned long or unsigned long long + * Macros to manipulate off_t as uintmax_t */ -#if defined(_LP64) -#define OFFT_F "%lu" -#define OFFT_FP(x) "%" x "lu" -#define OFFT_T u_long -#define ASC_OFFT(x,y,z) asc_ul(x,y,z) -#define OFFT_ASC(w,x,y,z) ul_asc((u_long)w,x,y,z) -#define OFFT_OCT(w,x,y,z) ul_oct((u_long)w,x,y,z) -#define STRTOOFFT(x,y,z) strtol(x,y,z) -#define OFFT_MAX LONG_MAX -#else -#define OFFT_F "%llu" -#define OFFT_FP(x) "%" x "llu" -#define OFFT_T unsigned long long -#define ASC_OFFT(x,y,z) asc_ull(x,y,z) -#define OFFT_ASC(w,x,y,z) ull_asc((unsigned long long)w,x,y,z) -#define OFFT_OCT(w,x,y,z) ull_oct((unsigned long long)w,x,y,z) -#define STRTOOFFT(x,y,z) strtoll(x,y,z) -#define OFFT_MAX LLONG_MAX -#endif +#define OFFT_F "%" PRIuMAX +#define OFFT_FP(x) "%" x PRIuMAX +#define OFFT_T uintmax_t +#define ASC_OFFT(x,y,z) asc_umax(x,y,z) +#define OFFT_ASC(w,x,y,z) umax_asc((uintmax_t)w,x,y,z) +#define OFFT_OCT(w,x,y,z) umax_oct((uintmax_t)w,x,y,z) +#define STRTOOFFT(x,y,z) strtoimax(x,y,z) +#define OFFT_MAX INTMAX_MAX + +#define TOP_HALF 0xffffffff00000000ULL +#define BOTTOM_HALF 0x00000000ffffffffULL + Index: src/bin/pax/tar.c diff -u src/bin/pax/tar.c:1.69 src/bin/pax/tar.c:1.70 --- src/bin/pax/tar.c:1.69 Tue Mar 20 14:42:28 2012 +++ src/bin/pax/tar.c Thu Aug 9 04:09:22 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: tar.c,v 1.69 2012/03/20 18:42:28 matt Exp $ */ +/* $NetBSD: tar.c,v 1.70 2012/08/09 08:09:22 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: tar.c,v 1.69 2012/03/20 18:42:28 matt Exp $"); +__RCSID("$NetBSD: tar.c,v 1.70 2012/08/09 08:09:22 christos Exp $"); #endif #endif /* not lint */ @@ -70,12 +70,10 @@ __RCSID("$NetBSD: tar.c,v 1.69 2012/03/2 static int expandname(char *, size_t, char **, size_t *, const char *, size_t); static void longlink(ARCHD *, int); -static u_long tar_chksm(char *, int); +static uint32_t tar_chksm(char *, int); static char *name_split(char *, int); -static int ul_oct(u_long, char *, int, int); -#if !defined(_LP64) -static int ull_oct(unsigned long long, char *, int, int); -#endif +static int u32_oct(uintmax_t, char *, int, int); +static int umax_oct(uintmax_t, char *, int, int); static int tar_gnutar_exclude_one(const char *, size_t); static int check_sum(char *, size_t, char *, size_t, int); @@ -111,14 +109,14 @@ char DEV_8[] = "/dev/rst8"; static int check_sum(char *hd, size_t hdlen, char *bl, size_t bllen, int quiet) { - u_long hdck, blck; + uint32_t hdck, blck; - hdck = asc_ul(hd, hdlen, OCT); + hdck = asc_u32(hd, hdlen, OCT); blck = tar_chksm(bl, bllen); if (hdck != blck) { if (!quiet) - tty_warn(0, "Header checksum %lo does not match %lo", + tty_warn(0, "Header checksum %o does not match %o", hdck, blck); return -1; } @@ -208,8 +206,8 @@ tar_trail(char *buf, int in_resync, int } /* - * ul_oct() - * convert an unsigned long to an octal string. many oddball field + * u32_oct() + * convert an uintmax_t to an octal string. many oddball field * termination characters are used by the various versions of tar in the * different fields. term selects which kind to use. str is '0' padded * at the front to len. we are unable to use only one format as many old @@ -219,9 +217,16 @@ tar_trail(char *buf, int in_resync, int */ static int -ul_oct(u_long val, char *str, int len, int term) +u32_oct(uintmax_t val, char *str, int len, int term) { char *pt; + uint64_t p; + + p = val & TOP_HALF; + if (p && p != TOP_HALF) + return -1; + + val &= BOTTOM_HALF; /* * term selects the appropriate character(s) for the end of the string @@ -250,20 +255,19 @@ ul_oct(u_long val, char *str, int len, i */ while (pt >= str) { *pt-- = '0' + (char)(val & 0x7); - if ((val = val >> 3) == (u_long)0) + if ((val = val >> 3) == 0) break; } while (pt >= str) *pt-- = '0'; - if (val != (u_long)0) + if (val != 0) return -1; return 0; } -#if !defined(_LP64) /* - * ull_oct() + * umax_oct() * convert an unsigned long long to an octal string. one of many oddball * field termination characters are used by the various versions of tar * in the different fields. term selects which kind to use. str is '0' @@ -274,7 +278,7 @@ ul_oct(u_long val, char *str, int len, i */ static int -ull_oct(unsigned long long val, char *str, int len, int term) +umax_oct(uintmax_t val, char *str, int len, int term) { char *pt; @@ -311,11 +315,10 @@ ull_oct(unsigned long long val, char *st while (pt >= str) *pt-- = '0'; - if (val != (unsigned long long)0) + if (val != 0) return -1; return 0; } -#endif /* * tar_chksm() @@ -327,12 +330,12 @@ ull_oct(unsigned long long val, char *st * unsigned long checksum */ -static u_long +static uint32_t tar_chksm(char *blk, int len) { char *stop; char *pt; - u_long chksm = BLNKSUM; /* initial value is checksum field sum */ + uint32_t chksm = BLNKSUM; /* initial value is checksum field sum */ /* * add the part of the block before the checksum field @@ -340,7 +343,7 @@ tar_chksm(char *blk, int len) pt = blk; stop = blk + CHK_OFFSET; while (pt < stop) - chksm += (u_long)(*pt++ & 0xff); + chksm += (uint32_t)(*pt++ & 0xff); /* * move past the checksum field and keep going, spec counts the * checksum field as the sum of 8 blanks (which is pre-computed as @@ -351,7 +354,7 @@ tar_chksm(char *blk, int len) pt += CHK_LEN; stop = blk + len; while (pt < stop) - chksm += (u_long)(*pt++ & 0xff); + chksm += (uint32_t)(*pt++ & 0xff); return chksm; } @@ -476,12 +479,12 @@ tar_rd(ARCHD *arcn, char *buf) &gnu_link_string, &gnu_link_length, hd->linkname, sizeof(hd->linkname)); } - arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & + arcn->sb.st_mode = (mode_t)(asc_u32(hd->mode,sizeof(hd->mode),OCT) & 0xfff); - arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); - arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); + arcn->sb.st_uid = (uid_t)asc_u32(hd->uid, sizeof(hd->uid), OCT); + arcn->sb.st_gid = (gid_t)asc_u32(hd->gid, sizeof(hd->gid), OCT); arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); - arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); + arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; /* @@ -571,7 +574,7 @@ tar_rd(ARCHD *arcn, char *buf) * tar_wr() * write a tar header for the file specified in the ARCHD to the archive. * Have to check for file types that cannot be stored and file names that - * are too long. Be careful of the term (last arg) to ul_oct, each field + * are too long. Be careful of the term (last arg) to u32_oct, each field * of tar has it own spec for the termination character(s). * ASSUMED: space after header in header block is zero filled * Return: @@ -658,7 +661,7 @@ tar_wr(ARCHD *arcn) */ hd->linkflag = AREGTYPE; hd->name[len-1] = '/'; - if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) + if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1)) goto out; } else if (arcn->type == PAX_SLK) { /* @@ -666,7 +669,7 @@ tar_wr(ARCHD *arcn) */ hd->linkflag = SYMTYPE; strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); - if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) + if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1)) goto out; } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { /* @@ -674,7 +677,7 @@ tar_wr(ARCHD *arcn) */ hd->linkflag = LNKTYPE; strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); - if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) + if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1)) goto out; } else { /* @@ -692,10 +695,10 @@ tar_wr(ARCHD *arcn) /* * copy those fields that are independent of the type */ - if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || - ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || - ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || - ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) + if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || + u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || + u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || + u32_oct((uintmax_t)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) goto out; /* @@ -703,7 +706,7 @@ tar_wr(ARCHD *arcn) * 0 tells the caller to now write the file data, 1 says no data needs * to be written */ - if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, + if (u32_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, sizeof(hd->chksum), 3)) goto out; /* XXX Something's wrong here * because a zero-byte file can @@ -850,10 +853,10 @@ ustar_rd(ARCHD *arcn, char *buf) * follow the spec to the letter. we should only have mode bits, strip * off all other crud we may be passed. */ - arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & + arcn->sb.st_mode = (mode_t)(asc_u32(hd->mode, sizeof(hd->mode), OCT) & 0xfff); arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); - arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); + arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; /* @@ -864,10 +867,10 @@ ustar_rd(ARCHD *arcn, char *buf) */ hd->gname[sizeof(hd->gname) - 1] = '\0'; if (gid_from_group(hd->gname, &(arcn->sb.st_gid)) < 0) - arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); + arcn->sb.st_gid = (gid_t)asc_u32(hd->gid, sizeof(hd->gid), OCT); hd->uname[sizeof(hd->uname) - 1] = '\0'; if (uid_from_user(hd->uname, &(arcn->sb.st_uid)) < 0) - arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); + arcn->sb.st_uid = (uid_t)asc_u32(hd->uid, sizeof(hd->uid), OCT); /* * set the defaults, these may be changed depending on the file type @@ -909,8 +912,8 @@ ustar_rd(ARCHD *arcn, char *buf) arcn->type = PAX_CHR; arcn->sb.st_mode |= S_IFCHR; } - devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); - devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); + devmajor = (dev_t)asc_u32(hd->devmajor,sizeof(hd->devmajor),OCT); + devminor = (dev_t)asc_u32(hd->devminor,sizeof(hd->devminor),OCT); arcn->sb.st_rdev = TODEV(devmajor, devminor); break; case SYMTYPE: @@ -1012,7 +1015,7 @@ longlink(ARCHD *arcn, int type) * ustar_wr() * write a ustar header for the file specified in the ARCHD to the archive * Have to check for file types that cannot be stored and file names that - * are too long. Be careful of the term (last arg) to ul_oct, we only use + * are too long. Be careful of the term (last arg) to u32_oct, we only use * '\0' for the termination character (this is different than picky tar) * ASSUMED: space after header in header block is zero filled * Return: @@ -1116,7 +1119,7 @@ ustar_wr(ARCHD *arcn) switch(arcn->type) { case PAX_DIR: hd->typeflag = DIRTYPE; - if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) + if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3)) return size_err("DIRTYPE", arcn); break; case PAX_CHR: @@ -1125,16 +1128,16 @@ ustar_wr(ARCHD *arcn) hd->typeflag = CHRTYPE; else hd->typeflag = BLKTYPE; - if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, + if (u32_oct((uintmax_t)MAJOR(arcn->sb.st_rdev), hd->devmajor, sizeof(hd->devmajor), 3) || - ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, + u32_oct((uintmax_t)MINOR(arcn->sb.st_rdev), hd->devminor, sizeof(hd->devminor), 3) || - ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) + u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3)) return size_err("DEVTYPE", arcn); break; case PAX_FIF: hd->typeflag = FIFOTYPE; - if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) + if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3)) return size_err("FIFOTYPE", arcn); break; case PAX_GLL: @@ -1148,7 +1151,7 @@ ustar_wr(ARCHD *arcn) else hd->typeflag = LNKTYPE; strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); - if (ul_oct((u_long)gnu_hack_len, hd->size, + if (u32_oct((uintmax_t)gnu_hack_len, hd->size, sizeof(hd->size), 3)) return size_err("LINKTYPE", arcn); break; @@ -1162,7 +1165,7 @@ ustar_wr(ARCHD *arcn) if (arcn->type == PAX_GLF) { hd->typeflag = LONGNAMETYPE; arcn->pad = TAR_PAD(gnu_hack_len); - if (OFFT_OCT((u_long)gnu_hack_len, hd->size, + if (OFFT_OCT((uint32_t)gnu_hack_len, hd->size, sizeof(hd->size), 3)) { tty_warn(1,"File is too long for ustar %s", arcn->org_name); @@ -1194,13 +1197,13 @@ ustar_wr(ARCHD *arcn) * set the remaining fields. Some versions want all 16 bits of mode * we better humor them (they really do not meet spec though).... */ - if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3)) + if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3)) return size_err("MODE", arcn); - if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)) + if (u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)) return size_err("UID", arcn); - if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) + if (u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) return size_err("GID", arcn); - if (ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) + if (u32_oct((uintmax_t)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) return size_err("MTIME", arcn); user = user_from_uid(arcn->sb.st_uid, 1); group = group_from_gid(arcn->sb.st_gid, 1); @@ -1212,7 +1215,7 @@ ustar_wr(ARCHD *arcn) * return 0 tells the caller to now write the file data, 1 says no data * needs to be written */ - if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, + if (u32_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, sizeof(hd->chksum), 3)) return size_err("CHKSUM", arcn); if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)