-/* $OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $ */
+/* $OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $ */
/* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
-static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
-static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $";
+static const char rcsid[] = "$OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/param.h>
* Routines for reading, writing and header identify of various versions of tar
*/
-static u_long tar_chksm __P((register char *, register int));
-static char *name_split __P((register char *, register int));
-static int ul_oct __P((u_long, register char *, register int, int));
-#ifndef NET2_STAT
-static int uqd_oct __P((u_quad_t, register char *, register int, int));
+static size_t expandname(char *, size_t, char **, const char *, size_t);
+static u_long tar_chksm(char *, int);
+static char *name_split(char *, int);
+static int ul_oct(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+static int uqd_oct(u_quad_t, char *, int, int);
#endif
+static uid_t uid_nobody;
+static uid_t uid_warn;
+static gid_t gid_nobody;
+static gid_t gid_warn;
+
/*
* Routines common to all versions of tar
*/
static int tar_nodir; /* do not write dirs under old tar */
+char *gnu_name_string; /* GNU ././@LongLink hackery name */
+char *gnu_link_string; /* GNU ././@LongLink hackery link */
/*
* tar_endwr()
* 0 if ok, -1 otherwise (what wr_skip returns)
*/
-#ifdef __STDC__
int
tar_endwr(void)
-#else
-int
-tar_endwr()
-#endif
{
return(wr_skip((off_t)(NULLCNT*BLKMULT)));
}
* size of trailer (2 * BLKMULT)
*/
-#ifdef __STDC__
off_t
tar_endrd(void)
-#else
-off_t
-tar_endrd()
-#endif
{
return((off_t)(NULLCNT*BLKMULT));
}
* could never contain a header.
*/
-#ifdef __STDC__
-int
-tar_trail(register char *buf, register int in_resync, register int *cnt)
-#else
int
-tar_trail(buf, in_resync, cnt)
- register char *buf;
- register int in_resync;
- register int *cnt;
-#endif
+tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt)
{
- register int i;
+ int i;
/*
* look for all zero, trailer is two consecutive blocks of zero
* 0 if the number fit into the string, -1 otherwise
*/
-#ifdef __STDC__
-static int
-ul_oct(u_long val, register char *str, register int len, int term)
-#else
static int
-ul_oct(val, str, len, term)
- u_long val;
- register char *str;
- register int len;
- int term;
-#endif
+ul_oct(u_long val, char *str, int len, int term)
{
- register char *pt;
+ char *pt;
/*
* term selects the appropriate character(s) for the end of the string
*/
pt = str + len - 1;
- switch(term) {
+ switch (term) {
case 3:
*pt-- = '\0';
break;
return(0);
}
-#ifndef NET2_STAT
+#ifndef LONG_OFF_T
/*
* uqd_oct()
* convert an u_quad_t to an octal string. one of many oddball field
* 0 if the number fit into the string, -1 otherwise
*/
-#ifdef __STDC__
-static int
-uqd_oct(u_quad_t val, register char *str, register int len, int term)
-#else
static int
-uqd_oct(val, str, len, term)
- u_quad_t val;
- register char *str;
- register int len;
- int term;
-#endif
+uqd_oct(u_quad_t val, char *str, int len, int term)
{
- register char *pt;
+ char *pt;
/*
* term selects the appropriate character(s) for the end of the string
*/
pt = str + len - 1;
- switch(term) {
+ switch (term) {
case 3:
*pt-- = '\0';
break;
/*
* tar_chksm()
* calculate the checksum for a tar block counting the checksum field as
- * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
+ * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
* NOTE: we use len to short circuit summing 0's on write since we ALWAYS
* pad headers with 0.
* Return:
* unsigned long checksum
*/
-#ifdef __STDC__
static u_long
-tar_chksm(register char *blk, register int len)
-#else
-static u_long
-tar_chksm(blk, len)
- register char *blk;
- register int len;
-#endif
+tar_chksm(char *blk, int len)
{
- register char *stop;
- register char *pt;
- u_long chksm = BLNKSUM; /* inital value is checksum field sum */
+ char *stop;
+ char *pt;
+ u_long chksm = BLNKSUM; /* initial value is checksum field sum */
/*
* add the part of the block before the checksum field
* 0 if a tar header, -1 otherwise
*/
-#ifdef __STDC__
int
-tar_id(register char *blk, int size)
-#else
-int
-tar_id(blk, size)
- register char *blk;
- int size;
-#endif
+tar_id(char *blk, int size)
{
- register HD_TAR *hd;
- register HD_USTAR *uhd;
+ HD_TAR *hd;
+ HD_USTAR *uhd;
if (size < BLKMULT)
return(-1);
return(-1);
if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
return(-1);
+ force_one_volume = 1;
return(0);
}
* 0 if ok -1 otherwise
*/
-#ifdef __STDC__
int
tar_opt(void)
-#else
-int
-tar_opt()
-#endif
{
OPLIST *opt;
* 0
*/
-#ifdef __STDC__
int
-tar_rd(register ARCHD *arcn, register char *buf)
-#else
-int
-tar_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
-#endif
+tar_rd(ARCHD *arcn, char *buf)
{
- register HD_TAR *hd;
- register char *pt;
+ HD_TAR *hd;
+ char *pt;
/*
* we only get proper sized buffers passed to us
*/
if (tar_id(buf, BLKMULT) < 0)
return(-1);
+ memset(arcn, 0, sizeof(*arcn));
arcn->org_name = arcn->name;
arcn->sb.st_nlink = 1;
- arcn->pat = NULL;
/*
* copy out the name and values in the stat buffer
*/
hd = (HD_TAR *)buf;
- arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1);
- arcn->name[arcn->nlen] = '\0';
+ if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
+ arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
+ &gnu_name_string, hd->name, sizeof(hd->name));
+ arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+ &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+ }
arcn->sb.st_mode = (mode_t)(asc_ul(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_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+ arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+ arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
pt = &(arcn->name[arcn->nlen - 1]);
arcn->pad = 0;
arcn->skip = 0;
- switch(hd->linkflag) {
+ switch (hd->linkflag) {
case SYMTYPE:
/*
* symbolic link, need to get the link name and set the type in
* the st_mode so -v printing will look correct.
*/
arcn->type = PAX_SLK;
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(arcn->ln_name) - 1);
- arcn->ln_name[arcn->ln_nlen] = '\0';
arcn->sb.st_mode |= S_IFLNK;
break;
case LNKTYPE:
*/
arcn->type = PAX_HLK;
arcn->sb.st_nlink = 2;
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(arcn->ln_name) - 1);
- arcn->ln_name[arcn->ln_nlen] = '\0';
/*
* no idea of what type this thing really points at, but
*/
arcn->sb.st_mode |= S_IFREG;
break;
+ case LONGLINKTYPE:
+ case LONGNAMETYPE:
+ /*
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
+ */
+ arcn->type =
+ hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
+ break;
case DIRTYPE:
/*
* It is a directory, set the mode for -v printing
arcn->type = PAX_DIR;
arcn->sb.st_mode |= S_IFDIR;
arcn->sb.st_nlink = 2;
- arcn->ln_name[0] = '\0';
- arcn->ln_nlen = 0;
break;
case AREGTYPE:
case REGTYPE:
} else {
/*
* have a file that will be followed by data. Set the
- * skip value to the size field and caluculate the size
+ * skip value to the size field and calculate the size
* of the padding.
*/
arcn->type = PAX_REG;
* strip off any trailing slash.
*/
if (*pt == '/') {
- *pt = '\0';
+ *pt = '\0';
--arcn->nlen;
}
return(0);
* data to write after the header, -1 if archive write failed
*/
-#ifdef __STDC__
int
-tar_wr(register ARCHD *arcn)
-#else
-int
-tar_wr(arcn)
- register ARCHD *arcn;
-#endif
+tar_wr(ARCHD *arcn)
{
- register HD_TAR *hd;
+ HD_TAR *hd;
int len;
char hdblk[sizeof(HD_TAR)];
/*
* check for those file system types which tar cannot store
*/
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_DIR:
/*
* user asked that dirs not be written to the archive
case PAX_HLK:
case PAX_HRG:
if (arcn->ln_nlen > sizeof(hd->linkname)) {
- paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
+ paxwarn(1, "Link name too long for tar %s",
+ arcn->ln_name);
return(1);
}
break;
len = arcn->nlen;
if (arcn->type == PAX_DIR)
++len;
- if (len >= sizeof(hd->name)) {
+ if (len > sizeof(hd->name)) {
paxwarn(1, "File name too long for tar %s", arcn->name);
return(1);
}
/*
- * copy the data out of the ARCHD into the tar header based on the type
- * of the file. Remember many tar readers want the unused fields to be
- * padded with zero. We set the linkflag field (type), the linkname
- * (or zero if not used),the size, and set the padding (if any) to be
- * added after the file data (0 for all other types, as they only have
- * a header)
+ * Copy the data out of the ARCHD into the tar header based on the type
+ * of the file. Remember, many tar readers want all fields to be
+ * padded with zero so we zero the header first. We then set the
+ * linkflag field (type), the linkname, the size, and set the padding
+ * (if any) to be added after the file data (0 for all other types,
+ * as they only have a header).
*/
+ memset(hdblk, 0, sizeof(hdblk));
hd = (HD_TAR *)hdblk;
- l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
- hd->name[sizeof(hd->name) - 1] = '\0';
+ fieldcpy(hd->name, sizeof(hd->name), arcn->name, sizeof(arcn->name));
arcn->pad = 0;
if (arcn->type == PAX_DIR) {
/*
* directories are the same as files, except have a filename
- * that ends with a /, we add the slash here. No data follows,
+ * that ends with a /, we add the slash here. No data follows
* dirs, so no pad.
*/
hd->linkflag = AREGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
hd->name[len-1] = '/';
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
* no data follows this file, so no pad
*/
hd->linkflag = SYMTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
- hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
* no data follows this file, so no pad
*/
hd->linkflag = LNKTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
- hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
} else {
* data follows this file, so set the pad
*/
hd->linkflag = AREGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
-# ifdef NET2_STAT
+# ifdef LONG_OFF_T
if (ul_oct((u_long)arcn->sb.st_size, hd->size,
sizeof(hd->size), 1)) {
# else
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))
+ ul_oct((u_long)(u_int)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
goto out;
/*
* 0 if ok, -1 otherwise
*/
-#ifdef __STDC__
int
ustar_strd(void)
-#else
-int
-ustar_strd()
-#endif
{
if ((usrtb_start() < 0) || (grptb_start() < 0))
return(-1);
* 0 if ok, -1 otherwise
*/
-#ifdef __STDC__
int
ustar_stwr(void)
-#else
-int
-ustar_stwr()
-#endif
{
if ((uidtb_start() < 0) || (gidtb_start() < 0))
return(-1);
* 0 if a ustar header, -1 otherwise
*/
-#ifdef __STDC__
int
ustar_id(char *blk, int size)
-#else
-int
-ustar_id(blk, size)
- char *blk;
- int size;
-#endif
{
- register HD_USTAR *hd;
+ HD_USTAR *hd;
if (size < BLKMULT)
return(-1);
* programs are fouled up and create archives missing the \0. Last we
* check the checksum. If ok we have to assume it is a valid header.
*/
- if (hd->name[0] == '\0')
+ if (hd->prefix[0] == '\0' && hd->name[0] == '\0')
return(-1);
if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
return(-1);
* 0
*/
-#ifdef __STDC__
int
-ustar_rd(register ARCHD *arcn, register char *buf)
-#else
-int
-ustar_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
-#endif
+ustar_rd(ARCHD *arcn, char *buf)
{
- register HD_USTAR *hd;
- register char *dest;
- register int cnt = 0;
+ HD_USTAR *hd;
+ char *dest;
+ int cnt = 0;
dev_t devmajor;
dev_t devminor;
*/
if (ustar_id(buf, BLKMULT) < 0)
return(-1);
+ memset(arcn, 0, sizeof(*arcn));
arcn->org_name = arcn->name;
arcn->sb.st_nlink = 1;
- arcn->pat = NULL;
- arcn->nlen = 0;
hd = (HD_USTAR *)buf;
/*
* see if the filename is split into two parts. if, so joint the parts.
* we copy the prefix first and add a / between the prefix and name.
+ *
+ * the length passed to l_strncpy must be the length of the field
+ * being copied *from*, since these fields are NOT null terminated
+ * when full. the destination buffer is plenty big enough to hold
+ * the longest supported ustar path length, so there's no need
+ * to check against that.
*/
dest = arcn->name;
if (*(hd->prefix) != '\0') {
- cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2);
+ cnt = fieldcpy(dest, sizeof(arcn->name) - 1, hd->prefix,
+ sizeof(hd->prefix));
dest += cnt;
*dest++ = '/';
cnt++;
+ } else {
+ cnt = 0;
+ }
+
+ if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
+ arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt,
+ &gnu_name_string, hd->name, sizeof(hd->name));
+ arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+ &gnu_link_string, hd->linkname, sizeof(hd->linkname));
}
- arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt);
- arcn->name[arcn->nlen] = '\0';
/*
* follow the spec to the letter. we should only have mode bits, strip
*/
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
0xfff);
- arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+ arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+ arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
/*
* set the defaults, these may be changed depending on the file type
*/
- arcn->ln_name[0] = '\0';
- arcn->ln_nlen = 0;
arcn->pad = 0;
arcn->skip = 0;
arcn->sb.st_rdev = (dev_t)0;
/*
* set the mode and PAX type according to the typeflag in the header
*/
- switch(hd->typeflag) {
+ switch (hd->typeflag) {
case FIFOTYPE:
arcn->type = PAX_FIF;
arcn->sb.st_mode |= S_IFIFO;
arcn->sb.st_mode |= S_IFREG;
arcn->sb.st_nlink = 2;
}
+ break;
+ case LONGLINKTYPE:
+ case LONGNAMETYPE:
/*
- * copy the link name
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
*/
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(arcn->ln_name) - 1);
- arcn->ln_name[arcn->ln_nlen] = '\0';
+ arcn->type =
+ hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
break;
case CONTTYPE:
case AREGTYPE:
* data to write after the header, -1 if archive write failed
*/
-#ifdef __STDC__
int
-ustar_wr(register ARCHD *arcn)
-#else
-int
-ustar_wr(arcn)
- register ARCHD *arcn;
-#endif
+ustar_wr(ARCHD *arcn)
{
- register HD_USTAR *hd;
- register char *pt;
+ HD_USTAR *hd;
+ char *pt;
char hdblk[sizeof(HD_USTAR)];
/*
paxwarn(1, "File name too long for ustar %s", arcn->name);
return(1);
}
+
+ /*
+ * zero out the header so we don't have to worry about zero fill below
+ */
+ memset(hdblk, 0, sizeof(hdblk));
hd = (HD_USTAR *)hdblk;
arcn->pad = 0L;
* occur, we remove the / and copy the first part to the prefix
*/
*pt = '\0';
- l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1);
+ fieldcpy(hd->prefix, sizeof(hd->prefix), arcn->name,
+ sizeof(arcn->name));
*pt++ = '/';
- } else
- memset(hd->prefix, 0, sizeof(hd->prefix));
+ }
/*
* copy the name part. this may be the whole path or the part after
* the prefix
*/
- l_strncpy(hd->name, pt, sizeof(hd->name) - 1);
- hd->name[sizeof(hd->name) - 1] = '\0';
+ fieldcpy(hd->name, sizeof(hd->name), pt,
+ sizeof(arcn->name) - (pt - arcn->name));
/*
* set the fields in the header that are type dependent
*/
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_DIR:
hd->typeflag = DIRTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- memset(hd->devminor, 0, sizeof(hd->devminor));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = CHRTYPE;
else
hd->typeflag = BLKTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
sizeof(hd->devmajor), 3) ||
ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
break;
case PAX_FIF:
hd->typeflag = FIFOTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- memset(hd->devminor, 0, sizeof(hd->devminor));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = SYMTYPE;
else
hd->typeflag = LNKTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
- hd->linkname[sizeof(hd->linkname) - 1] = '\0';
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- memset(hd->devminor, 0, sizeof(hd->devminor));
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = CONTTYPE;
else
hd->typeflag = REGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- memset(hd->devminor, 0, sizeof(hd->devminor));
arcn->pad = TAR_PAD(arcn->sb.st_size);
-# ifdef NET2_STAT
+# ifdef LONG_OFF_T
if (ul_oct((u_long)arcn->sb.st_size, hd->size,
sizeof(hd->size), 3)) {
# else
break;
}
- l_strncpy(hd->magic, TMAGIC, TMAGLEN);
- l_strncpy(hd->version, TVERSION, TVERSLEN);
+ strncpy(hd->magic, TMAGIC, TMAGLEN);
+ strncpy(hd->version, TVERSION, TVERSLEN);
/*
* 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_uid, hd->uid, sizeof(hd->uid), 3)) {
+ if (uid_nobody == 0) {
+ if (uid_name("nobody", &uid_nobody) == -1)
+ goto out;
+ }
+ if (uid_warn != arcn->sb.st_uid) {
+ uid_warn = arcn->sb.st_uid;
+ paxwarn(1,
+ "Ustar header field is too small for uid %lu, "
+ "using nobody", (u_long)arcn->sb.st_uid);
+ }
+ if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), 3))
+ goto out;
+ }
+ if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) {
+ if (gid_nobody == 0) {
+ if (gid_name("nobody", &gid_nobody) == -1)
+ goto out;
+ }
+ if (gid_warn != arcn->sb.st_gid) {
+ gid_warn = arcn->sb.st_gid;
+ paxwarn(1,
+ "Ustar header field is too small for gid %lu, "
+ "using nobody", (u_long)arcn->sb.st_gid);
+ }
+ if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), 3))
+ goto out;
+ }
if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
- ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
- ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
- ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+ ul_oct((u_long)(u_int)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
goto out;
- l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
- l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
+ strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
+ strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
/*
* calculate and store the checksum write the header to the archive
return(1);
out:
- /*
+ /*
* header field is out of range
*/
paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
* the file name is too long
*/
-#ifdef __STDC__
-static char *
-name_split(register char *name, register int len)
-#else
static char *
-name_split(name, len)
- register char *name;
- register int len;
-#endif
+name_split(char *name, int len)
{
- register char *start;
+ char *start;
/*
* check to see if the file name is small enough to fit in the name
* field. if so just return a pointer to the name.
+ * The strings can fill the complete name and prefix fields
+ * without a NUL terminator.
*/
- if (len < TNMSZ)
+ if (len <= TNMSZ)
return(name);
if (len > (TPFSZ + TNMSZ + 1))
return(NULL);
/*
* we start looking at the biggest sized piece that fits in the name
- * field. We walk foward looking for a slash to split at. The idea is
+ * field. We walk forward looking for a slash to split at. The idea is
* to find the biggest piece to fit in the name field (or the smallest
* prefix we can find) (the -1 is correct the biggest piece would
* include the slash between the two parts that gets thrown away)
*/
return(start);
}
+
+static size_t
+expandname(char *buf, size_t len, char **gnu_name, const char *name,
+ size_t limit)
+{
+ size_t nlen;
+
+ if (*gnu_name) {
+ /* *gnu_name is NUL terminated */
+ if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
+ nlen = len - 1;
+ free(*gnu_name);
+ *gnu_name = NULL;
+ } else
+ nlen = fieldcpy(buf, len, name, limit);
+ return(nlen);
+}