Where is a file mounted? Where is a file mounted? linux linux

Where is a file mounted?


This is what I've come up with. It turns out there's usually no need to iterate through the parent directories. All you have to do is get the file's device number and then find the corresponding mount entry with the same device number.

struct mntent *mountpoint(char *filename, struct mntent *mnt, char *buf, size_t buflen){    struct stat s;    FILE *      fp;    dev_t       dev;    if (stat(filename, &s) != 0) {        return NULL;    }    dev = s.st_dev;    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {        return NULL;    }    while (getmntent_r(fp, mnt, buf, buflen)) {        if (stat(mnt->mnt_dir, &s) != 0) {            continue;        }        if (s.st_dev == dev) {            endmntent(fp);            return mnt;        }    }    endmntent(fp);    // Should never reach here.    errno = EINVAL;    return NULL;}

Thanks to @RichardPennington for the heads up on realpath(), and on comparing device numbers instead of inode numbers.


You could start with realpath and work your way up checking each directory with stat to see if it on the same device. It does seem like there should be a simpler way.


Edit:

#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>int main(int argc, char **argv){    char *p;    char path[PATH_MAX];    struct stat buf;    dev_t dev;    if (realpath(argv[1], path) == NULL) {        fprintf(stderr, "can't find %s\n", argv[1]);        exit(1);    }    if (stat(path, &buf) != 0) {        fprintf(stderr, "can't statind %s\n", path);    exit(1);    }    dev = buf.st_dev;    while((p = strrchr(path, '/'))) {        *p = '\0';        stat(path, &buf);        if (buf.st_dev != dev) {            printf("mount point = %s\n", path);            exit(0);        }   }    printf("mount point = /\n");}

Thanksd for the distraction ;-)


This worked for me on OSX, which does not provide the mntent functions. In C++:

struct stat fileStat;int result = stat(path, &fileStat);if (result != 0) {    // handle error}    struct statfs* mounts;int numMounts = getmntinfo(&mounts, MNT_WAIT);if (numMounts == 0) {    // handle error}    for (int i = 0; i < numMounts; i++) {    if (fileStat.st_dev == mounts[i].f_fsid.val[0])        // mounts[i].f_mntonname is the mount path}