--- _gzip.c_orig Sun Aug 18 16:29:42 2002 +++ gzip.c Sun Aug 25 22:40:38 2002 @@ -210,6 +210,12 @@ int ascii = 0; /* convert end-of-lines to local OS conventions */ int to_stdout = 0; /* output to stdout (-c) */ +int to_named_file = 0; /* output to named file (-o) (or dir, if multiple files) */ +char o_file[MAX_PATH_LEN]; /* output filename of named file specified with -o */ +char actual_outfile[MAX_PATH_LEN]; /* output name of named file specified with -o */ +char actual_infile[MAX_PATH_LEN]; /* output name of named file specified with -o */ +char *basename; /* used to hold the base file name of the input file */ +int named_file_is_dir = 0; /* if output to named file (-o) is actually a dir */ int decompress = 0; /* decompress (-d) */ int force = 0; /* don't ask questions, compress links (-f) */ int no_name = -1; /* don't save or restore the original file name */ @@ -244,6 +250,7 @@ char ofname[MAX_PATH_LEN]; /* output file name */ int remove_ofname = 0; /* remove output file on error */ struct stat istat; /* status for input file */ +struct stat o_file_statbuf; /* status for named output file (or directory) */ int ifd; /* input file descriptor */ int ofd; /* output file descriptor */ unsigned insize; /* valid bytes in inbuf */ @@ -266,6 +273,7 @@ {"license", 0, 0, 'L'}, /* display software license */ {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */ {"name", 0, 0, 'N'}, /* save or restore original name & time */ + {"output", 1, 0, 'o'}, /* output to specified file (or dir, if multiple files */ {"quiet", 0, 0, 'q'}, /* quiet mode */ {"silent", 0, 0, 'q'}, /* quiet mode */ {"recursive", 0, 0, 'r'}, /* recurse through directories */ @@ -318,7 +326,7 @@ /* ======================================================================== */ local void usage() { - printf ("usage: %s [-%scdfhlLnN%stvV19] [-S suffix] [file ...]\n", + printf ("usage: %s [-%scdfhlLnN%stvV19] [-o path] [-S suffix] [file ...]\n", progname, #if O_BINARY "a", @@ -354,6 +362,7 @@ #endif " -n --no-name do not save or restore the original name and time stamp", " -N --name save or restore the original name and time stamp", + " -o --output decompress to named file path (or directory, if > 1 input file)", " -q --quiet suppress all warnings", #ifndef NO_DIR " -r --recursive operate recursively on directories", @@ -500,7 +509,7 @@ z_suffix = Z_SUFFIX; z_len = strlen(z_suffix); - while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789", + while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNo:qrS:tvVZ123456789", longopts, (int *)0)) != -1) { switch (optc) { case 'a': @@ -536,6 +545,57 @@ no_name = no_time = 1; break; case 'N': no_name = no_time = 0; break; + case 'o': + if (to_stdout != 0) + { + fprintf (stderr, "%s: cannot specify both STDOUT and output file\n", + progname); + usage (); + do_exit (ERROR); + } + else + { + if (strlen(optarg) > MAX_PATH_LEN) + { + fprintf (stderr, "%s: output filename too long!\n", progname); + do_exit(ERROR); + } + strncpy(o_file, optarg, MAX_PATH_LEN - 1); + o_file[MAX_PATH_LEN - 1] = '\0'; + to_named_file = 1; + + do_stat(o_file, &o_file_statbuf); + if (S_ISDIR(o_file_statbuf.st_mode)) + { + named_file_is_dir = 1; + // FIXME: how to check for slash portably?? + if (! strequ(o_file-1, "/")) + { + // FIXME: how to add slash portably?? + strncat(o_file, "/", MAX_PATH_LEN -1); + } + if (verbose) + { + fprintf (stderr, "named output file is a directory\n"); + } + } + + strncpy(actual_outfile, o_file, MAX_PATH_LEN -1); // for later + actual_outfile[MAX_PATH_LEN - 1] = '\0'; + + if (argc - optind > 1) // more than one file + { + if (! named_file_is_dir) + { + fprintf (stderr, + "%s: output path must be a dir if > 1 input file\n", + progname); + usage (); + do_exit(ERROR); + } + } + } + break; case 'q': quiet = 1; verbose = 0; break; case 'r': @@ -806,9 +866,32 @@ /* Generate output file name. For -r and (-t or -l), skip files * without a valid gzip suffix (check done in make_ofname). */ - if (to_stdout && !list && !test) { - strcpy(ofname, "stdout"); + if (to_stdout && !list && !test && !to_named_file) { + strcpy(ofname, "stdout"); + } else if (to_named_file && !test && !to_stdout && !named_file_is_dir) { + strncpy(ofname, o_file, MAX_PATH_LEN - 1); + ofname[MAX_PATH_LEN - 1] = '\0'; + } else if (to_named_file && !test && !to_stdout && named_file_is_dir) { + strncpy(actual_infile, ifname, MAX_PATH_LEN -1); + actual_infile[MAX_PATH_LEN - 1] = '\0'; + strncpy(actual_outfile, o_file, MAX_PATH_LEN -1); + actual_outfile[MAX_PATH_LEN - 1] = '\0'; + // make ifname just a filename; strip away any path info + // FIXME: how to do this portably?? + if ((basename = strrchr(ifname, '/')) != NULL && strlen(basename)>0) + { + basename++; + strncpy(ifname, basename, MAX_PATH_LEN -1); + ifname[MAX_PATH_LEN - 1] = '\0'; + } + strncpy(ifname, strncat(actual_outfile, ifname, + MAX_PATH_LEN -1), MAX_PATH_LEN -1); + ifname[MAX_PATH_LEN - 1] = '\0'; + if (make_ofname() != OK) { return; } + // flip it back again + strncpy(ifname, actual_infile, MAX_PATH_LEN -1); + ifname[MAX_PATH_LEN - 1] = '\0'; } else if (make_ofname() != OK) { return; } @@ -1140,6 +1223,7 @@ char *suff; /* ofname z suffix */ strcpy(ofname, ifname); + /* strip a version number if any and get the gzip suffix if present: */ suff = get_suffix(ofname);