diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-03-30 23:24:36 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-03-30 23:24:36 +0000 |
commit | 55a2e3247c87f7b7bb6c2c231c7267a1f7baef29 (patch) | |
tree | f4359d2488477890ab594acbce3373b892063ea5 | |
parent | bb242fb0e8b6fc8e3f380a5d728586349fe49dd4 (diff) | |
parent | f2f7b8481072aefbe99b92b535eb524938059ccb (diff) | |
download | toybox-55a2e3247c87f7b7bb6c2c231c7267a1f7baef29.tar.gz |
Snap for 5422062 from f2f7b8481072aefbe99b92b535eb524938059ccb to qt-release
Change-Id: I495ed954c300550f84c1d60878484e5ffe5b3d8b
-rw-r--r-- | .config | 2 | ||||
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | generated/config.h | 4 | ||||
-rw-r--r-- | generated/flags.h | 4 | ||||
-rw-r--r-- | generated/globals.h | 1 | ||||
-rw-r--r-- | lib/lib.c | 8 | ||||
-rw-r--r-- | lib/lib.h | 2 | ||||
-rw-r--r-- | lib/xwrap.c | 10 | ||||
-rw-r--r-- | toys/pending/tar.c | 164 | ||||
-rw-r--r-- | toys/posix/cp.c | 9 |
10 files changed, 122 insertions, 84 deletions
@@ -121,7 +121,7 @@ CONFIG_FREE=y # CONFIG_FSCK is not set CONFIG_FSFREEZE=y # CONFIG_FSTYPE is not set -# CONFIG_FSYNC is not set +CONFIG_FSYNC=y # CONFIG_FTPGET is not set # CONFIG_FTPPUT is not set CONFIG_GETCONF=y @@ -107,6 +107,7 @@ cc_defaults { "toys/other/free.c", "toys/other/freeramdisk.c", "toys/other/fsfreeze.c", + "toys/other/fsync.c", "toys/other/help.c", "toys/other/hwclock.c", "toys/other/i2ctools.c", @@ -299,6 +300,7 @@ cc_defaults { "flock", "fmt", "free", + "fsync", "getconf", "getenforce", "groups", diff --git a/generated/config.h b/generated/config.h index eccfc954..d018081a 100644 --- a/generated/config.h +++ b/generated/config.h @@ -216,8 +216,8 @@ #define USE_FSFREEZE(...) __VA_ARGS__ #define CFG_FSTYPE 0 #define USE_FSTYPE(...) -#define CFG_FSYNC 0 -#define USE_FSYNC(...) +#define CFG_FSYNC 1 +#define USE_FSYNC(...) __VA_ARGS__ #define CFG_FTPGET 0 #define USE_FTPGET(...) #define CFG_FTPPUT 0 diff --git a/generated/flags.h b/generated/flags.h index 3be9e367..0e74cc9e 100644 --- a/generated/flags.h +++ b/generated/flags.h @@ -934,7 +934,7 @@ #undef FOR_fstype #endif -// fsync <1d +// fsync <1d <1d #undef OPTSTR_fsync #define OPTSTR_fsync "<1d" #ifdef CLEANUP_fsync @@ -4131,7 +4131,7 @@ #ifndef TT #define TT this.fsync #endif -#define FLAG_d (FORCED_FLAG<<0) +#define FLAG_d (1<<0) #endif #ifdef FOR_ftpget diff --git a/generated/globals.h b/generated/globals.h index 79dc6b73..d3d76150 100644 --- a/generated/globals.h +++ b/generated/globals.h @@ -809,6 +809,7 @@ struct tar_data { struct arg_list *exclude; struct double_list *incl, *excl, *seen; + struct string_list *dirs; void *inodes; char *cwd; int fd, ouid, ggid; @@ -1059,16 +1059,16 @@ char *getbasename(char *name) return name; } -// Is this file under this directory? -int fileunderdir(char *file, char *dir) +// Return pointer to xabspath(file) if file is under dir, else 0 +char *fileunderdir(char *file, char *dir) { char *s1 = xabspath(dir, 1), *s2 = xabspath(file, -1), *ss = s2; int rc = s1 && s2 && strstart(&ss, s1) && (!s1[1] || s2[strlen(s1)] == '/'); free(s1); - free(s2); + if (!rc) free(s2); - return rc; + return rc ? s2 : 0; } // Execute a callback for each PID that matches a process name from a list. @@ -371,7 +371,7 @@ mode_t string_to_mode(char *mode_str, mode_t base); void mode_to_string(mode_t mode, char *buf); char *getdirname(char *name); char *getbasename(char *name); -int fileunderdir(char *file, char *dir); +char *fileunderdir(char *file, char *dir); void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)); pid_t __attribute__((returns_twice)) xvforkwrap(pid_t pid); diff --git a/lib/xwrap.c b/lib/xwrap.c index a8214e57..778cb38d 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -521,7 +521,7 @@ void xstat(char *path, struct stat *st) char *xabspath(char *path, int exact) { struct string_list *todo, *done = 0; - int try = 9999, dirfd = open("/", 0), missing = 0; + int try = 9999, dirfd = open("/", O_PATH), missing = 0; char *ret; // If this isn't an absolute path, start with cwd. @@ -554,7 +554,7 @@ char *xabspath(char *path, int exact) if (missing) missing--; else { - if (-1 == (x = openat(dirfd, "..", 0))) goto error; + if (-1 == (x = openat(dirfd, "..", O_PATH))) goto error; close(dirfd); dirfd = x; } @@ -578,7 +578,7 @@ char *xabspath(char *path, int exact) } if (errno != EINVAL && (exact || todo)) goto error; - fd = openat(dirfd, new->str, 0); + fd = openat(dirfd, new->str, O_PATH); if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; close(dirfd); dirfd = fd; @@ -591,7 +591,7 @@ char *xabspath(char *path, int exact) llist_traverse(done, free); done=0; close(dirfd); - dirfd = open("/", 0); + dirfd = open("/", O_PATH); } free(new); @@ -611,7 +611,7 @@ char *xabspath(char *path, int exact) try = 2; while (done) { - struct string_list *temp = llist_pop(&done);; + struct string_list *temp = llist_pop(&done); if (todo) try++; try += strlen(temp->str); diff --git a/toys/pending/tar.c b/toys/pending/tar.c index d0d840ba..8fb047bf 100644 --- a/toys/pending/tar.c +++ b/toys/pending/tar.c @@ -47,6 +47,7 @@ GLOBALS( struct arg_list *exclude; struct double_list *incl, *excl, *seen; + struct string_list *dirs; void *inodes; char *cwd; int fd, ouid, ggid; @@ -335,69 +336,84 @@ static void extract_to_command(void) } } -static void extract_to_disk(void) + +// Do pending directory utimes(), NULL to flush all. +static int dirflush(char *name) { - int flags, dst_fd = -1; - char *s; - struct stat ex; - - flags = strlen(TT.hdr.name); - if (flags>2) - if (strstr(TT.hdr.name, "/../") || !strcmp(TT.hdr.name, "../") || - !strcmp(TT.hdr.name+flags-3, "/..")) - error_msg("drop %s", TT.hdr.name); - - if (TT.hdr.name[flags-1] == '/') TT.hdr.name[flags-1] = 0; - //Regular file with preceding path - if ((s = strrchr(TT.hdr.name, '/')) && mkpath(TT.hdr.name) && errno !=EEXIST) - return error_msg(":%s: not created", TT.hdr.name); - - //remove old file, if exists - if (!FLAG(k) && !S_ISDIR(TT.hdr.mode) && !lstat(TT.hdr.name, &ex)) - if (unlink(TT.hdr.name)) perror_msg("can't remove: %s", TT.hdr.name); - - //hard link - if (S_ISREG(TT.hdr.mode) && TT.hdr.link_target) { - if (link(TT.hdr.link_target, TT.hdr.name)) - perror_msg("can't link '%s' -> '%s'", TT.hdr.name, TT.hdr.link_target); - goto COPY; + char *s = s, *ss; + + // Barf if name not in TT.cwd + if (name) { + ss = s = xabspath(name, -1); + if (TT.cwd && (!strstart(&ss, TT.cwd) || (*ss && *ss!='/'))) { + error_msg("'%s' not under '%s'", ss, TT.cwd); + free(s); + + return 1; + } } - switch (TT.hdr.mode & S_IFMT) { - case S_IFREG: - flags = O_WRONLY|O_CREAT|O_EXCL; - if (FLAG(overwrite)) flags = O_WRONLY|O_CREAT|O_TRUNC; - dst_fd = open(TT.hdr.name, flags, TT.hdr.mode & 07777); - if (dst_fd == -1) perror_msg("%s: can't open", TT.hdr.name); - break; - case S_IFDIR: - if ((mkdir(TT.hdr.name, TT.hdr.mode) == -1) && errno != EEXIST) - perror_msg("%s: can't create", TT.hdr.name); - break; - case S_IFLNK: - if (symlink(TT.hdr.link_target, TT.hdr.name)) - perror_msg("can't link '%s' -> '%s'", TT.hdr.name, TT.hdr.link_target); - break; - case S_IFBLK: - case S_IFCHR: - case S_IFIFO: - if (mknod(TT.hdr.name, TT.hdr.mode, TT.hdr.device)) - perror_msg("can't create '%s'", TT.hdr.name); - break; - default: - printf("type %o not supported\n", TT.hdr.mode); - break; + // Set deferred utimes() for directories this file isn't under. + // (Files must be depth-first ordered in tarball for this to matter.) + while (TT.dirs) { + long long ll = *(long long *)TT.dirs->str; + struct timeval times[2] = {{ll, 0},{ll, 0}}; + + if (name && strstart(&ss, ss = s) && (!*ss || *ss=='/')) break; + if (utimes(TT.dirs->str+sizeof(long long), times)) perror_msg("utimes %lld %s", *(long long *)TT.dirs->str, TT.dirs->str+sizeof(long long)); + free(llist_pop(&TT.dirs)); } - //copy file.... -COPY: - xsendfile_len(TT.fd, dst_fd, TT.hdr.size); - close(dst_fd); + // name was under TT.cwd + return 0; +} + +static void extract_to_disk(void) +{ + char *name = TT.hdr.name; + int ala = TT.hdr.mode; + + if (dirflush(name)) { + if (S_ISREG(ala) && !TT.hdr.link_target) skippy(TT.hdr.size); + + return; + } + + // create path before file if necessary + if (strrchr(name, '/') && mkpath(name) && errno !=EEXIST) + return perror_msg(":%s: can't mkdir", name); + + // remove old file, if exists + if (!FLAG(k) && !S_ISDIR(ala) && unlink(name) && errno!=ENOENT) + return perror_msg("can't remove: %s", name); + + if (S_ISREG(ala)) { + // hardlink? + if (TT.hdr.link_target) { + if (link(TT.hdr.link_target, name)) + return perror_msg("can't link '%s' -> '%s'", name, TT.hdr.link_target); + // write contents + } else { + int fd = xcreate(name, O_WRONLY|O_CREAT|(FLAG(overwrite)?O_TRUNC:O_EXCL), + WARN_ONLY|(ala & 07777)); + if (fd != -1) { + xsendfile_len(TT.fd, fd, TT.hdr.size); + close(fd); + } + } + } else if (S_ISDIR(ala)) { + if ((mkdir(name, 0700) == -1) && errno != EEXIST) + return perror_msg("%s: can't create", TT.hdr.name); + } else if (S_ISLNK(ala)) { + if (symlink(TT.hdr.link_target, TT.hdr.name)) + return perror_msg("can't link '%s' -> '%s'", name, TT.hdr.link_target); + } else if (mknod(name, ala, TT.hdr.device)) + return perror_msg("can't create '%s'", name); + if (!FLAG(o) && !geteuid()) { //set ownership..., --no-same-owner, --numeric-owner - uid_t u = TT.hdr.uid; - gid_t g = TT.hdr.gid; + int u = TT.hdr.uid, g = TT.hdr.gid; if (TT.owner) u = TT.ouid; else if (!FLAG(numeric_owner)) { @@ -411,17 +427,29 @@ COPY: if (gr) g = gr->gr_gid; } - if (lchown(TT.hdr.name, u, g)) - perror_msg("chown %d:%d '%s'", u, g, TT.hdr.name);; + if (lchown(name, u, g)) perror_msg("chown %d:%d '%s'", u, g, name);; } // || !FLAG(no_same_permissions)) - if (FLAG(p) && !S_ISLNK(TT.hdr.mode)) chmod(TT.hdr.name, TT.hdr.mode); + if (FLAG(p) && !S_ISLNK(ala)) chmod(TT.hdr.name, ala); - //apply mtime + // Apply mtime. if (!FLAG(m)) { - struct timeval times[2] = {{TT.hdr.mtime, 0},{TT.hdr.mtime, 0}}; - utimes(TT.hdr.name, times); + if (S_ISDIR(ala)) { + struct string_list *sl; + + // Writing files into a directory changes directory timestamps, so + // defer mtime updates until contents written. + + sl = xmalloc(sizeof(struct string_list)+sizeof(long long)+strlen(name)+1); + *(long long *)sl->str = TT.hdr.mtime; + strcpy(sl->str+sizeof(long long), name); + sl->next = TT.dirs; + TT.dirs = sl; + } else { + struct timeval times[2] = {{TT.hdr.mtime, 0},{TT.hdr.mtime, 0}}; + utimes(TT.hdr.name, times); + } } } @@ -435,13 +463,16 @@ static void unpack_tar(void) for (;;) { // align to next block and read it if (TT.hdr.size%512) skippy(512-TT.hdr.size%512); - if (!(i = readall(TT.fd, &tar, 512))) return; + i = readall(TT.fd, &tar, 512); - if (i != 512) error_exit("read error"); + if (i && i != 512) error_exit("read error"); // Two consecutive empty headers ends tar even if there's more data - if (!*tar.name) { - if (and++) return; + if (!i || !*tar.name) { + if (!i || and++) { + dirflush(0); + return; + } TT.hdr.size = 0; continue; } @@ -604,7 +635,8 @@ void tar_main(void) // Get destination directory if (TT.C) xchdir(TT.C); - TT.cwd = xabspath(s = xgetcwd(), 1); + s = xgetcwd(); + TT.cwd = (strcmp(s, "/")) ? xabspath(s = xgetcwd(), 1) : 0; free(s); // Are we reading? diff --git a/toys/posix/cp.c b/toys/posix/cp.c index 3b30f8a8..751a718c 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -409,12 +409,15 @@ void cp_main(void) char *s = (toys.optflags&FLAG_D) ? getdirname(src) : getbasename(src); TT.destname = xmprintf("%s/%s", destname, s); - if (toys.optflags&FLAG_D) { + if (FLAG(D)) { free(s); - if (!fileunderdir(TT.destname, destname)) { + if (!(s = fileunderdir(TT.destname, destname))) { error_msg("%s not under %s", TT.destname, destname); continue; - } else mkpath(TT.destname); + } + // TODO: .. follows abspath, not links... + free(s); + mkpath(TT.destname); } } else TT.destname = destname; |