bin/77666: Implement GNU tar's --strip-components option to bsdtar.

Sangwoo Shim ssw at neo.redjade.org
Fri Feb 18 08:10:30 GMT 2005


>Number:         77666
>Category:       bin
>Synopsis:       Implement GNU tar's --strip-components option to bsdtar.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Feb 18 08:10:29 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Sangwoo Shim
>Release:        6-CURRENT (of Feb 10)
>Organization:
Seoul Natl' Univ.
>Environment:
FreeBSD swoo.org 6.0-CURRENT FreeBSD 6.0-CURRENT #1: Thu Feb 10 18:05:38 KST 2005     root at swoo.org:/usr/obj/usr/src/sys/SWOO  amd64
>Description:
      Implemented GNU tar's --strip-components option to bsdtar.
This is handy in some cases. The patch can be downloaded at http://swoo.org/~sangwoo/bsdtar.diff
>How-To-Repeat:
      
>Fix:
Index: bsdtar.c
===================================================================
--- bsdtar.c    (revision 2)
+++ bsdtar.c    (working copy)
@@ -89,7 +89,7 @@
  * non-option.  Otherwise, GNU getopt() permutes the arguments and
  * screws up -C processing.
  */
-static const char *tar_opts = "+Bb:C:cF:f:HhI:jkLlmnOoPprtT:UuvW:wX:xyZz";
+static const char *tar_opts = "+Bb:C:cF:f:HhI:jkLlmnOoPprs:tT:UuvW:wX:xyZz";

 /*
  * Most of these long options are deliberately not documented.  They
@@ -161,6 +161,7 @@
        { "preserve-permissions", no_argument,     NULL, 'p' },
        { "read-full-blocks",   no_argument,       NULL, 'B' },
        { "same-permissions",   no_argument,       NULL, 'p' },
+       { "strip-components",   required_argument, NULL, 's' },
        { "to-stdout",          no_argument,       NULL, 'O' },
        { "totals",             no_argument,       NULL, OPTION_TOTALS },
        { "unlink",             no_argument,       NULL, 'U' },
@@ -188,6 +189,7 @@
        bsdtar = &bsdtar_storage;
        memset(bsdtar, 0, sizeof(*bsdtar));
        bsdtar->fd = -1; /* Mark as "unused" */
+       bsdtar->strip_components = 0; /* Reasonable default */
        option_o = 0;

        if (setlocale(LC_ALL, "") == NULL)
@@ -369,6 +371,9 @@
                case 'r': /* SUSv2 */
                        set_mode(bsdtar, opt);
                        break;
+               case 's':
+                       bsdtar->strip_components = atoi(optarg);
+                       break;
                case 'T': /* GNU tar */
                        bsdtar->names_from_file = optarg;
                        break;
Index: bsdtar.h
===================================================================
--- bsdtar.h    (revision 2)
+++ bsdtar.h    (working copy)
@@ -51,6 +51,7 @@
        int               bytes_per_block; /* -b block_size */
        int               verbose;   /* -v */
        int               extract_flags; /* Flags for extract operation */
+       int               strip_components; /* -s strip_components */
        char              mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */
        char              symlink_mode; /* H or L, per BSD conventions */
        char              create_compression; /* j, y, or z */
Index: read.c
===================================================================
--- read.c      (revision 2)
+++ read.c      (working copy)
@@ -313,8 +313,12 @@
        char *p;
        int r;

-       /* -P option forces us to just accept all pathnames. */
-       if (bsdtar->option_absolute_paths)
+       /*
+        * -P option forces us to just accept all pathnames. But, if -s option
+        * with larger than 0 option argument is specified, strip leading
+        * pathnames appropriately following GNU tar's behavior.
+        */
+       if (bsdtar->option_absolute_paths && !bsdtar->strip_components)
                return (0);

        /* Strip leading '/'. */
@@ -331,6 +335,26 @@
                archive_entry_set_pathname(entry, name);
        }

+       /* Strip leading components. (-s option) */
+       r = bsdtar->strip_components;
+       if (r > 0) {
+               pn = name;
+               while (r > 0) {
+                       if (*pn == '/') {
+                               r--;
+                               name = pn + 1;
+                       }
+                       pn++;
+                       if (*pn == '\0') {
+                               /* Overstripped, skip this entry. */
+                               bsdtar_warnc(bsdtar, 0,
+                                   "Strip request exceeded the path depth.");
+                               return (1);
+                       }
+               }
+               archive_entry_set_pathname(entry, name);
+       }
+
        /* Reject any archive entry with '..' as a path element. */
        pn = name;
        while (pn != NULL && pn[0] != '\0') {
Index: bsdtar.1
===================================================================
--- bsdtar.1    (revision 2)
+++ bsdtar.1    (working copy)
@@ -284,6 +284,12 @@
 is being run by root, the default is to restore the owner unless the
 .Fl o
 option is also specified.
+.It Fl s Ar number
+(x mode only)
+Strip given number of leading components from the pathnames. This option is
+behaves like
+.Fl --strip-components
+option of GNU tar.
 .It Fl T Ar filename
 (c mode only)
 Read names to be archived from

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list