bug-cpio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-cpio] Re: Destination directory patch


From: Sergey Poznyakoff
Subject: [Bug-cpio] Re: Destination directory patch
Date: Thu, 22 Jul 2010 11:43:40 +0300

P J P <address@hidden> ha escrit:

> Please have a look at the patch below;

Thanks. It unnecessarily complicates the operation by allocating new
filename for each archive member. Besides, it provides the -D option
only for copy-in, whereas it can be useful in other modes too.

I have implemented it another way. Attached is a patch.

Regards,
Sergey

>From cbc3c156df244df3985374da4cb1b7c83f163d6d Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <address@hidden>
Date: Thu, 22 Jul 2010 11:34:56 +0300
Subject: [PATCH] Provide a tar-like --directory (-D) option.

* src/copyin.c (process_copy_in): Call change_dir.
* src/copyout.c (process_copy_out): Likewise.
* src/copypass.c (process_copy_pass): Likewise.
* src/extern.h (change_directory_option): New extern.
(change_dir): New proto.
* src/global.c (change_directory_option): New global.
* src/main.c (options): New option --directory.
(parse_opt): Handle the --directory option.
* src/util.c (change_dir): New proto.

* doc/cpio.texi: Document the --directory option.
---
 doc/cpio.texi  |   32 ++++++++++++++++++++++++++++++++
 src/copyin.c   |    2 ++
 src/copyout.c  |    2 ++
 src/copypass.c |    2 ++
 src/extern.h   |    2 ++
 src/global.c   |    2 ++
 src/main.c     |    7 +++++++
 src/util.c     |   18 ++++++++++++++++++
 8 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/doc/cpio.texi b/doc/cpio.texi
index 1af808a..bcece3c 100644
--- a/doc/cpio.texi
+++ b/doc/cpio.texi
@@ -342,6 +342,38 @@ Set the I/O block size to @var{io-size} bytes.
 @itemx --make-directories
 Create leading directories where needed.
 
address@hidden -D @var{dir}
address@hidden address@hidden
+Change to the directory @var{dir} before starting the operation.  This
+can be used, for example, to extract an archive contents in a
+different directory:
+
address@hidden
+$ cpio -i -D /usr/local < archive
address@hidden example
+
address@hidden
+or to copy-pass files from one directory to another:
+
address@hidden
+$ cpio -D /usr/bin -p /usr/local/bin < filelist
address@hidden example
+
+  The @option{-D} option does not affect file names supplied as
+arguments to another command line options, such as @option{-F}
+or @option{-E}.  For example, the following invocation:
+
address@hidden
+cpio -D /tmp/foo -d -i -F arc
address@hidden example
+
address@hidden
+instructs @command{cpio} to open the archive file @file{arc} in
+the current working directory, then change to the directory
address@hidden/tmp/foo} and extract files to that directory.  If
address@hidden/tmp/foo} does not exist, it will be created first (the
address@hidden option) and then changed to.
+
 @item -E @var{file}
 @itemx address@hidden
 Read additional patterns specifying filenames to extract or list from
diff --git a/src/copyin.c b/src/copyin.c
index ac921e1..e1be4e2 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1338,6 +1338,8 @@ process_copy_in ()
     }
   output_is_seekable = true;
 
+  change_dir ();
+  
   /* While there is more input in the collection, process the input.  */
   while (!done)
     {
diff --git a/src/copyout.c b/src/copyout.c
index 7e6b624..e9849ff 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -625,6 +625,8 @@ process_copy_out ()
       output_is_seekable = S_ISREG (file_stat.st_mode);
     }
 
+  change_dir ();
+  
   if (append_flag)
     {
       process_copy_in ();
diff --git a/src/copypass.c b/src/copypass.c
index d249a31..1fcc8b3 100644
--- a/src/copypass.c
+++ b/src/copypass.c
@@ -75,6 +75,8 @@ process_copy_pass ()
   output_name.ds_string[dirname_len] = '/';
   output_is_seekable = true;
 
+  change_dir ();
+  
   /* Copy files with names read from stdin.  */
   while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
     {
diff --git a/src/extern.h b/src/extern.h
index 4f94d40..c25a6ef 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -97,6 +97,7 @@ extern char input_is_seekable;
 extern char output_is_seekable;
 extern int (*xstat) ();
 extern void (*copy_function) ();
+extern char *change_directory_option;
 
 
 /* copyin.c */
@@ -200,6 +201,7 @@ void cpio_to_stat (struct stat *st, struct cpio_file_stat 
*hdr);
 void cpio_safer_name_suffix (char *name, bool link_target,
                             bool absolute_names, bool strip_leading_dots);
 int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir);
+void change_dir (void);
 
 /* FIXME: These two defines should be defined in paxutils */
 #define LG_8  3
diff --git a/src/global.c b/src/global.c
index cff9720..29e7afc 100644
--- a/src/global.c
+++ b/src/global.c
@@ -193,3 +193,5 @@ int (*xstat) ();
 
 /* Which copy operation to perform. (-i, -o, -p) */
 void (*copy_function) () = 0;
+
+char *change_directory_option;
diff --git a/src/main.c b/src/main.c
index ba1b969..4c1c033 100644
--- a/src/main.c
+++ b/src/main.c
@@ -108,6 +108,9 @@ static struct argp_option options[] = {
 
   {"file", 'F', N_("address@hidden:]FILE-NAME"), 0,
    N_("Use this FILE-NAME instead of standard input or output. Optional USER 
and HOST specify the user and host names in case of a remote archive"), GRID+1 
},
+  {"directory", 'D', N_("DIR"), 0,
+   N_("Change to directory DIR"), GRID+1 },
+  
   {"force-local", FORCE_LOCAL_OPTION, 0, 0,
    N_("Archive file is local, even if its name contains colons"), GRID+1 },
   {"format", 'H', N_("FORMAT"), 0,
@@ -325,6 +328,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       create_dir_flag = true;
       break;
 
+    case 'D':
+      change_directory_option = arg;
+      break;
+      
     case 'f':          /* Only copy files not matching patterns.  */
       copy_matching_files = false;
       break;
diff --git a/src/util.c b/src/util.c
index 00953d5..0faccbc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1618,3 +1618,21 @@ cpio_create_dir (struct cpio_file_stat *file_hdr, int 
existing_dir)
   return 0;
 }
 
+void
+change_dir ()
+{
+  if (change_directory_option && chdir (change_directory_option))
+    {
+      if (errno == ENOENT && create_dir_flag)
+       {
+         if (make_path (change_directory_option, -1, -1,
+                        (warn_option & CPIO_WARN_INTERDIR) ?
+                        _("Creating directory `%s'") : NULL))
+           exit (PAXEXIT_FAILURE);
+         if (chdir (change_directory_option) == 0)
+           return;
+       }
+      error (PAXEXIT_FAILURE, errno,
+            _("cannot change to directory `%s'"), change_directory_option);
+    }
+}
-- 
1.6.0.3


reply via email to

[Prev in Thread] Current Thread [Next in Thread]