aboutsummaryrefslogtreecommitdiffstats
path: root/cpio
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2012-02-08 12:53:14 +0000
committerMartin Matuska <mm@FreeBSD.org>2012-02-08 12:53:14 +0000
commit17993d47e9beebea021707962fcdf2387b27cae9 (patch)
tree28a8e9d81eb7ed48e286dfc384e2e0ffccc238b5 /cpio
parentd8b2811c01ad218932b237af23558ab000e58265 (diff)
downloadsrc-17993d47e9beebea021707962fcdf2387b27cae9.tar.gz
src-17993d47e9beebea021707962fcdf2387b27cae9.zip
Update vendor libarchive dist to new "release" branch (post 3.0.3)
Git branch: release Git commit: 9af87742342aa4f37a22ec12c4cc1c82e00ffa2f Obtained from: https://github.com/libarchive/libarchive.git
Notes
Notes: svn path=/vendor/libarchive/dist/; revision=231200
Diffstat (limited to 'cpio')
-rw-r--r--cpio/bsdcpio.165
-rw-r--r--cpio/cmdline.c21
-rw-r--r--cpio/cpio.c96
-rw-r--r--cpio/cpio.h8
-rw-r--r--cpio/test/CMakeLists.txt6
-rw-r--r--cpio/test/main.c760
-rw-r--r--cpio/test/test.h98
-rw-r--r--cpio/test/test_0.c14
-rw-r--r--cpio/test/test_basic.c49
-rw-r--r--cpio/test/test_format_newc.c45
-rw-r--r--cpio/test/test_option_0.c92
-rw-r--r--cpio/test/test_option_c.c20
-rw-r--r--cpio/test/test_option_t.c31
-rw-r--r--cpio/test/test_option_u.c6
-rw-r--r--cpio/test/test_owner_parse.c11
15 files changed, 1016 insertions, 306 deletions
diff --git a/cpio/bsdcpio.1 b/cpio/bsdcpio.1
index 789ce74e1c48..1355130c5911 100644
--- a/cpio/bsdcpio.1
+++ b/cpio/bsdcpio.1
@@ -24,8 +24,8 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 5, 2010
-.Dt BSDCPIO 1
+.Dd December 21, 2007
+.Dt CPIO 1
.Os
.Sh NAME
.Nm cpio
@@ -59,7 +59,7 @@ is a mode indicator from the following list:
.Bl -tag -compact -width indent
.It Fl i
Input.
-Read an archive from standard input (unless overriden) and extract the
+Read an archive from standard input (unless overridden) and extract the
contents to disk or (if the
.Fl t
option is specified)
@@ -69,7 +69,7 @@ one of the patterns will be extracted.
.It Fl o
Output.
Read a list of filenames from standard input and produce a new archive
-on standard output (unless overriden) containing the specified items.
+on standard output (unless overridden) containing the specified items.
.It Fl p
Pass-through.
Read a list of filenames from standard input and copy the files to the
@@ -80,7 +80,7 @@ specified directory.
Unless specifically stated otherwise, options are applicable in
all operating modes.
.Bl -tag -width indent
-.It Fl 0
+.It Fl 0 , Fl Fl null
Read filenames separated by NUL characters instead of newlines.
This is necessary if any of the filenames being read might contain newlines.
.It Fl A
@@ -102,8 +102,8 @@ bytes.
(o mode only)
Use the old POSIX portable character format.
Equivalent to
-.Fl -format Ar odc .
-.It Fl d
+.Fl Fl format Ar odc .
+.It Fl d , Fl Fl make-directories
(i and p modes)
Create directories as necessary.
.It Fl E Ar file
@@ -111,14 +111,14 @@ Create directories as necessary.
Read list of file name patterns from
.Ar file
to list and extract.
-.It Fl F Ar file
+.It Fl F Ar file , Fl Fl file Ar file
Read archive from or write archive to
.Ar file .
.It Fl f Ar pattern
(i mode only)
Ignore files that match
.Ar pattern .
-.It Fl -format Ar format
+.It Fl H Ar format , Fl Fl format Ar format
(o mode only)
Produce the output archive in the specified format.
Supported formats include:
@@ -145,24 +145,21 @@ for more complete information about the
formats currently supported by the underlying
.Xr libarchive 3
library.
-.It Fl H Ar format
-Synonym for
-.Fl -format .
-.It Fl h , Fl -help
+.It Fl h , Fl Fl help
Print usage information.
.It Fl I Ar file
Read archive from
.Ar file .
-.It Fl i
+.It Fl i , Fl Fl extract
Input mode.
See above for description.
-.It Fl -insecure
+.It Fl Fl insecure
(i and p mode only)
Disable security checks during extraction or copying.
This allows extraction via symbolic links and path names containing
.Sq ..
in the name.
-.It Fl J
+.It Fl J , Fl Fl xz
(o mode only)
Compress the file with xz-compatible compression before writing it.
In input mode, this option is ignored; xz compression is recognized
@@ -175,20 +172,20 @@ Synonym for
All symbolic links will be followed.
Normally, symbolic links are archived and copied as symbolic links.
With this option, the target of the link will be archived or copied instead.
-.It Fl l
+.It Fl l , Fl Fl link
(p mode only)
Create links from the target directory to the original files,
instead of copying.
-.It Fl lzma
+.It Fl Fl lzma
(o mode only)
Compress the file with lzma-compatible compression before writing it.
In input mode, this option is ignored; lzma compression is recognized
automatically on input.
-.It Fl m
+.It Fl m , Fl Fl preserve-modification-time
(i and p modes)
Set file modification time on created files to match
those in the source.
-.It Fl n
+.It Fl n , Fl Fl numeric-uid-gid
(i mode, only with
.Fl t )
Display numeric uid and gid.
@@ -197,26 +194,26 @@ By default,
displays the user and group names when they are provided in the
archive, or looks up the user and group names in the system
password database.
-.It Fl no-preserve-owner
+.It Fl Fl no-preserve-owner
(i mode only)
Do not attempt to restore file ownership.
This is the default when run by non-root users.
.It Fl O Ar file
Write archive to
.Ar file .
-.It Fl o
+.It Fl o , Fl Fl create
Output mode.
See above for description.
-.It Fl p
+.It Fl p , Fl Fl pass-through
Pass-through mode.
See above for description.
-.It Fl preserve-owner
+.It Fl Fl preserve-owner
(i mode only)
Restore file ownership.
This is the default when run by the root user.
-.It Fl -quiet
+.It Fl Fl quiet
Suppress unnecessary messages.
-.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
+.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc , Fl Fl owner Oo user Oc Ns Oo : Oc Ns Oo group Oc
Set the owner and/or group on files in the output.
If group is specified with no user
(for example,
@@ -244,20 +241,24 @@ containing the name of the file and a line is read from
If the line read is blank, the file is skipped.
If the line contains a single period, the file is processed normally.
Otherwise, the line is taken to be the new name of the file.
-.It Fl t
+.It Fl t , Fl Fl list
(i mode only)
List the contents of the archive to stdout;
do not restore the contents to disk.
-.It Fl u
+.It Fl u , Fl Fl unconditional
(i and p modes)
Unconditionally overwrite existing files.
Ordinarily, an older file will not overwrite a newer file on disk.
-.It Fl v
+.It Fl V , Fl Fl dot
+Print a dot to stderr for each file as it is processed.
+Superseded by
+.Fl v .
+.It Fl v , Fl Fl verbose
Print the name of each file to stderr as it is processed.
With
.Fl t ,
provide a detailed listing of each file.
-.It Fl -version
+.It Fl Fl version
Print the program version information and exit.
.It Fl y
(o mode only)
@@ -275,6 +276,8 @@ Compress the archive with gzip-compatible compression before writing it.
In input mode, this option is ignored;
gzip compression is recognized automatically on input.
.El
+.Sh EXIT STATUS
+.Ex -std
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
@@ -290,8 +293,6 @@ See
.Xr environ 7
for more information.
.El
-.Sh EXIT STATUS
-.Ex -std
.Sh EXAMPLES
The
.Nm
diff --git a/cpio/cmdline.c b/cpio/cmdline.c
index ada549953ddf..390aebc8fb85 100644
--- a/cpio/cmdline.c
+++ b/cpio/cmdline.c
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cmdline.c,v 1.5 2008/12/06 07:30:40 kientzl
/*
* Short options for cpio. Please keep this sorted.
*/
-static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuvW:yZz";
+static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuVvW:yZz";
/*
* Long options for cpio. Please keep this sorted.
@@ -62,6 +62,7 @@ static const struct option {
int equivalent; /* Equivalent short option. */
} cpio_longopts[] = {
{ "create", 0, 'o' },
+ { "dot", 0, 'V' },
{ "extract", 0, 'i' },
{ "file", 1, 'F' },
{ "format", 1, 'H' },
@@ -109,7 +110,7 @@ cpio_getopt(struct cpio *cpio)
int opt = '?';
int required = 0;
- cpio->optarg = NULL;
+ cpio->argument = NULL;
/* First time through, initialize everything. */
if (state == state_start) {
@@ -188,7 +189,7 @@ cpio_getopt(struct cpio *cpio)
long_prefix = "-W "; /* For clearer errors. */
} else {
state = state_next_word;
- cpio->optarg = opt_word;
+ cpio->argument = opt_word;
}
}
}
@@ -202,7 +203,7 @@ cpio_getopt(struct cpio *cpio)
p = strchr(opt_word, '=');
if (p != NULL) {
optlength = (size_t)(p - opt_word);
- cpio->optarg = (char *)(uintptr_t)(p + 1);
+ cpio->argument = (char *)(uintptr_t)(p + 1);
} else {
optlength = strlen(opt_word);
}
@@ -241,9 +242,9 @@ cpio_getopt(struct cpio *cpio)
/* We've found a unique match; does it need an argument? */
if (match->required) {
/* Argument required: get next word if necessary. */
- if (cpio->optarg == NULL) {
- cpio->optarg = *cpio->argv;
- if (cpio->optarg == NULL) {
+ if (cpio->argument == NULL) {
+ cpio->argument = *cpio->argv;
+ if (cpio->argument == NULL) {
lafe_warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
@@ -254,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
}
} else {
/* Argument forbidden: fail if there is one. */
- if (cpio->optarg != NULL) {
+ if (cpio->argument != NULL) {
lafe_warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
@@ -340,7 +341,7 @@ owner_parse(const char *spec, int *uid, int *gid)
} else {
char *end;
errno = 0;
- *uid = strtoul(user, &end, 10);
+ *uid = (int)strtoul(user, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user);
@@ -358,7 +359,7 @@ owner_parse(const char *spec, int *uid, int *gid)
} else {
char *end;
errno = 0;
- *gid = strtoul(g, &end, 10);
+ *gid = (int)strtoul(g, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g);
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 29f405c091ee..025c50cfafd2 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -50,9 +50,15 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
@@ -69,9 +75,6 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
@@ -136,6 +139,16 @@ main(int argc, char *argv[])
cpio->buff = buff;
cpio->buff_size = sizeof(buff);
+#if defined(HAVE_SIGACTION) && defined(SIGPIPE)
+ { /* Ignore SIGPIPE signals. */
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, NULL);
+ }
+#endif
+
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
lafe_progname = "bsdcpio";
@@ -150,6 +163,10 @@ main(int argc, char *argv[])
else
lafe_progname = *argv;
}
+#if HAVE_SETLOCALE
+ if (setlocale(LC_ALL, "") == NULL)
+ lafe_warnc(0, "Failed to set default locale");
+#endif
cpio->uid_override = -1;
cpio->gid_override = -1;
@@ -187,9 +204,9 @@ main(int argc, char *argv[])
cpio->bytes_per_block = 5120;
break;
case 'C': /* NetBSD/OpenBSD */
- cpio->bytes_per_block = atoi(cpio->optarg);
+ cpio->bytes_per_block = atoi(cpio->argument);
if (cpio->bytes_per_block <= 0)
- lafe_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
+ lafe_errc(1, 0, "Invalid blocksize %s", cpio->argument);
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";
@@ -199,22 +216,22 @@ main(int argc, char *argv[])
break;
case 'E': /* NetBSD/OpenBSD */
lafe_include_from_file(&cpio->matching,
- cpio->optarg, cpio->option_null);
+ cpio->argument, cpio->option_null);
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'f': /* POSIX 1997 */
- lafe_exclude(&cpio->matching, cpio->optarg);
+ lafe_exclude(&cpio->matching, cpio->argument);
break;
case 'H': /* GNU cpio (also --format) */
- cpio->format = cpio->optarg;
+ cpio->format = cpio->argument;
break;
case 'h':
long_help();
break;
case 'I': /* NetBSD/OpenBSD */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'i': /* POSIX 1997 */
if (cpio->mode != '\0')
@@ -251,7 +268,7 @@ main(int argc, char *argv[])
cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
case 'O': /* GNU cpio */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'o': /* POSIX 1997 */
if (cpio->mode != '\0')
@@ -275,7 +292,7 @@ main(int argc, char *argv[])
case 'R': /* GNU cpio, also --owner */
/* TODO: owner_parse should return uname/gname
* also; use that to set [ug]name_override. */
- errmsg = owner_parse(cpio->optarg, &uid, &gid);
+ errmsg = owner_parse(cpio->argument, &uid, &gid);
if (errmsg) {
lafe_warnc(-1, "%s", errmsg);
usage();
@@ -302,6 +319,9 @@ main(int argc, char *argv[])
case 'v': /* POSIX 1997 */
cpio->verbose++;
break;
+ case 'V': /* GNU cpio */
+ cpio->dot++;
+ break;
case OPTION_VERSION: /* GNU convention */
version();
break;
@@ -345,6 +365,12 @@ main(int argc, char *argv[])
/* -l requires -p */
if (cpio->option_link && cpio->mode != 'p')
lafe_errc(1, 0, "Option -l requires -p");
+ /* -v overrides -V */
+ if (cpio->dot && cpio->verbose)
+ cpio->dot = 0;
+ /* -v overrides -V */
+ if (cpio->dot && cpio->verbose)
+ cpio->dot = 0;
/* TODO: Flag other nonsensical combinations. */
switch (cpio->mode) {
@@ -402,7 +428,7 @@ static const char *long_help_msg =
"First option must be a mode specifier:\n"
" -i Input -o Output -p Pass\n"
"Common Options:\n"
- " -v Verbose\n"
+ " -v Verbose filenames -V one dot per file\n"
"Create: %p -o [options] < [list of files] > [archive]\n"
" -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
" --format {odc|newc|ustar} Select archive format\n"
@@ -451,7 +477,7 @@ version(void)
{
fprintf(stdout,"bsdcpio %s -- %s\n",
BSDCPIO_VERSION_STRING,
- archive_version());
+ archive_version_string());
exit(0);
}
@@ -533,6 +559,8 @@ mode_out(struct cpio *cpio)
}
r = archive_write_close(cpio->archive);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
@@ -543,7 +571,7 @@ mode_out(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_write_finish(cpio->archive);
+ archive_write_free(cpio->archive);
}
/*
@@ -656,6 +684,8 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
/* Print out the destination name to the user. */
if (cpio->verbose)
fprintf(stderr,"%s", destpath);
+ if (cpio->dot)
+ fprintf(stderr, ".");
/*
* Option_link only makes sense in pass mode and for
@@ -725,7 +755,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
if (r == ARCHIVE_FATAL)
exit(1);
- if (r >= ARCHIVE_WARN && fd >= 0) {
+ if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
bytes_read = read(fd, cpio->buff, cpio->buff_size);
while (bytes_read > 0) {
r = archive_write_data(cpio->archive,
@@ -825,7 +855,7 @@ mode_in(struct cpio *cpio)
a = archive_read_new();
if (a == NULL)
lafe_errc(1, 0, "Couldn't allocate archive object");
- archive_read_support_compression_all(a);
+ archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
@@ -849,7 +879,9 @@ mode_in(struct cpio *cpio)
if (destpath == NULL)
continue;
if (cpio->verbose)
- fprintf(stdout, "%s\n", destpath);
+ fprintf(stderr, "%s\n", destpath);
+ if (cpio->dot)
+ fprintf(stderr, ".");
if (cpio->uid_override >= 0)
archive_entry_set_uid(entry, cpio->uid_override);
if (cpio->gid_override >= 0)
@@ -859,13 +891,16 @@ mode_in(struct cpio *cpio)
fprintf(stderr, "%s: %s\n",
archive_entry_pathname(entry),
archive_error_string(ext));
- } else if (archive_entry_size(entry) > 0) {
+ } else if (!archive_entry_size_is_set(entry)
+ || archive_entry_size(entry) > 0) {
r = extract_data(a, ext);
if (r != ARCHIVE_OK)
cpio->return_value = 1;
}
}
r = archive_read_close(a);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
r = archive_write_close(ext);
@@ -877,8 +912,8 @@ mode_in(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_read_finish(a);
- archive_write_finish(ext);
+ archive_read_free(a);
+ archive_write_free(ext);
exit(cpio->return_value);
}
@@ -892,7 +927,7 @@ extract_data(struct archive *ar, struct archive *aw)
int r;
size_t size;
const void *block;
- off_t offset;
+ int64_t offset;
for (;;) {
r = archive_read_data_block(ar, &block, &size, &offset);
@@ -922,7 +957,7 @@ mode_list(struct cpio *cpio)
a = archive_read_new();
if (a == NULL)
lafe_errc(1, 0, "Couldn't allocate archive object");
- archive_read_support_compression_all(a);
+ archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
@@ -952,7 +987,7 @@ mode_list(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_read_finish(a);
+ archive_read_free(a);
exit(0);
}
@@ -989,11 +1024,11 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
/* Use uname if it's present, else lookup name from uid. */
uname = archive_entry_uname(entry);
if (uname == NULL)
- uname = lookup_uname(cpio, archive_entry_uid(entry));
+ uname = lookup_uname(cpio, (uid_t)archive_entry_uid(entry));
/* Use gname if it's present, else lookup name from gid. */
gname = archive_entry_gname(entry);
if (gname == NULL)
- gname = lookup_gname(cpio, archive_entry_gid(entry));
+ gname = lookup_gname(cpio, (uid_t)archive_entry_gid(entry));
}
/* Print device number or file size. */
@@ -1075,6 +1110,8 @@ mode_pass(struct cpio *cpio, const char *destdir)
archive_entry_linkresolver_free(cpio->linkresolver);
r = archive_write_close(cpio->archive);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
@@ -1086,7 +1123,7 @@ mode_pass(struct cpio *cpio, const char *destdir)
blocks == 1 ? "block" : "blocks");
}
- archive_write_finish(cpio->archive);
+ archive_write_free(cpio->archive);
}
/*
@@ -1260,8 +1297,9 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
const char *
cpio_i64toa(int64_t n0)
{
- // 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
- // We also need 1 byte for '-' and 1 for '\0'.
+ /* 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
+ * We also need 1 byte for '-' and 1 for '\0'.
+ */
static char buff[22];
int64_t n = n0 < 0 ? -n0 : n0;
char *p = buff + sizeof(buff);
diff --git a/cpio/cpio.h b/cpio/cpio.h
index a86e924a7a77..dc68e66a6fed 100644
--- a/cpio/cpio.h
+++ b/cpio/cpio.h
@@ -43,18 +43,18 @@
*/
struct cpio {
/* Option parsing */
- const char *optarg;
+ const char *argument;
/* Options */
const char *filename;
- char mode; /* -i -o -p */
- char compress; /* -j, -y, or -z */
+ int mode; /* -i -o -p */
+ int compress; /* -j, -y, or -z */
const char *format; /* -H format */
int bytes_per_block; /* -b block_size */
int verbose; /* -v */
+ int dot; /* -V */
int quiet; /* --quiet */
int extract_flags; /* Flags for extract operation */
- char symlink_mode; /* H or L, per BSD conventions */
const char *compress_program;
int option_append; /* -A, only relevant for -o */
int option_atime_restore; /* -a */
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index a822bcdfba5b..2196c19aed0d 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -15,6 +15,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
test_cmdline.c
test_format_newc.c
test_gcpio_compat.c
+ test_option_0.c
test_option_B_upper.c
test_option_C_upper.c
test_option_J_upper.c
@@ -38,9 +39,6 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
test_passthrough_reverse.c
test_pathmatch.c
)
- IF(WIN32 AND NOT CYGWIN)
- LIST(APPEND bsdcpio_test_SOURCES ../cpio_windows.h)
- ENDIF(WIN32 AND NOT CYGWIN)
#
# Register target
@@ -60,7 +58,7 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
# test. We can use that to define the tests for cmake by
# defining a DEFINE_TEST macro and reading list.h in.
MACRO (DEFINE_TEST _testname)
- ADD_TEST_28(
+ ADD_TEST(
NAME bsdcpio_${_testname}
COMMAND bsdcpio_test -vv
-p $<TARGET_FILE:bsdcpio>
diff --git a/cpio/test/main.c b/cpio/test/main.c
index 90336a9e630d..d9e6c302bbb7 100644
--- a/cpio/test/main.c
+++ b/cpio/test/main.c
@@ -24,8 +24,18 @@
*/
#include "test.h"
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#include <errno.h>
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#include <limits.h>
#include <locale.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#include <stdarg.h>
#include <time.h>
@@ -40,8 +50,10 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kient
#define KNOWNREF "test_option_f.cpio.uu"
#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
#define PROGRAM "bsdcpio" /* Name of program being tested. */
-#undef LIBRARY /* Not testing a library. */
-#undef EXTRA_DUMP /* How to dump extra data */
+#define PROGRAM_ALIAS "cpio" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
/* How to generate extra version info. */
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
@@ -78,6 +90,7 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kient
#endif
#if !defined(__BORLANDC__)
#define access _access
+#undef chdir
#define chdir _chdir
#endif
#ifndef fileno
@@ -150,7 +163,7 @@ my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
memset(bhfi, 0, sizeof(*bhfi));
h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
return (0);
r = GetFileInformationByHandle(h, bhfi);
@@ -179,6 +192,8 @@ invalid_parameter_handler(const wchar_t * expression,
static int dump_on_failure = 0;
/* Default is to remove temp dirs and log data for successful tests. */
static int keep_temp_files = 0;
+/* Default is to run the specified tests once and report errors. */
+static int until_failure = 0;
/* Default is to just report pass/fail for each test. */
static int verbosity = 0;
#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
@@ -236,10 +251,14 @@ void
failure(const char *fmt, ...)
{
va_list ap;
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
+ if (fmt == NULL) {
+ nextmsg = NULL;
+ } else {
+ va_start(ap, fmt);
+ vsprintf(msgbuff, fmt, ap);
+ va_end(ap);
+ nextmsg = msgbuff;
+ }
}
/*
@@ -251,15 +270,14 @@ failure(const char *fmt, ...)
* pass __FILE__, __LINE__ directly into the function instead of using
* this hook. I suspect this machinery is used so rarely that we
* would be better off just removing it entirely. That would simplify
- * the code here noticably.
+ * the code here noticeably.
*/
-static const char *test_filename;
-static int test_line;
-static void *test_extra;
-void assertion_setup(const char *filename, int line)
+static const char *skipping_filename;
+static int skipping_line;
+void skipping_setup(const char *filename, int line)
{
- test_filename = filename;
- test_line = line;
+ skipping_filename = filename;
+ skipping_line = line;
}
/* Called at the beginning of each assert() function. */
@@ -286,6 +304,7 @@ static struct line {
int count;
int skip;
} failed_lines[10000];
+const char *failed_filename;
/* Count this failure, setup up log destination and handle initial report. */
static void
@@ -295,19 +314,16 @@ failure_start(const char *filename, int line, const char *fmt, ...)
/* Record another failure for this line. */
++failures;
- /* test_filename = filename; */
+ failed_filename = filename;
failed_lines[line].count++;
/* Determine whether to log header to console. */
switch (verbosity) {
- case VERBOSITY_FULL:
- log_console = 1;
- break;
case VERBOSITY_LIGHT_REPORT:
log_console = (failed_lines[line].count < 2);
break;
default:
- log_console = 0;
+ log_console = (verbosity >= VERBOSITY_FULL);
}
/* Log file:line header for this failure */
@@ -343,14 +359,16 @@ failure_finish(void *extra)
{
(void)extra; /* UNUSED (maybe) */
#ifdef EXTRA_DUMP
- if (extra != NULL)
+ if (extra != NULL) {
+ logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
logprintf(" detail: %s\n", EXTRA_DUMP(extra));
+ }
#endif
if (dump_on_failure) {
fprintf(stderr,
" *** forcing core dump so failure can be debugged ***\n");
- *(char *)(NULL) = 0;
+ abort();
exit(1);
}
}
@@ -365,12 +383,15 @@ test_skipping(const char *fmt, ...)
va_start(ap, fmt);
vsprintf(buff, fmt, ap);
va_end(ap);
+ /* Use failure() message if set. */
+ msg = nextmsg;
+ nextmsg = NULL;
/* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(test_filename, test_line, "SKIPPING: %s", buff);
+ failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
--failures; /* Undo failures++ in failure_start() */
/* Don't failure_finish() here. */
/* Mark as skip, so doesn't count as failed test. */
- failed_lines[test_line].skip = 1;
+ failed_lines[skipping_line].skip = 1;
++skips;
}
@@ -421,13 +442,102 @@ assertion_equal_int(const char *file, int line,
return (0);
}
-static void strdump(const char *e, const char *p)
+/*
+ * Utility to convert a single UTF-8 sequence.
+ */
+static int
+_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
+{
+ static const char utf8_count[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
+ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
+ };
+ int ch;
+ int cnt;
+ uint32_t wc;
+
+ *pwc = 0;
+
+ /* Sanity check. */
+ if (n == 0)
+ return (0);
+ /*
+ * Decode 1-4 bytes depending on the value of the first byte.
+ */
+ ch = (unsigned char)*s;
+ if (ch == 0)
+ return (0); /* Standard: return 0 for end-of-string. */
+ cnt = utf8_count[ch];
+
+ /* Invalide sequence or there are not plenty bytes. */
+ if (n < (size_t)cnt)
+ return (-1);
+
+ /* Make a Unicode code point from a single UTF-8 sequence. */
+ switch (cnt) {
+ case 1: /* 1 byte sequence. */
+ *pwc = ch & 0x7f;
+ return (cnt);
+ case 2: /* 2 bytes sequence. */
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
+ return (cnt);
+ case 3: /* 3 bytes sequence. */
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ if ((s[2] & 0xc0) != 0x80) return (-1);
+ wc = ((ch & 0x0f) << 12)
+ | ((s[1] & 0x3f) << 6)
+ | (s[2] & 0x3f);
+ if (wc < 0x800)
+ return (-1);/* Overlong sequence. */
+ break;
+ case 4: /* 4 bytes sequence. */
+ if (n < 4)
+ return (-1);
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ if ((s[2] & 0xc0) != 0x80) return (-1);
+ if ((s[3] & 0xc0) != 0x80) return (-1);
+ wc = ((ch & 0x07) << 18)
+ | ((s[1] & 0x3f) << 12)
+ | ((s[2] & 0x3f) << 6)
+ | (s[3] & 0x3f);
+ if (wc < 0x10000)
+ return (-1);/* Overlong sequence. */
+ break;
+ default:
+ return (-1);
+ }
+
+ /* The code point larger than 0x10FFFF is not leagal
+ * Unicode values. */
+ if (wc > 0x10FFFF)
+ return (-1);
+ /* Correctly gets a Unicode, returns used bytes. */
+ *pwc = wc;
+ return (cnt);
+}
+
+static void strdump(const char *e, const char *p, int ewidth, int utf8)
{
const char *q = p;
- logprintf(" %s = ", e);
+ logprintf(" %*s = ", ewidth, e);
if (p == NULL) {
- logprintf("NULL");
+ logprintf("NULL\n");
return;
}
logprintf("\"");
@@ -446,7 +556,37 @@ static void strdump(const char *e, const char *p)
}
}
logprintf("\"");
- logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q));
+ logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
+
+ /*
+ * If the current string is UTF-8, dump its code points.
+ */
+ if (utf8) {
+ size_t len;
+ uint32_t uc;
+ int n;
+ int cnt = 0;
+
+ p = q;
+ len = strlen(p);
+ logprintf(" [");
+ while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
+ if (p != q)
+ logprintf(" ");
+ logprintf("%04X", uc);
+ p += n;
+ len -= n;
+ cnt++;
+ }
+ logprintf("]");
+ logprintf(" (count %d", cnt);
+ if (n < 0) {
+ logprintf(",unknown %d bytes", len);
+ }
+ logprintf(")");
+
+ }
+ logprintf("\n");
}
/* Verify two strings are equal, dump them if not. */
@@ -454,14 +594,20 @@ int
assertion_equal_string(const char *file, int line,
const char *v1, const char *e1,
const char *v2, const char *e2,
- void *extra)
+ void *extra, int utf8)
{
+ int l1, l2;
+
assertion_count(file, line);
if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
return (1);
failure_start(file, line, "%s != %s", e1, e2);
- strdump(e1, v1);
- strdump(e2, v2);
+ l1 = strlen(e1);
+ l2 = strlen(e2);
+ if (l1 < l2)
+ l1 = l2;
+ strdump(e1, v1, l1, utf8);
+ strdump(e2, v2, l1, utf8);
failure_finish(extra);
return (0);
}
@@ -513,7 +659,9 @@ assertion_equal_wstring(const char *file, int line,
void *extra)
{
assertion_count(file, line);
- if (v1 == v2 || wcscmp(v1, v2) == 0)
+ if (v1 == v2)
+ return (1);
+ if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
return (1);
failure_start(file, line, "%s != %s", e1, e2);
wcsdump(e1, v1);
@@ -592,9 +740,9 @@ assertion_equal_mem(const char *file, int line,
offset += 16;
}
logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 64 ? l : 64, offset);
+ hexdump(v1, v2, l < 128 ? l : 128, offset);
logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 64 ? l : 64, offset);
+ hexdump(v2, v1, l < 128 ? l : 128, offset);
logprintf("\n");
failure_finish(extra);
return (0);
@@ -602,29 +750,24 @@ assertion_equal_mem(const char *file, int line,
/* Verify that the named file exists and is empty. */
int
-assertion_empty_file(const char *f1fmt, ...)
+assertion_empty_file(const char *filename, int line, const char *f1)
{
char buff[1024];
- char f1[1024];
struct stat st;
- va_list ap;
ssize_t s;
FILE *f;
- assertion_count(test_filename, test_line);
- va_start(ap, f1fmt);
- vsprintf(f1, f1fmt, ap);
- va_end(ap);
+ assertion_count(filename, line);
if (stat(f1, &st) != 0) {
- failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_start(filename, line, "Stat failed: %s", f1);
failure_finish(NULL);
return (0);
}
if (st.st_size == 0)
return (1);
- failure_start(test_filename, test_line, "File should be empty: %s", f1);
+ failure_start(filename, line, "File should be empty: %s", f1);
logprintf(" File size: %d\n", (int)st.st_size);
logprintf(" Contents:\n");
f = fopen(f1, "rb");
@@ -643,24 +786,19 @@ assertion_empty_file(const char *f1fmt, ...)
/* Verify that the named file exists and is not empty. */
int
-assertion_non_empty_file(const char *f1fmt, ...)
+assertion_non_empty_file(const char *filename, int line, const char *f1)
{
- char f1[1024];
struct stat st;
- va_list ap;
- assertion_count(test_filename, test_line);
- va_start(ap, f1fmt);
- vsprintf(f1, f1fmt, ap);
- va_end(ap);
+ assertion_count(filename, line);
if (stat(f1, &st) != 0) {
- failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_start(filename, line, "Stat failed: %s", f1);
failure_finish(NULL);
return (0);
}
if (st.st_size == 0) {
- failure_start(test_filename, test_line, "File empty: %s", f1);
+ failure_start(filename, line, "File empty: %s", f1);
failure_finish(NULL);
return (0);
}
@@ -670,19 +808,14 @@ assertion_non_empty_file(const char *f1fmt, ...)
/* Verify that two files have the same contents. */
/* TODO: hexdump the first bytes that actually differ. */
int
-assertion_equal_file(const char *fn1, const char *f2pattern, ...)
+assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
{
- char fn2[1024];
- va_list ap;
char buff1[1024];
char buff2[1024];
FILE *f1, *f2;
int n1, n2;
- assertion_count(test_filename, test_line);
- va_start(ap, f2pattern);
- vsprintf(fn2, f2pattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
f1 = fopen(fn1, "rb");
f2 = fopen(fn2, "rb");
@@ -701,24 +834,18 @@ assertion_equal_file(const char *fn1, const char *f2pattern, ...)
}
fclose(f1);
fclose(f2);
- failure_start(test_filename, test_line, "Files not identical");
+ failure_start(filename, line, "Files not identical");
logprintf(" file1=\"%s\"\n", fn1);
logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
/* Verify that the named file does exist. */
int
-assertion_file_exists(const char *fpattern, ...)
+assertion_file_exists(const char *filename, int line, const char *f)
{
- char f[1024];
- va_list ap;
-
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(f, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!_access(f, 0))
@@ -727,22 +854,16 @@ assertion_file_exists(const char *fpattern, ...)
if (!access(f, F_OK))
return (1);
#endif
- failure_start(test_filename, test_line, "File should exist: %s", f);
- failure_finish(test_extra);
+ failure_start(filename, line, "File should exist: %s", f);
+ failure_finish(NULL);
return (0);
}
/* Verify that the named file doesn't exist. */
int
-assertion_file_not_exists(const char *fpattern, ...)
+assertion_file_not_exists(const char *filename, int line, const char *f)
{
- char f[1024];
- va_list ap;
-
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(f, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
if (_access(f, 0))
@@ -751,31 +872,26 @@ assertion_file_not_exists(const char *fpattern, ...)
if (access(f, F_OK))
return (1);
#endif
- failure_start(test_filename, test_line, "File should not exist: %s", f);
- failure_finish(test_extra);
+ failure_start(filename, line, "File should not exist: %s", f);
+ failure_finish(NULL);
return (0);
}
/* Compare the contents of a file to a block of memory. */
int
-assertion_file_contents(const void *buff, int s, const char *fpattern, ...)
+assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
{
- char fn[1024];
- va_list ap;
char *contents;
FILE *f;
int n;
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(fn, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
f = fopen(fn, "rb");
if (f == NULL) {
- failure_start(test_filename, test_line,
+ failure_start(filename, line,
"File should exist: %s", fn);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
contents = malloc(s * 2);
@@ -785,34 +901,34 @@ assertion_file_contents(const void *buff, int s, const char *fpattern, ...)
free(contents);
return (1);
}
- failure_start(test_filename, test_line, "File contents don't match");
+ failure_start(filename, line, "File contents don't match");
logprintf(" file=\"%s\"\n", fn);
if (n > 0)
hexdump(contents, buff, n > 512 ? 512 : n, 0);
else {
logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : n, 0);
+ hexdump(buff, NULL, s > 512 ? 512 : s, 0);
}
- failure_finish(test_extra);
+ failure_finish(NULL);
free(contents);
return (0);
}
/* Check the contents of a text file, being tolerant of line endings. */
int
-assertion_text_file_contents(const char *buff, const char *fn)
+assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
{
char *contents;
const char *btxt, *ftxt;
FILE *f;
int n, s;
- assertion_count(test_filename, test_line);
+ assertion_count(filename, line);
f = fopen(fn, "r");
if (f == NULL) {
- failure_start(test_filename, test_line,
+ failure_start(filename, line,
"File doesn't exist: %s", fn);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
s = strlen(buff);
@@ -842,19 +958,122 @@ assertion_text_file_contents(const char *buff, const char *fn)
free(contents);
return (1);
}
- failure_start(test_filename, test_line, "Contents don't match");
+ failure_start(filename, line, "Contents don't match");
logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
+ if (n > 0) {
hexdump(contents, buff, n, 0);
- else {
+ logprintf(" expected\n", fn);
+ hexdump(buff, contents, s, 0);
+ } else {
logprintf(" File empty, contents should be:\n");
hexdump(buff, NULL, s, 0);
}
- failure_finish(test_extra);
+ failure_finish(NULL);
free(contents);
return (0);
}
+/* Verify that a text file contains the specified lines, regardless of order */
+/* This could be more efficient if we sorted both sets of lines, etc, but
+ * since this is used only for testing and only ever deals with a dozen or so
+ * lines at a time, this relatively crude approach is just fine. */
+int
+assertion_file_contains_lines_any_order(const char *file, int line,
+ const char *pathname, const char *lines[])
+{
+ char *buff;
+ size_t buff_size;
+ size_t expected_count, actual_count, i, j;
+ char **expected;
+ char *p, **actual;
+ char c;
+ int expected_failure = 0, actual_failure = 0;
+
+ assertion_count(file, line);
+
+ buff = slurpfile(&buff_size, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(pathname, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ /* Make a copy of the provided lines and count up the expected file size. */
+ expected_count = 0;
+ for (i = 0; lines[i] != NULL; ++i) {
+ }
+ expected_count = i;
+ expected = malloc(sizeof(char *) * expected_count);
+ for (i = 0; lines[i] != NULL; ++i) {
+ expected[i] = strdup(lines[i]);
+ }
+
+ /* Break the file into lines */
+ actual_count = 0;
+ for (c = '\0', p = buff; p < buff + buff_size; ++p) {
+ if (*p == '\x0d' || *p == '\x0a')
+ *p = '\0';
+ if (c == '\0' && *p != '\0')
+ ++actual_count;
+ c = *p;
+ }
+ actual = malloc(sizeof(char *) * actual_count);
+ for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ if (*p != '\0') {
+ actual[j] = p;
+ ++j;
+ }
+ }
+
+ /* Erase matching lines from both lists */
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] == NULL)
+ continue;
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] == NULL)
+ continue;
+ if (strcmp(expected[i], actual[j]) == 0) {
+ free(expected[i]);
+ expected[i] = NULL;
+ actual[j] = NULL;
+ break;
+ }
+ }
+ }
+
+ /* If there's anything left, it's a failure */
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] != NULL)
+ ++expected_failure;
+ }
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] != NULL)
+ ++actual_failure;
+ }
+ if (expected_failure == 0 && actual_failure == 0) {
+ free(buff);
+ free(expected);
+ free(actual);
+ return (1);
+ }
+ failure_start(file, line, "File doesn't match: %s", pathname);
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] != NULL) {
+ logprintf(" Expected but not present: %s\n", expected[i]);
+ free(expected[i]);
+ }
+ }
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] != NULL)
+ logprintf(" Present but not expected: %s\n", actual[j]);
+ }
+ failure_finish(NULL);
+ free(buff);
+ free(expected);
+ free(actual);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -944,8 +1163,11 @@ assertion_file_time(const char *file, int line,
ftime.dwHighDateTime = 0;
assertion_count(file, line);
+ /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
+ * a directory file. If not, CreateFile() will fail when
+ * the pathname is a directory. */
h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
failure_start(file, line, "Can't access %s\n", pathname);
failure_finish(NULL);
@@ -1010,14 +1232,14 @@ assertion_file_time(const char *file, int line,
time_t now = time(NULL);
if (filet < now - 10 || filet > now + 1) {
failure_start(file, line,
- "File %s has %ctime %ld, %ld seconds ago\n",
+ "File %s has %ctime %lld, %lld seconds ago\n",
pathname, type, filet, now - filet);
failure_finish(NULL);
return (0);
}
} else if (filet != t || filet_nsec != nsec) {
failure_start(file, line,
- "File %s has %ctime %ld.%09ld, expected %ld.%09ld",
+ "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
pathname, type, filet, filet_nsec, t, nsec);
failure_finish(NULL);
return (0);
@@ -1390,6 +1612,110 @@ assertion_umask(const char *file, int line, int mask)
return (1);
}
+/* Set times, report failures. */
+int
+assertion_utimes(const char *file, int line,
+ const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
+{
+ int r;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
+ + (((nsec)/1000)*10))
+ HANDLE h;
+ ULARGE_INTEGER wintm;
+ FILETIME fatime, fmtime;
+ FILETIME *pat, *pmt;
+
+ assertion_count(file, line);
+ h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ failure_start(file, line, "Can't access %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ if (at > 0 || at_nsec > 0) {
+ wintm.QuadPart = WINTIME(at, at_nsec);
+ fatime.dwLowDateTime = wintm.LowPart;
+ fatime.dwHighDateTime = wintm.HighPart;
+ pat = &fatime;
+ } else
+ pat = NULL;
+ if (mt > 0 || mt_nsec > 0) {
+ wintm.QuadPart = WINTIME(mt, mt_nsec);
+ fmtime.dwLowDateTime = wintm.LowPart;
+ fmtime.dwHighDateTime = wintm.HighPart;
+ pmt = &fmtime;
+ } else
+ pmt = NULL;
+ if (pat != NULL || pmt != NULL)
+ r = SetFileTime(h, NULL, pat, pmt);
+ else
+ r = 1;
+ CloseHandle(h);
+ if (r == 0) {
+ failure_start(file, line, "Can't SetFileTime %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+#else /* defined(_WIN32) && !defined(__CYGWIN__) */
+ struct stat st;
+ struct timeval times[2];
+
+#if !defined(__FreeBSD__)
+ mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
+#endif
+ if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
+ return (1);
+
+ r = lstat(pathname, &st);
+ if (r < 0) {
+ failure_start(file, line, "Can't stat %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ if (mt == 0 && mt_nsec == 0) {
+ mt = st.st_mtime;
+#if defined(__FreeBSD__)
+ mt_nsec = st.st_mtimespec.tv_nsec;
+ /* FreeBSD generally only stores to microsecond res, so round. */
+ mt_nsec = (mt_nsec / 1000) * 1000;
+#endif
+ }
+ if (at == 0 && at_nsec == 0) {
+ at = st.st_atime;
+#if defined(__FreeBSD__)
+ at_nsec = st.st_atimespec.tv_nsec;
+ /* FreeBSD generally only stores to microsecond res, so round. */
+ at_nsec = (at_nsec / 1000) * 1000;
+#endif
+ }
+
+ times[1].tv_sec = mt;
+ times[1].tv_usec = mt_nsec / 1000;
+
+ times[0].tv_sec = at;
+ times[0].tv_usec = at_nsec / 1000;
+
+#ifdef HAVE_LUTIMES
+ r = lutimes(pathname, times);
+#else
+ r = utimes(pathname, times);
+#endif
+ if (r < 0) {
+ failure_start(file, line, "Can't utimes %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
+}
+
/*
*
* UTILITIES for use by tests.
@@ -1615,6 +1941,27 @@ extract_reference_file(const char *name)
fclose(in);
}
+int
+is_LargeInode(const char *file)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ int r;
+
+ r = my_GetFileInformationByName(file, &bhfi);
+ if (r != 0)
+ return (0);
+ return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
+#else
+ struct stat st;
+ int64_t ino;
+
+ if (stat(file, &st) < 0)
+ return (0);
+ ino = (int64_t)st.st_ino;
+ return (ino > 0xffffffff);
+#endif
+}
/*
*
* TEST management
@@ -1644,7 +1991,7 @@ struct { void (*func)(void); const char *name; int failures; } tests[] = {
* Summarize repeated failures in the just-completed test.
*/
static void
-test_summarize(const char *filename, int failed)
+test_summarize(int failed)
{
unsigned int i;
@@ -1663,9 +2010,10 @@ test_summarize(const char *filename, int failed)
for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
if (failed_lines[i].count > 1 && !failed_lines[i].skip)
logprintf("%s:%d: Summary: Failed %d times\n",
- filename, i, failed_lines[i].count);
+ failed_filename, i, failed_lines[i].count);
}
/* Clear the failure history for the next file. */
+ failed_filename = NULL;
memset(failed_lines, 0, sizeof(failed_lines));
}
@@ -1675,6 +2023,7 @@ test_summarize(const char *filename, int failed)
static int
test_run(int i, const char *tmpdir)
{
+ char workdir[1024];
char logfilename[64];
int failures_before = failures;
int oldumask;
@@ -1701,11 +2050,12 @@ test_run(int i, const char *tmpdir)
logfile = fopen(logfilename, "w");
fprintf(logfile, "%s\n\n", tests[i].name);
/* Chdir() to a work dir for this specific test. */
- if (!assertMakeDir(tests[i].name, 0755)
- || !assertChdir(tests[i].name)) {
+ snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
+ testworkdir = workdir;
+ if (!assertMakeDir(testworkdir, 0755)
+ || !assertChdir(testworkdir)) {
fprintf(stderr,
- "ERROR: Can't chdir to work dir %s/%s\n",
- tmpdir, tests[i].name);
+ "ERROR: Can't chdir to work dir %s\n", testworkdir);
exit(1);
}
/* Explicitly reset the locale before each test. */
@@ -1719,6 +2069,7 @@ test_run(int i, const char *tmpdir)
/*
* Clean up and report afterwards.
*/
+ testworkdir = NULL;
/* Restore umask */
umask(oldumask);
/* Reset locale. */
@@ -1731,7 +2082,7 @@ test_run(int i, const char *tmpdir)
}
/* Report per-test summaries. */
tests[i].failures = failures - failures_before;
- test_summarize(test_filename, tests[i].failures);
+ test_summarize(tests[i].failures);
/* Close the per-test log file. */
fclose(logfile);
logfile = NULL;
@@ -1791,6 +2142,7 @@ usage(const char *program)
printf(" -q Quiet.\n");
printf(" -r <dir> Path to dir containing reference files.\n");
printf(" Default: Current directory.\n");
+ printf(" -u Keep running specifies tests until one fails.\n");
printf(" -v Verbose.\n");
printf("Available tests:\n");
for (i = 0; i < limit; i++)
@@ -1817,7 +2169,11 @@ get_refdir(const char *d)
}
/* Get the current dir. */
+#ifdef PATH_MAX
+ pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
+#else
pwd = getcwd(NULL, 0);
+#endif
while (pwd[strlen(pwd) - 1] == '\n')
pwd[strlen(pwd) - 1] = '\0';
@@ -1844,6 +2200,14 @@ get_refdir(const char *d)
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+#if defined(PROGRAM_ALIAS)
+ snprintf(buff, sizeof(buff), "%s/%s/test", pwd, PROGRAM_ALIAS);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+#endif
+
if (memcmp(pwd, "/usr/obj", 8) == 0) {
snprintf(buff, sizeof(buff), "%s", pwd + 8);
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
@@ -1876,16 +2240,26 @@ int
main(int argc, char **argv)
{
static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i, tests_run = 0, tests_failed = 0, option;
+ int i = 0, j = 0, start, end, tests_run = 0, tests_failed = 0, option;
time_t now;
char *refdir_alloc = NULL;
const char *progname;
+ char **saved_argv;
const char *tmp, *option_arg, *p;
- char tmpdir[256];
+ char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL;
char tmpdir_timestamp[256];
(void)argc; /* UNUSED */
+ /* Get the current dir. */
+#ifdef PATH_MAX
+ pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
+#else
+ pwd = getcwd(NULL, 0);
+#endif
+ while (pwd[strlen(pwd) - 1] == '\n')
+ pwd[strlen(pwd) - 1] = '\0';
+
#if defined(HAVE__CrtSetReportMode)
/* To stop to run the default invalid parameter handler. */
_set_invalid_parameter_handler(invalid_parameter_handler);
@@ -1898,11 +2272,35 @@ main(int argc, char **argv)
* tree.
*/
progname = p = argv[0];
+ if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ strcpy(testprogdir, progname);
while (*p != '\0') {
/* Support \ or / dir separators for Windows compat. */
if (*p == '/' || *p == '\\')
+ {
progname = p + 1;
+ i = j;
+ }
++p;
+ j++;
+ }
+ testprogdir[i] = '\0';
+ if (testprogdir[0] != '/')
+ {
+ /* Fixup path for relative directories. */
+ if ((testprogdir = (char *)realloc(testprogdir,
+ strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ strcpy(testprogdir + strlen(pwd) + 1, testprogdir);
+ strcpy(testprogdir, pwd);
+ testprogdir[strlen(pwd)] = '/';
}
#ifdef PROGRAM
@@ -1967,6 +2365,7 @@ main(int argc, char **argv)
#ifdef PROGRAM
testprogfile = option_arg;
#else
+ fprintf(stderr, "-p option not permitted\n");
usage(progname);
#endif
break;
@@ -1976,10 +2375,15 @@ main(int argc, char **argv)
case 'r':
refdir = option_arg;
break;
+ case 'u':
+ until_failure++;
+ break;
case 'v':
verbosity++;
break;
default:
+ fprintf(stderr, "Unrecognized option '%c'\n",
+ option);
usage(progname);
}
}
@@ -1990,7 +2394,19 @@ main(int argc, char **argv)
*/
#ifdef PROGRAM
if (testprogfile == NULL)
- usage(progname);
+ {
+ if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
+ strlen(PROGRAM) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ strcpy(tmp2, testprogdir);
+ strcat(tmp2, "/");
+ strcat(tmp2, PROGRAM);
+ testprogfile = tmp2;
+ }
+
{
char *testprg;
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -2011,6 +2427,16 @@ main(int argc, char **argv)
}
#endif
+#if !defined(_WIN32) && defined(SIGPIPE)
+ { /* Ignore SIGPIPE signals */
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(SIGPIPE, &sa, NULL);
+ }
+#endif
+
/*
* Create a temp directory for the following tests.
* Include the time the tests started as part of the name,
@@ -2063,42 +2489,88 @@ main(int argc, char **argv)
/*
* Run some or all of the individual tests.
*/
- if (*argv == NULL) {
- /* Default: Run all tests. */
- for (i = 0; i < limit; i++) {
- if (test_run(i, tmpdir))
- tests_failed++;
- tests_run++;
- }
- } else {
- while (*(argv) != NULL) {
- if (**argv >= '0' && **argv <= '9') {
- i = atoi(*argv);
- if (i < 0 || i >= limit) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- usage(progname);
- /* usage() never returns */
+ saved_argv = argv;
+ do {
+ argv = saved_argv;
+ if (*argv == NULL) {
+ /* Default: Run all tests. */
+ for (i = 0; i < limit; i++) {
+ tests_run++;
+ if (test_run(i, tmpdir)) {
+ tests_failed++;
+ if (until_failure)
+ goto finish;
}
- } else {
- for (i = 0; i < limit; ++i) {
- if (strcmp(*argv, tests[i].name) == 0)
- break;
+ }
+ } else {
+ while (*(argv) != NULL) {
+ if (**argv >= '0' && **argv <= '9') {
+ char *p = *argv;
+ start = 0;
+ while (*p >= '0' && *p <= '9') {
+ start *= 10;
+ start += *p - '0';
+ ++p;
+ }
+ if (*p == '\0') {
+ end = start;
+ } else if (*p == '-') {
+ ++p;
+ if (*p == '\0') {
+ end = limit - 1;
+ } else {
+ end = 0;
+ while (*p >= '0' && *p <= '9') {
+ end *= 10;
+ end += *p - '0';
+ ++p;
+ }
+ }
+ } else {
+ printf("*** INVALID Test %s\n", *argv);
+ free(refdir_alloc);
+ usage(progname);
+ return (1);
+ }
+ if (start < 0 || end >= limit || start > end) {
+ printf("*** INVALID Test %s\n", *argv);
+ free(refdir_alloc);
+ usage(progname);
+ return (1);
+ }
+ } else {
+ for (start = 0; start < limit; ++start) {
+ if (strcmp(*argv, tests[start].name) == 0)
+ break;
+ }
+ end = start;
+ if (start >= limit) {
+ printf("*** INVALID Test ``%s''\n",
+ *argv);
+ free(refdir_alloc);
+ usage(progname);
+ /* usage() never returns */
+ }
}
- if (i >= limit) {
- printf("*** INVALID Test ``%s''\n",
- *argv);
- free(refdir_alloc);
- usage(progname);
- /* usage() never returns */
+ while (start <= end) {
+ tests_run++;
+ if (test_run(start, tmpdir)) {
+ tests_failed++;
+ if (until_failure)
+ goto finish;
+ }
+ ++start;
}
+ argv++;
}
- if (test_run(i, tmpdir))
- tests_failed++;
- tests_run++;
- argv++;
}
- }
+ } while (until_failure);
+
+finish:
+ /* Must be freed after all tests run */
+ free(tmp2);
+ free(testprogdir);
+ free(pwd);
/*
* Report summary statistics.
diff --git a/cpio/test/test.h b/cpio/test/test.h
index 2d68f3104d14..46124f84b20e 100644
--- a/cpio/test/test.h
+++ b/cpio/test/test.h
@@ -48,9 +48,6 @@
#include <sys/types.h> /* Windows requires this before sys/stat.h */
#include <sys/stat.h>
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
@@ -63,6 +60,9 @@
#ifdef HAVE_IO_H
#include <io.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -83,13 +83,9 @@
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "../cpio_windows.h"
#if !defined(__BORLANDC__)
#define strdup _strdup
#endif
-#define LOCALE_DE "deu"
-#else
-#define LOCALE_DE "de_DE.UTF-8"
#endif
/* Visual Studio */
@@ -97,13 +93,11 @@
#define snprintf sprintf_s
#endif
-/* Cygwin */
-#if defined(__CYGWIN__)
-/* Cygwin-1.7.x is lazy about populating nlinks, so don't
- * expect it to be accurate. */
-# define NLINKS_INACCURATE_FOR_DIRS
+#if defined(__BORLANDC__)
+#pragma warn -8068 /* Constant out of range in comparison. */
#endif
+/* Haiku OS and QNX */
#if defined(__HAIKU__) || defined(__QNXNTO__)
/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
#include <stdint.h>
@@ -139,24 +133,24 @@
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
+#define assertEqualUTF8String(v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert two files are the same; allow printf-style expansion of second name.
- * See below for comments about variable arguments here...
- */
-#define assertEqualFile \
- assertion_setup(__FILE__, __LINE__);assertion_equal_file
-/* Assert that a file is empty; supports printf-style arguments. */
-#define assertEmptyFile \
- assertion_setup(__FILE__, __LINE__);assertion_empty_file
-/* Assert that a file is not empty; supports printf-style arguments. */
-#define assertNonEmptyFile \
- assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
+/* Assert two files are the same. */
+#define assertEqualFile(f1, f2) \
+ assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
+/* Assert that a file is empty. */
+#define assertEmptyFile(pathname) \
+ assertion_empty_file(__FILE__, __LINE__, (pathname))
+/* Assert that a file is not empty. */
+#define assertNonEmptyFile(pathname) \
+ assertion_non_empty_file(__FILE__, __LINE__, (pathname))
#define assertFileAtime(pathname, sec, nsec) \
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileAtimeRecent(pathname) \
@@ -166,14 +160,14 @@
#define assertFileBirthtimeRecent(pathname) \
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists \
- assertion_setup(__FILE__, __LINE__);assertion_file_exists
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileNotExists \
- assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
-/* Assert that file contents match a string; supports printf-style arguments. */
-#define assertFileContents \
- assertion_setup(__FILE__, __LINE__);assertion_file_contents
+#define assertFileExists(pathname) \
+ assertion_file_exists(__FILE__, __LINE__, pathname)
+/* Assert that a file exists. */
+#define assertFileNotExists(pathname) \
+ assertion_file_not_exists(__FILE__, __LINE__, pathname)
+/* Assert that file contents match a string. */
+#define assertFileContents(data, data_size, pathname) \
+ assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -182,8 +176,10 @@
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertTextFileContents \
- assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
+#define assertTextFileContents(text, pathname) \
+ assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
+#define assertFileContainsLinesAnyOrder(pathname, lines) \
+ assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
#define assertIsHardlink(path1, path2) \
@@ -205,6 +201,8 @@
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
+#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
+ assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
/*
* This would be simple with C99 variadic macros, but I don't want to
@@ -213,28 +211,29 @@
* but effective.
*/
#define skipping \
- assertion_setup(__FILE__, __LINE__);test_skipping
+ skipping_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
void failure(const char *fmt, ...);
int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *);
-int assertion_empty_file(const char *, ...);
-int assertion_equal_file(const char *, const char *, ...);
+int assertion_empty_file(const char *, int, const char *);
+int assertion_equal_file(const char *, int, const char *, const char *);
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
+int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int assertion_file_atime(const char *, int, const char *, long, long);
int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contents(const void *, int, const char *, ...);
-int assertion_file_exists(const char *, ...);
+int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contents(const char *, int, const void *, int, const char *);
+int assertion_file_exists(const char *, int, const char *);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, ...);
+int assertion_file_not_exists(const char *, int, const char *);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
@@ -245,11 +244,12 @@ int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, const char *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_non_empty_file(const char *, ...);
-int assertion_text_file_contents(const char *buff, const char *f);
+int assertion_non_empty_file(const char *, int, const char *);
+int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
int assertion_umask(const char *, int, int);
-void assertion_setup(const char *, int);
+int assertion_utimes(const char *, int, const char *, long, long, long, long );
+void skipping_setup(const char *, int);
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
@@ -267,6 +267,9 @@ int canGzip(void);
/* Return true if this platform can run the "gunzip" program. */
int canGunzip(void);
+/* Return true if the file has large i-node number(>0xffffffff). */
+int is_LargeInode(const char *);
+
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
@@ -274,6 +277,9 @@ char *slurpfile(size_t *, const char *fmt, ...);
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
+/* Path to working directory for current test */
+const char *testworkdir;
+
/*
* Special interfaces for program test harness.
*/
@@ -283,3 +289,7 @@ const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
diff --git a/cpio/test/test_0.c b/cpio/test/test_0.c
index 75a1437fd70e..fa52def7eaf3 100644
--- a/cpio/test/test_0.c
+++ b/cpio/test/test_0.c
@@ -40,15 +40,23 @@ DEFINE_TEST(test_0)
struct stat st;
failure("File %s does not exist?!", testprogfile);
- if (!assertEqualInt(0, stat(testprogfile, &st)))
+ if (!assertEqualInt(0, stat(testprogfile, &st))) {
+ fprintf(stderr,
+ "\nFile %s does not exist; aborting test.\n\n",
+ testprog);
exit(1);
+ }
failure("%s is not executable?!", testprogfile);
- if (!assert((st.st_mode & 0111) != 0))
+ if (!assert((st.st_mode & 0111) != 0)) {
+ fprintf(stderr,
+ "\nFile %s not executable; aborting test.\n\n",
+ testprog);
exit(1);
+ }
/*
- * Try to succesfully run the program; this requires that
+ * Try to successfully run the program; this requires that
* we know some option that will succeed.
*/
if (0 == systemf("%s --version >" DEV_NULL, testprog)) {
diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c
index 852b069a16e7..c40813e9a26f 100644
--- a/cpio/test/test_basic.c
+++ b/cpio/test/test_basic.c
@@ -33,12 +33,15 @@ verify_files(const char *msg)
*/
/* Regular file with 2 links. */
+ failure(msg);
assertIsReg("file", 0644);
failure(msg);
assertFileSize("file", 10);
+ failure(msg);
assertFileNLinks("file", 2);
/* Another name for the same file. */
+ failure(msg);
assertIsHardlink("linkfile", "file");
/* Symlink */
@@ -46,8 +49,11 @@ verify_files(const char *msg)
assertIsSymlink("symlink", "file");
/* Another file with 1 link and different permissions. */
+ failure(msg);
assertIsReg("file2", 0777);
+ failure(msg);
assertFileSize("file2", 10);
+ failure(msg);
assertFileNLinks("file2", 1);
/* dir */
@@ -58,7 +64,7 @@ static void
basic_cpio(const char *target,
const char *pack_options,
const char *unpack_options,
- const char *se)
+ const char *se, const char *se2)
{
int r;
@@ -87,7 +93,7 @@ basic_cpio(const char *target,
/* Verify stderr. */
failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
- assertTextFileContents(se, "unpack.err");
+ assertTextFileContents(se2, "unpack.err");
verify_files(pack_options);
@@ -125,6 +131,7 @@ DEFINE_TEST(test_basic)
{
FILE *filelist;
const char *msg;
+ char result[1024];
assertUmask(0);
@@ -132,28 +139,56 @@ DEFINE_TEST(test_basic)
* Create an assortment of files on disk.
*/
filelist = fopen("filelist", "w");
+ memset(result, 0, sizeof(result));
/* File with 10 bytes content. */
assertMakeFile("file", 0644, "1234567890");
fprintf(filelist, "file\n");
+ if (is_LargeInode("file"))
+ strncat(result,
+ "bsdcpio: file: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* hardlink to above file. */
assertMakeHardlink("linkfile", "file");
fprintf(filelist, "linkfile\n");
+ if (is_LargeInode("linkfile"))
+ strncat(result,
+ "bsdcpio: linkfile: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* Symlink to above file. */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
fprintf(filelist, "symlink\n");
+ if (is_LargeInode("symlink"))
+ strncat(result,
+ "bsdcpio: symlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
}
/* Another file with different permissions. */
assertMakeFile("file2", 0777, "1234567890");
fprintf(filelist, "file2\n");
+ if (is_LargeInode("file2"))
+ strncat(result,
+ "bsdcpio: file2: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* Directory. */
assertMakeDir("dir", 0775);
fprintf(filelist, "dir\n");
+ if (is_LargeInode("dir"))
+ strncat(result,
+ "bsdcpio: dir: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
+
/* All done. */
fclose(filelist);
@@ -161,12 +196,12 @@ DEFINE_TEST(test_basic)
/* Archive/dearchive with a variety of options. */
msg = canSymlink() ? "2 blocks\n" : "1 block\n";
- basic_cpio("copy", "", "", msg);
- basic_cpio("copy_odc", "--format=odc", "", msg);
- basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
- basic_cpio("copy_cpio", "-H odc", "", msg);
+ basic_cpio("copy", "", "", msg, msg);
+ basic_cpio("copy_odc", "--format=odc", "", msg, msg);
+ basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
+ basic_cpio("copy_cpio", "-H odc", "", msg, msg);
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
- basic_cpio("copy_ustar", "-H ustar", "", msg);
+ basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
/* Copy in one step using -p */
passthrough("passthrough");
diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c
index 06749a2f9caa..ced62a639e7a 100644
--- a/cpio/test/test_format_newc.c
+++ b/cpio/test/test_format_newc.c
@@ -68,6 +68,16 @@ from_hex(const char *p, size_t l)
return (r);
}
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int
+nlinks(const char *p)
+{
+ struct stat st;
+ assertEqualInt(0, stat(p, &st));
+ return st.st_nlink;
+}
+#endif
+
DEFINE_TEST(test_format_newc)
{
FILE *list;
@@ -77,6 +87,7 @@ DEFINE_TEST(test_format_newc)
time_t t, t2, now;
char *p, *e;
size_t s, fs, ns;
+ char result[1024];
assertUmask(0);
@@ -111,6 +122,29 @@ DEFINE_TEST(test_format_newc)
assertMakeDir("dir", 0775);
fprintf(list, "dir\n");
+ /* Setup result message. */
+ memset(result, 0, sizeof(result));
+ if (is_LargeInode("file1"))
+ strncat(result,
+ "bsdcpio: file1: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (canSymlink() && is_LargeInode("symlink"))
+ strncat(result,
+ "bsdcpio: symlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (is_LargeInode("dir"))
+ strncat(result,
+ "bsdcpio: dir: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (is_LargeInode("hardlink"))
+ strncat(result,
+ "bsdcpio: hardlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+
/* Record some facts about what we just created: */
now = time(NULL); /* They were all created w/in last two seconds. */
@@ -123,10 +157,11 @@ DEFINE_TEST(test_format_newc)
/* Verify that nothing went to stderr. */
if (canSymlink()) {
- assertTextFileContents("2 blocks\n", "newc.err");
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
} else {
- assertTextFileContents("1 block\n", "newc.err");
+ strncat(result, "1 block\n", sizeof(result) - strlen(result));
}
+ assertTextFileContents(result, "newc.err");
/* Verify that stdout is a well-formed cpio file in "newc" format. */
p = slurpfile(&s, "newc.out");
@@ -216,10 +251,10 @@ DEFINE_TEST(test_format_newc)
/* Mode: sgid bit sometimes propagates from parent dirs, ignore it. */
assertEqualInt(040775, from_hex(e + 14, 8) & ~02000);
#endif
- assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ assertEqualInt(uid, from_hex(e + 22, 8)); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
-#ifndef NLINKS_INACCURATE_FOR_DIRS
- assertEqualMem(e + 38, "00000002", 8); /* nlink */
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ assertEqualInt(nlinks("dir"), from_hex(e + 38, 8)); /* nlinks */
#endif
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
diff --git a/cpio/test/test_option_0.c b/cpio/test/test_option_0.c
new file mode 100644
index 000000000000..bc4aecd2afc2
--- /dev/null
+++ b/cpio/test/test_option_0.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_0)
+{
+ FILE *filelist;
+ int r;
+
+ assertUmask(0);
+
+ /* Create a few files. */
+ assertMakeFile("file1", 0644, "1234567890");
+ assertMakeFile("file2", 0644, "1234567890");
+ assertMakeFile("file3", 0644, "1234567890");
+ assertMakeFile("file4", 0644, "1234567890");
+
+ /* Create a file list of filenames with varying end-of-line. */
+ filelist = fopen("filelist", "wb");
+ assertEqualInt(fwrite("file1\x0a", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file2\x0d", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file3\x0a\x0d", 1, 7, filelist), 7);
+ assertEqualInt(fwrite("file4", 1, 5, filelist), 5);
+ fclose(filelist);
+
+ /* Create a file list of null-delimited names. */
+ filelist = fopen("filelistNull", "wb");
+ assertEqualInt(fwrite("file1\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file2\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file3\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file4", 1, 5, filelist), 5);
+ fclose(filelist);
+
+ assertUmask(022);
+
+ /* Pack up using the file list with text line endings. */
+ r = systemf("%s -o < filelist > archive 2> stderr1.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract into a new dir. */
+ assertMakeDir("copy", 0775);
+ assertChdir("copy");
+ r = systemf("%s -i < ../archive > stdout3.txt 2> stderr3.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify the files. */
+ assertIsReg("file1", 0644);
+ assertIsReg("file2", 0644);
+ assertIsReg("file3", 0644);
+ assertIsReg("file4", 0644);
+
+ assertChdir("..");
+
+ /* Pack up using the file list with nulls. */
+ r = systemf("%s -o0 < filelistNull > archiveNull 2> stderr2.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract into a new dir. */
+ assertMakeDir("copyNull", 0775);
+ assertChdir("copyNull");
+ r = systemf("%s -i < ../archiveNull > stdout4.txt 2> stderr4.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify the files. */
+ assertIsReg("file1", 0644);
+ assertIsReg("file2", 0644);
+ assertIsReg("file3", 0644);
+ assertIsReg("file4", 0644);
+}
diff --git a/cpio/test/test_option_c.c b/cpio/test/test_option_c.c
index 63dcdbd53d46..a634be10ba7c 100644
--- a/cpio/test/test_option_c.c
+++ b/cpio/test/test_option_c.c
@@ -51,6 +51,16 @@ from_octal(const char *p, size_t l)
return (r);
}
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int
+nlinks(const char *p)
+{
+ struct stat st;
+ assertEqualInt(0, stat(p, &st));
+ return st.st_nlink;
+}
+#endif
+
DEFINE_TEST(test_option_c)
{
FILE *filelist;
@@ -181,17 +191,19 @@ DEFINE_TEST(test_option_c)
/* Group members bits and others bits do not work. */
assertEqualMem(e + 18, "040777", 6); /* Mode */
#else
- /* Accept 042775 to accomodate systems where sgid bit propagates. */
+ /* Accept 042775 to accommodate systems where sgid bit propagates. */
if (memcmp(e + 18, "042775", 6) != 0)
assertEqualMem(e + 18, "040775", 6); /* Mode */
#endif
- assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
+ assertEqualInt(uid, from_octal(e + 24, 6)); /* uid */
/* Gid should be same as first entry. */
assert(is_octal(e + 30, 6)); /* gid */
assertEqualInt(gid, from_octal(e + 30, 6));
-#ifndef NLINKS_INACCURATE_FOR_DIRS
- assertEqualMem(e + 36, "000002", 6); /* Nlink */
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ assertEqualInt(nlinks("dir"), from_octal(e + 36, 6)); /* Nlink */
#endif
+
t = from_octal(e + 48, 11); /* mtime */
assert(t <= now); /* File wasn't created in future. */
assert(t >= now - 2); /* File was created w/in last 2 secs. */
diff --git a/cpio/test/test_option_t.c b/cpio/test/test_option_t.c
index 4427bb3a6cd7..6bcaee3c87ce 100644
--- a/cpio/test/test_option_t.c
+++ b/cpio/test/test_option_t.c
@@ -25,11 +25,17 @@
#include "test.h"
__FBSDID("$FreeBSD$");
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
DEFINE_TEST(test_option_t)
{
char *p;
int r;
+ time_t mtime;
+ char date[32];
+ char date2[32];
/* List reference archive, make sure the TOC is correct. */
extract_reference_file("test_option_t.cpio");
@@ -75,17 +81,20 @@ DEFINE_TEST(test_option_t)
/* Since -n uses numeric UID/GID, this part should be the
* same on every system. */
assertEqualMem(p, "-rw-r--r-- 1 1000 1000 0 ",42);
- /* Date varies depending on local timezone. */
- if (memcmp(p + 42, "Dec 31 1969", 12) == 0) {
- /* East of Greenwich we get Dec 31, 1969. */
- } else {
- /* West of Greenwich get Jan 1, 1970 */
- assertEqualMem(p + 42, "Jan ", 4);
- /* Some systems format "Jan 01", some "Jan 1" */
- assert(p[46] == ' ' || p[46] == '0');
- assertEqualMem(p + 47, "1 1970 ", 8);
- }
- assertEqualMem(p + 54, " file", 5);
+
+ /* Date varies depending on local timezone and locale. */
+ mtime = 1;
+#ifdef HAVE_LOCALE_H
+ setlocale(LC_ALL, "");
+#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ strftime(date2, sizeof(date), "%b %d %Y", localtime(&mtime));
+ _snprintf(date, sizeof(date)-1, "%12s file", date2);
+#else
+ strftime(date2, sizeof(date), "%b %e %Y", localtime(&mtime));
+ snprintf(date, sizeof(date)-1, "%12s file", date2);
+#endif
+ assertEqualMem(p + 42, date, strlen(date));
free(p);
/* But "-n" without "-t" is an error. */
diff --git a/cpio/test/test_option_u.c b/cpio/test/test_option_u.c
index 08058aa45396..b377def020fb 100644
--- a/cpio/test/test_option_u.c
+++ b/cpio/test/test_option_u.c
@@ -41,7 +41,7 @@ DEFINE_TEST(test_option_u)
assertMakeFile("f", 0644, "a");
/* Copy the file to the "copy" dir. */
- r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pd copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
@@ -60,7 +60,7 @@ DEFINE_TEST(test_option_u)
assertEqualInt(0, utime("f", &times));
/* Copy the file to the "copy" dir. */
- r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pd copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
@@ -70,7 +70,7 @@ DEFINE_TEST(test_option_u)
assertEqualMem(p, "a", 1);
/* Copy the file to the "copy" dir with -u (force) */
- r = systemf("echo f | %s -pud copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pud copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
diff --git a/cpio/test/test_owner_parse.c b/cpio/test/test_owner_parse.c
index d07724e0e776..a9f605398e36 100644
--- a/cpio/test/test_owner_parse.c
+++ b/cpio/test/test_owner_parse.c
@@ -30,9 +30,8 @@ __FBSDID("$FreeBSD$");
#if !defined(_WIN32)
#define ROOT "root"
-static int root_uids[] = { 0 };
-/* Solaris 9 root has gid 1 (other) */
-static int root_gids[] = { 0, 1 };
+static const int root_uids[] = { 0 };
+static const int root_gids[] = { 0, 1 };
#elif defined(__CYGWIN__)
/* On cygwin, the Administrator user most likely exists (unless
* it has been renamed or is in a non-English localization), but
@@ -43,13 +42,13 @@ static int root_gids[] = { 0, 1 };
* Use CreateWellKnownSID() and LookupAccountName()?
*/
#define ROOT "Administrator"
-static int root_uids[] = { 500 };
-static int root_gids[] = { 513, 545, 544 };
+static const int root_uids[] = { 500 };
+static const int root_gids[] = { 513, 545, 544 };
#endif
#if defined(ROOT)
static int
-int_in_list(int i, int *l, size_t n)
+int_in_list(int i, const int *l, size_t n)
{
while (n-- > 0)
if (*l++ == i)