aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-07-22 11:34:56 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-07-22 12:55:37 +0300
commit4c7d4359d2dc58126e4e7c6e3dd7cc196322ef28 (patch)
treecfb147da59dd1e5cdfac7eb5638f5ce28ec2675e
parentf40dd3ef902337afd9c5ccc6d69538e155ea26e7 (diff)
downloadcpio-4c7d4359d2dc58126e4e7c6e3dd7cc196322ef28.tar.gz
cpio-4c7d4359d2dc58126e4e7c6e3dd7cc196322ef28.tar.bz2
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.
-rw-r--r--doc/cpio.texi32
-rw-r--r--src/copyin.c2
-rw-r--r--src/copyout.c2
-rw-r--r--src/copypass.c2
-rw-r--r--src/extern.h2
-rw-r--r--src/global.c2
-rw-r--r--src/main.c7
-rw-r--r--src/util.c18
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.
342@itemx --make-directories 342@itemx --make-directories
343Create leading directories where needed. 343Create leading directories where needed.
344 344
345@item -D @var{dir}
346@item --directory=@var{dir}
347Change to the directory @var{dir} before starting the operation. This
348can be used, for example, to extract an archive contents in a
349different directory:
350
351@example
352$ cpio -i -D /usr/local < archive
353@end example
354
355@noindent
356or to copy-pass files from one directory to another:
357
358@example
359$ cpio -D /usr/bin -p /usr/local/bin < filelist
360@end example
361
362 The @option{-D} option does not affect file names supplied as
363arguments to another command line options, such as @option{-F}
364or @option{-E}. For example, the following invocation:
365
366@example
367cpio -D /tmp/foo -d -i -F arc
368@end example
369
370@noindent
371instructs @command{cpio} to open the archive file @file{arc} in
372the current working directory, then change to the directory
373@file{/tmp/foo} and extract files to that directory. If
374@file{/tmp/foo} does not exist, it will be created first (the
375@option{-d} option) and then changed to.
376
345@item -E @var{file} 377@item -E @var{file}
346@itemx --pattern-file=@var{file} 378@itemx --pattern-file=@var{file}
347Read additional patterns specifying filenames to extract or list from 379Read additional patterns specifying filenames to extract or list from
diff --git a/src/copyin.c b/src/copyin.c
index 44b694d..d41b17f 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1343,6 +1343,8 @@ process_copy_in ()
1343 } 1343 }
1344 output_is_seekable = true; 1344 output_is_seekable = true;
1345 1345
1346 change_dir ();
1347
1346 /* While there is more input in the collection, process the input. */ 1348 /* While there is more input in the collection, process the input. */
1347 while (!done) 1349 while (!done)
1348 { 1350 {
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 ()
625 output_is_seekable = S_ISREG (file_stat.st_mode); 625 output_is_seekable = S_ISREG (file_stat.st_mode);
626 } 626 }
627 627
628 change_dir ();
629
628 if (append_flag) 630 if (append_flag)
629 { 631 {
630 process_copy_in (); 632 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 ()
75 output_name.ds_string[dirname_len] = '/'; 75 output_name.ds_string[dirname_len] = '/';
76 output_is_seekable = true; 76 output_is_seekable = true;
77 77
78 change_dir ();
79
78 /* Copy files with names read from stdin. */ 80 /* Copy files with names read from stdin. */
79 while (ds_fgetstr (stdin, &input_name, name_end) != NULL) 81 while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
80 { 82 {
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;
97extern char output_is_seekable; 97extern char output_is_seekable;
98extern int (*xstat) (); 98extern int (*xstat) ();
99extern void (*copy_function) (); 99extern void (*copy_function) ();
100extern char *change_directory_option;
100 101
101 102
102/* copyin.c */ 103/* copyin.c */
@@ -200,6 +201,7 @@ void cpio_to_stat (struct stat *st, struct cpio_file_stat *hdr);
200void cpio_safer_name_suffix (char *name, bool link_target, 201void cpio_safer_name_suffix (char *name, bool link_target,
201 bool absolute_names, bool strip_leading_dots); 202 bool absolute_names, bool strip_leading_dots);
202int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir); 203int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir);
204void change_dir (void);
203 205
204/* FIXME: These two defines should be defined in paxutils */ 206/* FIXME: These two defines should be defined in paxutils */
205#define LG_8 3 207#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) ();
193 193
194/* Which copy operation to perform. (-i, -o, -p) */ 194/* Which copy operation to perform. (-i, -o, -p) */
195void (*copy_function) () = 0; 195void (*copy_function) () = 0;
196
197char *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[] = {
108 108
109 {"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0, 109 {"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
110 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 }, 110 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 },
111 {"directory", 'D', N_("DIR"), 0,
112 N_("Change to directory DIR"), GRID+1 },
113
111 {"force-local", FORCE_LOCAL_OPTION, 0, 0, 114 {"force-local", FORCE_LOCAL_OPTION, 0, 0,
112 N_("Archive file is local, even if its name contains colons"), GRID+1 }, 115 N_("Archive file is local, even if its name contains colons"), GRID+1 },
113 {"format", 'H', N_("FORMAT"), 0, 116 {"format", 'H', N_("FORMAT"), 0,
@@ -325,6 +328,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
325 create_dir_flag = true; 328 create_dir_flag = true;
326 break; 329 break;
327 330
331 case 'D':
332 change_directory_option = arg;
333 break;
334
328 case 'f': /* Only copy files not matching patterns. */ 335 case 'f': /* Only copy files not matching patterns. */
329 copy_matching_files = false; 336 copy_matching_files = false;
330 break; 337 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)
1618 return 0; 1618 return 0;
1619} 1619}
1620 1620
1621void
1622change_dir ()
1623{
1624 if (change_directory_option && chdir (change_directory_option))
1625 {
1626 if (errno == ENOENT && create_dir_flag)
1627 {
1628 if (make_path (change_directory_option, -1, -1,
1629 (warn_option & CPIO_WARN_INTERDIR) ?
1630 _("Creating directory `%s'") : NULL))
1631 exit (PAXEXIT_FAILURE);
1632 if (chdir (change_directory_option) == 0)
1633 return;
1634 }
1635 error (PAXEXIT_FAILURE, errno,
1636 _("cannot change to directory `%s'"), change_directory_option);
1637 }
1638}

Return to:

Send suggestions and report system problems to the System administrator.