summaryrefslogtreecommitdiffstats
path: root/toolbox/upstream-netbsd/bin
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2014-07-22 17:20:15 -0700
committerElliott Hughes <enh@google.com>2014-07-25 10:51:19 -0700
commit7bb5660647d0106f96b000c25f5690a45734c38c (patch)
treeba1d62bc77ee88071f170df38c97ac1e5dbf4a12 /toolbox/upstream-netbsd/bin
parenteb49dd791ec80d42cbe066b78b6f0d8c17791ecd (diff)
downloadsystem_core-7bb5660647d0106f96b000c25f5690a45734c38c.zip
system_core-7bb5660647d0106f96b000c25f5690a45734c38c.tar.gz
system_core-7bb5660647d0106f96b000c25f5690a45734c38c.tar.bz2
Refresh toolbox.
Use more upstream NetBSD, and update those things that were already NetBSD. Note that unlike bionic, the upstream-netbsd directory isn't pristine; we have changes marked by __ANDROID__. Bug: 16493461 (cherry picked from commit fd4c6b0a3a25921a9fe24691a695d715aecb6afe) Change-Id: I53267edaac0b92ad062a5df0f3201e3952eb084e
Diffstat (limited to 'toolbox/upstream-netbsd/bin')
-rw-r--r--toolbox/upstream-netbsd/bin/cat/cat.c329
-rw-r--r--toolbox/upstream-netbsd/bin/cp/cp.c548
-rw-r--r--toolbox/upstream-netbsd/bin/cp/extern.h61
-rw-r--r--toolbox/upstream-netbsd/bin/cp/utils.c444
-rw-r--r--toolbox/upstream-netbsd/bin/dd/args.c391
-rw-r--r--toolbox/upstream-netbsd/bin/dd/conv.c283
-rw-r--r--toolbox/upstream-netbsd/bin/dd/dd.c598
-rw-r--r--toolbox/upstream-netbsd/bin/dd/dd.h127
-rw-r--r--toolbox/upstream-netbsd/bin/dd/dd_hostops.c53
-rw-r--r--toolbox/upstream-netbsd/bin/dd/extern.h82
-rw-r--r--toolbox/upstream-netbsd/bin/dd/misc.c342
-rw-r--r--toolbox/upstream-netbsd/bin/dd/position.c185
-rw-r--r--toolbox/upstream-netbsd/bin/ln/ln.c230
-rw-r--r--toolbox/upstream-netbsd/bin/mv/mv.c396
-rw-r--r--toolbox/upstream-netbsd/bin/mv/pathnames.h45
-rw-r--r--toolbox/upstream-netbsd/bin/rm/rm.c625
-rw-r--r--toolbox/upstream-netbsd/bin/rmdir/rmdir.c121
-rw-r--r--toolbox/upstream-netbsd/bin/sleep/sleep.c159
-rw-r--r--toolbox/upstream-netbsd/bin/sync/sync.c59
19 files changed, 5078 insertions, 0 deletions
diff --git a/toolbox/upstream-netbsd/bin/cat/cat.c b/toolbox/upstream-netbsd/bin/cat/cat.c
new file mode 100644
index 0000000..cca8cf5
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/cat/cat.c
@@ -0,0 +1,329 @@
+/* $NetBSD: cat.c,v 1.54 2013/12/08 08:32:13 spz Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kevin Fall.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(lint)
+__COPYRIGHT(
+"@(#) Copyright (c) 1989, 1993\
+ The Regents of the University of California. All rights reserved.");
+#if 0
+static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
+#else
+__RCSID("$NetBSD: cat.c,v 1.54 2013/12/08 08:32:13 spz Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag;
+static size_t bsize;
+static int rval;
+static const char *filename;
+
+void cook_args(char *argv[]);
+void cook_buf(FILE *);
+void raw_args(char *argv[]);
+void raw_cat(int);
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ struct flock stdout_lock;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "B:beflnstuv")) != -1)
+ switch (ch) {
+ case 'B':
+ bsize = (size_t)strtol(optarg, NULL, 0);
+ break;
+ case 'b':
+ bflag = nflag = 1; /* -b implies -n */
+ break;
+ case 'e':
+ eflag = vflag = 1; /* -e implies -v */
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 't':
+ tflag = vflag = 1; /* -t implies -v */
+ break;
+ case 'u':
+ setbuf(stdout, NULL);
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ case '?':
+ (void)fprintf(stderr,
+ "Usage: %s [-beflnstuv] [-B bsize] [-] "
+ "[file ...]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ argv += optind;
+
+ if (lflag) {
+ stdout_lock.l_len = 0;
+ stdout_lock.l_start = 0;
+ stdout_lock.l_type = F_WRLCK;
+ stdout_lock.l_whence = SEEK_SET;
+ if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
+ err(EXIT_FAILURE, "stdout");
+ }
+
+ if (bflag || eflag || nflag || sflag || tflag || vflag)
+ cook_args(argv);
+ else
+ raw_args(argv);
+ if (fclose(stdout))
+ err(EXIT_FAILURE, "stdout");
+ return rval;
+}
+
+void
+cook_args(char **argv)
+{
+ FILE *fp;
+
+ fp = stdin;
+ filename = "stdin";
+ do {
+ if (*argv) {
+ if (!strcmp(*argv, "-"))
+ fp = stdin;
+ else if ((fp = fopen(*argv,
+ fflag ? "rf" : "r")) == NULL) {
+ warn("%s", *argv);
+ rval = EXIT_FAILURE;
+ ++argv;
+ continue;
+ }
+ filename = *argv++;
+ }
+ cook_buf(fp);
+ if (fp != stdin)
+ (void)fclose(fp);
+ else
+ clearerr(fp);
+ } while (*argv);
+}
+
+void
+cook_buf(FILE *fp)
+{
+ int ch, gobble, line, prev;
+
+ line = gobble = 0;
+ for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
+ if (prev == '\n') {
+ if (ch == '\n') {
+ if (sflag) {
+ if (!gobble && nflag && !bflag)
+ (void)fprintf(stdout,
+ "%6d\t\n", ++line);
+ else if (!gobble && putchar(ch) == EOF)
+ break;
+ gobble = 1;
+ continue;
+ }
+ if (nflag) {
+ if (!bflag) {
+ (void)fprintf(stdout,
+ "%6d\t", ++line);
+ if (ferror(stdout))
+ break;
+ } else if (eflag) {
+ (void)fprintf(stdout,
+ "%6s\t", "");
+ if (ferror(stdout))
+ break;
+ }
+ }
+ } else if (nflag) {
+ (void)fprintf(stdout, "%6d\t", ++line);
+ if (ferror(stdout))
+ break;
+ }
+ }
+ gobble = 0;
+ if (ch == '\n') {
+ if (eflag)
+ if (putchar('$') == EOF)
+ break;
+ } else if (ch == '\t') {
+ if (tflag) {
+ if (putchar('^') == EOF || putchar('I') == EOF)
+ break;
+ continue;
+ }
+ } else if (vflag) {
+ if (!isascii(ch)) {
+ if (putchar('M') == EOF || putchar('-') == EOF)
+ break;
+ ch = toascii(ch);
+ }
+ if (iscntrl(ch)) {
+ if (putchar('^') == EOF ||
+ putchar(ch == '\177' ? '?' :
+ ch | 0100) == EOF)
+ break;
+ continue;
+ }
+ }
+ if (putchar(ch) == EOF)
+ break;
+ }
+ if (ferror(fp)) {
+ warn("%s", filename);
+ rval = EXIT_FAILURE;
+ clearerr(fp);
+ }
+ if (ferror(stdout))
+ err(EXIT_FAILURE, "stdout");
+}
+
+void
+raw_args(char **argv)
+{
+ int fd;
+
+ fd = fileno(stdin);
+ filename = "stdin";
+ do {
+ if (*argv) {
+ if (!strcmp(*argv, "-")) {
+ fd = fileno(stdin);
+ if (fd < 0)
+ goto skip;
+ } else if (fflag) {
+ struct stat st;
+ fd = open(*argv, O_RDONLY|O_NONBLOCK, 0);
+ if (fd < 0)
+ goto skip;
+
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ goto skip;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ close(fd);
+ warnx("%s: not a regular file", *argv);
+ goto skipnomsg;
+ }
+ }
+ else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
+skip:
+ warn("%s", *argv);
+skipnomsg:
+ rval = EXIT_FAILURE;
+ ++argv;
+ continue;
+ }
+ filename = *argv++;
+ } else if (fd < 0) {
+ err(EXIT_FAILURE, "stdin");
+ }
+ raw_cat(fd);
+ if (fd != fileno(stdin))
+ (void)close(fd);
+ } while (*argv);
+}
+
+void
+raw_cat(int rfd)
+{
+ static char *buf;
+ static char fb_buf[BUFSIZ];
+
+ ssize_t nr, nw, off;
+ int wfd;
+
+ wfd = fileno(stdout);
+ if (wfd < 0)
+ err(EXIT_FAILURE, "stdout");
+ if (buf == NULL) {
+ struct stat sbuf;
+
+ if (bsize == 0) {
+ if (fstat(wfd, &sbuf) == 0 && sbuf.st_blksize > 0 &&
+ (size_t)sbuf.st_blksize > sizeof(fb_buf))
+ bsize = sbuf.st_blksize;
+ }
+ if (bsize > sizeof(fb_buf)) {
+ buf = malloc(bsize);
+ if (buf == NULL)
+ warnx("malloc, using %zu buffer", bsize);
+ }
+ if (buf == NULL) {
+ bsize = sizeof(fb_buf);
+ buf = fb_buf;
+ }
+ }
+ while ((nr = read(rfd, buf, bsize)) > 0)
+ for (off = 0; nr; nr -= nw, off += nw)
+ if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
+ err(EXIT_FAILURE, "stdout");
+ if (nr < 0) {
+ warn("%s", filename);
+ rval = EXIT_FAILURE;
+ }
+}
diff --git a/toolbox/upstream-netbsd/bin/cp/cp.c b/toolbox/upstream-netbsd/bin/cp/cp.c
new file mode 100644
index 0000000..4bbe1b7
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/cp/cp.c
@@ -0,0 +1,548 @@
+/* $NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems Inc.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT(
+"@(#) Copyright (c) 1988, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95";
+#else
+__RCSID("$NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Cp copies source files to target files.
+ *
+ * The global PATH_T structure "to" always contains the path to the
+ * current target file. Since fts(3) does not change directories,
+ * this path can be either absolute or dot-relative.
+ *
+ * The basic algorithm is to initialize "to" and use fts(3) to traverse
+ * the file hierarchy rooted in the argument list. A trivial case is the
+ * case of 'cp file1 file2'. The more interesting case is the case of
+ * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
+ * path (relative to the root of the traversal) is appended to dir (stored
+ * in "to") to form the final target path.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#define STRIP_TRAILING_SLASH(p) { \
+ while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \
+ *--(p).p_end = '\0'; \
+}
+
+static char empty[] = "";
+PATH_T to = { .p_end = to.p_path, .target_end = empty };
+
+uid_t myuid;
+int Hflag, Lflag, Rflag, Pflag, fflag, iflag, lflag, pflag, rflag, vflag, Nflag;
+mode_t myumask;
+sig_atomic_t pinfo;
+
+enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
+
+static int copy(char *[], enum op, int);
+
+static void
+progress(int sig __unused)
+{
+
+ pinfo++;
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stat to_stat, tmp_stat;
+ enum op type;
+ int ch, fts_options, r, have_trailing_slash;
+ char *target, **src;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ Hflag = Lflag = Pflag = Rflag = 0;
+ while ((ch = getopt(argc, argv, "HLNPRfailprv")) != -1)
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'N':
+ Nflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'a':
+ Pflag = 1;
+ pflag = 1;
+ Rflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'i':
+ iflag = isatty(fileno(stdin));
+ fflag = 0;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ usage();
+
+ fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
+ if (rflag) {
+ if (Rflag) {
+ errx(EXIT_FAILURE,
+ "the -R and -r options may not be specified together.");
+ /* NOTREACHED */
+ }
+ if (Hflag || Lflag || Pflag) {
+ errx(EXIT_FAILURE,
+ "the -H, -L, and -P options may not be specified with the -r option.");
+ /* NOTREACHED */
+ }
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+
+ if (Rflag) {
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else if (!Pflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
+ }
+
+ myuid = getuid();
+
+ /* Copy the umask for explicit mode setting. */
+ myumask = umask(0);
+ (void)umask(myumask);
+
+ /* Save the target base in "to". */
+ target = argv[--argc];
+ if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path))
+ errx(EXIT_FAILURE, "%s: name too long", target);
+ to.p_end = to.p_path + strlen(to.p_path);
+ have_trailing_slash = (to.p_end[-1] == '/');
+ if (have_trailing_slash)
+ STRIP_TRAILING_SLASH(to);
+ to.target_end = to.p_end;
+
+ /* Set end of argument list for fts(3). */
+ argv[argc] = NULL;
+
+ (void)signal(SIGINFO, progress);
+
+ /*
+ * Cp has two distinct cases:
+ *
+ * cp [-R] source target
+ * cp [-R] source1 ... sourceN directory
+ *
+ * In both cases, source can be either a file or a directory.
+ *
+ * In (1), the target becomes a copy of the source. That is, if the
+ * source is a file, the target will be a file, and likewise for
+ * directories.
+ *
+ * In (2), the real target is not directory, but "directory/source".
+ */
+ if (Pflag)
+ r = lstat(to.p_path, &to_stat);
+ else
+ r = stat(to.p_path, &to_stat);
+ if (r == -1 && errno != ENOENT) {
+ err(EXIT_FAILURE, "%s", to.p_path);
+ /* NOTREACHED */
+ }
+ if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
+ /*
+ * Case (1). Target is not a directory.
+ */
+ if (argc > 1)
+ usage();
+ /*
+ * Need to detect the case:
+ * cp -R dir foo
+ * Where dir is a directory and foo does not exist, where
+ * we want pathname concatenations turned on but not for
+ * the initial mkdir().
+ */
+ if (r == -1) {
+ if (rflag || (Rflag && (Lflag || Hflag)))
+ r = stat(*argv, &tmp_stat);
+ else
+ r = lstat(*argv, &tmp_stat);
+ if (r == -1) {
+ err(EXIT_FAILURE, "%s", *argv);
+ /* NOTREACHED */
+ }
+
+ if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
+ type = DIR_TO_DNE;
+ else
+ type = FILE_TO_FILE;
+ } else
+ type = FILE_TO_FILE;
+
+ if (have_trailing_slash && type == FILE_TO_FILE) {
+ if (r == -1)
+ errx(1, "directory %s does not exist",
+ to.p_path);
+ else
+ errx(1, "%s is not a directory", to.p_path);
+ }
+ } else {
+ /*
+ * Case (2). Target is a directory.
+ */
+ type = FILE_TO_DIR;
+ }
+
+ /*
+ * make "cp -rp src/ dst" behave like "cp -rp src dst" not
+ * like "cp -rp src/. dst"
+ */
+ for (src = argv; *src; src++) {
+ size_t len = strlen(*src);
+ while (len-- > 1 && (*src)[len] == '/')
+ (*src)[len] = '\0';
+ }
+
+ exit(copy(argv, type, fts_options));
+ /* NOTREACHED */
+}
+
+static int dnestack[MAXPATHLEN]; /* unlikely we'll have more nested dirs */
+static ssize_t dnesp;
+static void
+pushdne(int dne)
+{
+
+ dnestack[dnesp++] = dne;
+ assert(dnesp < MAXPATHLEN);
+}
+
+static int
+popdne(void)
+{
+ int rv;
+
+ rv = dnestack[--dnesp];
+ assert(dnesp >= 0);
+ return rv;
+}
+
+static int
+copy(char *argv[], enum op type, int fts_options)
+{
+ struct stat to_stat;
+ FTS *ftsp;
+ FTSENT *curr;
+ int base, dne, sval;
+ int this_failed, any_failed;
+ size_t nlen;
+ char *p, *target_mid;
+
+ base = 0; /* XXX gcc -Wuninitialized (see comment below) */
+
+ if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL)
+ err(EXIT_FAILURE, "%s", argv[0]);
+ /* NOTREACHED */
+ for (any_failed = 0; (curr = fts_read(ftsp)) != NULL;) {
+ this_failed = 0;
+ switch (curr->fts_info) {
+ case FTS_NS:
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s", curr->fts_path,
+ strerror(curr->fts_errno));
+ this_failed = any_failed = 1;
+ continue;
+ case FTS_DC: /* Warn, continue. */
+ warnx("%s: directory causes a cycle", curr->fts_path);
+ this_failed = any_failed = 1;
+ continue;
+ }
+
+ /*
+ * If we are in case (2) or (3) above, we need to append the
+ * source name to the target name.
+ */
+ if (type != FILE_TO_FILE) {
+ if ((curr->fts_namelen +
+ to.target_end - to.p_path + 1) > MAXPATHLEN) {
+ warnx("%s/%s: name too long (not copied)",
+ to.p_path, curr->fts_name);
+ this_failed = any_failed = 1;
+ continue;
+ }
+
+ /*
+ * Need to remember the roots of traversals to create
+ * correct pathnames. If there's a directory being
+ * copied to a non-existent directory, e.g.
+ * cp -R a/dir noexist
+ * the resulting path name should be noexist/foo, not
+ * noexist/dir/foo (where foo is a file in dir), which
+ * is the case where the target exists.
+ *
+ * Also, check for "..". This is for correct path
+ * concatentation for paths ending in "..", e.g.
+ * cp -R .. /tmp
+ * Paths ending in ".." are changed to ".". This is
+ * tricky, but seems the easiest way to fix the problem.
+ *
+ * XXX
+ * Since the first level MUST be FTS_ROOTLEVEL, base
+ * is always initialized.
+ */
+ if (curr->fts_level == FTS_ROOTLEVEL) {
+ if (type != DIR_TO_DNE) {
+ p = strrchr(curr->fts_path, '/');
+ base = (p == NULL) ? 0 :
+ (int)(p - curr->fts_path + 1);
+
+ if (!strcmp(&curr->fts_path[base],
+ ".."))
+ base += 1;
+ } else
+ base = curr->fts_pathlen;
+ }
+
+ p = &curr->fts_path[base];
+ nlen = curr->fts_pathlen - base;
+ target_mid = to.target_end;
+ if (*p != '/' && target_mid[-1] != '/')
+ *target_mid++ = '/';
+ *target_mid = 0;
+
+ if (target_mid - to.p_path + nlen >= PATH_MAX) {
+ warnx("%s%s: name too long (not copied)",
+ to.p_path, p);
+ this_failed = any_failed = 1;
+ continue;
+ }
+ (void)strncat(target_mid, p, nlen);
+ to.p_end = target_mid + nlen;
+ *to.p_end = 0;
+ STRIP_TRAILING_SLASH(to);
+ }
+
+ sval = Pflag ? lstat(to.p_path, &to_stat) : stat(to.p_path, &to_stat);
+ /* Not an error but need to remember it happened */
+ if (sval == -1)
+ dne = 1;
+ else {
+ if (to_stat.st_dev == curr->fts_statp->st_dev &&
+ to_stat.st_ino == curr->fts_statp->st_ino) {
+ warnx("%s and %s are identical (not copied).",
+ to.p_path, curr->fts_path);
+ this_failed = any_failed = 1;
+ if (S_ISDIR(curr->fts_statp->st_mode))
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ continue;
+ }
+ if (!S_ISDIR(curr->fts_statp->st_mode) &&
+ S_ISDIR(to_stat.st_mode)) {
+ warnx("cannot overwrite directory %s with non-directory %s",
+ to.p_path, curr->fts_path);
+ this_failed = any_failed = 1;
+ continue;
+ }
+ dne = 0;
+ }
+
+ switch (curr->fts_statp->st_mode & S_IFMT) {
+ case S_IFLNK:
+ /* Catch special case of a non dangling symlink */
+ if((fts_options & FTS_LOGICAL) ||
+ ((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) {
+ if (copy_file(curr, dne))
+ this_failed = any_failed = 1;
+ } else {
+ if (copy_link(curr, !dne))
+ this_failed = any_failed = 1;
+ }
+ break;
+ case S_IFDIR:
+ if (!Rflag && !rflag) {
+ if (curr->fts_info == FTS_D)
+ warnx("%s is a directory (not copied).",
+ curr->fts_path);
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ this_failed = any_failed = 1;
+ break;
+ }
+
+ /*
+ * Directories get noticed twice:
+ * In the first pass, create it if needed.
+ * In the second pass, after the children have been copied, set the permissions.
+ */
+ if (curr->fts_info == FTS_D) /* First pass */
+ {
+ /*
+ * If the directory doesn't exist, create the new
+ * one with the from file mode plus owner RWX bits,
+ * modified by the umask. Trade-off between being
+ * able to write the directory (if from directory is
+ * 555) and not causing a permissions race. If the
+ * umask blocks owner writes, we fail..
+ */
+ pushdne(dne);
+ if (dne) {
+ if (mkdir(to.p_path,
+ curr->fts_statp->st_mode | S_IRWXU) < 0)
+ err(EXIT_FAILURE, "%s",
+ to.p_path);
+ /* NOTREACHED */
+ } else if (!S_ISDIR(to_stat.st_mode)) {
+ errno = ENOTDIR;
+ err(EXIT_FAILURE, "%s",
+ to.p_path);
+ /* NOTREACHED */
+ }
+ }
+ else if (curr->fts_info == FTS_DP) /* Second pass */
+ {
+ /*
+ * If not -p and directory didn't exist, set it to be
+ * the same as the from directory, umodified by the
+ * umask; arguably wrong, but it's been that way
+ * forever.
+ */
+ if (pflag && setfile(curr->fts_statp, 0))
+ this_failed = any_failed = 1;
+ else if ((dne = popdne()))
+ (void)chmod(to.p_path,
+ curr->fts_statp->st_mode);
+ }
+ else
+ {
+ warnx("directory %s encountered when not expected.",
+ curr->fts_path);
+ this_failed = any_failed = 1;
+ break;
+ }
+
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (Rflag) {
+ if (copy_special(curr->fts_statp, !dne))
+ this_failed = any_failed = 1;
+ } else
+ if (copy_file(curr, dne))
+ this_failed = any_failed = 1;
+ break;
+ case S_IFIFO:
+ if (Rflag) {
+ if (copy_fifo(curr->fts_statp, !dne))
+ this_failed = any_failed = 1;
+ } else
+ if (copy_file(curr, dne))
+ this_failed = any_failed = 1;
+ break;
+ default:
+ if (copy_file(curr, dne))
+ this_failed = any_failed = 1;
+ break;
+ }
+ if (vflag && !this_failed)
+ (void)printf("%s -> %s\n", curr->fts_path, to.p_path);
+ }
+ if (errno) {
+ err(EXIT_FAILURE, "fts_read");
+ /* NOTREACHED */
+ }
+ (void)fts_close(ftsp);
+ return (any_failed);
+}
diff --git a/toolbox/upstream-netbsd/bin/cp/extern.h b/toolbox/upstream-netbsd/bin/cp/extern.h
new file mode 100644
index 0000000..e393844
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/cp/extern.h
@@ -0,0 +1,61 @@
+/* $NetBSD: extern.h,v 1.17 2012/01/04 15:58:37 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)extern.h 8.2 (Berkeley) 4/1/94
+ */
+
+#ifndef _EXTERN_H_
+#define _EXTERN_H_
+
+typedef struct {
+ char *p_end; /* pointer to NULL at end of path */
+ char *target_end; /* pointer to end of target base */
+ char p_path[MAXPATHLEN + 1]; /* pointer to the start of a path */
+} PATH_T;
+
+extern PATH_T to;
+extern uid_t myuid;
+extern int Rflag, rflag, Hflag, Lflag, Pflag, fflag, iflag, lflag, pflag, Nflag;
+extern mode_t myumask;
+extern sig_atomic_t pinfo;
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int copy_fifo(struct stat *, int);
+int copy_file(FTSENT *, int);
+int copy_link(FTSENT *, int);
+int copy_special(struct stat *, int);
+int set_utimes(const char *, struct stat *);
+int setfile(struct stat *, int);
+void usage(void) __attribute__((__noreturn__));
+__END_DECLS
+
+#endif /* !_EXTERN_H_ */
diff --git a/toolbox/upstream-netbsd/bin/cp/utils.c b/toolbox/upstream-netbsd/bin/cp/utils.c
new file mode 100644
index 0000000..d8f900a
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/cp/utils.c
@@ -0,0 +1,444 @@
+/* $NetBSD: utils.c,v 1.42 2013/12/11 06:00:11 dholland Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
+#else
+__RCSID("$NetBSD: utils.c,v 1.42 2013/12/11 06:00:11 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/extattr.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#define MMAP_MAX_SIZE (8 * 1048576)
+#define MMAP_MAX_WRITE (64 * 1024)
+
+int
+set_utimes(const char *file, struct stat *fs)
+{
+ static struct timeval tv[2];
+
+#ifdef __ANDROID__
+ tv[0].tv_sec = fs->st_atime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = fs->st_mtime;
+ tv[1].tv_usec = 0;
+
+ if (utimes(file, tv)) {
+ warn("utimes: %s", file);
+ return 1;
+ }
+#else
+ TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+
+ if (lutimes(file, tv)) {
+ warn("lutimes: %s", file);
+ return (1);
+ }
+#endif
+ return (0);
+}
+
+struct finfo {
+ const char *from;
+ const char *to;
+ size_t size;
+};
+
+static void
+progress(const struct finfo *fi, size_t written)
+{
+ int pcent = (int)((100.0 * written) / fi->size);
+
+ pinfo = 0;
+ (void)fprintf(stderr, "%s => %s %zu/%zu bytes %d%% written\n",
+ fi->from, fi->to, written, fi->size, pcent);
+}
+
+int
+copy_file(FTSENT *entp, int dne)
+{
+ static char buf[MAXBSIZE];
+ struct stat to_stat, *fs;
+ int ch, checkch, from_fd, rcount, rval, to_fd, tolnk, wcount;
+ char *p;
+ size_t ptotal = 0;
+
+ if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
+ warn("%s", entp->fts_path);
+ return (1);
+ }
+
+ to_fd = -1;
+ fs = entp->fts_statp;
+ tolnk = ((Rflag && !(Lflag || Hflag)) || Pflag);
+
+ /*
+ * If the file exists and we're interactive, verify with the user.
+ * If the file DNE, set the mode to be the from file, minus setuid
+ * bits, modified by the umask; arguably wrong, but it makes copying
+ * executables work right and it's been that way forever. (The
+ * other choice is 666 or'ed with the execute bits on the from file
+ * modified by the umask.)
+ */
+ if (!dne) {
+ struct stat sb;
+ int sval;
+
+ if (iflag) {
+ (void)fprintf(stderr, "overwrite %s? ", to.p_path);
+ checkch = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (checkch != 'y' && checkch != 'Y') {
+ (void)close(from_fd);
+ return (0);
+ }
+ }
+
+ sval = tolnk ?
+ lstat(to.p_path, &sb) : stat(to.p_path, &sb);
+ if (sval == -1) {
+ warn("stat: %s", to.p_path);
+ (void)close(from_fd);
+ return (1);
+ }
+
+ if (!(tolnk && S_ISLNK(sb.st_mode)))
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+ } else
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+
+ if (to_fd == -1 && (fflag || tolnk)) {
+ /*
+ * attempt to remove existing destination file name and
+ * create a new file
+ */
+ (void)unlink(to.p_path);
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ }
+
+ if (to_fd == -1) {
+ warn("%s", to.p_path);
+ (void)close(from_fd);
+ return (1);
+ }
+
+ rval = 0;
+
+ /* if hard linking then simply close the open fds, link and return */
+ if (lflag) {
+ (void)close(from_fd);
+ (void)close(to_fd);
+ (void)unlink(to.p_path);
+ if (link(entp->fts_path, to.p_path)) {
+ warn("%s", to.p_path);
+ return (1);
+ }
+ return (0);
+ }
+
+ /*
+ * There's no reason to do anything other than close the file
+ * now if it's empty, so let's not bother.
+ */
+#ifndef __ANDROID__ // Files in /proc report length 0. mmap will fail but we'll fall back to read.
+ if (fs->st_size > 0) {
+#endif
+ struct finfo fi;
+
+ fi.from = entp->fts_path;
+ fi.to = to.p_path;
+ fi.size = (size_t)fs->st_size;
+
+ /*
+ * Mmap and write if less than 8M (the limit is so
+ * we don't totally trash memory on big files).
+ * This is really a minor hack, but it wins some CPU back.
+ */
+ bool use_read;
+
+ use_read = true;
+ if (fs->st_size <= MMAP_MAX_SIZE) {
+ size_t fsize = (size_t)fs->st_size;
+ p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED,
+ from_fd, (off_t)0);
+ if (p != MAP_FAILED) {
+ size_t remainder;
+
+ use_read = false;
+
+ (void) madvise(p, (size_t)fs->st_size,
+ MADV_SEQUENTIAL);
+
+ /*
+ * Write out the data in small chunks to
+ * avoid locking the output file for a
+ * long time if the reading the data from
+ * the source is slow.
+ */
+ remainder = fsize;
+ do {
+ ssize_t chunk;
+
+ chunk = (remainder > MMAP_MAX_WRITE) ?
+ MMAP_MAX_WRITE : remainder;
+ if (write(to_fd, &p[fsize - remainder],
+ chunk) != chunk) {
+ warn("%s", to.p_path);
+ rval = 1;
+ break;
+ }
+ remainder -= chunk;
+ ptotal += chunk;
+ if (pinfo)
+ progress(&fi, ptotal);
+ } while (remainder > 0);
+
+ if (munmap(p, fsize) < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+ }
+
+ if (use_read) {
+ while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
+ wcount = write(to_fd, buf, (size_t)rcount);
+ if (rcount != wcount || wcount == -1) {
+ warn("%s", to.p_path);
+ rval = 1;
+ break;
+ }
+ ptotal += wcount;
+ if (pinfo)
+ progress(&fi, ptotal);
+ }
+ if (rcount < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+#ifndef __ANDROID__
+ }
+#endif
+
+#ifndef __ANDROID__
+ if (pflag && (fcpxattr(from_fd, to_fd) != 0))
+ warn("%s: error copying extended attributes", to.p_path);
+#endif
+
+ (void)close(from_fd);
+
+ if (rval == 1) {
+ (void)close(to_fd);
+ return (1);
+ }
+
+ if (pflag && setfile(fs, to_fd))
+ rval = 1;
+ /*
+ * If the source was setuid or setgid, lose the bits unless the
+ * copy is owned by the same user and group.
+ */
+#define RETAINBITS \
+ (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+ if (!pflag && dne
+ && fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
+ if (fstat(to_fd, &to_stat)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ } else if (fs->st_gid == to_stat.st_gid &&
+ fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ }
+ if (close(to_fd)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ /* set the mod/access times now after close of the fd */
+ if (pflag && set_utimes(to.p_path, fs)) {
+ rval = 1;
+ }
+ return (rval);
+}
+
+int
+copy_link(FTSENT *p, int exists)
+{
+ int len;
+ char target[MAXPATHLEN];
+
+ if ((len = readlink(p->fts_path, target, sizeof(target)-1)) == -1) {
+ warn("readlink: %s", p->fts_path);
+ return (1);
+ }
+ target[len] = '\0';
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (symlink(target, to.p_path)) {
+ warn("symlink: %s", target);
+ return (1);
+ }
+ return (pflag ? setfile(p->fts_statp, 0) : 0);
+}
+
+int
+copy_fifo(struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mkfifo(to.p_path, from_stat->st_mode)) {
+ warn("mkfifo: %s", to.p_path);
+ return (1);
+ }
+ return (pflag ? setfile(from_stat, 0) : 0);
+}
+
+int
+copy_special(struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
+ warn("mknod: %s", to.p_path);
+ return (1);
+ }
+ return (pflag ? setfile(from_stat, 0) : 0);
+}
+
+
+/*
+ * Function: setfile
+ *
+ * Purpose:
+ * Set the owner/group/permissions for the "to" file to the information
+ * in the stat structure. If fd is zero, also call set_utimes() to set
+ * the mod/access times. If fd is non-zero, the caller must do a utimes
+ * itself after close(fd).
+ */
+int
+setfile(struct stat *fs, int fd)
+{
+ int rval, islink;
+
+ rval = 0;
+ islink = S_ISLNK(fs->st_mode);
+ fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
+
+ /*
+ * Changing the ownership probably won't succeed, unless we're root
+ * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
+ * the mode; current BSD behavior is to remove all setuid bits on
+ * chown. If chown fails, lose setuid/setgid bits.
+ */
+ if (fd ? fchown(fd, fs->st_uid, fs->st_gid) :
+ lchown(to.p_path, fs->st_uid, fs->st_gid)) {
+ if (errno != EPERM) {
+ warn("chown: %s", to.p_path);
+ rval = 1;
+ }
+ fs->st_mode &= ~(S_ISUID | S_ISGID);
+ }
+#ifdef __ANDROID__
+ if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) {
+#else
+ if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) {
+#endif
+ warn("chmod: %s", to.p_path);
+ rval = 1;
+ }
+
+#ifndef __ANDROID__
+ if (!islink && !Nflag) {
+ unsigned long fflags = fs->st_flags;
+ /*
+ * XXX
+ * NFS doesn't support chflags; ignore errors unless
+ * there's reason to believe we're losing bits.
+ * (Note, this still won't be right if the server
+ * supports flags and we were trying to *remove* flags
+ * on a file that we copied, i.e., that we didn't create.)
+ */
+ errno = 0;
+ if ((fd ? fchflags(fd, fflags) :
+ chflags(to.p_path, fflags)) == -1)
+ if (errno != EOPNOTSUPP || fs->st_flags != 0) {
+ warn("chflags: %s", to.p_path);
+ rval = 1;
+ }
+ }
+#endif
+ /* if fd is non-zero, caller must call set_utimes() after close() */
+ if (fd == 0 && set_utimes(to.p_path, fs))
+ rval = 1;
+ return (rval);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src target\n"
+ " %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src1 ... srcN directory\n",
+ getprogname(), getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/toolbox/upstream-netbsd/bin/dd/args.c b/toolbox/upstream-netbsd/bin/dd/args.c
new file mode 100644
index 0000000..207e300
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/args.c
@@ -0,0 +1,391 @@
+/* $NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static int c_arg(const void *, const void *);
+
+#ifdef NO_MSGFMT
+static void f_msgfmt(char *) __dead;
+#else
+static void f_msgfmt(char *);
+#endif /* NO_MSGFMT */
+
+#ifdef NO_CONV
+static void f_conv(char *) __dead;
+#else
+static void f_conv(char *);
+static int c_conv(const void *, const void *);
+#endif /* NO_CONV */
+
+static void f_bs(char *);
+static void f_cbs(char *);
+static void f_count(char *);
+static void f_files(char *);
+static void f_ibs(char *);
+static void f_if(char *);
+static void f_obs(char *);
+static void f_of(char *);
+static void f_seek(char *);
+static void f_skip(char *);
+static void f_progress(char *);
+
+static const struct arg {
+ const char *name;
+ void (*f)(char *);
+ u_int set, noset;
+} args[] = {
+ /* the array needs to be sorted by the first column so
+ bsearch() can be used to find commands quickly */
+ { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
+ { "cbs", f_cbs, C_CBS, C_CBS },
+ { "conv", f_conv, 0, 0 },
+ { "count", f_count, C_COUNT, C_COUNT },
+ { "files", f_files, C_FILES, C_FILES },
+ { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
+ { "if", f_if, C_IF, C_IF },
+ { "iseek", f_skip, C_SKIP, C_SKIP },
+ { "msgfmt", f_msgfmt, 0, 0 },
+ { "obs", f_obs, C_OBS, C_BS|C_OBS },
+ { "of", f_of, C_OF, C_OF },
+ { "oseek", f_seek, C_SEEK, C_SEEK },
+ { "progress", f_progress, 0, 0 },
+ { "seek", f_seek, C_SEEK, C_SEEK },
+ { "skip", f_skip, C_SKIP, C_SKIP },
+};
+
+/*
+ * args -- parse JCL syntax of dd.
+ */
+void
+jcl(char **argv)
+{
+ struct arg *ap, tmp;
+ char *oper, *arg;
+
+ in.dbsz = out.dbsz = 512;
+
+ while ((oper = *++argv) != NULL) {
+ if ((oper = strdup(oper)) == NULL) {
+ errx(EXIT_FAILURE,
+ "unable to allocate space for the argument %s",
+ *argv);
+ /* NOTREACHED */
+ }
+ if ((arg = strchr(oper, '=')) == NULL) {
+ errx(EXIT_FAILURE, "unknown operand %s", oper);
+ /* NOTREACHED */
+ }
+ *arg++ = '\0';
+ if (!*arg) {
+ errx(EXIT_FAILURE, "no value specified for %s", oper);
+ /* NOTREACHED */
+ }
+ tmp.name = oper;
+ if (!(ap = bsearch(&tmp, args,
+ __arraycount(args), sizeof(*args), c_arg))) {
+ errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
+ /* NOTREACHED */
+ }
+ if (ddflags & ap->noset) {
+ errx(EXIT_FAILURE,
+ "%s: illegal argument combination or already set",
+ tmp.name);
+ /* NOTREACHED */
+ }
+ ddflags |= ap->set;
+ ap->f(arg);
+ }
+
+ /* Final sanity checks. */
+
+ if (ddflags & C_BS) {
+ /*
+ * Bs is turned off by any conversion -- we assume the user
+ * just wanted to set both the input and output block sizes
+ * and didn't want the bs semantics, so we don't warn.
+ */
+ if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
+ C_UNBLOCK | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
+ ddflags &= ~C_BS;
+ ddflags |= C_IBS|C_OBS;
+ }
+
+ /* Bs supersedes ibs and obs. */
+ if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
+ warnx("bs supersedes ibs and obs");
+ }
+
+ /*
+ * Ascii/ebcdic and cbs implies block/unblock.
+ * Block/unblock requires cbs and vice-versa.
+ */
+ if (ddflags & (C_BLOCK|C_UNBLOCK)) {
+ if (!(ddflags & C_CBS)) {
+ errx(EXIT_FAILURE, "record operations require cbs");
+ /* NOTREACHED */
+ }
+ cfunc = ddflags & C_BLOCK ? block : unblock;
+ } else if (ddflags & C_CBS) {
+ if (ddflags & (C_ASCII|C_EBCDIC)) {
+ if (ddflags & C_ASCII) {
+ ddflags |= C_UNBLOCK;
+ cfunc = unblock;
+ } else {
+ ddflags |= C_BLOCK;
+ cfunc = block;
+ }
+ } else {
+ errx(EXIT_FAILURE,
+ "cbs meaningless if not doing record operations");
+ /* NOTREACHED */
+ }
+ } else
+ cfunc = def;
+
+ /* Read, write and seek calls take off_t as arguments.
+ *
+ * The following check is not done because an off_t is a quad
+ * for current NetBSD implementations.
+ *
+ * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
+ * errx(1, "seek offsets cannot be larger than %d", INT_MAX);
+ */
+}
+
+static int
+c_arg(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct arg *)a)->name,
+ ((const struct arg *)b)->name));
+}
+
+static void
+f_bs(char *arg)
+{
+
+ in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_cbs(char *arg)
+{
+
+ cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
+}
+
+static void
+f_count(char *arg)
+{
+
+ cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
+ if (!cpy_cnt)
+ terminate(0);
+}
+
+static void
+f_files(char *arg)
+{
+
+ files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
+ if (!files_cnt)
+ terminate(0);
+}
+
+static void
+f_ibs(char *arg)
+{
+
+ if (!(ddflags & C_BS))
+ in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_if(char *arg)
+{
+
+ in.name = arg;
+}
+
+#ifdef NO_MSGFMT
+/* Build a small version (i.e. for a ramdisk root) */
+static void
+f_msgfmt(char *arg)
+{
+
+ errx(EXIT_FAILURE, "msgfmt option disabled");
+ /* NOTREACHED */
+}
+#else /* NO_MSGFMT */
+static void
+f_msgfmt(char *arg)
+{
+
+ /*
+ * If the format string is not valid, dd_write_msg() will print
+ * an error and exit.
+ */
+ dd_write_msg(arg, 0);
+
+ msgfmt = arg;
+}
+#endif /* NO_MSGFMT */
+
+static void
+f_obs(char *arg)
+{
+
+ if (!(ddflags & C_BS))
+ out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_of(char *arg)
+{
+
+ out.name = arg;
+}
+
+static void
+f_seek(char *arg)
+{
+
+ out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
+}
+
+static void
+f_skip(char *arg)
+{
+
+ in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
+}
+
+static void
+f_progress(char *arg)
+{
+
+ progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
+}
+
+#ifdef NO_CONV
+/* Build a small version (i.e. for a ramdisk root) */
+static void
+f_conv(char *arg)
+{
+
+ errx(EXIT_FAILURE, "conv option disabled");
+ /* NOTREACHED */
+}
+#else /* NO_CONV */
+
+static const struct conv {
+ const char *name;
+ u_int set, noset;
+ const u_char *ctab;
+} clist[] = {
+ { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
+ { "block", C_BLOCK, C_UNBLOCK, NULL },
+ { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
+ { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
+ { "lcase", C_LCASE, C_UCASE, NULL },
+ { "noerror", C_NOERROR, 0, NULL },
+ { "notrunc", C_NOTRUNC, 0, NULL },
+ { "oldascii", C_ASCII, C_EBCDIC, e2a_32V },
+ { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V },
+ { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V },
+ { "osync", C_OSYNC, C_BS, NULL },
+ { "sparse", C_SPARSE, 0, NULL },
+ { "swab", C_SWAB, 0, NULL },
+ { "sync", C_SYNC, 0, NULL },
+ { "ucase", C_UCASE, C_LCASE, NULL },
+ { "unblock", C_UNBLOCK, C_BLOCK, NULL },
+ /* If you add items to this table, be sure to add the
+ * conversions to the C_BS check in the jcl routine above.
+ */
+};
+
+static void
+f_conv(char *arg)
+{
+ struct conv *cp, tmp;
+
+ while (arg != NULL) {
+ tmp.name = strsep(&arg, ",");
+ if (!(cp = bsearch(&tmp, clist,
+ __arraycount(clist), sizeof(*clist), c_conv))) {
+ errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
+ /* NOTREACHED */
+ }
+ if (ddflags & cp->noset) {
+ errx(EXIT_FAILURE,
+ "%s: illegal conversion combination", tmp.name);
+ /* NOTREACHED */
+ }
+ ddflags |= cp->set;
+ if (cp->ctab)
+ ctab = cp->ctab;
+ }
+}
+
+static int
+c_conv(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct conv *)a)->name,
+ ((const struct conv *)b)->name));
+}
+
+#endif /* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/conv.c b/toolbox/upstream-netbsd/bin/dd/conv.c
new file mode 100644
index 0000000..d4a8a09
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/conv.c
@@ -0,0 +1,283 @@
+/* $NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "dd.h"
+#include "extern.h"
+
+/*
+ * def --
+ * Copy input to output. Input is buffered until reaches obs, and then
+ * output until less than obs remains. Only a single buffer is used.
+ * Worst case buffer calculation is (ibs + obs - 1).
+ */
+void
+def(void)
+{
+ uint64_t cnt;
+ u_char *inp;
+ const u_char *t;
+
+ if ((t = ctab) != NULL)
+ for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
+ *inp = t[*inp];
+
+ /* Make the output buffer look right. */
+ out.dbp = in.dbp;
+ out.dbcnt = in.dbcnt;
+
+ if (in.dbcnt >= out.dbsz) {
+ /* If the output buffer is full, write it. */
+ dd_out(0);
+
+ /*
+ * Ddout copies the leftover output to the beginning of
+ * the buffer and resets the output buffer. Reset the
+ * input buffer to match it.
+ */
+ in.dbp = out.dbp;
+ in.dbcnt = out.dbcnt;
+ }
+}
+
+void
+def_close(void)
+{
+
+ /* Just update the count, everything is already in the buffer. */
+ if (in.dbcnt)
+ out.dbcnt = in.dbcnt;
+}
+
+#ifdef NO_CONV
+/* Build a smaller version (i.e. for a miniroot) */
+/* These can not be called, but just in case... */
+static const char no_block[] = "unblock and -DNO_CONV?";
+void block(void) { errx(EXIT_FAILURE, "%s", no_block + 2); }
+void block_close(void) { errx(EXIT_FAILURE, "%s", no_block + 2); }
+void unblock(void) { errx(EXIT_FAILURE, "%s", no_block); }
+void unblock_close(void) { errx(EXIT_FAILURE, "%s", no_block); }
+#else /* NO_CONV */
+
+/*
+ * Copy variable length newline terminated records with a max size cbsz
+ * bytes to output. Records less than cbs are padded with spaces.
+ *
+ * max in buffer: MAX(ibs, cbsz)
+ * max out buffer: obs + cbsz
+ */
+void
+block(void)
+{
+ static int intrunc;
+ int ch = 0; /* pacify gcc */
+ uint64_t cnt, maxlen;
+ u_char *inp, *outp;
+ const u_char *t;
+
+ /*
+ * Record truncation can cross block boundaries. If currently in a
+ * truncation state, keep tossing characters until reach a newline.
+ * Start at the beginning of the buffer, as the input buffer is always
+ * left empty.
+ */
+ if (intrunc) {
+ for (inp = in.db, cnt = in.dbrcnt;
+ cnt && *inp++ != '\n'; --cnt);
+ if (!cnt) {
+ in.dbcnt = 0;
+ in.dbp = in.db;
+ return;
+ }
+ intrunc = 0;
+ /* Adjust the input buffer numbers. */
+ in.dbcnt = cnt - 1;
+ in.dbp = inp + cnt - 1;
+ }
+
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation is done as we copy into the output buffer.
+ */
+ for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
+ maxlen = MIN(cbsz, in.dbcnt);
+ if ((t = ctab) != NULL)
+ for (cnt = 0;
+ cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
+ *outp++ = t[ch];
+ else
+ for (cnt = 0;
+ cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
+ *outp++ = ch;
+ /*
+ * Check for short record without a newline. Reassemble the
+ * input block.
+ */
+ if (ch != '\n' && in.dbcnt < cbsz) {
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ break;
+ }
+
+ /* Adjust the input buffer numbers. */
+ in.dbcnt -= cnt;
+ if (ch == '\n')
+ --in.dbcnt;
+
+ /* Pad short records with spaces. */
+ if (cnt < cbsz)
+ (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
+ else {
+ /*
+ * If the next character wouldn't have ended the
+ * block, it's a truncation.
+ */
+ if (!in.dbcnt || *inp != '\n')
+ ++st.trunc;
+
+ /* Toss characters to a newline. */
+ for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
+ if (!in.dbcnt)
+ intrunc = 1;
+ else
+ --in.dbcnt;
+ }
+
+ /* Adjust output buffer numbers. */
+ out.dbp += cbsz;
+ if ((out.dbcnt += cbsz) >= out.dbsz)
+ dd_out(0);
+ outp = out.dbp;
+ }
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+block_close(void)
+{
+
+ /*
+ * Copy any remaining data into the output buffer and pad to a record.
+ * Don't worry about truncation or translation, the input buffer is
+ * always empty when truncating, and no characters have been added for
+ * translation. The bottom line is that anything left in the input
+ * buffer is a truncated record. Anything left in the output buffer
+ * just wasn't big enough.
+ */
+ if (in.dbcnt) {
+ ++st.trunc;
+ (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
+ (void)memset(out.dbp + in.dbcnt,
+ ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
+ out.dbcnt += cbsz;
+ }
+}
+
+/*
+ * Convert fixed length (cbsz) records to variable length. Deletes any
+ * trailing blanks and appends a newline.
+ *
+ * max in buffer: MAX(ibs, cbsz) + cbsz
+ * max out buffer: obs + cbsz
+ */
+void
+unblock(void)
+{
+ uint64_t cnt;
+ u_char *inp;
+ const u_char *t;
+
+ /* Translation and case conversion. */
+ if ((t = ctab) != NULL)
+ for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
+ *inp = t[*inp];
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation has to already be done or we might not recognize the
+ * spaces.
+ */
+ for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
+ for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
+ if (t >= inp) {
+ cnt = t - inp + 1;
+ (void)memmove(out.dbp, inp, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ ++out.dbcnt;
+ *out.dbp++ = '\n';
+ if (out.dbcnt >= out.dbsz)
+ dd_out(0);
+ }
+ if (in.dbcnt)
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+unblock_close(void)
+{
+ uint64_t cnt;
+ u_char *t;
+
+ if (in.dbcnt) {
+ warnx("%s: short input record", in.name);
+ for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
+ if (t >= in.db) {
+ cnt = t - in.db + 1;
+ (void)memmove(out.dbp, in.db, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ ++out.dbcnt;
+ *out.dbp++ = '\n';
+ }
+}
+
+#endif /* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.c b/toolbox/upstream-netbsd/bin/dd/dd.c
new file mode 100644
index 0000000..03d080c
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/dd.c
@@ -0,0 +1,598 @@
+/* $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static void dd_close(void);
+static void dd_in(void);
+static void getfdtype(IO *);
+static void redup_clean_fd(IO *);
+static void setup(void);
+
+int main(int, char *[]);
+
+IO in, out; /* input/output state */
+STAT st; /* statistics */
+void (*cfunc)(void); /* conversion function */
+uint64_t cpy_cnt; /* # of blocks to copy */
+static off_t pending = 0; /* pending seek if sparse */
+u_int ddflags; /* conversion options */
+uint64_t cbsz; /* conversion block size */
+u_int files_cnt = 1; /* # of files to copy */
+uint64_t progress = 0; /* display sign of life */
+const u_char *ctab; /* conversion table */
+sigset_t infoset; /* a set blocking SIGINFO */
+const char *msgfmt = "posix"; /* default summary() message format */
+
+/*
+ * Ops for stdin/stdout and crunch'd dd. These are always host ops.
+ */
+static const struct ddfops ddfops_stdfd = {
+ .op_open = open,
+ .op_close = close,
+ .op_fcntl = fcntl,
+ .op_ioctl = ioctl,
+ .op_fstat = fstat,
+ .op_fsync = fsync,
+ .op_ftruncate = ftruncate,
+ .op_lseek = lseek,
+ .op_read = read,
+ .op_write = write,
+};
+extern const struct ddfops ddfops_prog;
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ errx(EXIT_FAILURE, "usage: dd [operand ...]");
+ /* NOTREACHED */
+ }
+ }
+ argc -= (optind - 1);
+ argv += (optind - 1);
+
+ jcl(argv);
+#ifndef CRUNCHOPS
+ if (ddfops_prog.op_init && ddfops_prog.op_init() == -1)
+ err(1, "prog init");
+#endif
+ setup();
+
+ (void)signal(SIGINFO, summaryx);
+ (void)signal(SIGINT, terminate);
+ (void)sigemptyset(&infoset);
+ (void)sigaddset(&infoset, SIGINFO);
+
+ (void)atexit(summary);
+
+ while (files_cnt--)
+ dd_in();
+
+ dd_close();
+ exit(0);
+ /* NOTREACHED */
+}
+
+static void
+setup(void)
+{
+#ifdef CRUNCHOPS
+ const struct ddfops *prog_ops = &ddfops_stdfd;
+#else
+ const struct ddfops *prog_ops = &ddfops_prog;
+#endif
+
+ if (in.name == NULL) {
+ in.name = "stdin";
+ in.fd = STDIN_FILENO;
+ in.ops = &ddfops_stdfd;
+ } else {
+ in.ops = prog_ops;
+ in.fd = ddop_open(in, in.name, O_RDONLY, 0);
+ if (in.fd < 0)
+ err(EXIT_FAILURE, "%s", in.name);
+ /* NOTREACHED */
+
+ /* Ensure in.fd is outside the stdio descriptor range */
+ redup_clean_fd(&in);
+ }
+
+ getfdtype(&in);
+
+ if (files_cnt > 1 && !(in.flags & ISTAPE)) {
+ errx(EXIT_FAILURE, "files is not supported for non-tape devices");
+ /* NOTREACHED */
+ }
+
+ if (out.name == NULL) {
+ /* No way to check for read access here. */
+ out.fd = STDOUT_FILENO;
+ out.name = "stdout";
+ out.ops = &ddfops_stdfd;
+ } else {
+ out.ops = prog_ops;
+#define OFLAGS \
+ (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
+ out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
+ /*
+ * May not have read access, so try again with write only.
+ * Without read we may have a problem if output also does
+ * not support seeks.
+ */
+ if (out.fd < 0) {
+ out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
+ DEFFILEMODE);
+ out.flags |= NOREAD;
+ }
+ if (out.fd < 0) {
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+ }
+
+ /* Ensure out.fd is outside the stdio descriptor range */
+ redup_clean_fd(&out);
+ }
+
+ getfdtype(&out);
+
+ /*
+ * Allocate space for the input and output buffers. If not doing
+ * record oriented I/O, only need a single buffer.
+ */
+ if (!(ddflags & (C_BLOCK|C_UNBLOCK))) {
+ size_t dbsz = out.dbsz;
+ if (!(ddflags & C_BS))
+ dbsz += in.dbsz - 1;
+ if ((in.db = malloc(dbsz)) == NULL) {
+ err(EXIT_FAILURE, NULL);
+ /* NOTREACHED */
+ }
+ out.db = in.db;
+ } else if ((in.db =
+ malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
+ (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
+ err(EXIT_FAILURE, NULL);
+ /* NOTREACHED */
+ }
+ in.dbp = in.db;
+ out.dbp = out.db;
+
+ /* Position the input/output streams. */
+ if (in.offset)
+ pos_in();
+ if (out.offset)
+ pos_out();
+
+ /*
+ * Truncate the output file; ignore errors because it fails on some
+ * kinds of output files, tapes, for example.
+ */
+ if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
+ (void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
+
+ /*
+ * If converting case at the same time as another conversion, build a
+ * table that does both at once. If just converting case, use the
+ * built-in tables.
+ */
+ if (ddflags & (C_LCASE|C_UCASE)) {
+#ifdef NO_CONV
+ /* Should not get here, but just in case... */
+ errx(EXIT_FAILURE, "case conv and -DNO_CONV");
+ /* NOTREACHED */
+#else /* NO_CONV */
+ u_int cnt;
+
+ if (ddflags & C_ASCII || ddflags & C_EBCDIC) {
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt < 256; ++cnt)
+ casetab[cnt] = tolower(ctab[cnt]);
+ } else {
+ for (cnt = 0; cnt < 256; ++cnt)
+ casetab[cnt] = toupper(ctab[cnt]);
+ }
+ } else {
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt < 256; ++cnt)
+ casetab[cnt] = tolower(cnt);
+ } else {
+ for (cnt = 0; cnt < 256; ++cnt)
+ casetab[cnt] = toupper(cnt);
+ }
+ }
+
+ ctab = casetab;
+#endif /* NO_CONV */
+ }
+
+ (void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */
+}
+
+static void
+getfdtype(IO *io)
+{
+ struct mtget mt;
+ struct stat sb;
+
+ if (io->ops->op_fstat(io->fd, &sb)) {
+ err(EXIT_FAILURE, "%s", io->name);
+ /* NOTREACHED */
+ }
+ if (S_ISCHR(sb.st_mode))
+ io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
+ ? ISCHR : ISTAPE;
+ else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
+ && errno == ESPIPE)
+ io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */
+}
+
+/*
+ * Move the parameter file descriptor to a descriptor that is outside the
+ * stdio descriptor range, if necessary. This is required to avoid
+ * accidentally outputting completion or error messages into the
+ * output file that were intended for the tty.
+ */
+static void
+redup_clean_fd(IO *io)
+{
+ int fd = io->fd;
+ int newfd;
+
+ if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
+ fd != STDERR_FILENO)
+ /* File descriptor is ok, return immediately. */
+ return;
+
+ /*
+ * 3 is the first descriptor greater than STD*_FILENO. Any
+ * free descriptor valued 3 or above is acceptable...
+ */
+ newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
+ if (newfd < 0) {
+ err(EXIT_FAILURE, "dupfd IO");
+ /* NOTREACHED */
+ }
+
+ io->ops->op_close(fd);
+ io->fd = newfd;
+}
+
+static void
+dd_in(void)
+{
+ int flags;
+ int64_t n;
+
+ for (flags = ddflags;;) {
+ if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
+ return;
+
+ /*
+ * Clear the buffer first if doing "sync" on input.
+ * If doing block operations use spaces. This will
+ * affect not only the C_NOERROR case, but also the
+ * last partial input block which should be padded
+ * with zero and not garbage.
+ */
+ if (flags & C_SYNC) {
+ if (flags & (C_BLOCK|C_UNBLOCK))
+ (void)memset(in.dbp, ' ', in.dbsz);
+ else
+ (void)memset(in.dbp, 0, in.dbsz);
+ }
+
+ n = ddop_read(in, in.fd, in.dbp, in.dbsz);
+ if (n == 0) {
+ in.dbrcnt = 0;
+ return;
+ }
+
+ /* Read error. */
+ if (n < 0) {
+
+ /*
+ * If noerror not specified, die. POSIX requires that
+ * the warning message be followed by an I/O display.
+ */
+ if (!(flags & C_NOERROR)) {
+ err(EXIT_FAILURE, "%s", in.name);
+ /* NOTREACHED */
+ }
+ warn("%s", in.name);
+ summary();
+
+ /*
+ * If it's not a tape drive or a pipe, seek past the
+ * error. If your OS doesn't do the right thing for
+ * raw disks this section should be modified to re-read
+ * in sector size chunks.
+ */
+ if (!(in.flags & (ISPIPE|ISTAPE)) &&
+ ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR))
+ warn("%s", in.name);
+
+ /* If sync not specified, omit block and continue. */
+ if (!(ddflags & C_SYNC))
+ continue;
+
+ /* Read errors count as full blocks. */
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ ++st.in_full;
+
+ /* Handle full input blocks. */
+ } else if ((uint64_t)n == in.dbsz) {
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_full;
+
+ /* Handle partial input blocks. */
+ } else {
+ /* If sync, use the entire block. */
+ if (ddflags & C_SYNC)
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ else
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_part;
+ }
+
+ /*
+ * POSIX states that if bs is set and no other conversions
+ * than noerror, notrunc or sync are specified, the block
+ * is output without buffering as it is read.
+ */
+ if (ddflags & C_BS) {
+ out.dbcnt = in.dbcnt;
+ dd_out(1);
+ in.dbcnt = 0;
+ continue;
+ }
+
+ if (ddflags & C_SWAB) {
+ if ((n = in.dbrcnt) & 1) {
+ ++st.swab;
+ --n;
+ }
+ swab(in.dbp, in.dbp, n);
+ }
+
+ in.dbp += in.dbrcnt;
+ (*cfunc)();
+ }
+}
+
+/*
+ * Cleanup any remaining I/O and flush output. If necessary, output file
+ * is truncated.
+ */
+static void
+dd_close(void)
+{
+
+ if (cfunc == def)
+ def_close();
+ else if (cfunc == block)
+ block_close();
+ else if (cfunc == unblock)
+ unblock_close();
+ if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) {
+ (void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
+ out.dbcnt = out.dbsz;
+ }
+ /* If there are pending sparse blocks, make sure
+ * to write out the final block un-sparse
+ */
+ if ((out.dbcnt == 0) && pending) {
+ memset(out.db, 0, out.dbsz);
+ out.dbcnt = out.dbsz;
+ out.dbp = out.db + out.dbcnt;
+ pending -= out.dbsz;
+ }
+ if (out.dbcnt)
+ dd_out(1);
+
+ /*
+ * Reporting nfs write error may be deferred until next
+ * write(2) or close(2) system call. So, we need to do an
+ * extra check. If an output is stdout, the file structure
+ * may be shared with other processes and close(2) just
+ * decreases the reference count.
+ */
+ if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
+ && errno != EINVAL) {
+ err(EXIT_FAILURE, "fsync stdout");
+ /* NOTREACHED */
+ }
+ if (ddop_close(out, out.fd) == -1) {
+ err(EXIT_FAILURE, "close");
+ /* NOTREACHED */
+ }
+}
+
+void
+dd_out(int force)
+{
+ static int warned;
+ int64_t cnt, n, nw;
+ u_char *outp;
+
+ /*
+ * Write one or more blocks out. The common case is writing a full
+ * output block in a single write; increment the full block stats.
+ * Otherwise, we're into partial block writes. If a partial write,
+ * and it's a character device, just warn. If a tape device, quit.
+ *
+ * The partial writes represent two cases. 1: Where the input block
+ * was less than expected so the output block was less than expected.
+ * 2: Where the input block was the right size but we were forced to
+ * write the block in multiple chunks. The original versions of dd(1)
+ * never wrote a block in more than a single write, so the latter case
+ * never happened.
+ *
+ * One special case is if we're forced to do the write -- in that case
+ * we play games with the buffer size, and it's usually a partial write.
+ */
+ outp = out.db;
+ for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
+ for (cnt = n;; cnt -= nw) {
+
+ if (!force && ddflags & C_SPARSE) {
+ int sparse, i;
+ sparse = 1; /* Is buffer sparse? */
+ for (i = 0; i < cnt; i++)
+ if (outp[i] != 0) {
+ sparse = 0;
+ break;
+ }
+ if (sparse) {
+ pending += cnt;
+ outp += cnt;
+ nw = 0;
+ break;
+ }
+ }
+ if (pending != 0) {
+ if (ddop_lseek(out,
+ out.fd, pending, SEEK_CUR) == -1)
+ err(EXIT_FAILURE, "%s: seek error creating sparse file",
+ out.name);
+ }
+ nw = bwrite(&out, outp, cnt);
+ if (nw <= 0) {
+ if (nw == 0)
+ errx(EXIT_FAILURE,
+ "%s: end of device", out.name);
+ /* NOTREACHED */
+ if (errno != EINTR)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+ nw = 0;
+ }
+ if (pending) {
+ st.bytes += pending;
+ st.sparse += pending/out.dbsz;
+ st.out_full += pending/out.dbsz;
+ pending = 0;
+ }
+ outp += nw;
+ st.bytes += nw;
+ if (nw == n) {
+ if ((uint64_t)n != out.dbsz)
+ ++st.out_part;
+ else
+ ++st.out_full;
+ break;
+ }
+ ++st.out_part;
+ if (nw == cnt)
+ break;
+ if (out.flags & ISCHR && !warned) {
+ warned = 1;
+ warnx("%s: short write on character device", out.name);
+ }
+ if (out.flags & ISTAPE)
+ errx(EXIT_FAILURE,
+ "%s: short write on tape device", out.name);
+ /* NOTREACHED */
+
+ }
+ if ((out.dbcnt -= n) < out.dbsz)
+ break;
+ }
+
+ /* Reassemble the output block. */
+ if (out.dbcnt)
+ (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
+ out.dbp = out.db + out.dbcnt;
+
+ if (progress && (st.out_full + st.out_part) % progress == 0)
+ (void)write(STDERR_FILENO, ".", 1);
+}
+
+/*
+ * A protected against SIGINFO write
+ */
+ssize_t
+bwrite(IO *io, const void *buf, size_t len)
+{
+ sigset_t oset;
+ ssize_t rv;
+ int oerrno;
+
+ (void)sigprocmask(SIG_BLOCK, &infoset, &oset);
+ rv = io->ops->op_write(io->fd, buf, len);
+ oerrno = errno;
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+ errno = oerrno;
+ return (rv);
+}
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.h b/toolbox/upstream-netbsd/bin/dd/dd.h
new file mode 100644
index 0000000..b01c7b3
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/dd.h
@@ -0,0 +1,127 @@
+/* $NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)dd.h 8.3 (Berkeley) 4/2/94
+ */
+
+#include <sys/stat.h>
+
+struct ddfops {
+ int (*op_init)(void);
+
+ int (*op_open)(const char *, int, ...);
+ int (*op_close)(int);
+
+ int (*op_fcntl)(int, int, ...);
+#ifdef __ANDROID__
+ int (*op_ioctl)(int, int, ...);
+#else
+ int (*op_ioctl)(int, unsigned long, ...);
+#endif
+
+ int (*op_fstat)(int, struct stat *);
+ int (*op_fsync)(int);
+ int (*op_ftruncate)(int, off_t);
+
+ off_t (*op_lseek)(int, off_t, int);
+
+ ssize_t (*op_read)(int, void *, size_t);
+ ssize_t (*op_write)(int, const void *, size_t);
+};
+
+#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, __VA_ARGS__)
+#define ddop_close(dir, a1) dir.ops->op_close(a1)
+#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
+#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
+#define ddop_fsync(dir, a1) dir.ops->op_fsync(a1)
+#define ddop_ftruncate(dir, a1, a2) dir.ops->op_ftruncate(a1, a2)
+#define ddop_lseek(dir, a1, a2, a3) dir.ops->op_lseek(a1, a2, a3)
+#define ddop_read(dir, a1, a2, a3) dir.ops->op_read(a1, a2, a3)
+#define ddop_write(dir, a1, a2, a3) dir.ops->op_write(a1, a2, a3)
+
+/* Input/output stream state. */
+typedef struct {
+ u_char *db; /* buffer address */
+ u_char *dbp; /* current buffer I/O address */
+ uint64_t dbcnt; /* current buffer byte count */
+ int64_t dbrcnt; /* last read byte count */
+ uint64_t dbsz; /* buffer size */
+
+#define ISCHR 0x01 /* character device (warn on short) */
+#define ISPIPE 0x02 /* pipe (not truncatable) */
+#define ISTAPE 0x04 /* tape (not seekable) */
+#define NOREAD 0x08 /* not readable */
+ u_int flags;
+
+ const char *name; /* name */
+ int fd; /* file descriptor */
+ uint64_t offset; /* # of blocks to skip */
+ struct ddfops const *ops; /* ops to use with fd */
+} IO;
+
+typedef struct {
+ uint64_t in_full; /* # of full input blocks */
+ uint64_t in_part; /* # of partial input blocks */
+ uint64_t out_full; /* # of full output blocks */
+ uint64_t out_part; /* # of partial output blocks */
+ uint64_t trunc; /* # of truncated records */
+ uint64_t swab; /* # of odd-length swab blocks */
+ uint64_t sparse; /* # of sparse output blocks */
+ uint64_t bytes; /* # of bytes written */
+ struct timeval start; /* start time of dd */
+} STAT;
+
+/* Flags (in ddflags). */
+#define C_ASCII 0x00001
+#define C_BLOCK 0x00002
+#define C_BS 0x00004
+#define C_CBS 0x00008
+#define C_COUNT 0x00010
+#define C_EBCDIC 0x00020
+#define C_FILES 0x00040
+#define C_IBS 0x00080
+#define C_IF 0x00100
+#define C_LCASE 0x00200
+#define C_NOERROR 0x00400
+#define C_NOTRUNC 0x00800
+#define C_OBS 0x01000
+#define C_OF 0x02000
+#define C_SEEK 0x04000
+#define C_SKIP 0x08000
+#define C_SWAB 0x10000
+#define C_SYNC 0x20000
+#define C_UCASE 0x40000
+#define C_UNBLOCK 0x80000
+#define C_OSYNC 0x100000
+#define C_SPARSE 0x200000
diff --git a/toolbox/upstream-netbsd/bin/dd/dd_hostops.c b/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
new file mode 100644
index 0000000..d6e7a89
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
@@ -0,0 +1,53 @@
+/* $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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 <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "dd.h"
+
+const struct ddfops ddfops_prog = {
+ .op_open = open,
+ .op_close = close,
+ .op_fcntl = fcntl,
+ .op_ioctl = ioctl,
+ .op_fstat = fstat,
+ .op_fsync = fsync,
+ .op_ftruncate = ftruncate,
+ .op_lseek = lseek,
+ .op_read = read,
+ .op_write = write,
+};
diff --git a/toolbox/upstream-netbsd/bin/dd/extern.h b/toolbox/upstream-netbsd/bin/dd/extern.h
new file mode 100644
index 0000000..9c59021
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/extern.h
@@ -0,0 +1,82 @@
+/* $NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 4/2/94
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef NO_CONV
+__dead void block(void);
+__dead void block_close(void);
+__dead void unblock(void);
+__dead void unblock_close(void);
+#else
+void block(void);
+void block_close(void);
+void unblock(void);
+void unblock_close(void);
+#endif
+
+#ifndef NO_MSGFMT
+int dd_write_msg(const char *, int);
+#endif
+
+void dd_out(int);
+void def(void);
+void def_close(void);
+void jcl(char **);
+void pos_in(void);
+void pos_out(void);
+void summary(void);
+void summaryx(int);
+__dead void terminate(int);
+void unblock(void);
+void unblock_close(void);
+ssize_t bwrite(IO *, const void *, size_t);
+
+extern IO in, out;
+extern STAT st;
+extern void (*cfunc)(void);
+extern uint64_t cpy_cnt;
+extern uint64_t cbsz;
+extern u_int ddflags;
+extern u_int files_cnt;
+extern uint64_t progress;
+extern const u_char *ctab;
+extern const u_char a2e_32V[], a2e_POSIX[];
+extern const u_char e2a_32V[], e2a_POSIX[];
+extern const u_char a2ibm_32V[], a2ibm_POSIX[];
+extern u_char casetab[];
+extern const char *msgfmt;
diff --git a/toolbox/upstream-netbsd/bin/dd/misc.c b/toolbox/upstream-netbsd/bin/dd/misc.c
new file mode 100644
index 0000000..0fac98b
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/misc.c
@@ -0,0 +1,342 @@
+/* $NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+#include <inttypes.h>
+
+#include "dd.h"
+#include "extern.h"
+
+#define tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
+
+static void posix_summary(void);
+#ifndef NO_MSGFMT
+static void custom_summary(void);
+static void human_summary(void);
+static void quiet_summary(void);
+
+static void buffer_write(const char *, size_t, int);
+#endif /* NO_MSGFMT */
+
+void
+summary(void)
+{
+
+ if (progress)
+ (void)write(STDERR_FILENO, "\n", 1);
+
+#ifdef NO_MSGFMT
+ return posix_summary();
+#else /* NO_MSGFMT */
+ if (strncmp(msgfmt, "human", sizeof("human")) == 0)
+ return human_summary();
+
+ if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
+ return posix_summary();
+
+ if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
+ return quiet_summary();
+
+ return custom_summary();
+#endif /* NO_MSGFMT */
+}
+
+static void
+posix_summary(void)
+{
+ char buf[100];
+ int64_t mS;
+ struct timeval tv;
+
+ if (progress)
+ (void)write(STDERR_FILENO, "\n", 1);
+
+ (void)gettimeofday(&tv, NULL);
+ mS = tv2mS(tv) - tv2mS(st.start);
+ if (mS == 0)
+ mS = 1;
+
+ /* Use snprintf(3) so that we don't reenter stdio(3). */
+ (void)snprintf(buf, sizeof(buf),
+ "%llu+%llu records in\n%llu+%llu records out\n",
+ (unsigned long long)st.in_full, (unsigned long long)st.in_part,
+ (unsigned long long)st.out_full, (unsigned long long)st.out_part);
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ if (st.swab) {
+ (void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
+ (unsigned long long)st.swab,
+ (st.swab == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.trunc) {
+ (void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
+ (unsigned long long)st.trunc,
+ (st.trunc == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.sparse) {
+ (void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
+ (unsigned long long)st.sparse,
+ (st.sparse == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ (void)snprintf(buf, sizeof(buf),
+ "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
+ (unsigned long long) st.bytes,
+ (long) (mS / 1000),
+ (int) (mS % 1000),
+ (unsigned long long) (st.bytes * 1000LL / mS));
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+/* ARGSUSED */
+void
+summaryx(int notused)
+{
+
+ summary();
+}
+
+/* ARGSUSED */
+void
+terminate(int signo)
+{
+
+ summary();
+ (void)raise_default_signal(signo);
+ _exit(127);
+}
+
+#ifndef NO_MSGFMT
+/*
+ * Buffer write(2) calls
+ */
+static void
+buffer_write(const char *str, size_t size, int flush)
+{
+ static char wbuf[128];
+ static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */
+
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ if (str != NULL) {
+ wbuf[cnt++] = str[i];
+ }
+ if (cnt >= sizeof(wbuf)) {
+ (void)write(STDERR_FILENO, wbuf, cnt);
+ cnt = 0;
+ }
+ }
+
+ if (flush != 0) {
+ (void)write(STDERR_FILENO, wbuf, cnt);
+ cnt = 0;
+ }
+}
+
+/*
+ * Write summary to stderr according to format 'fmt'. If 'enable' is 0, it
+ * will not attempt to write anything. Can be used to validate the
+ * correctness of the 'fmt' string.
+ */
+int
+dd_write_msg(const char *fmt, int enable)
+{
+ char hbuf[7], nbuf[32];
+ const char *ptr;
+ int64_t mS;
+ struct timeval tv;
+
+ (void)gettimeofday(&tv, NULL);
+ mS = tv2mS(tv) - tv2mS(st.start);
+ if (mS == 0)
+ mS = 1;
+
+#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \
+ while (/*CONSTCOND*/0)
+#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \
+ while (/*CONSTCOND*/0)
+
+ for (ptr = fmt; *ptr; ptr++) {
+ if (*ptr != '%') {
+ ADDC(*ptr);
+ continue;
+ }
+
+ switch (*++ptr) {
+ case 'b':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.bytes);
+ ADDS(nbuf);
+ break;
+ case 'B':
+ if (humanize_number(hbuf, sizeof(hbuf),
+ st.bytes, "B",
+ HN_AUTOSCALE, HN_DECIMAL) == -1)
+ warnx("humanize_number (bytes transferred)");
+ ADDS(hbuf);
+ break;
+ case 'e':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long) (st.bytes * 1000LL / mS));
+ ADDS(nbuf);
+ break;
+ case 'E':
+ if (humanize_number(hbuf, sizeof(hbuf),
+ st.bytes * 1000LL / mS, "B",
+ HN_AUTOSCALE, HN_DECIMAL) == -1)
+ warnx("humanize_number (bytes per second)");
+ ADDS(hbuf); ADDS("/sec");
+ break;
+ case 'i':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.in_part);
+ ADDS(nbuf);
+ break;
+ case 'I':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.in_full);
+ ADDS(nbuf);
+ break;
+ case 'o':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.out_part);
+ ADDS(nbuf);
+ break;
+ case 'O':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.out_full);
+ ADDS(nbuf);
+ break;
+ case 's':
+ (void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
+ (long) (mS / 1000), (int) (mS % 1000));
+ ADDS(nbuf);
+ break;
+ case 'p':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.sparse);
+ ADDS(nbuf);
+ break;
+ case 't':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.trunc);
+ ADDS(nbuf);
+ break;
+ case 'w':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.swab);
+ ADDS(nbuf);
+ break;
+ case 'P':
+ ADDS("block");
+ if (st.sparse != 1) ADDS("s");
+ break;
+ case 'T':
+ ADDS("block");
+ if (st.trunc != 1) ADDS("s");
+ break;
+ case 'W':
+ ADDS("block");
+ if (st.swab != 1) ADDS("s");
+ break;
+ case '%':
+ ADDC(*ptr);
+ break;
+ default:
+ if (*ptr == '\0')
+ goto done;
+ errx(EXIT_FAILURE, "unknown specifier '%c' in "
+ "msgfmt string", *ptr);
+ /* NOTREACHED */
+ }
+ }
+
+done:
+ /* flush buffer */
+ buffer_write(NULL, 0, 1);
+ return 0;
+}
+
+static void
+custom_summary(void)
+{
+
+ dd_write_msg(msgfmt, 1);
+}
+
+static void
+human_summary(void)
+{
+ (void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1);
+ if (st.swab) {
+ (void)dd_write_msg("%w odd length swab %W\n", 1);
+ }
+ if (st.trunc) {
+ (void)dd_write_msg("%t truncated %T\n", 1);
+ }
+ if (st.sparse) {
+ (void)dd_write_msg("%p sparse output %P\n", 1);
+ }
+ (void)dd_write_msg("%b bytes (%B) transferred in %s secs "
+ "(%e bytes/sec - %E)\n", 1);
+}
+
+static void
+quiet_summary(void)
+{
+
+ /* stay quiet */
+}
+#endif /* NO_MSGFMT */
diff --git a/toolbox/upstream-netbsd/bin/dd/position.c b/toolbox/upstream-netbsd/bin/dd/position.c
new file mode 100644
index 0000000..36dd580
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/dd/position.c
@@ -0,0 +1,185 @@
+/* $NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+/*
+ * Position input/output data streams before starting the copy. Device type
+ * dependent. Seekable devices use lseek, and the rest position by reading.
+ * Seeking past the end of file can cause null blocks to be written to the
+ * output.
+ */
+void
+pos_in(void)
+{
+ int bcnt, cnt, nr, warned;
+
+ /* If not a pipe or tape device, try to seek on it. */
+ if (!(in.flags & (ISPIPE|ISTAPE))) {
+ if (ddop_lseek(in, in.fd,
+ (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
+ err(EXIT_FAILURE, "%s", in.name);
+ /* NOTREACHED */
+ }
+ return;
+ /* NOTREACHED */
+ }
+
+ /*
+ * Read the data. If a pipe, read until satisfy the number of bytes
+ * being skipped. No differentiation for reading complete and partial
+ * blocks for other devices.
+ */
+ for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
+ if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) {
+ if (in.flags & ISPIPE) {
+ if (!(bcnt -= nr)) {
+ bcnt = in.dbsz;
+ --cnt;
+ }
+ } else
+ --cnt;
+ continue;
+ }
+
+ if (nr == 0) {
+ if (files_cnt > 1) {
+ --files_cnt;
+ continue;
+ }
+ errx(EXIT_FAILURE, "skip reached end of input");
+ /* NOTREACHED */
+ }
+
+ /*
+ * Input error -- either EOF with no more files, or I/O error.
+ * If noerror not set die. POSIX requires that the warning
+ * message be followed by an I/O display.
+ */
+ if (ddflags & C_NOERROR) {
+ if (!warned) {
+
+ warn("%s", in.name);
+ warned = 1;
+ summary();
+ }
+ continue;
+ }
+ err(EXIT_FAILURE, "%s", in.name);
+ /* NOTREACHED */
+ }
+}
+
+void
+pos_out(void)
+{
+ struct mtop t_op;
+ int n;
+ uint64_t cnt;
+
+ /*
+ * If not a tape, try seeking on the file. Seeking on a pipe is
+ * going to fail, but don't protect the user -- they shouldn't
+ * have specified the seek operand.
+ */
+ if (!(out.flags & ISTAPE)) {
+ if (ddop_lseek(out, out.fd,
+ (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+ return;
+ }
+
+ /* If no read access, try using mtio. */
+ if (out.flags & NOREAD) {
+ t_op.mt_op = MTFSR;
+ t_op.mt_count = out.offset;
+
+ if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+ return;
+ }
+
+ /* Read it. */
+ for (cnt = 0; cnt < out.offset; ++cnt) {
+ if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
+ continue;
+
+ if (n < 0)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+
+ /*
+ * If reach EOF, fill with NUL characters; first, back up over
+ * the EOF mark. Note, cnt has not yet been incremented, so
+ * the EOF read does not count as a seek'd block.
+ */
+ t_op.mt_op = MTBSR;
+ t_op.mt_count = 1;
+ if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+
+ while (cnt++ < out.offset)
+ if ((uint64_t)(n = bwrite(&out,
+ out.db, out.dbsz)) != out.dbsz)
+ err(EXIT_FAILURE, "%s", out.name);
+ /* NOTREACHED */
+ break;
+ }
+}
diff --git a/toolbox/upstream-netbsd/bin/ln/ln.c b/toolbox/upstream-netbsd/bin/ln/ln.c
new file mode 100644
index 0000000..9127477
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/ln/ln.c
@@ -0,0 +1,230 @@
+/* $NetBSD: ln.c,v 1.35 2011/08/29 14:38:30 joerg Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94";
+#else
+__RCSID("$NetBSD: ln.c,v 1.35 2011/08/29 14:38:30 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int fflag; /* Unlink existing files. */
+static int hflag; /* Check new name for symlink first. */
+static int iflag; /* Interactive mode. */
+static int sflag; /* Symbolic, not hard, link. */
+static int vflag; /* Verbose output */
+
+ /* System link call. */
+static int (*linkf)(const char *, const char *);
+static char linkch;
+
+static int linkit(const char *, const char *, int);
+__dead static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ int ch, exitval;
+ char *sourcedir;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "fhinsv")) != -1)
+ switch (ch) {
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'h':
+ case 'n':
+ hflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ fflag = 0;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (sflag) {
+ linkf = symlink;
+ linkch = '-';
+ } else {
+ linkf = link;
+ linkch = '=';
+ }
+
+ switch(argc) {
+ case 0:
+ usage();
+ /* NOTREACHED */
+ case 1: /* ln target */
+ exit(linkit(argv[0], ".", 1));
+ /* NOTREACHED */
+ case 2: /* ln target source */
+ exit(linkit(argv[0], argv[1], 0));
+ /* NOTREACHED */
+ }
+
+ /* ln target1 target2 directory */
+ sourcedir = argv[argc - 1];
+ if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+ /* we were asked not to follow symlinks, but found one at
+ the target--simulate "not a directory" error */
+ errno = ENOTDIR;
+ err(EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (stat(sourcedir, &sb)) {
+ err(EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ usage();
+ /* NOTREACHED */
+ }
+ for (exitval = 0; *argv != sourcedir; ++argv)
+ exitval |= linkit(*argv, sourcedir, 1);
+ exit(exitval);
+ /* NOTREACHED */
+}
+
+static int
+linkit(const char *target, const char *source, int isdir)
+{
+ struct stat sb;
+ const char *p;
+ char path[MAXPATHLEN];
+ int ch, exists, first;
+
+ if (!sflag) {
+ /* If target doesn't exist, quit now. */
+ if (stat(target, &sb)) {
+ warn("%s", target);
+ return (1);
+ }
+ }
+
+ /* If the source is a directory (and not a symlink if hflag),
+ append the target's name. */
+ if (isdir ||
+ (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
+ (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
+ if ((p = strrchr(target, '/')) == NULL)
+ p = target;
+ else
+ ++p;
+ (void)snprintf(path, sizeof(path), "%s/%s", source, p);
+ source = path;
+ }
+
+ exists = !lstat(source, &sb);
+
+ /*
+ * If the file exists, then unlink it forcibly if -f was specified
+ * and interactively if -i was specified.
+ */
+ if (fflag && exists) {
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ } else if (iflag && exists) {
+ fflush(stdout);
+ (void)fprintf(stderr, "replace %s? ", source);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first != 'y' && first != 'Y') {
+ (void)fprintf(stderr, "not replaced\n");
+ return (1);
+ }
+
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ }
+
+ /* Attempt the link. */
+ if ((*linkf)(target, source)) {
+ warn("%s", source);
+ return (1);
+ }
+ if (vflag)
+ (void)printf("%s %c> %s\n", source, linkch, target);
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
+ getprogname(), getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/toolbox/upstream-netbsd/bin/mv/mv.c b/toolbox/upstream-netbsd/bin/mv/mv.c
new file mode 100644
index 0000000..4be6c30
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/mv/mv.c
@@ -0,0 +1,396 @@
+/* $NetBSD: mv.c,v 1.43 2011/08/29 14:46:54 joerg Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Smith of The State University of New York at Buffalo.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mv.c 8.2 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: mv.c,v 1.43 2011/08/29 14:46:54 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/extattr.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+static int fflg, iflg, vflg;
+static int stdin_ok;
+
+static int copy(char *, char *);
+static int do_move(char *, char *);
+static int fastcopy(char *, char *, struct stat *);
+__dead static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, len, rval;
+ char *p, *endp;
+ struct stat sb;
+ char path[MAXPATHLEN + 1];
+ size_t baselen;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "ifv")) != -1)
+ switch (ch) {
+ case 'i':
+ fflg = 0;
+ iflg = 1;
+ break;
+ case 'f':
+ iflg = 0;
+ fflg = 1;
+ break;
+ case 'v':
+ vflg = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ usage();
+
+ stdin_ok = isatty(STDIN_FILENO);
+
+ /*
+ * If the stat on the target fails or the target isn't a directory,
+ * try the move. More than 2 arguments is an error in this case.
+ */
+ if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) {
+ if (argc > 2)
+ usage();
+ exit(do_move(argv[0], argv[1]));
+ }
+
+ /* It's a directory, move each file into it. */
+ baselen = strlcpy(path, argv[argc - 1], sizeof(path));
+ if (baselen >= sizeof(path))
+ errx(1, "%s: destination pathname too long", argv[argc - 1]);
+ endp = &path[baselen];
+ if (!baselen || *(endp - 1) != '/') {
+ *endp++ = '/';
+ ++baselen;
+ }
+ for (rval = 0; --argc; ++argv) {
+ p = *argv + strlen(*argv) - 1;
+ while (*p == '/' && p != *argv)
+ *p-- = '\0';
+ if ((p = strrchr(*argv, '/')) == NULL)
+ p = *argv;
+ else
+ ++p;
+
+ if ((baselen + (len = strlen(p))) >= MAXPATHLEN) {
+ warnx("%s: destination pathname too long", *argv);
+ rval = 1;
+ } else {
+ memmove(endp, p, len + 1);
+ if (do_move(*argv, path))
+ rval = 1;
+ }
+ }
+ exit(rval);
+ /* NOTREACHED */
+}
+
+static int
+do_move(char *from, char *to)
+{
+ struct stat sb;
+ char modep[15];
+
+ /*
+ * (1) If the destination path exists, the -f option is not specified
+ * and either of the following conditions are true:
+ *
+ * (a) The permissions of the destination path do not permit
+ * writing and the standard input is a terminal.
+ * (b) The -i option is specified.
+ *
+ * the mv utility shall write a prompt to standard error and
+ * read a line from standard input. If the response is not
+ * affirmative, mv shall do nothing more with the current
+ * source file...
+ */
+ if (!fflg && !access(to, F_OK)) {
+ int ask = 1;
+ int ch;
+
+ if (iflg) {
+ if (access(from, F_OK)) {
+ warn("rename %s", from);
+ return (1);
+ }
+ (void)fprintf(stderr, "overwrite %s? ", to);
+ } else if (stdin_ok && access(to, W_OK) && !stat(to, &sb)) {
+ if (access(from, F_OK)) {
+ warn("rename %s", from);
+ return (1);
+ }
+ strmode(sb.st_mode, modep);
+ (void)fprintf(stderr, "override %s%s%s/%s for %s? ",
+ modep + 1, modep[9] == ' ' ? "" : " ",
+ user_from_uid(sb.st_uid, 0),
+ group_from_gid(sb.st_gid, 0), to);
+ } else
+ ask = 0;
+ if (ask) {
+ if ((ch = getchar()) != EOF && ch != '\n') {
+ int ch2;
+ while ((ch2 = getchar()) != EOF && ch2 != '\n')
+ continue;
+ }
+ if (ch != 'y' && ch != 'Y')
+ return (0);
+ }
+ }
+
+ /*
+ * (2) If rename() succeeds, mv shall do nothing more with the
+ * current source file. If it fails for any other reason than
+ * EXDEV, mv shall write a diagnostic message to the standard
+ * error and do nothing more with the current source file.
+ *
+ * (3) If the destination path exists, and it is a file of type
+ * directory and source_file is not a file of type directory,
+ * or it is a file not of type directory, and source file is
+ * a file of type directory, mv shall write a diagnostic
+ * message to standard error, and do nothing more with the
+ * current source file...
+ */
+ if (!rename(from, to)) {
+ if (vflg)
+ printf("%s -> %s\n", from, to);
+ return (0);
+ }
+
+ if (errno != EXDEV) {
+ warn("rename %s to %s", from, to);
+ return (1);
+ }
+
+ /*
+ * (4) If the destination path exists, mv shall attempt to remove it.
+ * If this fails for any reason, mv shall write a diagnostic
+ * message to the standard error and do nothing more with the
+ * current source file...
+ */
+ if (!lstat(to, &sb)) {
+ if ((S_ISDIR(sb.st_mode)) ? rmdir(to) : unlink(to)) {
+ warn("can't remove %s", to);
+ return (1);
+ }
+ }
+
+ /*
+ * (5) The file hierarchy rooted in source_file shall be duplicated
+ * as a file hierarchy rooted in the destination path...
+ */
+ if (lstat(from, &sb)) {
+ warn("%s", from);
+ return (1);
+ }
+
+ return (S_ISREG(sb.st_mode) ?
+ fastcopy(from, to, &sb) : copy(from, to));
+}
+
+static int
+fastcopy(char *from, char *to, struct stat *sbp)
+{
+ struct timeval tval[2];
+ static blksize_t blen;
+ static char *bp;
+ int nread, from_fd, to_fd;
+
+ if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
+ warn("%s", from);
+ return (1);
+ }
+ if ((to_fd =
+ open(to, O_CREAT | O_TRUNC | O_WRONLY, sbp->st_mode)) < 0) {
+ warn("%s", to);
+ (void)close(from_fd);
+ return (1);
+ }
+ if (!blen && !(bp = malloc(blen = sbp->st_blksize))) {
+ warn(NULL);
+ blen = 0;
+ (void)close(from_fd);
+ (void)close(to_fd);
+ return (1);
+ }
+ while ((nread = read(from_fd, bp, blen)) > 0)
+ if (write(to_fd, bp, nread) != nread) {
+ warn("%s", to);
+ goto err;
+ }
+ if (nread < 0) {
+ warn("%s", from);
+err: if (unlink(to))
+ warn("%s: remove", to);
+ (void)close(from_fd);
+ (void)close(to_fd);
+ return (1);
+ }
+
+#ifndef __ANDROID__
+ if (fcpxattr(from_fd, to_fd) == -1)
+ warn("%s: error copying extended attributes", to);
+#endif
+
+ (void)close(from_fd);
+#ifdef BSD4_4
+ TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec);
+#else
+ tval[0].tv_sec = sbp->st_atime;
+ tval[1].tv_sec = sbp->st_mtime;
+ tval[0].tv_usec = 0;
+ tval[1].tv_usec = 0;
+#endif
+#ifdef __SVR4
+ if (utimes(to, tval))
+#else
+ if (futimes(to_fd, tval))
+#endif
+ warn("%s: set times", to);
+ if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
+ if (errno != EPERM)
+ warn("%s: set owner/group", to);
+ sbp->st_mode &= ~(S_ISUID | S_ISGID);
+ }
+ if (fchmod(to_fd, sbp->st_mode))
+ warn("%s: set mode", to);
+#ifndef __ANDROID__
+ if (fchflags(to_fd, sbp->st_flags) && (errno != EOPNOTSUPP))
+ warn("%s: set flags (was: 0%07o)", to, sbp->st_flags);
+#endif
+
+ if (close(to_fd)) {
+ warn("%s", to);
+ return (1);
+ }
+
+ if (unlink(from)) {
+ warn("%s: remove", from);
+ return (1);
+ }
+
+ if (vflg)
+ printf("%s -> %s\n", from, to);
+
+ return (0);
+}
+
+static int
+copy(char *from, char *to)
+{
+ pid_t pid;
+ int status;
+
+ if ((pid = vfork()) == 0) {
+ execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to, NULL);
+ warn("%s", _PATH_CP);
+ _exit(1);
+ }
+ if (waitpid(pid, &status, 0) == -1) {
+ warn("%s: waitpid", _PATH_CP);
+ return (1);
+ }
+ if (!WIFEXITED(status)) {
+ warnx("%s: did not terminate normally", _PATH_CP);
+ return (1);
+ }
+ if (WEXITSTATUS(status)) {
+ warnx("%s: terminated with %d (non-zero) status",
+ _PATH_CP, WEXITSTATUS(status));
+ return (1);
+ }
+ if (!(pid = vfork())) {
+ execl(_PATH_RM, "mv", "-rf", "--", from, NULL);
+ warn("%s", _PATH_RM);
+ _exit(1);
+ }
+ if (waitpid(pid, &status, 0) == -1) {
+ warn("%s: waitpid", _PATH_RM);
+ return (1);
+ }
+ if (!WIFEXITED(status)) {
+ warnx("%s: did not terminate normally", _PATH_RM);
+ return (1);
+ }
+ if (WEXITSTATUS(status)) {
+ warnx("%s: terminated with %d (non-zero) status",
+ _PATH_RM, WEXITSTATUS(status));
+ return (1);
+ }
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s [-fiv] source target\n"
+ " %s [-fiv] source ... directory\n", getprogname(),
+ getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/toolbox/upstream-netbsd/bin/mv/pathnames.h b/toolbox/upstream-netbsd/bin/mv/pathnames.h
new file mode 100644
index 0000000..7838946
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/mv/pathnames.h
@@ -0,0 +1,45 @@
+/* $NetBSD: pathnames.h,v 1.8 2004/08/19 22:26:07 christos Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 5/31/93
+ */
+
+#ifdef __ANDROID__
+#define _PATH_RM "/system/bin/rm"
+#define _PATH_CP "/system/bin/cp"
+#else
+#ifdef RESCUEDIR
+#define _PATH_RM RESCUEDIR "/rm"
+#define _PATH_CP RESCUEDIR "/cp"
+#else
+#define _PATH_RM "/bin/rm"
+#define _PATH_CP "/bin/cp"
+#endif
+#endif
diff --git a/toolbox/upstream-netbsd/bin/rm/rm.c b/toolbox/upstream-netbsd/bin/rm/rm.c
new file mode 100644
index 0000000..f183810
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/rm/rm.c
@@ -0,0 +1,625 @@
+/* $NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994, 2003
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rm.c 8.8 (Berkeley) 4/27/95";
+#else
+__RCSID("$NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <grp.h>
+#include <locale.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int dflag, eval, fflag, iflag, Pflag, stdin_ok, vflag, Wflag;
+static int xflag;
+static sig_atomic_t pinfo;
+
+static int check(char *, char *, struct stat *);
+static void checkdot(char **);
+static void progress(int);
+static void rm_file(char **);
+static int rm_overwrite(char *, struct stat *);
+static void rm_tree(char **);
+__dead static void usage(void);
+
+/*
+ * For the sake of the `-f' flag, check whether an error number indicates the
+ * failure of an operation due to an non-existent file, either per se (ENOENT)
+ * or because its filename argument was illegal (ENAMETOOLONG, ENOTDIR).
+ */
+#define NONEXISTENT(x) \
+ ((x) == ENOENT || (x) == ENAMETOOLONG || (x) == ENOTDIR)
+
+/*
+ * rm --
+ * This rm is different from historic rm's, but is expected to match
+ * POSIX 1003.2 behavior. The most visible difference is that -f
+ * has two specific effects now, ignore non-existent files and force
+ * file removal.
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch, rflag;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ Pflag = rflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "dfiPRrvWx")) != -1)
+ switch (ch) {
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'i':
+ fflag = 0;
+ iflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ break;
+ case 'R':
+ case 'r': /* Compatibility. */
+ rflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
+#ifndef __ANDROID__
+ case 'W':
+ Wflag = 1;
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ if (fflag)
+ return 0;
+ usage();
+ }
+
+ (void)signal(SIGINFO, progress);
+
+ checkdot(argv);
+
+ if (*argv) {
+ stdin_ok = isatty(STDIN_FILENO);
+
+ if (rflag)
+ rm_tree(argv);
+ else
+ rm_file(argv);
+ }
+
+ exit(eval);
+ /* NOTREACHED */
+}
+
+static void
+rm_tree(char **argv)
+{
+ FTS *fts;
+ FTSENT *p;
+ int flags, needstat, rval;
+
+ /*
+ * Remove a file hierarchy. If forcing removal (-f), or interactive
+ * (-i) or can't ask anyway (stdin_ok), don't stat the file.
+ */
+ needstat = !fflag && !iflag && stdin_ok;
+
+ /*
+ * If the -i option is specified, the user can skip on the pre-order
+ * visit. The fts_number field flags skipped directories.
+ */
+#define SKIPPED 1
+
+ flags = FTS_PHYSICAL;
+ if (!needstat)
+ flags |= FTS_NOSTAT;
+#ifndef __ANDROID__
+ if (Wflag)
+ flags |= FTS_WHITEOUT;
+#endif
+ if (xflag)
+ flags |= FTS_XDEV;
+ if ((fts = fts_open(argv, flags, NULL)) == NULL)
+ err(1, "fts_open failed");
+ while ((p = fts_read(fts)) != NULL) {
+
+ switch (p->fts_info) {
+ case FTS_DNR:
+ if (!fflag || p->fts_errno != ENOENT) {
+ warnx("%s: %s", p->fts_path,
+ strerror(p->fts_errno));
+ eval = 1;
+ }
+ continue;
+ case FTS_ERR:
+ errx(EXIT_FAILURE, "%s: %s", p->fts_path,
+ strerror(p->fts_errno));
+ /* NOTREACHED */
+ case FTS_NS:
+ /*
+ * FTS_NS: assume that if can't stat the file, it
+ * can't be unlinked.
+ */
+ if (fflag && NONEXISTENT(p->fts_errno))
+ continue;
+ if (needstat) {
+ warnx("%s: %s", p->fts_path,
+ strerror(p->fts_errno));
+ eval = 1;
+ continue;
+ }
+ break;
+ case FTS_D:
+ /* Pre-order: give user chance to skip. */
+ if (!fflag && !check(p->fts_path, p->fts_accpath,
+ p->fts_statp)) {
+ (void)fts_set(fts, p, FTS_SKIP);
+ p->fts_number = SKIPPED;
+ }
+ continue;
+ case FTS_DP:
+ /* Post-order: see if user skipped. */
+ if (p->fts_number == SKIPPED)
+ continue;
+ break;
+ default:
+ if (!fflag &&
+ !check(p->fts_path, p->fts_accpath, p->fts_statp))
+ continue;
+ }
+
+ rval = 0;
+ /*
+ * If we can't read or search the directory, may still be
+ * able to remove it. Don't print out the un{read,search}able
+ * message unless the remove fails.
+ */
+ switch (p->fts_info) {
+ case FTS_DP:
+ case FTS_DNR:
+ rval = rmdir(p->fts_accpath);
+ if (rval != 0 && fflag && errno == ENOENT)
+ continue;
+ break;
+
+#ifndef __ANDROID__
+ case FTS_W:
+ rval = undelete(p->fts_accpath);
+ if (rval != 0 && fflag && errno == ENOENT)
+ continue;
+ break;
+#endif
+
+ default:
+ if (Pflag) {
+ if (rm_overwrite(p->fts_accpath, NULL))
+ continue;
+ }
+ rval = unlink(p->fts_accpath);
+ if (rval != 0 && fflag && NONEXISTENT(errno))
+ continue;
+ break;
+ }
+ if (rval != 0) {
+ warn("%s", p->fts_path);
+ eval = 1;
+ } else if (vflag || pinfo) {
+ pinfo = 0;
+ (void)printf("%s\n", p->fts_path);
+ }
+ }
+ if (errno)
+ err(1, "fts_read");
+ fts_close(fts);
+}
+
+static void
+rm_file(char **argv)
+{
+ struct stat sb;
+ int rval;
+ char *f;
+
+ /*
+ * Remove a file. POSIX 1003.2 states that, by default, attempting
+ * to remove a directory is an error, so must always stat the file.
+ */
+ while ((f = *argv++) != NULL) {
+ /* Assume if can't stat the file, can't unlink it. */
+ if (lstat(f, &sb)) {
+#ifndef __ANDROID__
+ if (Wflag) {
+ sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
+ } else {
+#endif
+ if (!fflag || !NONEXISTENT(errno)) {
+ warn("%s", f);
+ eval = 1;
+ }
+ continue;
+#ifndef __ANDROID__
+ }
+ } else if (Wflag) {
+ warnx("%s: %s", f, strerror(EEXIST));
+ eval = 1;
+ continue;
+#endif
+ }
+
+ if (S_ISDIR(sb.st_mode) && !dflag) {
+ warnx("%s: is a directory", f);
+ eval = 1;
+ continue;
+ }
+ if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
+ continue;
+#ifndef __ANDROID__
+ if (S_ISWHT(sb.st_mode))
+ rval = undelete(f);
+ else if (S_ISDIR(sb.st_mode))
+#else
+ if (S_ISDIR(sb.st_mode))
+#endif
+ rval = rmdir(f);
+ else {
+ if (Pflag) {
+ if (rm_overwrite(f, &sb))
+ continue;
+ }
+ rval = unlink(f);
+ }
+ if (rval && (!fflag || !NONEXISTENT(errno))) {
+ warn("%s", f);
+ eval = 1;
+ }
+ if (vflag && rval == 0)
+ (void)printf("%s\n", f);
+ }
+}
+
+/*
+ * rm_overwrite --
+ * Overwrite the file 3 times with varying bit patterns.
+ *
+ * This is an expensive way to keep people from recovering files from your
+ * non-snapshotted FFS filesystems using fsdb(8). Really. No more. Only
+ * regular files are deleted, directories (and therefore names) will remain.
+ * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
+ * System V file system). In a logging file system, you'll have to have
+ * kernel support.
+ *
+ * A note on standards: U.S. DoD 5220.22-M "National Industrial Security
+ * Program Operating Manual" ("NISPOM") is often cited as a reference
+ * for clearing and sanitizing magnetic media. In fact, a matrix of
+ * "clearing" and "sanitization" methods for various media was given in
+ * Chapter 8 of the original 1995 version of NISPOM. However, that
+ * matrix was *removed from the document* when Chapter 8 was rewritten
+ * in Change 2 to the document in 2001. Recently, the Defense Security
+ * Service has made a revised clearing and sanitization matrix available
+ * in Microsoft Word format on the DSS web site. The standardization
+ * status of this matrix is unclear. Furthermore, one must be very
+ * careful when referring to this matrix: it is intended for the "clearing"
+ * prior to reuse or "sanitization" prior to disposal of *entire media*,
+ * not individual files and the only non-physically-destructive method of
+ * "sanitization" that is permitted for magnetic disks of any kind is
+ * specifically noted to be prohibited for media that have contained
+ * Top Secret data.
+ *
+ * It is impossible to actually conform to the exact procedure given in
+ * the matrix if one is overwriting a file, not an entire disk, because
+ * the procedure requires examination and comparison of the disk's defect
+ * lists. Any program that claims to securely erase *files* while
+ * conforming to the standard, then, is not correct. We do as much of
+ * what the standard requires as can actually be done when erasing a
+ * file, rather than an entire disk; but that does not make us conformant.
+ *
+ * Furthermore, the presence of track caches, disk and controller write
+ * caches, and so forth make it extremely difficult to ensure that data
+ * have actually been written to the disk, particularly when one tries
+ * to repeatedly overwrite the same sectors in quick succession. We call
+ * fsync(), but controllers with nonvolatile cache, as well as IDE disks
+ * that just plain lie about the stable storage of data, will defeat this.
+ *
+ * Finally, widely respected research suggests that the given procedure
+ * is nowhere near sufficient to prevent the recovery of data using special
+ * forensic equipment and techniques that are well-known. This is
+ * presumably one reason that the matrix requires physical media destruction,
+ * rather than any technique of the sort attempted here, for secret data.
+ *
+ * Caveat Emptor.
+ *
+ * rm_overwrite will return 0 on success.
+ */
+
+static int
+rm_overwrite(char *file, struct stat *sbp)
+{
+ struct stat sb, sb2;
+ int fd, randint;
+ char randchar;
+
+ fd = -1;
+ if (sbp == NULL) {
+ if (lstat(file, &sb))
+ goto err;
+ sbp = &sb;
+ }
+ if (!S_ISREG(sbp->st_mode))
+ return 0;
+
+ /* flags to try to defeat hidden caching by forcing seeks */
+ if ((fd = open(file, O_RDWR|O_SYNC|O_RSYNC|O_NOFOLLOW, 0)) == -1)
+ goto err;
+
+ if (fstat(fd, &sb2)) {
+ goto err;
+ }
+
+ if (sb2.st_dev != sbp->st_dev || sb2.st_ino != sbp->st_ino ||
+ !S_ISREG(sb2.st_mode)) {
+ errno = EPERM;
+ goto err;
+ }
+
+#define RAND_BYTES 1
+#define THIS_BYTE 0
+
+#define WRITE_PASS(mode, byte) do { \
+ off_t len; \
+ size_t wlen, i; \
+ char buf[8 * 1024]; \
+ \
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \
+ goto err; \
+ \
+ if (mode == THIS_BYTE) \
+ memset(buf, byte, sizeof(buf)); \
+ for (len = sbp->st_size; len > 0; len -= wlen) { \
+ if (mode == RAND_BYTES) { \
+ for (i = 0; i < sizeof(buf); \
+ i+= sizeof(u_int32_t)) \
+ *(int *)(buf + i) = arc4random(); \
+ } \
+ wlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
+ if ((size_t)write(fd, buf, wlen) != wlen) \
+ goto err; \
+ } \
+ sync(); /* another poke at hidden caches */ \
+} while (/* CONSTCOND */ 0)
+
+#define READ_PASS(byte) do { \
+ off_t len; \
+ size_t rlen; \
+ char pattern[8 * 1024]; \
+ char buf[8 * 1024]; \
+ \
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \
+ goto err; \
+ \
+ memset(pattern, byte, sizeof(pattern)); \
+ for(len = sbp->st_size; len > 0; len -= rlen) { \
+ rlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
+ if((size_t)read(fd, buf, rlen) != rlen) \
+ goto err; \
+ if(memcmp(buf, pattern, rlen)) \
+ goto err; \
+ } \
+ sync(); /* another poke at hidden caches */ \
+} while (/* CONSTCOND */ 0)
+
+ /*
+ * DSS sanitization matrix "clear" for magnetic disks:
+ * option 'c' "Overwrite all addressable locations with a single
+ * character."
+ */
+ randint = arc4random();
+ randchar = *(char *)&randint;
+ WRITE_PASS(THIS_BYTE, randchar);
+
+ /*
+ * DSS sanitization matrix "sanitize" for magnetic disks:
+ * option 'd', sub 2 "Overwrite all addressable locations with a
+ * character, then its complement. Verify "complement" character
+ * was written successfully to all addressable locations, then
+ * overwrite all addressable locations with random characters; or
+ * verify third overwrite of random characters." The rest of the
+ * text in d-sub-2 specifies requirements for overwriting spared
+ * sectors; we cannot conform to it when erasing only a file, thus
+ * we do not conform to the standard.
+ */
+
+ /* 1. "a character" */
+ WRITE_PASS(THIS_BYTE, 0xff);
+
+ /* 2. "its complement" */
+ WRITE_PASS(THIS_BYTE, 0x00);
+
+ /* 3. "Verify 'complement' character" */
+ READ_PASS(0x00);
+
+ /* 4. "overwrite all addressable locations with random characters" */
+
+ WRITE_PASS(RAND_BYTES, 0x00);
+
+ /*
+ * As the file might be huge, and we note that this revision of
+ * the matrix says "random characters", not "a random character"
+ * as the original did, we do not verify the random-character
+ * write; the "or" in the standard allows this.
+ */
+
+ if (close(fd) == -1) {
+ fd = -1;
+ goto err;
+ }
+
+ return 0;
+
+err: eval = 1;
+ warn("%s", file);
+ if (fd != -1)
+ close(fd);
+ return 1;
+}
+
+static int
+check(char *path, char *name, struct stat *sp)
+{
+ int ch, first;
+ char modep[15];
+
+ /* Check -i first. */
+ if (iflag)
+ (void)fprintf(stderr, "remove '%s'? ", path);
+ else {
+ /*
+ * If it's not a symbolic link and it's unwritable and we're
+ * talking to a terminal, ask. Symbolic links are excluded
+ * because their permissions are meaningless. Check stdin_ok
+ * first because we may not have stat'ed the file.
+ */
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ !(access(name, W_OK) && (errno != ETXTBSY)))
+ return (1);
+ strmode(sp->st_mode, modep);
+ if (Pflag) {
+ warnx(
+ "%s: -P was specified but file could not"
+ " be overwritten", path);
+ return 0;
+ }
+ (void)fprintf(stderr, "override %s%s%s:%s for '%s'? ",
+ modep + 1, modep[9] == ' ' ? "" : " ",
+ user_from_uid(sp->st_uid, 0),
+ group_from_gid(sp->st_gid, 0), path);
+ }
+ (void)fflush(stderr);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ return (first == 'y' || first == 'Y');
+}
+
+/*
+ * POSIX.2 requires that if "." or ".." are specified as the basename
+ * portion of an operand, a diagnostic message be written to standard
+ * error and nothing more be done with such operands.
+ *
+ * Since POSIX.2 defines basename as the final portion of a path after
+ * trailing slashes have been removed, we'll remove them here.
+ */
+#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
+static void
+checkdot(char **argv)
+{
+ char *p, **save, **t;
+ int complained;
+
+ complained = 0;
+ for (t = argv; *t;) {
+ /* strip trailing slashes */
+ p = strrchr(*t, '\0');
+ while (--p > *t && *p == '/')
+ *p = '\0';
+
+ /* extract basename */
+ if ((p = strrchr(*t, '/')) != NULL)
+ ++p;
+ else
+ p = *t;
+
+ if (ISDOT(p)) {
+ if (!complained++)
+ warnx("\".\" and \"..\" may not be removed");
+ eval = 1;
+ for (save = t; (t[0] = t[1]) != NULL; ++t)
+ continue;
+ t = save;
+ } else
+ ++t;
+ }
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: %s [-f|-i] [-dPRrvWx] file ...\n",
+ getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
+
+static void
+progress(int sig __unused)
+{
+
+ pinfo++;
+}
diff --git a/toolbox/upstream-netbsd/bin/rmdir/rmdir.c b/toolbox/upstream-netbsd/bin/rmdir/rmdir.c
new file mode 100644
index 0000000..03261ce
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/rmdir/rmdir.c
@@ -0,0 +1,121 @@
+/* $NetBSD: rmdir.c,v 1.26 2011/08/29 14:49:38 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rmdir.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: rmdir.c,v 1.26 2011/08/29 14:49:38 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int rm_path(char *);
+__dead static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, errors, pflag;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ pflag = 0;
+ while ((ch = getopt(argc, argv, "p")) != -1)
+ switch(ch) {
+ case 'p':
+ pflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+
+ for (errors = 0; *argv; argv++) {
+ /* We rely on the kernel to ignore trailing '/' characters. */
+ if (rmdir(*argv) < 0) {
+ warn("%s", *argv);
+ errors = 1;
+ } else if (pflag)
+ errors |= rm_path(*argv);
+ }
+
+ exit(errors);
+ /* NOTREACHED */
+}
+
+static int
+rm_path(char *path)
+{
+ char *p;
+
+ while ((p = strrchr(path, '/')) != NULL) {
+ *p = 0;
+ if (p[1] == 0)
+ /* Ignore trailing '/' on deleted name */
+ continue;
+
+ if (rmdir(path) < 0) {
+ warn("%s", path);
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s [-p] directory ...\n", getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/toolbox/upstream-netbsd/bin/sleep/sleep.c b/toolbox/upstream-netbsd/bin/sleep/sleep.c
new file mode 100644
index 0000000..4349af4
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/sleep/sleep.c
@@ -0,0 +1,159 @@
+/* $NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#include <err.h>
+#include <locale.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+__dead static void alarmhandle(int);
+__dead static void usage(void);
+
+static volatile sig_atomic_t report_requested;
+static void
+report_request(int signo __unused)
+{
+
+ report_requested = 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *arg, *temp;
+ double fval, ival, val;
+ struct timespec ntime;
+ time_t original;
+ int ch, fracflag, rv;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ (void)signal(SIGALRM, alarmhandle);
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ /*
+ * Okay, why not just use atof for everything? Why bother
+ * checking if there is a fraction in use? Because the old
+ * sleep handled the full range of integers, that's why, and a
+ * double can't handle a large long. This is fairly useless
+ * given how large a number a double can hold on most
+ * machines, but now we won't ever have trouble. If you want
+ * 1000000000.9 seconds of sleep, well, that's your
+ * problem. Why use an isdigit() check instead of checking for
+ * a period? Because doing it this way means locales will be
+ * handled transparently by the atof code.
+ */
+ fracflag = 0;
+ arg = *argv;
+ for (temp = arg; *temp != '\0'; temp++)
+ if (!isdigit((unsigned char)*temp))
+ fracflag++;
+
+ if (fracflag) {
+ val = atof(arg);
+ if (val <= 0)
+ usage();
+ ival = floor(val);
+ fval = (1000000000 * (val-ival));
+ ntime.tv_sec = ival;
+ ntime.tv_nsec = fval;
+ }
+ else {
+ ntime.tv_sec = atol(arg);
+ if (ntime.tv_sec <= 0)
+ return EXIT_SUCCESS;
+ ntime.tv_nsec = 0;
+ }
+
+ original = ntime.tv_sec;
+ signal(SIGINFO, report_request);
+ while ((rv = nanosleep(&ntime, &ntime)) != 0) {
+ if (report_requested) {
+ /* Reporting does not bother with nanoseconds. */
+ warnx("about %d second(s) left out of the original %d",
+ (int)ntime.tv_sec, (int)original);
+ report_requested = 0;
+ } else
+ break;
+ }
+
+ if (rv == -1)
+ err(EXIT_FAILURE, "nanosleep failed");
+
+ return EXIT_SUCCESS;
+ /* NOTREACHED */
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s seconds\n", getprogname());
+ exit(EXIT_FAILURE);
+ /* NOTREACHED */
+}
+
+/* ARGSUSED */
+static void
+alarmhandle(int i)
+{
+ _exit(EXIT_SUCCESS);
+ /* NOTREACHED */
+}
diff --git a/toolbox/upstream-netbsd/bin/sync/sync.c b/toolbox/upstream-netbsd/bin/sync/sync.c
new file mode 100644
index 0000000..2b9c367
--- /dev/null
+++ b/toolbox/upstream-netbsd/bin/sync/sync.c
@@ -0,0 +1,59 @@
+/* $NetBSD: sync.c,v 1.13 2008/07/20 00:52:40 lukem Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1987, 1993\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sync.c 8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: sync.c,v 1.13 2008/07/20 00:52:40 lukem Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int, char *[]);
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ setprogname(argv[0]);
+ sync();
+ exit(0);
+ /* NOTREACHED */
+}