aboutsummaryrefslogtreecommitdiff
path: root/cpio/cpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpio/cpio.c')
-rw-r--r--cpio/cpio.c123
1 files changed, 67 insertions, 56 deletions
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 77eefe809f37..6e6c2c3356c0 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -8,6 +8,8 @@
#include "cpio_platform.h"
+#include "lafe_getline.h"
+
#include <sys/types.h>
#include <archive.h>
#include <archive_entry.h>
@@ -33,6 +35,9 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -83,7 +88,7 @@ struct name_cache {
static int extract_data(struct archive *, struct archive *);
const char * cpio_i64toa(int64_t);
-static const char *cpio_rename(const char *name);
+static void cpio_rename(struct archive_entry *);
static int entry_to_archive(struct cpio *, struct archive_entry *);
static int file_to_archive(struct cpio *, const char *);
static void free_cache(struct name_cache *cache);
@@ -110,19 +115,16 @@ static void passphrase_free(char *);
int
main(int argc, char *argv[])
{
- static char buff[16384];
struct cpio _cpio; /* Allocated on stack. */
struct cpio *cpio;
struct cpio_owner owner;
const char *errmsg;
char *tptr;
- int opt, t;
+ int opt;
+ long t;
cpio = &_cpio;
memset(cpio, 0, sizeof(*cpio));
- cpio->buff = buff;
- cpio->buff_size = sizeof(buff);
-
#if defined(HAVE_SIGACTION)
{
@@ -204,13 +206,13 @@ main(int argc, char *argv[])
case 'C': /* NetBSD/OpenBSD */
errno = 0;
tptr = NULL;
- t = (int)strtol(cpio->argument, &tptr, 10);
- if (errno || t <= 0 || *(cpio->argument) == '\0' ||
+ t = strtol(cpio->argument, &tptr, 10);
+ if (errno || t <= 0 || t > INT_MAX || *(cpio->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid blocksize: %s",
cpio->argument);
}
- cpio->bytes_per_block = t;
+ cpio->bytes_per_block = (int)t;
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";
@@ -222,7 +224,7 @@ main(int argc, char *argv[])
if (archive_match_include_pattern_from_file(
cpio->matching, cpio->argument,
cpio->option_null) != ARCHIVE_OK)
- lafe_errc(1, 0, "Error : %s",
+ lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching));
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
@@ -231,7 +233,7 @@ main(int argc, char *argv[])
case 'f': /* POSIX 1997 */
if (archive_match_exclude_pattern(cpio->matching,
cpio->argument) != ARCHIVE_OK)
- lafe_errc(1, 0, "Error : %s",
+ lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching));
break;
case OPTION_GRZIP:
@@ -247,7 +249,7 @@ main(int argc, char *argv[])
cpio->filename = cpio->argument;
break;
case 'i': /* POSIX 1997 */
- if (cpio->mode != '\0')
+ if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0,
"Cannot use both -i and -%c", cpio->mode);
cpio->mode = opt;
@@ -289,13 +291,13 @@ main(int argc, char *argv[])
cpio->filename = cpio->argument;
break;
case 'o': /* POSIX 1997 */
- if (cpio->mode != '\0')
+ if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0,
"Cannot use both -o and -%c", cpio->mode);
cpio->mode = opt;
break;
case 'p': /* POSIX 1997 */
- if (cpio->mode != '\0')
+ if (cpio->mode != '\0' && cpio->mode != opt)
lafe_errc(1, 0,
"Cannot use both -p and -%c", cpio->mode);
cpio->mode = opt;
@@ -316,17 +318,21 @@ main(int argc, char *argv[])
if (owner_parse(cpio->argument, &owner, &errmsg) != 0) {
if (!errmsg)
errmsg = "Error parsing owner";
- lafe_warnc(-1, "%s", errmsg);
+ lafe_warnc(0, "%s", errmsg);
usage();
}
if (owner.uid != -1)
cpio->uid_override = owner.uid;
- if (owner.uname != NULL)
+ if (owner.uname != NULL) {
+ free(cpio->uname_override);
cpio->uname_override = owner.uname;
+ }
if (owner.gid != -1)
cpio->gid_override = owner.gid;
- if (owner.gname != NULL)
+ if (owner.gname != NULL) {
+ free(cpio->gname_override);
cpio->gname_override = owner.gname;
+ }
break;
case 'r': /* POSIX 1997 */
cpio->option_rename = 1;
@@ -409,7 +415,7 @@ main(int argc, char *argv[])
while (*cpio->argv != NULL) {
if (archive_match_include_pattern(cpio->matching,
*cpio->argv) != ARCHIVE_OK)
- lafe_errc(1, 0, "Error : %s",
+ lafe_errc(1, 0, "%s",
archive_error_string(cpio->matching));
--cpio->argc;
++cpio->argv;
@@ -427,7 +433,7 @@ main(int argc, char *argv[])
break;
default:
lafe_errc(1, 0,
- "Must specify at least one of -i, -o, or -p");
+ "Must specify one of -i, -o, or -p");
}
archive_match_free(cpio->matching);
@@ -524,7 +530,7 @@ mode_out(struct cpio *cpio)
int r;
if (cpio->option_append)
- lafe_errc(1, 0, "Append mode not yet supported.");
+ lafe_errc(1, 0, "Append mode not yet supported");
cpio->archive_read_disk = archive_read_disk_new();
if (cpio->archive_read_disk == NULL)
@@ -638,7 +644,7 @@ mode_out(struct cpio *cpio)
int64_t blocks =
(archive_filter_bytes(cpio->archive, 0) + 511)
/ 512;
- fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_write_free(cpio->archive);
@@ -696,7 +702,6 @@ remove_leading_slash(const char *p)
static int
file_to_archive(struct cpio *cpio, const char *srcpath)
{
- const char *destpath;
struct archive_entry *entry, *spare;
size_t len;
int r;
@@ -738,7 +743,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
* pass mode or the name that will go into the archive in
* output mode.
*/
- destpath = srcpath;
if (cpio->destdir) {
len = cpio->destdir_len + strlen(srcpath) + 8;
if (len >= cpio->pass_destpath_alloc) {
@@ -754,15 +758,17 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
}
strcpy(cpio->pass_destpath, cpio->destdir);
strcat(cpio->pass_destpath, remove_leading_slash(srcpath));
- destpath = cpio->pass_destpath;
+ archive_entry_set_pathname(entry, cpio->pass_destpath);
+ } else {
+ archive_entry_set_pathname(entry, srcpath);
}
if (cpio->option_rename)
- destpath = cpio_rename(destpath);
- if (destpath == NULL) {
+ cpio_rename(entry);
+
+ if (archive_entry_pathname(entry) == NULL) {
archive_entry_free(entry);
return (0);
}
- archive_entry_copy_pathname(entry, destpath);
/*
* If we're trying to preserve hardlinks, match them here.
@@ -791,7 +797,6 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
const char *destpath = archive_entry_pathname(entry);
const char *srcpath = archive_entry_sourcepath(entry);
int fd = -1;
- ssize_t bytes_read;
int r;
/* Print out the destination name to the user. */
@@ -869,21 +874,23 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
exit(1);
if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
- bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size);
+ static char buff[16384];
+ ssize_t bytes_read;
+
+ bytes_read = read(fd, buff, sizeof(buff));
while (bytes_read > 0) {
ssize_t bytes_write;
bytes_write = archive_write_data(cpio->archive,
- cpio->buff, bytes_read);
+ buff, bytes_read);
if (bytes_write < 0)
lafe_errc(1, archive_errno(cpio->archive),
"%s", archive_error_string(cpio->archive));
if (bytes_write < bytes_read) {
lafe_warnc(0,
"Truncated write; file may have "
- "grown while being archived.");
+ "grown while being archived");
}
- bytes_read = read(fd, cpio->buff,
- (unsigned)cpio->buff_size);
+ bytes_read = read(fd, buff, sizeof(buff));
}
}
@@ -997,11 +1004,9 @@ mode_in(struct cpio *cpio)
}
if (archive_match_path_excluded(cpio->matching, entry))
continue;
- if (cpio->option_rename) {
- destpath = cpio_rename(archive_entry_pathname(entry));
- archive_entry_set_pathname(entry, destpath);
- } else
- destpath = archive_entry_pathname(entry);
+ if (cpio->option_rename)
+ cpio_rename(entry);
+ destpath = archive_entry_pathname(entry);
if (destpath == NULL)
continue;
if (cpio->verbose)
@@ -1040,7 +1045,7 @@ mode_in(struct cpio *cpio)
if (!cpio->quiet) {
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512;
- fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_read_free(a);
@@ -1125,7 +1130,7 @@ mode_list(struct cpio *cpio)
if (!cpio->quiet) {
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512;
- fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ fprintf(stderr, "%lld %s\n", (long long)blocks,
blocks == 1 ? "block" : "blocks");
}
archive_read_free(a);
@@ -1292,54 +1297,60 @@ mode_pass(struct cpio *cpio, const char *destdir)
* that an input of '.' means the name should be unchanged. GNU cpio
* treats '.' as a literal new name.
*/
-static const char *
-cpio_rename(const char *name)
+void
+cpio_rename(struct archive_entry *entry)
{
- static char buff[1024];
+ char *buff = NULL, *p, *ret = NULL;
FILE *t;
- char *p, *ret;
+ size_t n = 0;
+ ssize_t r;
#if defined(_WIN32) && !defined(__CYGWIN__)
FILE *to;
t = fopen("CONIN$", "r");
if (t == NULL)
- return (name);
+ return;
to = fopen("CONOUT$", "w");
if (to == NULL) {
fclose(t);
- return (name);
+ return;
}
- fprintf(to, "%s (Enter/./(new name))? ", name);
+ fprintf(to, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
fclose(to);
#else
t = fopen("/dev/tty", "r+");
if (t == NULL)
- return (name);
- fprintf(t, "%s (Enter/./(new name))? ", name);
+ return;
+ fprintf(t, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
fflush(t);
#endif
- p = fgets(buff, sizeof(buff), t);
+ r = getline(&buff, &n, t);
fclose(t);
- if (p == NULL)
+ if (r < 1)
/* End-of-file is a blank line. */
- return (NULL);
+ goto done;
+ p = buff;
while (*p == ' ' || *p == '\t')
++p;
if (*p == '\n' || *p == '\0')
/* Empty line. */
- return (NULL);
- if (*p == '.' && p[1] == '\n')
+ goto done;
+ if (*p == '.' && p[1] == '\n') {
/* Single period preserves original name. */
- return (name);
+ free(buff);
+ return;
+ }
ret = p;
/* Trim the final newline. */
while (*p != '\0' && *p != '\n')
++p;
/* Overwrite the final \n with a null character. */
*p = '\0';
- return (ret);
+done:
+ archive_entry_set_pathname(entry, ret);
+ free(buff);
}
static void