aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-07-27 15:37:08 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-07-27 15:37:08 +0000
commit79eb556198d5d655cdbc11f422ce7e673f25bfb0 (patch)
treef7f108cb38174ad1f8a431aba2ea44a4d2af671d
parent31dc00ec66c37d95e02913d4e785a287412e2b83 (diff)
downloadzisofs-tools-79eb556198d5d655cdbc11f422ce7e673f25bfb0.tar.gz
Reinstate recursion control and file root options.
-rw-r--r--iso9660.h5
-rw-r--r--mkzftree.124
-rw-r--r--mkzftree.c106
-rw-r--r--mkzftree.h3
-rw-r--r--walk.c219
5 files changed, 216 insertions, 141 deletions
diff --git a/iso9660.h b/iso9660.h
index e85e7ac..746ae89 100644
--- a/iso9660.h
+++ b/iso9660.h
@@ -36,11 +36,10 @@ unsigned int get_721(void *);
void set_722(void *, unsigned int);
unsigned int get_722(void *);
void set_723(void *, unsigned int);
-#define get_723(x) get_721(x)
-void set_731(void *pnt, unsigned int);
+void set_731(void *, unsigned int);
unsigned int get_731(void *);
void set_732(void *, unsigned int);
unsigned int get_732(void *);
void set_733(void *, unsigned int);
+#define get_723(x) get_721(x)
#define get_733(x) get_731(x)
-
diff --git a/mkzftree.1 b/mkzftree.1
index a7286d9..c226123 100644
--- a/mkzftree.1
+++ b/mkzftree.1
@@ -41,10 +41,28 @@ Compress in parallel. The
.I parallelism
value indicates how many compression threads are allowed to run.
.TP
-\fB-x\fP, \fB\-\-one-filesystem\fP
-Do not cross filesystem boundaries.
+\fB\-x\fP, \fB\-\-one-filesystem\fP
+Do not cross filesystem boundaries, but create directory stubs at
+mount points.
.TP
-\fB-v\fP, \fB\-\-verbose\fP
+\fB\-X\fP, \fB\-\-strict-one-filesystem\fP
+Do not cross filesystem boundaries, and do not create directory stubs
+at mount points.
+.TP
+\fB\-l\fP, \fB\-\-local\fP
+Do not recurse into subdirectories, but create the directories
+themselves.
+.TP
+\fB\-L\fP, \fB\-\-strict-local\fP
+Do not recurse into subdirectories, and do not create directories.
+.TP
+\fB\-F\fP, \fB\-\-file\fP
+Indicates that \fIINPUT\fP may not necessarily be a directory; this
+allows operation on a single file. If \fI\-F\fP is specified, and
+\fIINPUT\fP is a symlink, the symlink will be copied rather than
+whatever it happens to point to.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
Increase the program verbosity.
.TP
\fB\-V\fP \fIvalue\fP, \fB\-\-verbosity\fP \fIvalue\fP
diff --git a/mkzftree.c b/mkzftree.c
index 9b66657..4f7aafa 100644
--- a/mkzftree.c
+++ b/mkzftree.c
@@ -80,6 +80,8 @@ int force = 0; /* Always compress */
int level = 9; /* Compression level */
int parallel = 0; /* Parallelism (0 = strictly serial) */
int onefs = 0; /* One filesystem only */
+int onedir = 0; /* One directory only */
+int do_mkdir = 1; /* Create stub directories */
enum verbosity verbosity = default_verbosity; /* Default verbosity */
munger_func munger = block_compress_file; /* Default action */
@@ -87,18 +89,22 @@ munger_func munger = block_compress_file; /* Default action */
const char *program;
/* Long options */
-#define OPTSTRING "fl:up:xvqV:h"
+#define OPTSTRING "fl:up:xXlLFvqV:h"
#ifdef HAVE_GETOPT_LONG
const struct option long_options[] = {
- { "force", 0, 0, 'f' },
- { "level", 1, 0, 'l' },
- { "uncompress", 0, 0, 'u' },
- { "parallelism", 1, 0, 'p' },
- { "one-filesystem", 0, 0, 'x' },
- { "verbose", 0, 0, 'v' },
- { "quiet", 0, 0, 'q' },
- { "verbosity", 1, 0, 'V' },
- { "help", 0, 0, 'h' },
+ { "force", 0, 0, 'f' },
+ { "level", 1, 0, 'l' },
+ { "uncompress", 0, 0, 'u' },
+ { "parallelism", 1, 0, 'p' },
+ { "one-filesystem", 0, 0, 'x' },
+ { "strict-one-filesystem", 0, 0, 'X' },
+ { "local", 0, 0, 'l' },
+ { "strict-local", 0, 0, 'L' },
+ { "file", 0, 0, 'F' },
+ { "verbose", 0, 0, 'v' },
+ { "quiet", 0, 0, 'q' },
+ { "verbosity", 1, 0, 'V' },
+ { "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};
#define LO(X) X
@@ -111,14 +117,18 @@ static void usage(enum verbosity level, int err)
{
message(level,
"Usage: %s [options] intree outtree\n"
- LO(" --force ")" -f Always compress, even if result is larger\n"
- LO(" --level # ")" -z # Set compression level (1-9)\n"
- LO(" --uncompress ")" -u Uncompress an already compressed tree\n"
- LO(" --parallelism # ")" -p # Process up to # files in parallel\n"
- LO(" --one-filesystem")" -x Do not cross filesystem boundaries\n"
- LO(" --verbose ")" -v Increase message verbosity\n"
- LO(" --verbosity # ")" -V # Set message verbosity to # (default = %d)\n"
- LO(" --quiet ")" -q No messages, not even errors (-V 0)\n"
+ LO(" --force ")" -f Always compress, even if result is larger\n"
+ LO(" --level # ")" -z # Set compression level (1-9)\n"
+ LO(" --uncompress ")" -u Uncompress an already compressed tree\n"
+ LO(" --parallelism # ")" -p # Process up to # files in parallel\n"
+ LO(" --one-filesystem ")" -x Do not cross filesystem boundaries\n"
+ LO(" --strict-one-filesystem")" -X Same as -x, but don't create stubs dirs\n"
+ LO(" --local ")" -l Do not recurse into subdirectoires\n"
+ LO(" --strict-local ")" -L Same as -l, but don't create stubs dirs\n"
+ LO(" --file ")" -F Operate possibly on a single file\n"
+ LO(" --verbose ")" -v Increase message verbosity\n"
+ LO(" --verbosity # ")" -V # Set message verbosity to # (default = %d)\n"
+ LO(" --quiet ")" -q No messages, not even errors (-V 0)\n"
,program, (int)default_verbosity);
exit(err);
}
@@ -142,6 +152,7 @@ int main(int argc, char *argv[])
struct stat st;
struct utimbuf ut;
int opt, err;
+ int file_root = 0;
program = argv[0];
@@ -180,6 +191,22 @@ int main(int argc, char *argv[])
break;
case 'x':
onefs = 1;
+ do_mkdir = 1;
+ break;
+ case 'l':
+ onedir = 1;
+ do_mkdir = 1;
+ break;
+ case 'X':
+ onefs = 1;
+ do_mkdir = 0;
+ break;
+ case 'L':
+ onedir = 1;
+ do_mkdir = 0;
+ break;
+ case 'F':
+ file_root = 1;
break;
default:
usage(vl_error, EX_USAGE);
@@ -195,28 +222,39 @@ int main(int argc, char *argv[])
umask(077);
- /* Special case: we use stat() for the root, not lstat() */
- if ( stat(in, &st) ) {
- message(vl_error, "%s: %s: %s\n", program, in, strerror(errno));
- exit(EX_NOINPUT);
- }
- if ( !S_ISDIR(st.st_mode) ) {
- message(vl_error, "%s: %s: Not a directory\n", program, in);
- exit(EX_DATAERR);
- }
+ if ( file_root ) {
+ if ( lstat(in, &st) ) {
+ message(vl_error, "%s: %s: %s\n", program, in, strerror(errno));
+ exit(EX_NOINPUT);
+ }
- err = munge_tree(in, out);
+ err = munge_entry(in, out, NULL);
+ } else {
+ /* Special case: we use stat() for the root, not lstat() */
+ if ( stat(in, &st) ) {
+ message(vl_error, "%s: %s: %s\n", program, in, strerror(errno));
+ exit(EX_NOINPUT);
+ }
+ if ( !S_ISDIR(st.st_mode) ) {
+ message(vl_error, "%s: %s: Not a directory\n", program, in);
+ exit(EX_DATAERR);
+ }
+
+ err = munge_tree(in, out);
+ }
wait_for_all_workers();
-
+
if ( err )
exit(err);
- chown(out, st.st_uid, st.st_gid);
- chmod(out, st.st_mode);
- ut.actime = st.st_atime;
- ut.modtime = st.st_mtime;
- utime(out, &ut);
+ if ( !file_root ) {
+ chown(out, st.st_uid, st.st_gid);
+ chmod(out, st.st_mode);
+ ut.actime = st.st_atime;
+ ut.modtime = st.st_mtime;
+ utime(out, &ut);
+ }
return 0;
}
diff --git a/mkzftree.h b/mkzftree.h
index 25b7171..5611a20 100644
--- a/mkzftree.h
+++ b/mkzftree.h
@@ -49,6 +49,8 @@ extern int force; /* Always compress */
extern int level; /* Compression level */
extern int parallel; /* Parallelism (0 = strictly serial) */
extern int onefs; /* One filesystem only */
+extern int onedir; /* One directory only */
+extern int do_mkdir; /* Create stub directories */
extern munger_func munger; /* Default action */
enum verbosity {
vl_quiet, /* No messages */
@@ -60,6 +62,7 @@ extern enum verbosity verbosity; /* Message verbosity */
/* walk.c */
int munge_tree(const char *, const char *);
+int munge_entry(const char *, const char *, const struct stat *);
/* workers.c */
void wait_for_all_workers(void);
diff --git a/walk.c b/walk.c
index c037690..95cddd9 100644
--- a/walk.c
+++ b/walk.c
@@ -73,12 +73,10 @@ static int munge_path(const char *inpath, const char *outpath, struct stat *st)
int munge_tree(const char *intree, const char *outtree)
{
- char buffer[BUFSIZ];
char *in_path, *out_path, *in_file, *out_file;
DIR *thisdir;
struct dirent *dirent;
- struct stat st, dirst;
- struct utimbuf ut;
+ struct stat dirst;
int err = 0;
/* Construct buffers with the common filename prefix, and point to the end */
@@ -121,126 +119,145 @@ int munge_tree(const char *intree, const char *outtree)
if ( !strcmp(dirent->d_name, ".") ||
!strcmp(dirent->d_name, "..") )
continue; /* Ignore . and .. */
-
+
strcpy(in_file, dirent->d_name);
strcpy(out_file, dirent->d_name);
+
+ err = munge_entry(in_path, out_path, &dirst);
+ if ( err )
+ break;
+ }
+ closedir(thisdir);
+
+ free(in_path);
+ free(out_path);
+
+ return err;
+}
- message(vl_filename, "%s -> %s\n", in_path, out_path);
- if ( lstat(in_path, &st) ) {
- message(vl_error, "%s: Failed to stat file %s: %s\n",
- program, in_path, strerror(errno));
- err = EX_NOINPUT;
- break;
- }
-
- if ( S_ISREG(st.st_mode) ) {
- if ( st.st_nlink > 1 ) {
- /* Hard link. */
- const char *linkname;
-
- if ( (linkname = hash_find_file(&st)) != NULL ) {
- /* We've seen it before, hard link it */
-
- if ( link(linkname, out_path) ) {
- message(vl_error, "%s: hard link %s -> %s failed: %s\n",
- program, out_path, linkname, strerror(errno));
- err = EX_CANTCREAT;
- break;
- }
- } else {
- /* First encounter, compress and enter into hash */
- if ( (err = munge_path(in_path, out_path, &st)) != 0 ) {
- message(vl_error, "%s: %s: %s", program, in_path, strerror(errno));
- break;
- }
- hash_insert_file(&st, out_path);
+int munge_entry(const char *in_path, const char *out_path, const struct stat *dirst)
+{
+ struct stat st;
+ struct utimbuf ut;
+ int err = 0;
+
+ message(vl_filename, "%s -> %s\n", in_path, out_path);
+
+ if ( lstat(in_path, &st) ) {
+ message(vl_error, "%s: Failed to stat file %s: %s\n",
+ program, in_path, strerror(errno));
+ return EX_NOINPUT;
+ }
+
+ if ( S_ISREG(st.st_mode) ) {
+ if ( st.st_nlink > 1 ) {
+ /* Hard link. */
+ const char *linkname;
+
+ if ( (linkname = hash_find_file(&st)) != NULL ) {
+ /* We've seen it before, hard link it */
+
+ if ( link(linkname, out_path) ) {
+ message(vl_error, "%s: hard link %s -> %s failed: %s\n",
+ program, out_path, linkname, strerror(errno));
+ return EX_CANTCREAT;
}
} else {
- /* Singleton file; no funnies */
+ /* First encounter, compress and enter into hash */
if ( (err = munge_path(in_path, out_path, &st)) != 0 ) {
message(vl_error, "%s: %s: %s", program, in_path, strerror(errno));
- break;
+ return err;
}
+ hash_insert_file(&st, out_path);
}
- } else if ( S_ISDIR(st.st_mode) ) {
- /* Recursion: see recursion */
- /* Don't decend if -x is specified and st_dev is different */
- if ( !onefs || dirst.st_dev == st.st_dev ) {
- if ( (err = munge_tree(in_path, out_path)) != 0 )
- break;
- }
- } else if ( S_ISLNK(st.st_mode) ) {
- int chars;
- if ( (chars = readlink(in_path, buffer, BUFSIZ)) < 0 ) {
- message(vl_error, "%s: readlink failed for %s: %s\n",
- program, in_path, strerror(errno));
- err = EX_NOINPUT;
- break;
+ } else {
+ /* Singleton file; no funnies */
+ if ( (err = munge_path(in_path, out_path, &st)) != 0 ) {
+ message(vl_error, "%s: %s: %s", program, in_path, strerror(errno));
+ return err;
}
- buffer[chars] = '\0';
- if ( symlink(buffer, out_path) ) {
- message(vl_error, "%s: symlink %s -> %s failed: %s\n",
- program, out_path, buffer, strerror(errno));
- err = EX_CANTCREAT;
- break;
+ }
+ } else if ( S_ISDIR(st.st_mode) ) {
+ /* Recursion: see recursion */
+ if ( !onedir && (!onefs || (dirst && dirst->st_dev == st.st_dev)) ) {
+ if ( (err = munge_tree(in_path, out_path)) != 0 )
+ return err;
+ } else if ( do_mkdir ) {
+ /* Create stub directories */
+ if ( mkdir(out_path, st.st_mode) ) {
+ message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+ return EX_CANTCREAT;
}
- } else {
- if ( st.st_nlink > 1 ) {
- /* Hard link. */
- const char *linkname;
-
- if ( (linkname = hash_find_file(&st)) != NULL ) {
- /* We've seen it before, hard link it */
-
- if ( link(linkname, out_path) ) {
- message(vl_error, "%s: hard link %s -> %s failed: %s\n",
- program, out_path, linkname, strerror(errno));
- err = EX_CANTCREAT;
- break;
- }
- } else {
- /* First encounter, create and enter into hash */
- if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
- message(vl_error, "%s: mknod failed for %s: %s\n",
- program, out_path, strerror(errno));
- err = EX_CANTCREAT;
- break;
- }
- hash_insert_file(&st, out_path);
+ }
+ } else if ( S_ISLNK(st.st_mode) ) {
+ int chars;
+#ifdef PATH_MAX
+#define BUFFER_SLACK PATH_MAX
+#else
+#define BUFFER_SLACK BUFSIZ
+#endif
+ int buffer_len = st.st_size + BUFFER_SLACK + 1;
+ char *buffer = xmalloc(buffer_len);
+ if ( (chars = readlink(in_path, buffer, buffer_len)) < 0 ) {
+ message(vl_error, "%s: readlink failed for %s: %s\n",
+ program, in_path, strerror(errno));
+ return EX_NOINPUT;
+ }
+ buffer[chars] = '\0';
+ if ( symlink(buffer, out_path) ) {
+ message(vl_error, "%s: symlink %s -> %s failed: %s\n",
+ program, out_path, buffer, strerror(errno));
+ return EX_CANTCREAT;
+ }
+ } else {
+ if ( st.st_nlink > 1 ) {
+ /* Hard link. */
+ const char *linkname;
+
+ if ( (linkname = hash_find_file(&st)) != NULL ) {
+ /* We've seen it before, hard link it */
+
+ if ( link(linkname, out_path) ) {
+ message(vl_error, "%s: hard link %s -> %s failed: %s\n",
+ program, out_path, linkname, strerror(errno));
+ return EX_CANTCREAT;
}
} else {
- /* Singleton node; no funnies */
- if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
- message(vl_error, "%s: mknod failed for %s: %s\n",
- program, out_path, strerror(errno));
- err = EX_CANTCREAT;
- break;
- }
+ /* First encounter, create and enter into hash */
+ if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
+ message(vl_error, "%s: mknod failed for %s: %s\n",
+ program, out_path, strerror(errno));
+ return EX_CANTCREAT;
+ }
+ hash_insert_file(&st, out_path);
+ }
+ } else {
+ /* Singleton node; no funnies */
+ if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
+ message(vl_error, "%s: mknod failed for %s: %s\n",
+ program, out_path, strerror(errno));
+ return EX_CANTCREAT;
}
}
-
- /* This is done by munge_path() for files */
- if ( !S_ISREG(st.st_mode) ) {
+ }
+
+ /* This is done by munge_path() for files */
+ if ( !S_ISREG(st.st_mode) ) {
#ifdef HAVE_LCHOWN
- lchown(out_path, st.st_uid, st.st_gid);
+ lchown(out_path, st.st_uid, st.st_gid);
#endif
- if ( !S_ISLNK(st.st_mode) ) {
+ if ( !S_ISLNK(st.st_mode) ) {
#ifndef HAVE_LCHOWN
- chown(out_path, st.st_uid, st.st_gid);
+ chown(out_path, st.st_uid, st.st_gid);
#endif
- chmod(out_path, st.st_mode);
- ut.actime = st.st_atime;
- ut.modtime = st.st_mtime;
- utime(out_path, &ut);
- }
+ chmod(out_path, st.st_mode);
+ ut.actime = st.st_atime;
+ ut.modtime = st.st_mtime;
+ utime(out_path, &ut);
}
}
- closedir(thisdir);
-
- free(in_path);
- free(out_path);
-
+
return err;
}