/* main.c - main program and argument processing for cpio.
Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Phil Nelson <phil@cs.wwu.edu>,
David MacKenzie <djm@gnu.ai.mit.edu>,
and John Oleynick <juo@klinzhai.rutgers.edu>. */
struct option long_opts
[] =
{"block-size", 1, 0, 130},
{"dereference", 0, 0, 'L'},
{"force-local", 0, &f_force_local
, 1},
{"link", 0, &link_flag
, TRUE
},
{"list", 0, &table_flag
, TRUE
},
{"make-directories", 0, &create_dir_flag
, TRUE
},
{"no-preserve-owner", 0, 0, 134},
{"nonmatching", 0, ©_matching_files
, FALSE
},
{"numeric-uid-gid", 0, &numeric_uid
, TRUE
},
{"pass-through", 0, 0, 'p'},
{"pattern-file", 1, 0, 'E'},
{"preserve-modification-time", 0, &retain_time_flag
, TRUE
},
{"rename", 0, &rename_flag
, TRUE
},
{"swap-bytes", 0, 0, 's'},
{"swap-halfwords", 0, 0, 'S'},
{"reset-access-time", 0, &reset_time_flag
, TRUE
},
{"unconditional", 0, &unconditional_flag
, TRUE
},
{"verbose", 0, &verbose_flag
, TRUE
},
{"debug", 0, &debug_flag
, TRUE
},
/* Print usage message and exit with error. */
Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
[-O [[user@]host:]archive] [-F [[user@]host:]archive]\n\
[--file=[[user@]host:]archive] [--format=format] [--message=message]\n\
[--null] [--reset-access-time] [--verbose] [--dot] [--append]\n\
[--block-size=blocks] [--dereference] [--io-size=bytes]\n\
[--force-local] [--help] [--version] < name-list [> archive]\n", program_name
);
%s {-i|--extract} [-bcdfmnrtsuvBSV] [-C bytes] [-E file] [-H format]\n\
[-M message] [-R [user][:.][group]] [-I [[user@]host:]archive]\n\
[-F [[user@]host:]archive] [--file=[[user@]host:]archive]\n\
[--make-directories] [--nonmatching] [--preserve-modification-time]\n\
[--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap] [--dot]\n\
[--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
[--io-size=bytes] [--pattern-file=file] [--format=format]\n\
[--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
[--force-local] [--help] [--version] [pattern...] [< archive]\n",
%s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
[--null] [--reset-access-time] [--make-directories] [--link]\n\
[--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
[--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
[--help] [--version] destination-directory < name-list\n", program_name
);
/* Process the arguments. Set all options and set up the copy pass
directory or the copy in patterns. */
process_args (argc
, argv
)
extern char *version_string
;
void (*copy_in
) (); /* Work around for pcc bug. */
char *input_archive_name
= 0;
char *output_archive_name
= 0;
while ((c
= getopt_long (argc
, argv
,
"0aAbBcC:dfE:F:H:iI:lLmM:noO:prR:sStuvVz",
long_opts
, (int *) 0)) != -1)
case 0: /* A long option that just sets a flag. */
case '0': /* Read null-terminated filenames. */
case 'a': /* Reset access times. */
case 'A': /* Append to the archive. */
case 'b': /* Swap bytes and halfwords. */
swap_halfwords_flag
= TRUE
;
case 'B': /* Set block size to 5120. */
case 130: /* --block-size */
io_block_size
= atoi (optarg
);
error (2, 0, "invalid block size");
case 'c': /* Use the old portable ASCII format. */
if (archive_format
!= arf_unknown
)
archive_format
= arf_newascii
; /* -H newc. */
archive_format
= arf_oldascii
; /* -H odc. */
case 'C': /* Block size. */
io_block_size
= atoi (optarg
);
error (2, 0, "invalid block size");
case 'd': /* Create directories where needed. */
case 'f': /* Only copy files not matching patterns. */
copy_matching_files
= FALSE
;
case 'E': /* Pattern file name. */
pattern_file_name
= optarg
;
case 'F': /* Archive file name. */
case 'H': /* Header format name. */
if (archive_format
!= arf_unknown
)
if (!strcmp (optarg
, "crc") || !strcmp (optarg
, "CRC"))
archive_format
= arf_crcascii
;
else if (!strcmp (optarg
, "newc") || !strcmp (optarg
, "NEWC"))
archive_format
= arf_newascii
;
else if (!strcmp (optarg
, "odc") || !strcmp (optarg
, "ODC"))
archive_format
= arf_oldascii
;
else if (!strcmp (optarg
, "bin") || !strcmp (optarg
, "BIN"))
archive_format
= arf_binary
;
else if (!strcmp (optarg
, "ustar") || !strcmp (optarg
, "USTAR"))
archive_format
= arf_ustar
;
else if (!strcmp (optarg
, "tar") || !strcmp (optarg
, "TAR"))
archive_format
= arf_tar
;
else if (!strcmp (optarg
, "hpodc") || !strcmp (optarg
, "HPODC"))
archive_format
= arf_hpoldascii
;
else if (!strcmp (optarg
, "hpbin") || !strcmp (optarg
, "HPBIN"))
archive_format
= arf_hpbinary
;
invalid archive format `%s'; valid formats are:\n\
crc newc odc bin ustar tar (all-caps also recognized)", optarg
);
case 'i': /* Copy-in mode. */
copy_function
= process_copy_in
;
case 'I': /* Input archive file name. */
input_archive_name
= optarg
;
case 'k': /* Handle corrupted archives. We always handle
corrupted archives, but recognize this
option for compatability. */
case 'l': /* Link files when possible. */
case 'L': /* Dereference symbolic links. */
case 'm': /* Retain previous file modify times. */
case 'M': /* New media message. */
set_new_media_message (optarg
);
case 'n': /* Long list owner and group as numbers. */
case 134: /* --no-preserve-owner */
if (set_owner_flag
|| set_group_flag
)
case 'o': /* Copy-out mode. */
copy_function
= process_copy_out
;
case 'O': /* Output archive file name. */
output_archive_name
= optarg
;
case 'p': /* Copy-pass mode. */
copy_function
= process_copy_pass
;
case 'r': /* Interactively rename. */
case 'R': /* Set the owner. */
e
= parse_user_spec (optarg
, &set_owner
, &set_group
, &u
, &g
);
error (2, 0, "%s: %s", optarg
, e
);
case 's': /* Swap bytes. */
case 'S': /* Swap halfwords. */
swap_halfwords_flag
= TRUE
;
case 't': /* Only print a list. */
case 'u': /* Replace all! Unconditionally! */
unconditional_flag
= TRUE
;
case 'V': /* Print `.' for each file. */
printf ("GNU cpio %s", version_string
);
/* Do error checking and look at other args. */
copy_function
= process_copy_in
;
if ((!table_flag
|| !verbose_flag
) && numeric_uid
)
/* Work around for pcc bug. */
copy_in
= process_copy_in
;
copy_out
= process_copy_out
;
if (copy_function
== copy_in
)
if (link_flag
|| reset_time_flag
|| xstat
!= lstat
|| append_flag
|| (archive_name
&& input_archive_name
))
if (archive_format
== arf_crcascii
)
num_patterns
= argc
- optind
;
save_patterns
= &argv
[optind
];
archive_name
= input_archive_name
;
else if (copy_function
== copy_out
)
if (argc
!= optind
|| create_dir_flag
|| rename_flag
|| table_flag
|| unconditional_flag
|| link_flag
|| retain_time_flag
|| no_chown_flag
|| set_owner_flag
|| set_group_flag
|| swap_bytes_flag
|| swap_halfwords_flag
|| (append_flag
&& !(archive_name
|| output_archive_name
))
|| input_archive_name
|| (archive_name
&& output_archive_name
))
if (archive_format
== arf_unknown
)
archive_format
= arf_binary
;
archive_name
= output_archive_name
;
if (argc
- 1 != optind
|| archive_format
!= arf_unknown
|| swap_bytes_flag
|| swap_halfwords_flag
|| table_flag
|| rename_flag
|| append_flag
)
directory_name
= argv
[optind
];
if (copy_function
!= copy_in
&& copy_function
!= copy_out
)
archive_des
= open_archive (archive_name
);
error (1, errno
, "%s", archive_name
);
/* Prevent SysV non-root users from giving away files inadvertantly.
This happens automatically on BSD, where only root can give
if (set_owner_flag
== FALSE
&& set_group_flag
== FALSE
&& geteuid ())
/* Initialize the input and output buffers to their proper size and
initialize all variables associated with the input and output
/* Make sure buffers can always hold 2 blocks and that they
are big enough to hold 1 tar record (512 bytes) even if it
is not aligned on a block boundary. The extra buffer space
is needed by process_copyin and peek_in_buf to automatically
figure out what kind of archive it is reading. */
if (io_block_size
>= 512)
buf_size
= 2 * io_block_size
;
input_buffer
= (char *) xmalloc (buf_size
);
/* Leave space for an `int' sentinel for `empty_output_buffer',
in case we ever put back sparseness checking. */
output_buffer
= (char *) xmalloc (buf_size
+ sizeof (int) * 2);
out_buff
= output_buffer
;
/* Clear the block of zeros. */
_fmode
= O_BINARY
; /* Put stdin and stdout in binary mode. */
#ifdef __EMX__ /* gcc on OS/2. */
_response (&argc
, &argv
);
_wildcard (&argc
, &argv
);
process_args (argc
, argv
);
if (archive_des
>= 0 && rmtclose (archive_des
) == -1)
error (1, errno
, "error closing archive");