#include <fnmatch.h>
#include <getopt.h>
-#ifdef CONFIG_FEATURE_TAR_CREATE
+#if ENABLE_FEATURE_TAR_CREATE
/* Tar file constants */
return TRUE;
}
-# ifdef CONFIG_FEATURE_TAR_FROM
+# if ENABLE_FEATURE_TAR_FROM
static int exclude_file(const llist_t *excluded_files, const char *file)
{
while (excluded_files) {
const llist_t *exclude, const int gzip);
#endif /* tar_create */
-#ifdef CONFIG_FEATURE_TAR_FROM
+#if ENABLE_FEATURE_TAR_FROM
static llist_t *append_file_list_to_list(llist_t *list)
{
FILE *src_stream;
#define append_file_list_to_list(x) 0
#endif
-#ifdef CONFIG_FEATURE_TAR_COMPRESS
+#if ENABLE_FEATURE_TAR_COMPRESS
static char get_header_tar_Z(archive_handle_t *archive_handle)
{
/* Can't lseek over pipes */
#define get_header_tar_Z 0
#endif
-#define CTX_TEST (1 << 0)
-#define CTX_EXTRACT (1 << 1)
-#define TAR_OPT_BASEDIR (1 << 2)
-#define TAR_OPT_TARNAME (1 << 3)
-#define TAR_OPT_2STDOUT (1 << 4)
-#define TAR_OPT_P (1 << 5)
-#define TAR_OPT_VERBOSE (1 << 6)
-#define TAR_OPT_KEEP_OLD (1 << 7)
-
-#define TAR_OPT_AFTER_START 8
-
-#define CTX_CREATE (1 << (TAR_OPT_AFTER_START))
-#define TAR_OPT_DEREFERENCE (1 << (TAR_OPT_AFTER_START + 1))
-#ifdef CONFIG_FEATURE_TAR_CREATE
-# define TAR_OPT_STR_CREATE "ch"
-# define TAR_OPT_AFTER_CREATE TAR_OPT_AFTER_START + 2
-#else
-# define TAR_OPT_STR_CREATE ""
-# define TAR_OPT_AFTER_CREATE TAR_OPT_AFTER_START
-#endif
-
-#define TAR_OPT_BZIP2 (1 << (TAR_OPT_AFTER_CREATE))
-#ifdef CONFIG_FEATURE_TAR_BZIP2
-# define TAR_OPT_STR_BZIP2 "j"
-# define TAR_OPT_AFTER_BZIP2 TAR_OPT_AFTER_CREATE + 1
-#else
-# define TAR_OPT_STR_BZIP2 ""
-# define TAR_OPT_AFTER_BZIP2 TAR_OPT_AFTER_CREATE
-#endif
-
-#define TAR_OPT_LZMA (1 << (TAR_OPT_AFTER_BZIP2))
-#ifdef CONFIG_FEATURE_TAR_LZMA
-# define TAR_OPT_STR_LZMA "a"
-# define TAR_OPT_AFTER_LZMA TAR_OPT_AFTER_BZIP2 + 1
-#else
-# define TAR_OPT_STR_LZMA ""
-# define TAR_OPT_AFTER_LZMA TAR_OPT_AFTER_BZIP2
-#endif
-
-#define TAR_OPT_INCLUDE_FROM (1 << (TAR_OPT_AFTER_LZMA))
-#define TAR_OPT_EXCLUDE_FROM (1 << (TAR_OPT_AFTER_LZMA + 1))
-#ifdef CONFIG_FEATURE_TAR_FROM
-# define TAR_OPT_STR_FROM "T:X:"
-# define TAR_OPT_AFTER_FROM TAR_OPT_AFTER_LZMA + 2
-#else
-# define TAR_OPT_STR_FROM ""
-# define TAR_OPT_AFTER_FROM TAR_OPT_AFTER_LZMA
-#endif
-
-#define TAR_OPT_GZIP (1 << (TAR_OPT_AFTER_FROM))
-#ifdef CONFIG_FEATURE_TAR_GZIP
-# define TAR_OPT_STR_GZIP "z"
-# define TAR_OPT_AFTER_GZIP TAR_OPT_AFTER_FROM + 1
-#else
-# define TAR_OPT_STR_GZIP ""
-# define TAR_OPT_AFTER_GZIP TAR_OPT_AFTER_FROM
-#endif
-
-#define TAR_OPT_UNCOMPRESS (1 << (TAR_OPT_AFTER_GZIP))
-#ifdef CONFIG_FEATURE_TAR_COMPRESS
-# define TAR_OPT_STR_COMPRESS "Z"
-# define TAR_OPT_AFTER_COMPRESS TAR_OPT_AFTER_GZIP + 1
-#else
-# define TAR_OPT_STR_COMPRESS ""
-# define TAR_OPT_AFTER_COMPRESS TAR_OPT_AFTER_GZIP
-#endif
-
-#define TAR_OPT_NOPRESERVE_OWN (1 << (TAR_OPT_AFTER_COMPRESS))
-#define TAR_OPT_NOPRESERVE_PERM (1 << (TAR_OPT_AFTER_COMPRESS + 1))
-#define TAR_OPT_STR_NOPRESERVE "\203\213"
-#define TAR_OPT_AFTER_NOPRESERVE TAR_OPT_AFTER_COMPRESS + 2
-
-static const char tar_options[] = "txC:f:Opvk" \
- TAR_OPT_STR_CREATE \
- TAR_OPT_STR_BZIP2 \
- TAR_OPT_STR_LZMA \
- TAR_OPT_STR_FROM \
- TAR_OPT_STR_GZIP \
- TAR_OPT_STR_COMPRESS \
- TAR_OPT_STR_NOPRESERVE;
-
-#ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
+enum {
+ OPTBIT_KEEP_OLD = 7,
+ USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,)
+ USE_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,)
+ USE_FEATURE_TAR_BZIP2( OPTBIT_BZIP2 ,)
+ USE_FEATURE_TAR_LZMA( OPTBIT_LZMA ,)
+ USE_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
+ USE_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
+ USE_FEATURE_TAR_GZIP( OPTBIT_GZIP ,)
+ USE_FEATURE_TAR_COMPRESS(OPTBIT_COMPRESS ,)
+ OPTBIT_NOPRESERVE_OWN,
+ OPTBIT_NOPRESERVE_PERM,
+ OPT_TEST = 1 << 0, // t
+ OPT_EXTRACT = 1 << 1, // x
+ OPT_BASEDIR = 1 << 2, // C
+ OPT_TARNAME = 1 << 3, // f
+ OPT_2STDOUT = 1 << 4, // O
+ OPT_P = 1 << 5, // p
+ OPT_VERBOSE = 1 << 6, // v
+ OPT_KEEP_OLD = 1 << 7, // k
+ OPT_CREATE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_CREATE )) + 0, // c
+ OPT_DEREFERENCE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_DEREFERENCE )) + 0, // h
+ OPT_BZIP2 = USE_FEATURE_TAR_BZIP2( (1<<OPTBIT_BZIP2 )) + 0, // j
+ OPT_LZMA = USE_FEATURE_TAR_LZMA( (1<<OPTBIT_LZMA )) + 0, // a
+ OPT_INCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_INCLUDE_FROM)) + 0, // T
+ OPT_EXCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_EXCLUDE_FROM)) + 0, // X
+ OPT_GZIP = USE_FEATURE_TAR_GZIP( (1<<OPTBIT_GZIP )) + 0, // z
+ OPT_COMPRESS = USE_FEATURE_TAR_COMPRESS((1<<OPTBIT_COMPRESS )) + 0, // Z
+ OPT_NOPRESERVE_OWN = 1 << OPTBIT_NOPRESERVE_OWN , // no-same-owner
+ OPT_NOPRESERVE_PERM = 1 << OPTBIT_NOPRESERVE_PERM, // no-same-permissions
+};
+#if ENABLE_FEATURE_TAR_LONG_OPTIONS
static const struct option tar_long_options[] = {
{ "list", 0, NULL, 't' },
{ "extract", 0, NULL, 'x' },
{ "same-permissions", 0, NULL, 'p' },
{ "verbose", 0, NULL, 'v' },
{ "keep-old", 0, NULL, 'k' },
- { "no-same-owner", 0, NULL, '\203' },
- { "no-same-permissions",0, NULL, '\213' },
-# ifdef CONFIG_FEATURE_TAR_CREATE
+# if ENABLE_FEATURE_TAR_CREATE
{ "create", 0, NULL, 'c' },
{ "dereference", 0, NULL, 'h' },
# endif
-# ifdef CONFIG_FEATURE_TAR_BZIP2
+# if ENABLE_FEATURE_TAR_BZIP2
{ "bzip2", 0, NULL, 'j' },
# endif
-# ifdef CONFIG_FEATURE_TAR_LZMA
+# if ENABLE_FEATURE_TAR_LZMA
{ "lzma", 0, NULL, 'a' },
# endif
-# ifdef CONFIG_FEATURE_TAR_FROM
+# if ENABLE_FEATURE_TAR_FROM
{ "files-from", 1, NULL, 'T' },
{ "exclude-from", 1, NULL, 'X' },
- { "exclude", 1, NULL, '\n' },
+ { "exclude", 1, NULL, 0xfd },
# endif
-# ifdef CONFIG_FEATURE_TAR_GZIP
+# if ENABLE_FEATURE_TAR_GZIP
{ "gzip", 0, NULL, 'z' },
# endif
-# ifdef CONFIG_FEATURE_TAR_COMPRESS
+# if ENABLE_FEATURE_TAR_COMPRESS
{ "compress", 0, NULL, 'Z' },
# endif
+ { "no-same-owner", 0, NULL, 0xfe },
+ { "no-same-permissions",0, NULL, 0xff },
{ 0, 0, 0, 0 }
};
#else
/* Initialise default values */
tar_handle = init_handle();
- tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
+ tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS
+ | ARCHIVE_PRESERVE_DATE
+ | ARCHIVE_EXTRACT_UNCONDITIONAL;
/* Prepend '-' to the first argument if required */
- opt_complementary = ENABLE_FEATURE_TAR_CREATE ?
- "--:X::T::\n::c:t:x:?:c--tx:t--cx:x--ct" :
- "--:X::T::\n::t:x:?:t--x:x--t";
+ opt_complementary = "--:" // first arg is options
+ "?:" // bail out with usage instead of error return
+ "X::T::" // cumulative lists
+ "\xfd::" // cumulative lists for --exclude
+ USE_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
+ USE_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
+ SKIP_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
if (ENABLE_FEATURE_TAR_LONG_OPTIONS)
applet_long_options = tar_long_options;
- opt = getopt32(argc, argv, tar_options,
- &base_dir, /* Change to dir <optarg> */
- &tar_filename /* archive filename */
-#ifdef CONFIG_FEATURE_TAR_FROM
- , &(tar_handle->accept),
- &(tar_handle->reject),
- &excludes
-#endif
- );
-
- if (opt & CTX_TEST) {
+ opt = getopt32(argc, argv,
+ "txC:f:Opvk"
+ USE_FEATURE_TAR_CREATE( "ch" )
+ USE_FEATURE_TAR_BZIP2( "j" )
+ USE_FEATURE_TAR_LZMA( "a" )
+ USE_FEATURE_TAR_FROM( "T:X:")
+ USE_FEATURE_TAR_GZIP( "z" )
+ USE_FEATURE_TAR_COMPRESS("Z" )
+ ,
+ &base_dir, // -C dir
+ &tar_filename, // -f filename
+ USE_FEATURE_TAR_FROM(&(tar_handle->accept),) // T
+ USE_FEATURE_TAR_FROM(&(tar_handle->reject),) // X
+ USE_FEATURE_TAR_FROM(&excludes ) // --exclude
+ );
+
+ if (opt & OPT_TEST) {
if (tar_handle->action_header == header_list
|| tar_handle->action_header == header_verbose_list
) {
} else
tar_handle->action_header = header_list;
}
- if ((opt & CTX_EXTRACT) && tar_handle->action_data != data_extract_to_stdout)
+ if ((opt & OPT_EXTRACT) && tar_handle->action_data != data_extract_to_stdout)
tar_handle->action_data = data_extract_all;
- if (opt & TAR_OPT_2STDOUT)
+ if (opt & OPT_2STDOUT)
tar_handle->action_data = data_extract_to_stdout;
- if (opt & TAR_OPT_VERBOSE) {
+ if (opt & OPT_VERBOSE) {
if (tar_handle->action_header == header_list
|| tar_handle->action_header == header_verbose_list
) {
} else
tar_handle->action_header = header_list;
}
- if (opt & TAR_OPT_KEEP_OLD)
+ if (opt & OPT_KEEP_OLD)
tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
- if (opt & TAR_OPT_NOPRESERVE_OWN)
+ if (opt & OPT_NOPRESERVE_OWN)
tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN;
- if (opt & TAR_OPT_NOPRESERVE_PERM)
+ if (opt & OPT_NOPRESERVE_PERM)
tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM;
- if (ENABLE_FEATURE_TAR_GZIP && (opt & TAR_OPT_GZIP))
+ if (opt & OPT_GZIP)
get_header_ptr = get_header_tar_gz;
- if (ENABLE_FEATURE_TAR_BZIP2 && (opt & TAR_OPT_BZIP2))
+ if (opt & OPT_BZIP2)
get_header_ptr = get_header_tar_bz2;
- if (ENABLE_FEATURE_TAR_LZMA && (opt & TAR_OPT_LZMA))
+ if (opt & OPT_LZMA)
get_header_ptr = get_header_tar_lzma;
- if (ENABLE_FEATURE_TAR_COMPRESS && (opt & TAR_OPT_UNCOMPRESS))
+ if (opt & OPT_COMPRESS)
get_header_ptr = get_header_tar_Z;
if (ENABLE_FEATURE_TAR_FROM) {
FILE *tar_stream;
int flags;
- if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {
+ if (opt & OPT_CREATE) {
/* Make sure there is at least one file to tar up. */
if (tar_handle->accept == NULL)
bb_error_msg_and_die("empty archive");
xchdir(base_dir);
/* create an archive */
- if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {
+ if (opt & OPT_CREATE) {
int verboseFlag = FALSE;
int zipMode = 0;
) {
verboseFlag = TRUE;
}
- writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERENCE,
+ writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
tar_handle->accept,
tar_handle->reject, zipMode);
/* NB: writeTarFile() closes tar_handle->src_fd */
Special characters:
+ "-" A dash as the first char in a opt_complementary group forces
+ all arguments to be treated as options, even if they have
+ no leading dashes. Next char in this case can't be a digit (0-9),
+ use ':' or end of line. For example:
+
+ opt_complementary = "-:w-x:x-w";
+ getopt32(argc, argv, "wx");
+
+ Allows any arguments to be given without a dash (./program w x)
+ as well as with a dash (./program -x).
+
+ "--" A double dash at the beginning of opt_complementary means the
+ argv[1] string should always be treated as options, even if it isn't
+ prefixed with a "-". This is useful for special syntax in applets
+ such as "ar" and "tar":
+ tar xvf foo.tar
+
+ "-N" A dash as the first char in a opt_complementary group followed
+ by a single digit (0-9) means that at least N non-option
+ arguments must be present on the command line
+
+ "=N" An equal sign as the first char in a opt_complementary group followed
+ by a single digit (0-9) means that exactly N non-option
+ arguments must be present on the command line
+
+ "?N" A "?" as the first char in a opt_complementary group followed
+ by a single digit (0-9) means that at most N arguments must be present
+ on the command line.
+
+ "V-" An option with dash before colon or end-of-line results in
+ bb_show_usage being called if this option is encountered.
+ This is typically used to implement "print verbose usage message
+ and exit" option.
+
"-" A dash between two options causes the second of the two
to be unset (and ignored) if it is given on the command line.
if (opt & 4)
printf("Detected odd -x usage\n");
- "-" A dash as the first char in a opt_complementary group forces
- all arguments to be treated as options, even if they have
- no leading dashes. Next char in this case can't be a digit (0-9),
- use ':' or end of line. For example:
-
- opt_complementary = "-:w-x:x-w";
- getopt32(argc, argv, "wx");
-
- Allows any arguments to be given without a dash (./program w x)
- as well as with a dash (./program -x).
-
- "-N" A dash as the first char in a opt_complementary group followed
- by a single digit (0-9) means that at least N non-option
- arguments must be present on the command line
-
- "=N" An equal sign as the first char in a opt_complementary group followed
- by a single digit (0-9) means that exactly N non-option
- arguments must be present on the command line
-
- "V-" An option with dash before colon or end-of-line results in
- bb_show_usage being called if this option is encountered.
- This is typically used to implement "print verbose usage message
- and exit" option.
-
"--" A double dash between two options, or between an option and a group
of options, means that they are mutually exclusive. Unlike
the "-" case above, an error will be forced if the options
if BB_GETOPT_ERROR is detected, don't return, call bb_show_usage
and exit instead. Next char after '?' can't be a digit.
- "?N" A "?" as the first char in a opt_complementary group followed
- by a single digit (0-9) means that at most N arguments must be present
- on the command line.
-
"::" A double colon after a char in opt_complementary means that the
option can occur multiple times. Each occurrence will be saved as
a llist_t element instead of char*.
root:x:0:0:root:/root:/bin/bash
user:x:500:500::/home/user:/bin/bash
- "--" A double dash at the beginning of opt_complementary means the
- argv[1] string should always be treated as options, even if it isn't
- prefixed with a "-". This is useful for special syntax in applets
- such as "ar" and "tar":
- tar xvf foo.tar
-
"?" An "?" between an option and a group of options means that
at least one of them is required to occur if the first option
occurs in preceding command line arguments.