mirror of
https://github.com/ckolivas/lrzip.git
synced 2026-03-31 01:45:20 +02:00
Implement gzip compatible -r recursive option
This commit is contained in:
parent
8853f2e449
commit
7a03965214
81
main.c
81
main.c
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2006-2015 Con Kolivas
|
||||
Copyright (C) 2006-2016 Con Kolivas
|
||||
Copyright (C) 2011 Peter Hyman
|
||||
Copyright (C) 1998-2003 Andrew Tridgell
|
||||
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
|
||||
|
|
@ -60,6 +61,8 @@
|
|||
/* needed for CRC routines */
|
||||
#include "lzma/C/7zCrc.h"
|
||||
|
||||
#define MAX_PATH_LEN 4096
|
||||
|
||||
static rzip_control base_control, local_control, *control;
|
||||
|
||||
static void usage(bool compat)
|
||||
|
|
@ -252,6 +255,38 @@ static void set_stdout(struct rzip_control *control)
|
|||
register_outputfile(control, control->msgout);
|
||||
}
|
||||
|
||||
/* Recursively enter all directories, adding all regular files to the dirlist array */
|
||||
static void recurse_dirlist(char *indir, char **dirlist, int *entries)
|
||||
{
|
||||
char fname[MAX_PATH_LEN];
|
||||
struct stat istat;
|
||||
struct dirent *dp;
|
||||
DIR *dirp;
|
||||
|
||||
dirp = opendir(indir);
|
||||
if (unlikely(!dirp))
|
||||
failure("Unable to open directory %s\n", indir);
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
|
||||
continue;
|
||||
sprintf(fname, "%s/%s", indir, dp->d_name);
|
||||
if (unlikely(stat(fname, &istat)))
|
||||
failure("Unable to stat file %s\n", fname);
|
||||
if (S_ISDIR(istat.st_mode)) {
|
||||
recurse_dirlist(fname, dirlist, entries);
|
||||
continue;
|
||||
}
|
||||
if (!S_ISREG(istat.st_mode)) {
|
||||
print_err("Not regular file %s\n", fname);
|
||||
continue;
|
||||
}
|
||||
print_maxverbose("Added file %s\n", fname);
|
||||
*dirlist = realloc(*dirlist, MAX_PATH_LEN * (*entries + 1));
|
||||
strcpy(*dirlist + MAX_PATH_LEN * (*entries)++, fname);
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
bool lrzcat = false, compat = false, recurse = false;
|
||||
|
|
@ -506,27 +541,49 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* One extra iteration for the case of no parameters means we will default to stdin/out */
|
||||
for (i = 0; i <= argc; i++) {
|
||||
char *dirlist = NULL, *infile = NULL;
|
||||
int direntries = 0, curentry = 0;
|
||||
|
||||
if (i < argc)
|
||||
control->infile = argv[i];
|
||||
infile = argv[i];
|
||||
else if (!(i == 0 && STDIN))
|
||||
break;
|
||||
if (control->infile) {
|
||||
if ((strcmp(control->infile, "-") == 0))
|
||||
if (infile) {
|
||||
if ((strcmp(infile, "-") == 0))
|
||||
control->flags |= FLAG_STDIN;
|
||||
else {
|
||||
struct stat infile_stat;
|
||||
bool isdir = false;
|
||||
struct stat istat;
|
||||
|
||||
stat(control->infile, &infile_stat);
|
||||
if (unlikely(S_ISDIR(infile_stat.st_mode)))
|
||||
failure("lrzip only works directly on FILES.\n"
|
||||
"Use lrztar or pipe through tar for compressing directories.\n");
|
||||
if (unlikely(stat(infile, &istat)))
|
||||
failure("Failed to stat %s\n", infile);
|
||||
isdir = S_ISDIR(istat.st_mode);
|
||||
if (!recurse && (isdir || !S_ISREG(istat.st_mode))) {
|
||||
failure("lrzip only works directly on regular FILES.\n"
|
||||
"Use -r recursive, lrztar or pipe through tar for compressing directories.\n");
|
||||
}
|
||||
if (recurse && !isdir)
|
||||
failure("%s not a directory, -r recursive needs a directory\n", infile);
|
||||
}
|
||||
}
|
||||
|
||||
if (recurse && (STDIN || STDOUT))
|
||||
failure("Cannot use -r recursive with STDIO\n");
|
||||
if (recurse) {
|
||||
if (unlikely(STDIN || STDOUT))
|
||||
failure("Cannot use -r recursive with STDIO\n");
|
||||
recurse_dirlist(infile, &dirlist, &direntries);
|
||||
}
|
||||
|
||||
if (INFO && STDIN)
|
||||
failure("Will not get file info from STDIN\n");
|
||||
recursion:
|
||||
if (recurse) {
|
||||
if (curentry >= direntries) {
|
||||
free(dirlist);
|
||||
break;
|
||||
}
|
||||
infile = dirlist + MAX_PATH_LEN * curentry++;
|
||||
}
|
||||
control->infile = infile;
|
||||
|
||||
/* If no output filename is specified, and we're using
|
||||
* stdin, use stdout */
|
||||
|
|
@ -602,6 +659,8 @@ int main(int argc, char *argv[])
|
|||
seconds = total_time - hours * 3600 - minutes * 60;
|
||||
if (!INFO)
|
||||
print_progress("Total time: %02d:%02d:%05.2f\n", hours, minutes, seconds);
|
||||
if (recurse)
|
||||
goto recursion;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue