diff options
Diffstat (limited to 'mnt_usable.c')
-rw-r--r-- | mnt_usable.c | 44 |
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"); |