about summary refs log tree commit homepage
path: root/mnt_usable.c
diff options
context:
space:
mode:
Diffstat (limited to 'mnt_usable.c')
-rw-r--r--mnt_usable.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/mnt_usable.c b/mnt_usable.c
index 1d590b1..9ba52e4 100644
--- a/mnt_usable.c
+++ b/mnt_usable.c
@@ -16,18 +16,58 @@
 #define MY_STATFS statvfs
 #endif
 
+static bool resolve_symlink(char **orig)
+{
+        char *p = canonicalize_filename_mode(*orig, CAN_EXISTING);
+
+        if (p) {
+                free(*orig);
+                *orig = p;
+                return true;
+        }
+        return false;
+}
+
+static bool stat_harder(struct mount_entry *me)
+{
+        struct stat sb;
+
+        /* the device number may not have been populated, do it */
+        if (me->me_dev == (dev_t)-1) {
+                if (stat(me->me_mountdir, &sb) != 0)
+                        return false;
+                me->me_dev = sb.st_dev;
+        }
+
+        /*
+         * resolve symlinks for things that look like paths
+         * and skip dead symlinks
+         */
+        if (me->me_devname[0] == '/') {
+                if (lstat(me->me_devname, &sb) == 0
+                    && S_ISLNK(sb.st_mode)
+                    && ! resolve_symlink(&me->me_devname))
+                        return false;
+        }
+        return true;
+}
+
 /*
  * prevents us from using filesystems of unknown size, since those could
  * be stalled/dead network mounts
  */
-bool mog_mnt_usable(const char *path)
+bool mog_mnt_usable(struct mount_entry *me)
 {
         struct MY_STATFS buf;
+        const char *path = me->me_mountdir;
+
+        if (me->me_dummy)
+                return false;
 
 retry:
         errno = 0;
         if (MY_STATFS(path, &buf) == 0)
-                return (buf.f_blocks > 0);
+                return (buf.f_blocks > 0) ? stat_harder(me) : false;
 
         /* unknown */
         assert(errno != EFAULT && "BUG: EFAULT from statfs/statvfs");