Merge branch 'upstream'
[debian/pax] / ar_subs.c
index eaf3362cd9bff4f6a09a48eb257b981deb70f5db..382462cd6540f148abe3258affcc8650a0426d8c 100644 (file)
--- a/ar_subs.c
+++ b/ar_subs.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $    */
+/*     $OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $    */
 /*     $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ar_subs.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_subs.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $";
 #endif
 #endif /* not lint */
 
@@ -61,9 +57,9 @@ static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Ex
 #include "pax.h"
 #include "extern.h"
 
-static void wr_archive __P((register ARCHD *, int is_app));
-static int get_arc __P((void));
-static int next_head __P((register ARCHD *));
+static void wr_archive(ARCHD *, int is_app);
+static int get_arc(void);
+static int next_head(ARCHD *);
 extern sigset_t s_mask;
 
 /*
@@ -80,16 +76,11 @@ u_long flcnt;                               /* number of files processed */
  *     (no pattern matches all).
  */
 
-#ifdef __STDC__
 void
 list(void)
-#else
-void
-list()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        time_t now;
 
@@ -114,6 +105,17 @@ list()
         * step through the archive until the format says it is done
         */
        while (next_head(arcn) == 0) {
+               if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+                       /*
+                        * we need to read, to get the real filename
+                        */
+                       off_t cnt;
+                       if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
+
                /*
                 * check for pattern, and user specified options match.
                 * When all patterns are matched we are done.
@@ -162,16 +164,11 @@ list()
  *     pattern(s) (no patterns extracts all members)
  */
 
-#ifdef __STDC__
 void
 extract(void)
-#else
-void
-extract()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        off_t cnt;
        ARCHD archd;
        struct stat sb;
@@ -202,6 +199,15 @@ extract()
         * says it is done
         */
        while (next_head(arcn) == 0) {
+               if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+                       /*
+                        * we need to read, to get the real filename
+                        */
+                       if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
 
                /*
                 * check for pattern, and user specified options match. When
@@ -221,7 +227,7 @@ extract()
 
                /*
                 * with -u or -D only extract when the archive member is newer
-                * than the file with the same name in the file system (nos
+                * than the file with the same name in the file system (no
                 * test of being the same type is required).
                 * NOTE: this test is done BEFORE name modifications as
                 * specified by pax. this operation can be confusing to the
@@ -262,7 +268,7 @@ extract()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -287,7 +293,7 @@ extract()
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -322,7 +328,7 @@ extract()
                                (void)putc('\n', listf);
                                vfpart = 0;
                        }
-                       continue;
+                       goto popd;
                }
                /*
                 * we have a file with data here. If we can not create it, skip
@@ -331,7 +337,7 @@ extract()
                if ((fd = file_creat(arcn)) < 0) {
                        (void)rd_skip(arcn->skip + arcn->pad);
                        purg_lnk(arcn);
-                       continue;
+                       goto popd;
                }
                /*
                 * extract the file from the archive and skip over padding and
@@ -346,6 +352,7 @@ extract()
                if (!res)
                        (void)rd_skip(cnt + arcn->pad);
 
+popd:
                /*
                 * if required, chdir around.
                 */
@@ -373,21 +380,14 @@ extract()
  *     previously written archive.
  */
 
-#ifdef __STDC__
 static void
-wr_archive(register ARCHD *arcn, int is_app)
-#else
-static void
-wr_archive(arcn, is_app)
-       register ARCHD *arcn;
-       int is_app;
-#endif
+wr_archive(ARCHD *arcn, int is_app)
 {
-       register int res;
-       register int hlk;
-       register int wr_one;
+       int res;
+       int hlk;
+       int wr_one;
        off_t cnt;
-       int (*wrf)();
+       int (*wrf)(ARCHD *);
        int fd = -1;
        time_t now;
 
@@ -398,11 +398,22 @@ wr_archive(arcn, is_app)
        if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
                return;
 
+       /*
+        * if this is not append, and there are no files, we do not write a 
+        * trailer
+        */
+       wr_one = is_app;
+
        /*
         * start up the file traversal code and format specific write
         */
-       if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
+       if (ftree_start() < 0) {
+               if (is_app)
+                       goto trailer;
                return;
+       } else if (((*frmt->st_wr)() < 0))
+               return;
+
        wrf = frmt->wr;
 
        /*
@@ -412,11 +423,6 @@ wr_archive(arcn, is_app)
        if (iflag && (name_start() < 0))
                return;
 
-       /*
-        * if this not append, and there are no files, we do no write a trailer
-        */
-       wr_one = is_app;
-
        now = time(NULL);
 
        /*
@@ -436,8 +442,10 @@ wr_archive(arcn, is_app)
                         */
                        if ((res = chk_ftime(arcn)) < 0)
                                break;
-                       if (res > 0)
+                       if (res > 0) {
+                               ftree_skipped_newer(arcn);
                                continue;
+                       }
                }
 
                /*
@@ -480,7 +488,7 @@ wr_archive(arcn, is_app)
                if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
                        /*
                         * unable to obtain the crc we need, close the file,
-                        * purge link table entry 
+                        * purge link table entry
                         */
                        rdfile_close(arcn, &fd);
                        purg_lnk(arcn);
@@ -491,7 +499,7 @@ wr_archive(arcn, is_app)
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -507,7 +515,7 @@ wr_archive(arcn, is_app)
                }
                wr_one = 1;
                if (res > 0) {
-                       /* 
+                       /*
                         * format write says no file data needs to be stored
                         * so we are done messing with this file
                         */
@@ -544,8 +552,9 @@ wr_archive(arcn, is_app)
                        break;
        }
 
+trailer:
        /*
-        * tell format to write trailer; pad to block boundry; reset directory
+        * tell format to write trailer; pad to block boundary; reset directory
         * mode/access times, and check if all patterns supplied by the user
         * were matched. block off signals to avoid chance for multiple entry
         * into the cleanup code
@@ -570,7 +579,7 @@ wr_archive(arcn, is_app)
  *     is called to add the new members.
  *     PAX IMPLEMENTATION DETAIL NOTE:
  *     -u is implemented by adding the new members to the end of the archive.
- *     Care is taken so that these do not end up as links to the older 
+ *     Care is taken so that these do not end up as links to the older
  *     version of the same file already stored in the archive. It is expected
  *     when extraction occurs these newer versions will over-write the older
  *     ones stored "earlier" in the archive (this may be a bad assumption as
@@ -583,16 +592,11 @@ wr_archive(arcn, is_app)
  *     over write existing files that it creates.
  */
 
-#ifdef __STDC__
 void
 append(void)
-#else
-void
-append()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        FSUB *orgfrmt;
        int udev;
@@ -603,7 +607,7 @@ append()
 
        /*
         * Do not allow an append operation if the actual archive is of a
-        * different format than the user specified foramt.
+        * different format than the user specified format.
         */
        if (get_arc() < 0)
                return;
@@ -699,7 +703,7 @@ append()
        lnk_end();
 
        /*
-        * try to postion for write, if this fails quit. if any error occurs,
+        * try to position for write, if this fails quit. if any error occurs,
         * we will refuse to write
         */
        if (appnd_start(tlen) < 0)
@@ -712,7 +716,7 @@ append()
                (void)fputs("done.\n", listf);
                vfpart = 0;
        }
-       
+
        /*
         * go to the writing phase to add the new members
         */
@@ -724,13 +728,8 @@ append()
  *     write a new archive
  */
 
-#ifdef __STDC__
 void
 archive(void)
-#else
-void
-archive()
-#endif
 {
        ARCHD archd;
 
@@ -755,20 +754,15 @@ archive()
  *     (except the files are forced to be under the destination directory).
  */
 
-#ifdef __STDC__
 void
 copy(void)
-#else
-void
-copy()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
-       register int fddest;
-       register char *dest_pt;
-       register int dlen;
-       register int drem;
+       ARCHD *arcn;
+       int res;
+       int fddest;
+       char *dest_pt;
+       int dlen;
+       int drem;
        int fdsrc = -1;
        struct stat sb;
        ARCHD archd;
@@ -779,13 +773,18 @@ copy()
         * set up the destination dir path and make sure it is a directory. We
         * make sure we have a trailing / on the destination
         */
-       dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
+       dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
+       if (dlen >= sizeof(dirbuf) ||
+           (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
+               paxwarn(1, "directory name is too long %s", dirptr);
+               return;
+       }
        dest_pt = dirbuf + dlen;
        if (*(dest_pt-1) != '/') {
                *dest_pt++ = '/';
+               *dest_pt = '\0';
                ++dlen;
        }
-       *dest_pt = '\0';
        drem = PAXPATHLEN - dlen;
 
        if (stat(dirptr, &sb) < 0) {
@@ -800,7 +799,7 @@ copy()
 
        /*
         * start up the hard link table; file traversal routines and the
-        * modification time and access mode database 
+        * modification time and access mode database
         */
        if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
                return;
@@ -843,17 +842,12 @@ copy()
                        /*
                         * create the destination name
                         */
-                       if (*(arcn->name) == '/')
-                               res = 1;
-                       else
-                               res = 0;
-                       if ((arcn->nlen - res) > drem) {
+                       if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
+                           drem + 1) > drem) {
                                paxwarn(1, "Destination pathname too long %s",
                                        arcn->name);
                                continue;
                        }
-                       (void)strncpy(dest_pt, arcn->name + res, drem);
-                       dirbuf[PAXPATHLEN] = '\0';
 
                        /*
                         * if existing file is same age or newer skip
@@ -861,10 +855,11 @@ copy()
                        res = lstat(dirbuf, &sb);
                        *dest_pt = '\0';
 
-                       if (res == 0) {
+                       if (res == 0) {
+                               ftree_skipped_newer(arcn);
                                if (uflag && Dflag) {
                                        if ((arcn->sb.st_mtime<=sb.st_mtime) &&
-                                           (arcn->sb.st_ctime<=sb.st_ctime))
+                                           (arcn->sb.st_ctime<=sb.st_ctime))
                                                continue;
                                } else if (Dflag) {
                                        if (arcn->sb.st_ctime <= sb.st_ctime)
@@ -891,7 +886,7 @@ copy()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -907,7 +902,7 @@ copy()
                }
 
                if (vflag) {
-                       (void)fputs(arcn->name, listf);
+                       (void)safe_print(arcn->name, listf);
                        vfpart = 1;
                }
                ++flcnt;
@@ -1007,21 +1002,15 @@ copy()
  *     the specs for rd_wrbuf() for more details)
  */
 
-#ifdef __STDC__
-static int
-next_head(register ARCHD *arcn)
-#else
 static int
-next_head(arcn)
-       register ARCHD *arcn;
-#endif
+next_head(ARCHD *arcn)
 {
-       register int ret;
-       register char *hdend;
-       register int res;
-       register int shftsz;
-       register int hsz;
-       register int in_resync = 0;     /* set when we are in resync mode */
+       int ret;
+       char *hdend;
+       int res;
+       int shftsz;
+       int hsz;
+       int in_resync = 0;              /* set when we are in resync mode */
        int cnt = 0;                    /* counter for trailer function */
        int first = 1;                  /* on 1st read, EOF isn't premature. */
 
@@ -1032,7 +1021,7 @@ next_head(arcn)
        res = hsz = frmt->hsz;
        hdend = hdbuf;
        shftsz = hsz - 1;
-       for(;;) {
+       for (;;) {
                /*
                 * keep looping until we get a contiguous FULL buffer
                 * (frmt->hsz is the proper size)
@@ -1096,7 +1085,7 @@ next_head(arcn)
                        /*
                         * this format has trailers outside of valid headers
                         */
-                       if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
+                       if ((ret = (*frmt->trail)(arcn,hdbuf,in_resync,&cnt)) == 0){
                                /*
                                 * valid trailer found, drain input as required
                                 */
@@ -1143,7 +1132,7 @@ next_head(arcn)
         * the header. NOTE: the parameters are different than trailer routines
         * which encode trailers outside of the header!
         */
-       if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
+       if (frmt->inhead && ((*frmt->trail)(arcn,NULL,0,NULL) == 0)) {
                /*
                 * valid trailer found, drain input as required
                 */
@@ -1165,18 +1154,13 @@ next_head(arcn)
  *     0 if archive found -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_arc(void)
-#else
-static int
-get_arc()
-#endif
 {
-       register int i;
-       register int hdsz = 0;
-       register int res;
-       register int minhd = BLKMULT;
+       int i;
+       int hdsz = 0;
+       int res;
+       int minhd = BLKMULT;
        char *hdend;
        int notice = 0;
 
@@ -1193,7 +1177,7 @@ get_arc()
        res = BLKMULT;
        hdsz = 0;
        hdend = hdbuf;
-       for(;;) {
+       for (;;) {
                for (;;) {
                        /*
                         * fill the buffer with at least the smallest header
@@ -1239,7 +1223,7 @@ get_arc()
                        if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
                                continue;
                        frmt = &(fsub[ford[i]]);
-                       /* 
+                       /*
                         * yuck, to avoid slow special case code in the extract
                         * routines, just push this header back as if it was
                         * not seen. We have left extra space at start of the