From aec194e573e6f94a7bf3c3d64b2a86c1f2057638 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 25 Jun 2019 08:40:18 -0700 Subject: losetup: minor fixes. Fix `losetup -f` to not fail with an error. Add the missing \n for `losetup -f --show FILE`. Use decimal for the device number, like the desktop losetup. Switch to the FLAG macro. Make the tests runnable as tests, and expand coverage a bit. With this patch, the tests pass both with and without TEST_HOST on the desktop. Note though that this patch is part of fixing some real-life losetup issues, not part of the "test cleanup" I'm also looking at. losetup is low down that list! --- tests/losetup.test | 18 +++++++++++------- toys/other/losetup.c | 41 ++++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/tests/losetup.test b/tests/losetup.test index f30a0fe2..c04a72b9 100755 --- a/tests/losetup.test +++ b/tests/losetup.test @@ -13,13 +13,17 @@ fi truncate -s 1M blah.img && FILE="$(readlink -f blah.img)" -DEV="$(printf '%04s' $(stat -t blah.img | awk '{print $7}'))" -NODE="$(stat -t blah.img | awk '{print $8}')" +DEV="$(stat --format %d blah.img)" +NODE="$(stat --format %i blah.img)" -losetup -f -losetup -f -s -losetup -f file - -losetup -d +# TODO: assumes there are no loopback devices! +testcmd "-f" "-f" "/dev/loop0\n" "" "" +testcmd "-f blah.img" "-f blah.img" "" "" "" +testcmd "-f --show" "-f --show blah.img" "/dev/loop1\n" "" "" +testcmd "-a" "-a | sort" \ + "/dev/loop0: [$DEV]:$NODE ($FILE)\n/dev/loop1: [$DEV]:$NODE ($FILE)\n" "" "" +testcmd "-d /dev/loop0" "-d /dev/loop0 && losetup -a" \ + "/dev/loop1: [$DEV]:$NODE ($FILE)\n" "" "" +testcmd "-D" "-D && losetup -a" "" "" "" rm blah.img diff --git a/toys/other/losetup.c b/toys/other/losetup.c index d77a9500..02856c27 100644 --- a/toys/other/losetup.c +++ b/toys/other/losetup.c @@ -4,7 +4,7 @@ * * No standard. (Sigh.) -USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdca[!afj]", TOYFLAG_SBIN)) +USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdcaD[!afj]", TOYFLAG_SBIN)) config LOSETUP bool "losetup" @@ -18,17 +18,18 @@ config LOSETUP Instead of a device: -a Iterate through all loopback devices -f Find first unused loop device (may create one) - -j Iterate through all loopback devices associated with FILE + -j FILE Iterate through all loopback devices associated with FILE existing: -c Check capacity (file size changed) - -d Detach loopback device + -d DEV Detach loopback device + -D Detach all loopback devices new: -s Show device name (alias --show) - -o Start association at OFFSET into FILE + -o OFF Start association at offset OFF into FILE -r Read only - -S Limit SIZE of loopback association (alias --sizelimit) + -S SIZE Limit SIZE of loopback association (alias --sizelimit) */ #define FOR_losetup @@ -51,7 +52,6 @@ static void loopback_setup(char *device, char *file) { struct loop_info64 *loop = (void *)(toybuf+32); int lfd = -1, ffd = ffd; - unsigned flags = toys.optflags; // Open file (ffd) and loop device (lfd) @@ -78,7 +78,12 @@ static void loopback_setup(char *device, char *file) // Stat the loop device to see if there's a current association. memset(loop, 0, sizeof(struct loop_info64)); if (-1 == lfd || ioctl(lfd, LOOP_GET_STATUS64, loop)) { - if (errno == ENXIO && (flags & (FLAG_a|FLAG_j))) goto done; + if (errno == ENXIO && (FLAG(a) || FLAG(j))) goto done; + // ENXIO expected if we're just trying to print the first unused device. + if (errno == ENXIO && FLAG(f) && !file) { + puts(device); + goto done; + } if (errno != ENXIO || !file) { perror_msg_raw(device ? device : "-f"); goto done; @@ -90,9 +95,9 @@ static void loopback_setup(char *device, char *file) goto done; // Check size of file or delete existing association - if (flags & (FLAG_c|FLAG_d)) { + if (FLAG(c) || FLAG(d)) { // The constant is LOOP_SET_CAPACITY - if (ioctl(lfd, (flags & FLAG_c) ? 0x4C07 : LOOP_CLR_FD, 0)) { + if (ioctl(lfd, FLAG(c) ? 0x4C07 : LOOP_CLR_FD, 0)) { perror_msg_raw(device); goto done; } @@ -107,11 +112,11 @@ static void loopback_setup(char *device, char *file) xstrncpy((char *)loop->lo_file_name, s, LO_NAME_SIZE); s[LO_NAME_SIZE-1] = 0; if (ioctl(lfd, LOOP_SET_STATUS64, loop)) perror_exit("%s=%s", device, file); - if (flags & FLAG_s) printf("%s", device); + if (FLAG(s)) puts(device); free(s); - } else if (flags & FLAG_f) printf("%s", device); + } else { - xprintf("%s: [%04llx]:%llu (%s)", device, (long long)loop->lo_device, + xprintf("%s: [%lld]:%llu (%s)", device, (long long)loop->lo_device, (long long)loop->lo_inode, loop->lo_file_name); if (loop->lo_offset) xprintf(", offset %llu", (unsigned long long)loop->lo_offset); @@ -145,7 +150,7 @@ void losetup_main(void) { char **s; - TT.openflags = (toys.optflags & FLAG_r) ? O_RDONLY : O_RDWR; + TT.openflags = FLAG(r) ? O_RDONLY : O_RDWR; if (TT.j) { struct stat st; @@ -164,17 +169,19 @@ void losetup_main(void) // -f(dc FILE) - if (toys.optflags & FLAG_f) { + if (FLAG(D)) toys.optflags |= FLAG_a | FLAG_d; + + if (FLAG(f)) { if (toys.optc > 1) perror_exit("max 1 arg"); loopback_setup(NULL, *toys.optargs); - } else if (toys.optflags & (FLAG_a|FLAG_j)) { + } else if (FLAG(a) || FLAG(j)) { if (toys.optc) error_exit("bad args"); dirtree_read("/dev", dash_a); // Do we need one DEVICE argument? } else { - char *file = (toys.optflags & (FLAG_d|FLAG_c)) ? NULL : toys.optargs[1]; + char *file = (FLAG(c) || FLAG(d)) ? NULL : toys.optargs[1]; - if (!toys.optc || (file && toys.optc != 2)) + if (!toys.optc || (file && toys.optc != 2)) help_exit("needs %d arg%s", 1+!!file, file ? "s" : ""); for (s = toys.optargs; *s; s++) { loopback_setup(*s, file); -- cgit v1.2.3