]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - sys-utils/fstrim.c
docs: update year in libs docs
[thirdparty/util-linux.git] / sys-utils / fstrim.c
index e0e9e57a984512de0710f8fa7b174eaf856658ba..e6d7af3ea9fcf59d34439460e470bbf9698a3c06 100644 (file)
@@ -65,11 +65,27 @@ struct fstrim_control {
                     dryrun : 1;
 };
 
+static int is_directory(const char *path, int silent)
+{
+       struct stat sb;
+
+       if (stat(path, &sb) == -1) {
+               if (!silent)
+                       warn(_("stat of %s failed"), path);
+               return 0;
+       }
+       if (!S_ISDIR(sb.st_mode)) {
+               if (!silent)
+                       warnx(_("%s: not a directory"), path);
+               return 0;
+       }
+       return 1;
+}
+
 /* returns: 0 = success, 1 = unsupported, < 0 = error */
 static int fstrim_filesystem(struct fstrim_control *ctl, const char *path, const char *devname)
 {
        int fd = -1, rc;
-       struct stat sb;
        struct fstrim_range range;
        char *rpath = realpath(path, NULL);
 
@@ -87,16 +103,6 @@ static int fstrim_filesystem(struct fstrim_control *ctl, const char *path, const
                rc = -errno;
                goto done;
        }
-       if (fstat(fd, &sb) == -1) {
-               warn(_("stat of %s failed"), path);
-               rc = -errno;
-               goto done;
-       }
-       if (!S_ISDIR(sb.st_mode)) {
-               warnx(_("%s: not a directory"), path);
-               rc = -EINVAL;
-               goto done;
-       }
 
        if (ctl->dryrun) {
                if (devname)
@@ -278,6 +284,7 @@ static int fstrim_all(struct fstrim_control *ctl)
        if (!itr)
                err(MNT_EX_FAIL, _("failed to initialize libmount iterator"));
 
+       /* Remove useless entries and canonicalize the table */
        while (mnt_table_next_fs(tab, itr, &fs) == 0) {
                const char *src = mnt_fs_get_srcpath(fs),
                           *tgt = mnt_fs_get_target(fs);
@@ -304,15 +311,13 @@ static int fstrim_all(struct fstrim_control *ctl)
                        continue;
                }
        }
-       mnt_free_iter(itr);
 
        /* de-duplicate by source */
        mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp);
 
-       itr = mnt_new_iter(MNT_ITER_BACKWARD);
-       if (!itr)
-               err(MNT_EX_FAIL, _("failed to initialize libmount iterator"));
+       mnt_reset_iter(itr, MNT_ITER_BACKWARD);
 
+       /* Do FITRIM */
        while (mnt_table_next_fs(tab, itr, &fs) == 0) {
                const char *src = mnt_fs_get_srcpath(fs),
                           *tgt = mnt_fs_get_target(fs);
@@ -328,15 +333,16 @@ static int fstrim_all(struct fstrim_control *ctl)
                if (rc)
                        continue;       /* overlaying mount */
 
-               /* FSTRIM on read-only filesystem can fail, and it can fail */
-               if (access(path, W_OK) != 0) {
+               /* FITRIM on read-only filesystem can fail, and it can fail */
+               if (access(tgt, W_OK) != 0) {
                        if (errno == EROFS)
                                continue;
                        if (errno == EACCES)
                                continue;
                }
 
-               if (!has_discard(src, &wholedisk))
+               if (!is_directory(tgt, 1) ||
+                   !has_discard(src, &wholedisk))
                        continue;
                cnt++;
 
@@ -385,7 +391,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -l, --length <num>  the number of bytes to discard\n"), out);
        fputs(_(" -m, --minimum <num> the minimum extent length to discard\n"), out);
        fputs(_(" -v, --verbose       print number of discarded bytes\n"), out);
-       fputs(_("     --quiet         suppress error messages\n"), out);
+       fputs(_("     --quiet         suppress trim error messages\n"), out);
        fputs(_(" -n, --dry-run       does everything, but trim\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
@@ -476,6 +482,9 @@ int main(int argc, char **argv)
        if (all)
                return fstrim_all(&ctl);        /* MNT_EX_* codes */
 
+       if (!is_directory(path, 0))
+               return EXIT_FAILURE;
+
        rc = fstrim_filesystem(&ctl, path, NULL);
        if (rc == 1 && !ctl.quiet)
                warnx(_("%s: the discard operation is not supported"), path);