From f51b02947baeb149d12a60befc9988634485af13 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 29 Jun 2022 21:54:42 -0500 Subject: [PATCH] Add same_file() and same_def_ino() convenience functions, plus minor cleanups. --- lib/lib.c | 15 +++++++++++++-- lib/lib.h | 7 +++++++ toys/other/mountpoint.c | 26 +++++++++++--------------- toys/pending/lsof.c | 19 ++++++++----------- toys/pending/mke2fs.c | 4 +--- toys/posix/cp.c | 6 ++---- toys/posix/du.c | 14 +++++--------- toys/posix/find.c | 12 ++++-------- toys/posix/pwd.c | 3 +-- toys/posix/tail.c | 13 ++++++------- toys/posix/tar.c | 21 +++++++++------------ 11 files changed, 67 insertions(+), 73 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index c36a7381..c2c65a71 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -519,6 +519,18 @@ int strcasestart(char **a, char *b) return i; } +int same_file(struct stat *st1, struct stat *st2) +{ + return st1->st_ino==st2->st_ino && st1->st_dev==st2->st_dev; +} + +int same_dev_ino(struct stat *st, struct dev_ino *di) +{ + return st->st_ino==di->ino && st->st_dev==di->dev; +} + + + // Return how long the file at fd is, if there's any way to determine it. off_t fdlength(int fd) { @@ -1134,8 +1146,7 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name), char buf[32]; sprintf(buf, "/proc/%u/exe", u); - if (stat(buf, &st2)) continue; - if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) continue; + if (stat(buf, &st2) && !same_file(&st1, &st2)) continue; goto match; } diff --git a/lib/lib.h b/lib/lib.h index 178000ea..5c68ac9b 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -30,6 +30,11 @@ struct num_cache { char data[]; }; +struct dev_ino { + dev_t dev; + ino_t ino; +}; + void llist_free_arg(void *node); void llist_free_double(void *node); void llist_traverse(void *list, void (*using)(void *node)); @@ -235,6 +240,8 @@ int unescape2(char **c, int echo); char *strend(char *str, char *suffix); int strstart(char **a, char *b); int strcasestart(char **a, char *b); +int same_file(struct stat *st1, struct stat *st2); +int same_dev_ino(struct stat *st, struct dev_ino *di); off_t fdlength(int fd); void loopfiles_rw(char **argv, int flags, int permissions, void (*function)(int fd, char *name)); diff --git a/toys/other/mountpoint.c b/toys/other/mountpoint.c index a97c600a..fb538c42 100644 --- a/toys/other/mountpoint.c +++ b/toys/other/mountpoint.c @@ -23,7 +23,7 @@ config MOUNTPOINT static void die(char *gripe) { - if (!(toys.optflags & FLAG_q)) printf("%s: not a %s\n", *toys.optargs, gripe); + if (!FLAG(q)) printf("%s: not a %s\n", *toys.optargs, gripe); toys.exitval++; xexit(); @@ -33,34 +33,30 @@ void mountpoint_main(void) { struct stat st1, st2; char *arg = *toys.optargs; - int quiet = toys.optflags & FLAG_q; if (lstat(arg, &st1)) perror_exit_raw(arg); - if (toys.optflags & FLAG_x) { - if (S_ISBLK(st1.st_mode)) { - if (!quiet) - printf("%u:%u\n", dev_major(st1.st_rdev), dev_minor(st1.st_rdev)); + if (FLAG(x)) { + if (!S_ISBLK(st1.st_mode)) die("block device"); + if (!FLAG(q)) + printf("%u:%u\n", dev_major(st1.st_rdev), dev_minor(st1.st_rdev)); - return; - } - die("block device"); + return; } - // TODO: Ignore the fact a file can be a mountpoint for --bind mounts. + // TODO: a file can be a mountpoint for --bind mounts. if (!S_ISDIR(st1.st_mode)) die("directory"); arg = xmprintf("%s/..", arg); xstat(arg, &st2); - if (CFG_TOYBOX_FREE) free(arg); + free(arg); // If the device is different, it's a mount point. If the device _and_ // inode are the same, it's probably "/". This misses --bind mounts from // elsewhere in the same filesystem, but so does the other one and in the // absence of a spec I guess that's the expected behavior? - toys.exitval = !(st1.st_dev != st2.st_dev || st1.st_ino == st2.st_ino); - if (toys.optflags & FLAG_d) - printf("%u:%u\n", dev_major(st1.st_dev), dev_minor(st1.st_dev)); - else if (!quiet) + toys.exitval = !same_file(&st1, &st2); + if (FLAG(d)) printf("%u:%u\n", dev_major(st1.st_dev), dev_minor(st1.st_dev)); + else if (!FLAG(q)) printf("%s is %sa mountpoint\n", *toys.optargs, toys.exitval ? "not " : ""); } diff --git a/toys/pending/lsof.c b/toys/pending/lsof.c index e4b53112..079963b3 100644 --- a/toys/pending/lsof.c +++ b/toys/pending/lsof.c @@ -42,8 +42,7 @@ struct file_info { char *name, fd[8], rw, locks, type[10], device[32], size_off[32], node[32]; // For filtering. - dev_t st_dev; - ino_t st_ino; + struct dev_ino di; }; static void print_info(void *data) @@ -55,13 +54,11 @@ static void print_info(void *data) int i; for (i = 0; ist_dev) - if (TT.sought_files[i].st_ino==fi->st_ino) break; - + if (same_file(TT.sought_files+i, &fi->di)) break; if (i==toys.optc) return; } - if (toys.optflags&FLAG_t) { + if (FLAG(t)) { if (fi->pi.pid != TT.last_shown_pid) printf("%d\n", TT.last_shown_pid = fi->pi.pid); } else { @@ -130,7 +127,7 @@ static struct file_info *add_socket(ino_t inode, const char *type) struct file_info *fi = xzalloc(sizeof(struct file_info)); dlist_add_nomalloc(&TT.all_sockets, (struct double_list *)fi); - fi->st_ino = inode; + fi->di.ino = inode; strcpy(fi->type, type); return fi; } @@ -231,9 +228,9 @@ static int find_socket(struct file_info *fi, long inode) void* list = TT.all_sockets; while (list) { - struct file_info *s = (struct file_info*) llist_pop(&list); + struct file_info *s = (struct file_info *)llist_pop(&list); - if (s->st_ino == inode) { + if (s->di.ino == inode) { fi->name = s->name ? strdup(s->name) : NULL; strcpy(fi->type, s->type); return 1; @@ -282,8 +279,8 @@ static void fill_stat(struct file_info *fi, const char *path) snprintf(fi->node, sizeof(fi->node), "%ld", (long)sb.st_ino); // Stash st_dev and st_ino for filtering. - fi->st_dev = sb.st_dev; - fi->st_ino = sb.st_ino; + fi->di.dev = sb.st_dev; + fi->di.ino = sb.st_ino; } struct file_info *new_file_info(struct proc_info *pi, const char *fd) diff --git a/toys/pending/mke2fs.c b/toys/pending/mke2fs.c index ee0a5b11..0741157f 100644 --- a/toys/pending/mke2fs.c +++ b/toys/pending/mke2fs.c @@ -342,9 +342,7 @@ static void check_treelinks(struct dirtree *tree) // Look for other copies of current node current->st.st_nlink = 0; for (that = tree; that; that = treenext(that)) { - if (current->st.st_ino == that->st.st_ino && - current->st.st_dev == that->st.st_dev) - { + if (same_file(current, that)) { current->st.st_nlink++; current->st.st_ino = inode; } diff --git a/toys/posix/cp.c b/toys/posix/cp.c index 7b9889a2..a7359821 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -148,10 +148,8 @@ static int cp_node(struct dirtree *try) // Detect recursive copies via repeated top node (cp -R .. .) or // identical source/target (fun with hardlinks). - if ((TT.top.st_dev == try->st.st_dev && TT.top.st_ino == try->st.st_ino - && (catch = TT.destname)) - || (!fstatat(cfd, catch, &cst, 0) && cst.st_dev == try->st.st_dev - && cst.st_ino == try->st.st_ino)) + if ((same_file(&TT.top, &try->st) && (catch = TT.destname)) + || (!fstatat(cfd, catch, &cst, 0) && same_file(&cst, &try->st))) { error_msg("'%s' is '%s'", catch, err = dirtree_path(try, 0)); free(err); diff --git a/toys/posix/du.c b/toys/posix/du.c index 86118676..05dea096 100644 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -89,17 +89,15 @@ static int seen_inode(void **list, struct stat *st) else if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { struct inode_list { struct inode_list *next; - ino_t ino; - dev_t dev; + struct dev_ino di; } *new; for (new = *list; new; new = new->next) - if(new->ino == st->st_ino && new->dev == st->st_dev) - return 1; + if(same_dev_ino(st, &new->di)) return 1; new = xzalloc(sizeof(*new)); - new->ino = st->st_ino; - new->dev = st->st_dev; + new->di.ino = st->st_ino; + new->di.dev = st->st_dev; new->next = *list; *list = new; } @@ -123,9 +121,7 @@ static int do_du(struct dirtree *node) if (FLAG(L)) { struct dirtree *try = node; - while ((try = try->parent)) - if (node->st.st_dev==try->st.st_dev && node->st.st_ino==try->st.st_ino) - return 0; + while ((try = try->parent)) if (same_file(&node->st, &try->st)) return 0; } // Don't count hard links twice diff --git a/toys/posix/find.c b/toys/posix/find.c index bca7c67b..89d4d5a6 100644 --- a/toys/posix/find.c +++ b/toys/posix/find.c @@ -238,7 +238,7 @@ static int do_find(struct dirtree *new) struct dirtree *n; for (n = new->parent; n; n = n->parent) { - if (n->st.st_ino==new->st.st_ino && n->st.st_dev==new->st.st_dev) { + if (same_file(&n->st, &new->st)) { error_msg("'%s': loop detected", s = dirtree_path(new, 0)); free(s); @@ -467,10 +467,7 @@ static int do_find(struct dirtree *new) uid_t uid; gid_t gid; struct timespec tm; - struct { - dev_t d; - ino_t i; - }; + struct dev_ino di; }; } *udl; struct stat st; @@ -485,7 +482,7 @@ static int do_find(struct dirtree *new) goto error; if (*s=='s' || !s[5] || s[6]!='t') { xstat(arg, &st); - if (*s=='s') udl->d = st.st_dev, udl->i = st.st_ino; + if (*s=='s') udl->di.dev = st.st_dev, udl->di.ino = st.st_ino; else udl->tm = *(struct timespec *)(((char *)&st) + macoff[!s[5] ? 0 : stridx("ac", s[6])+1]); } else if (s[6] == 't') { @@ -502,8 +499,7 @@ static int do_find(struct dirtree *new) if (check) { if (*s == 'u') test = new->st.st_uid == udl->uid; else if (*s == 'g') test = new->st.st_gid == udl->gid; - else if (*s == 's') - test = new->st.st_dev == udl->d && new->st.st_ino == udl->i; + else if (*s == 's') test = same_dev_ino(&new->st, &udl->di); else { struct timespec *tm = (void *)(((char *)&new->st) + macoff[!s[5] ? 0 : stridx("ac", s[5])+1]); diff --git a/toys/posix/pwd.c b/toys/posix/pwd.c index c7dc78f7..c6f45ad0 100644 --- a/toys/posix/pwd.c +++ b/toys/posix/pwd.c @@ -41,8 +41,7 @@ void pwd_main(void) // If current directory exists, make sure it matches. if (s && pwd) - if (stat(pwd, &st1) || stat(PWD, &st2) || st1.st_ino != st2.st_ino || - st1.st_dev != st2.st_dev) s = 0; + if (stat(pwd, &st1) || stat(PWD, &st2) || !same_file(&st1, &st2)) s = 0; } else s = 0; // If -L didn't give us a valid path, use cwd. diff --git a/toys/posix/tail.c b/toys/posix/tail.c index f34e10cc..8a7d6d84 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -36,8 +36,7 @@ GLOBALS( struct { char *path; int fd; - dev_t dev; - ino_t ino; + struct dev_ino di; } *F; ) @@ -159,12 +158,12 @@ static void tail_continue() continue; } - if (fd<0 || sb.st_dev!=TT.F[i].dev || sb.st_ino!=TT.F[i].ino) { + if (fd<0 || !same_dev_ino(&sb, &TT.F[i].di)) { if (fd>=0) close(fd); if (-1 == (TT.F[i].fd = fd = open(path, O_RDONLY))) continue; error_msg("following new file: %s\n", path); - TT.F[i].dev = sb.st_dev; - TT.F[i].ino = sb.st_ino; + TT.F[i].di.dev = sb.st_dev; + TT.F[i].di.ino = sb.st_ino; } else if (sb.st_size <= (pos = lseek(fd, 0, SEEK_CUR))) { if (pos == sb.st_size) continue; error_msg("file truncated: %s\n", path); @@ -201,8 +200,8 @@ static void do_tail(int fd, char *name) if (FLAG(F)) { if (fd != -1) { if (fstat(fd, &sb)) perror_exit("%s", name); - TT.F[TT.file_no].dev = sb.st_dev; - TT.F[TT.file_no].ino = sb.st_ino; + TT.F[TT.file_no].di.dev = sb.st_dev; + TT.F[TT.file_no].di.ino = sb.st_ino; } TT.F[TT.file_no].fd = fd; TT.F[TT.file_no].path = s; diff --git a/toys/posix/tar.c b/toys/posix/tar.c index 040716ba..57e1e140 100644 --- a/toys/posix/tar.c +++ b/toys/posix/tar.c @@ -58,15 +58,15 @@ GLOBALS( struct double_list *incl, *excl, *seen; struct string_list *dirs; char *cwd, **xfsed; - int fd, ouid, ggid, hlc, warn, adev, aino, sparselen, pid; + int fd, ouid, ggid, hlc, warn, sparselen, pid; + struct dev_ino archive_di; long long *sparse; time_t mtt; // hardlinks seen so far (hlc many) struct { char *arg; - ino_t ino; - dev_t dev; + struct dev_ino di; } *hlx; // Parsed information about a tar header. @@ -200,7 +200,7 @@ static int add_to_tar(struct dirtree *node) char *name, *lnk, *hname, *xfname = 0; if (!dirtree_notdotdot(node)) return 0; - if (TT.adev == st->st_dev && TT.aino == st->st_ino) { + if (same_dev_ino(st, &TT.archive_di)) { error_msg("'%s' file is the archive; not dumped", node->name); return 0; } @@ -262,10 +262,7 @@ static int add_to_tar(struct dirtree *node) // Are there hardlinks to a non-directory entry? if (st->st_nlink>1 && !S_ISDIR(st->st_mode)) { // Have we seen this dev&ino before? - for (i = 0; ist_ino == TT.hlx[i].ino && st->st_dev == TT.hlx[i].dev) - break; - } + for (i = 0; ist_ino; - TT.hlx[TT.hlc].dev = st->st_dev; + TT.hlx[TT.hlc].di.ino = st->st_ino; + TT.hlx[TT.hlc].di.dev = st->st_dev; TT.hlc++; i = 0; } @@ -948,8 +945,8 @@ void tar_main(void) struct stat st; if (!fstat(TT.fd, &st)) { - TT.aino = st.st_ino; - TT.adev = st.st_dev; + TT.archive_di.ino = st.st_ino; + TT.archive_di.dev = st.st_dev; } } -- 2.39.2