Imported Debian patch 1.5-15
[debian/pax] / tar.c
diff --git a/tar.c b/tar.c
index c73657d5d85afd01664dab2a269ece4a5c5ed8c2..af7f2141f8a4614ce3d795d2dc570637e34fd17c 100644 (file)
--- a/tar.c
+++ b/tar.c
@@ -47,6 +47,7 @@ static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $"
 #endif /* not lint */
 
 #include <sys/types.h>
+#include <sys/sysmacros.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/param.h>
@@ -841,15 +842,21 @@ ustar_rd(arcn, 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 = l_strncpy(dest, hd->prefix, sizeof(hd->prefix));
                dest += cnt;
                *dest++ = '/';
                cnt++;
        }
-       arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt);
+       arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(hd->name));
        arcn->name[arcn->nlen] = '\0';
 
        /*
@@ -936,9 +943,12 @@ ustar_rd(arcn, buf)
                }
                /*
                 * copy the link name
+                *
+                * see comment above (for hd->name) regarding the length
+                * passed to l_strncpy
                 */
                arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
+                       sizeof(hd->linkname));
                arcn->ln_name[arcn->ln_nlen] = '\0';
                break;
        case CONTTYPE:
@@ -1020,7 +1030,7 @@ ustar_wr(arcn)
                 * occur, we remove the / and copy the first part to the prefix
                 */
                *pt = '\0';
-               l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1);
+               l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
                *pt++ = '/';
        } else
                memset(hd->prefix, 0, sizeof(hd->prefix));
@@ -1029,8 +1039,7 @@ ustar_wr(arcn)
         * 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';
+       l_strncpy(hd->name, pt, sizeof(hd->name));
 
        /*
         * set the fields in the header that are type dependent
@@ -1040,7 +1049,9 @@ ustar_wr(arcn)
                hd->typeflag = DIRTYPE;
                memset(hd->linkname, 0, sizeof(hd->linkname));
                memset(hd->devmajor, 0, sizeof(hd->devmajor));
+               hd->devmajor[0] = '0';
                memset(hd->devminor, 0, sizeof(hd->devminor));
+               hd->devminor[0] = '0';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1062,7 +1073,9 @@ ustar_wr(arcn)
                hd->typeflag = FIFOTYPE;
                memset(hd->linkname, 0, sizeof(hd->linkname));
                memset(hd->devmajor, 0, sizeof(hd->devmajor));
+               hd->devmajor[0] = '0';
                memset(hd->devminor, 0, sizeof(hd->devminor));
+               hd->devminor[0] = '0';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1073,10 +1086,11 @@ ustar_wr(arcn)
                        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';
+               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
                memset(hd->devmajor, 0, sizeof(hd->devmajor));
+               hd->devmajor[0] = '0';
                memset(hd->devminor, 0, sizeof(hd->devminor));
+               hd->devminor[0] = '0';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1092,7 +1106,9 @@ ustar_wr(arcn)
                        hd->typeflag = REGTYPE;
                memset(hd->linkname, 0, sizeof(hd->linkname));
                memset(hd->devmajor, 0, sizeof(hd->devmajor));
+               hd->devmajor[0] = '0';
                memset(hd->devminor, 0, sizeof(hd->devminor));
+               hd->devminor[0] = '0';
                arcn->pad = TAR_PAD(arcn->sb.st_size);
 #              ifdef NET2_STAT
                if (ul_oct((u_long)arcn->sb.st_size, hd->size,
@@ -1174,7 +1190,7 @@ name_split(name, len)
         * 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.
         */
-       if (len < TNMSZ)
+       if (len <= TNMSZ)
                return(name);
        if (len > (TPFSZ + TNMSZ + 1))
                return(NULL);