diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-07-22 11:34:56 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-07-22 12:55:37 +0300 |
commit | 4c7d4359d2dc58126e4e7c6e3dd7cc196322ef28 (patch) | |
tree | cfb147da59dd1e5cdfac7eb5638f5ce28ec2675e | |
parent | f40dd3ef902337afd9c5ccc6d69538e155ea26e7 (diff) | |
download | cpio-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.texi | 32 | ||||
-rw-r--r-- | src/copyin.c | 2 | ||||
-rw-r--r-- | src/copyout.c | 2 | ||||
-rw-r--r-- | src/copypass.c | 2 | ||||
-rw-r--r-- | src/extern.h | 2 | ||||
-rw-r--r-- | src/global.c | 2 | ||||
-rw-r--r-- | src/main.c | 7 | ||||
-rw-r--r-- | 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. | |||
342 | @itemx --make-directories | 342 | @itemx --make-directories |
343 | Create leading directories where needed. | 343 | Create leading directories where needed. |
344 | 344 | ||
345 | @item -D @var{dir} | ||
346 | @item --directory=@var{dir} | ||
347 | Change to the directory @var{dir} before starting the operation. This | ||
348 | can be used, for example, to extract an archive contents in a | ||
349 | different directory: | ||
350 | |||
351 | @example | ||
352 | $ cpio -i -D /usr/local < archive | ||
353 | @end example | ||
354 | |||
355 | @noindent | ||
356 | or 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 | ||
363 | arguments to another command line options, such as @option{-F} | ||
364 | or @option{-E}. For example, the following invocation: | ||
365 | |||
366 | @example | ||
367 | cpio -D /tmp/foo -d -i -F arc | ||
368 | @end example | ||
369 | |||
370 | @noindent | ||
371 | instructs @command{cpio} to open the archive file @file{arc} in | ||
372 | the 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} |
347 | Read additional patterns specifying filenames to extract or list from | 379 | Read 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; | |||
97 | extern char output_is_seekable; | 97 | extern char output_is_seekable; |
98 | extern int (*xstat) (); | 98 | extern int (*xstat) (); |
99 | extern void (*copy_function) (); | 99 | extern void (*copy_function) (); |
100 | extern 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); | |||
200 | void cpio_safer_name_suffix (char *name, bool link_target, | 201 | void 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); |
202 | int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir); | 203 | int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir); |
204 | void 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) */ |
195 | void (*copy_function) () = 0; | 195 | void (*copy_function) () = 0; |
196 | |||
197 | char *change_directory_option; | ||
@@ -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; |
@@ -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 | ||
1621 | void | ||
1622 | change_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 | } | ||