Mount folder

Why mounting folders

While it is common to mount a drive or partition (eventually done behind the scenes by your graphical environment, for example when attaching a USB stick), it is also possible to mount single folders.

Mounting a single folder in another location means having two views of the same files under two different paths. Modifications on one side are immediately reflected on the other side.

A similar effect can be achieved with symlinks, with some differences, which most of the time are not that relevant.

When talking about files, it is possible to also use a hardlink. A hardlink cannot be distinguished from a real file, all filenames are equally valid, and as long at least one exists, the content will not be removed.

In the case of folders, it is generally not possible to use them.

The first difference is that symlinks are stored on the disk as files.

Thus they need to be deleted if you do not want to persist them, you cannot "temporarily" link two directories.

They also need to be supported by the file system; for example, FAT32 does not support symlinks.

Windows supports many different and incompatible types of symlinks, and most applications will have issues if not use the "correct" type. Some of the link types used on Windows are (many have been listed here)

  • .lnk files. Those are regular files, but handled as symlinks by explorer.exe

  • reparse points 🗄️

  • symlink 🗄️ are supported Since Windows Vista, but only for administrators. On Windows 10 it is sufficient to have developer mode enabled. Contrary to symlinks on other platforms, symlinks to folders and files are of different types.

  • NFS symlinks 🗄️

  • cygwin symlinks. Those are (if configured appropriately) regular files, but handled as links by the Cygwin environment

  • hard link and junctions 🗄️ (junctions are implemented as reparse points)

Cygwin, depending on the environment will create one type of symbolic link, or another 🗄️.

Another difference is that it is possible to query for symlinks.

mkdir bar;
ln -s bar foo;
ls -ld foo;

Other tools that solve symlinks are readlink -f and pwd -P.

With mounts, it is generally not as easy to determine if two files on different paths are the same on disk.

Linux bind mount

ON GNU/Linux systems it is possible to mount a directory from somewhere to somewhere else:

mount -o bind "$source" "$destination";
# equivalent
mount --bind "$source" "$destination";

Note that mount --bind also supports mounting a non-directory onto a non-directory: "$source" can be a regular file, but in this case "$destination" needs to be a regular file too.

Also, a normal user might not be able to execute the mount command, in many distributions administrator rights are required to avoid escalation attacks.

A bind mount makes it more difficult to distinguish if two files with the same content and name are the same

mkdir bar foo;
mount --bind bar foo;
# create some files inside bar
touch bar/a;

readlink -f won’t show any relation between files inside foo and bar. With df -Th it is possible to see where foo and bar are mounted, but not if there is a relation between those folders.

For most programs this won’t be an issue, as long as they can access the files.

It is an issue when writing a program like fdupes or similar programs for finding and removing duplicate files.

If a program removes bar/a because it is a duplicate of foo/a, it has removed the only copy on the drive!

Some information on how and where a folder is mounted can be found in /proc/mounts

read-only view

One of the biggest advantages of mounting folders is being able to mount them with different flags, for example as read-only.

mkdir bar foo;
mount --bind -o ro bar foo;
touch bar/a; # succeeds
touch foo/b; # fails

This makes it possible to point a program to a read-only view of the content in order to be sure that files will not even be modified by accident, and let other programs, who are supposed to modify the content, access the original files.

It also makes it possible to mound the directory with a different set of permissions, a different user or a different group.

Access content of the original directory

Generally, when mounting directory bar on directory foo, the content of directory foo will not be accessible until bar is unmounted.

Trying a second mount will not help

cd tmp; mkdir bar foo; touch bar/a foo/b;
ls foo;
mount --bind bar foo;
ls foo; # b is not there anymore
mkdir baz;
mount --bind foo baz;
ls baz; # b is still not there

Making a bind to the parent folder(!) makes the content of foo available again:

cd tmp; mkdir bar foo; touch bar/a foo/b;
ls foo;
mount --bind bar foo;
ls foo; # b is not there anymore
mkdir baz;
mount --bind . baz;
ls baz/foo; # b is there (!)

persists across reboots

The easiest solution is to add the bind mount to /etc/fstab

/etc/fstab
# <file system>                           <mount point>  <type>  <options>       <dump>  <pass>

# ...

/source                                   /destination   none    noatime,bind    0       0

Note that if your system is using systemd, the mount entries are applied in parallel.

Thus it can happen that /source will not be mounted to /destination correctly, becase /source is not avaiable at that point.

In this case, use the additional parameter x-systemd.requires=/dependant-mount-point, to let systemd know that two mount point have a dependency.

For example

/etc/fstab
# <file system>                           <mount point>  <type>  <options>                            <dump>  <pass>
UUID=ac6b5298-8125-46c6-9611-38910b3e3612 /              ext4    noatime,discard,commit=600           0       1

# other mount points

/home/fekir/games                         /mnt/games     none    x-systemd.requires=/,noatime,bind    0       0

Windows

Windows does not have something similar to mount --bind, but it does have some tools that look similar.

In Windows mounting something and creating symlinks are less frequent operations, so there is less material to look at, and the documentation is not always helpful.

Mount a folder in a drive letter

subst

subst does something similar to mounting folders, but it is restricted to mounting folders as new drives, not onto existing folders.

Associates a path with a drive letter.

SUBST [drive1: [drive2:]path] SUBST drive1: /D

drive1:        Specifies a virtual drive to which you want to assign a path.
[drive2:]path  Specifies a physical drive and path you want to assign to
               a virtual drive.
/D             Deletes a substituted (virtual) drive.

Type SUBST with no parameters to display a list of current virtual drives.

— help message of subst

For example subst G: 'C:\test\' will create a virtual drive G: that points to C:/test.

Such a tool has still its use cases.

One would be, for example, working with programs that cannot handle correctly long paths.

Mounting some deep subfolders directly under a different drive would make the resulting path shorter; hopefully short enough.

While it is true that 8.3 filenames are still supported and are enabled by default, they are only available if the file already exists.

Thus if a program needs to create a new file, with a too-long path, it might fail.

Also note that subst does not need administrator privileges, and the created drive will be available only to the current user.

DOS Devices

Virtual devices created with subst do not persist across a reboot. It is possible to execute subst automatically at startup, but there is another possibility: a registry entry.

dosdevices.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]
"F:"="\\??\\C:\\test1"
"G:"="\\??\\C:\\test2"

It is the most robust solution, as the drives will be available for all users, and early in the boot phase. Thus even if some services depend on the virtual drive, they should start correctly.

Note that it is not possible to use / as a delimiter for folders, it will create an invalid virtual drive.

Also note that \\ will be written as \ in the registry, thus if you are using regedit for adding the entries directly, one needs to write a single backslash, like \??\C:\test1.

net use and PS-Drive

You might find that the command net use G: \\localhost\c$\test, or the PowerShell command New-PSDrive -Name "G" -PSProvider "FileSystem" -Root "\\localhost\c$\test" (eventually with -Persist as an additional parameter), will also create a virtual drive pointing to a folder.

Using a network drive will be generally less performant than subst and the registry entry at DOS Devices, which is equivalent to accessing the disk directly.

Note 📝
network drives mounted with subst appear as disconnected in explorer.exe, even if they are accessible. As side effect the amount of space is not shown correctly. Drives mounted with subst also do not show in net use as mounted network drives. Thus using net use for mounting network drives provides a better user-experience.

Mount a drive in a folder

It is possible to mount a drive in a folder instead of a drive letter 🗄️, but contrary to subst, it is not able to "mount" a directory, only real devices

The simplest way to create such a mount seems to be by using mountvol.

On my machine, the output on mountvol looks like

Creates, deletes, or lists a volume mount point.

MOUNTVOL [drive:]path VolumeName
MOUNTVOL [drive:]path /D
MOUNTVOL [drive:]path /L
MOUNTVOL [drive:]path /P
MOUNTVOL /R
MOUNTVOL /N
MOUNTVOL /E

    path        Specifies the existing NTFS directory where the mount
                point will reside.
    VolumeName  Specifies the volume name that is the target of the mount
                point.
    /D          Removes the volume mount point from the specified directory.
    /L          Lists the mounted volume name for the specified directory.
    /P          Removes the volume mount point from the specified directory,
                dismounts the volume, and makes the volume not mountable.
                You can make the volume mountable again by creating a volume
                mount point.
    /R          Removes volume mount point directories and registry settings
                for volumes that are no longer in the system.
    /N          Disables automatic mounting of new volumes.
    /E          Re-enables automatic mounting of new volumes.

Possible values for VolumeName along with current mount points are:

    \\?\Volume{d54c3537-0000-0000-0000-100000000000}\
        C:\

    \\?\Volume{d54c3537-0000-0000-0000-60df0f000000}\
        *** NO MOUNT POINTS ***

    \\?\Volume{6977c166-8bdd-11e9-866a-806e6f6e6963}\
        D:\

Thus for mounting the C:/ drive in a subfolder

mkdir C:/data
mountvol C/data: "\\?\Volume{d54c3537-0000-0000-0000-100000000000}\"

After mounting the output of mountvol will list the new mount point

Creates, deletes, or lists a volume mount point.

MOUNTVOL [drive:]path VolumeName
MOUNTVOL [drive:]path /D
MOUNTVOL [drive:]path /L
MOUNTVOL [drive:]path /P
MOUNTVOL /R
MOUNTVOL /N
MOUNTVOL /E

    path        Specifies the existing NTFS directory where the mount
                point will reside.
    VolumeName  Specifies the volume name that is the target of the mount
                point.
    /D          Removes the volume mount point from the specified directory.
    /L          Lists the mounted volume name for the specified directory.
    /P          Removes the volume mount point from the specified directory,
                dismounts the volume, and makes the volume not mountable.
                You can make the volume mountable again by creating a volume
                mount point.
    /R          Removes volume mount point directories and registry settings
                for volumes that are no longer in the system.
    /N          Disables automatic mounting of new volumes.
    /E          Re-enables automatic mounting of new volumes.

Possible values for VolumeName along with current mount points are:

    \\?\Volume{d54c3537-0000-0000-0000-100000000000}\
        C:\
        C:\data\

    \\?\Volume{d54c3537-0000-0000-0000-60df0f000000}\
        *** NO MOUNT POINTS ***

    \\?\Volume{6977c166-8bdd-11e9-866a-806e6f6e6963}\
        D:\

And for unmounting, use the parameter /D and/or /P.

Unfortunately, it is not possible to use mountvol with subst, as mountvol does not work with virtual drives.

Contrary to subst, the changes made with mountvol will persist across reboots.

Cygwin

As cygwin strives to provide a POSIX environment, the tools to use is /etc/fstab and/or mount.

The default /etc/fstab should look like

# /etc/fstab
#
#    This file is read once by the first process in a Cygwin process tree.
#    To pick up changes, restart all Cygwin processes.  For a description
#    see https://cygwin.com/cygwin-ug-net/using.html#mount-table

# This is default anyway:
none /cygdrive cygdrive binary,posix=0,user 0 0

Unfortunately, it does not support some options, for example making a read-only mount.

Considering that it is easy to bypass (for example when invoking a non-cygwin tool) it does probably not make much sense to implement it.


Do you want to share your opinion? Or is there an error, some parts that are not clear enough?

You can contact me anytime.