Take the 2-minute tour ×

Given a path to a file or directory, how can I determine the mount point for that file? For example, if /tmp is mounted as a tmpfs filesystem then given the file name /tmp/foo/bar I want to know that it's stored on a tmpfs rooted at /tmp.

This will be in C++ and I'd like to avoid invoking external commands via system(). The code should be robust--not necessarily against deliberate tampering but definitely in the face of nested mountpoints, symlinks, etc.

I haven't been able to find a simple system call to do this. It looks like I'll have to write the check myself. Here's a rough outline of what I'm planning.

  1. Canonicalize the file name a la the readlink shell command. How?
  2. Read /etc/mtab with getmntent() & co.
  3. Determine the corresponding mount entry for the file. How?

For #1 is there a simple system call or do I need to read each directory component of the path and resolve them with readlink(2) if they are symlinks? And handle . and .. myself? Seems like a pain.

For #3 I've got various ideas on how to do this. Not sure which is best.

  1. open() the file, its parent, its parent's parent, etc. using openat(fd, "..") until I reach one of the /etc/mtab entries. (How do I know when I do? fstat() them and compare the inode numbers?)
  2. Find the longest directory name in the mount table which is a substring of my file name.

I'm leaning towards the first option but before I code it all up I want to make sure I'm not overlooking anything--ideally a built-in function that does this already!

share|improve this question
Why vote to close this? It is a good question. –  Richard Pennington Feb 25 '10 at 20:06
Whoever voted to close it probably just read the title and/or the first two lines. This is clearly an appropriate (and interesting) question. –  Tyler McHenry Feb 25 '10 at 20:15
See also Python version and a shell command. –  Mechanical snail Aug 21 '13 at 7:21

4 Answers 4

up vote 15 down vote accepted

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) {

        if (s.st_dev == dev) {
            return mnt;


    // 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.

share|improve this answer
Nice. Much better than mine since you get all the information you need. –  Richard Pennington Feb 25 '10 at 21:54
You might want to use /proc/mounts instead of /etc/mtab - /etc/mtab is maintained by the mount command and could be fudged with, whereas /proc/mounts is a representation of the mount table itself. BSD users should use getmntinfo() –  Daniel Papasian Feb 25 '10 at 22:03
That should even work on device special files, without the need for the special-case at the end (stat.st_dev is always the ID of the device containing the file, even for device special files). –  caf Feb 26 '10 at 0:40
Since devices can be mounted more than once, isn't there some additional checking needed to check that you have the right mount of the device? –  ergosys Mar 10 '12 at 6:57

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.


#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) {

    if (stat(path, &buf) != 0) {
        fprintf(stderr, "can't statind %s\n", path);

    dev = buf.st_dev;
    while((p = strrchr(path, '/'))) {
        *p = '\0';
        stat(path, &buf);
        if (buf.st_dev != dev) {
            printf("mount point = %s\n", path);
    printf("mount point = /\n");

Thanksd for the distraction ;-)

share|improve this answer

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
share|improve this answer
Is your OSX(C++) any kind of linux or not? getmntinfo sounds like FreeBSD/OSX(C++) library call, but not linux or POSIX. –  osgx May 29 at 23:41
What is your point? –  Peter Tseng May 30 at 0:51
The question was about linux. –  osgx May 30 at 1:18
Thanks for the answer, Peter. –  John Kugelman May 30 at 12:39
Yes, I did indicate that it's OSX, which is often easily ported to/from Linux. –  Peter Tseng May 31 at 1:33

You should be able to read in /etc/mtab, parse out all the locations where something is already mounted, and see if any of your files in question are located in any of those locations (or their sub-directories). You shouldn't need any special system functions for this, if you have the mount points and file paths as strings then you can process them using normal string processing functions.

Obviously, symlinks can throw a wrench into this whole process. Any file path that includes a symlink will have to be converted into its "actual" path before processing it. Hopefully there's a way to do this without individually checking a file and each of its parents, but you can always brute-force it if you must. You'll probably want to use realpath to remove symlinks.

share|improve this answer

Your Answer


