Source

rsync_backup / fs.py

Full commit
# -*- coding: ascii
"""
filesystem tools: mounting, etc.

Note: bind mounting to /rootfs is a trick to get the REAL stuff from the
      disk, but not the (virtual) filesystem files mounted on top of that.
      It also makes special excludes for /dev /proc /sys unneccessary if one
      wants to backup the root filesystem.

author: Thomas Waldmann
license: BSD
"""

import os
import errno
from subprocess import check_call as cmd


def make_dir(path):
    """make sure directory <path> exists"""
    try:
        # make sure that dst_path exists
        os.mkdir(path)
    except OSError as err:
        # no problem if it already was there
        if err.errno != errno.EEXIST:
            raise


def mount(src, mountpoint):
    """mount src on mountpoint"""
    cmd("mount %(src)s %(mountpoint)s" % dict(src=src, mountpoint=mountpoint),
        shell=True)
    # TODO: check if mount succeeded with os.path.ismount(mountpoint)


def umount(mountpoint):
    """umount mountpoint"""
    cmd("umount %(mountpoint)s" % dict(mountpoint=mountpoint),
        shell=True)


def _process_pathes(command, pathes, dst_path, root_path="/", **kw):
    """process command on all pathes below dst_path directory"""
    prefix_len = len(os.path.commonprefix(pathes))
    for path in pathes:
        dst = os.path.join(dst_path, path[prefix_len:])
        make_dir(dst)
        cmd(command % dict(src=path, dst=dst), shell=True)


def mount_pathes(pathes, dst_path, root_path="/", **kw):
    """bind-mount all pathes below dst_path directory"""
    _process_pathes("mount --bind %(src)s %(dst)s", pathes, dst_path, root_path, **kw)


def umount_pathes(pathes, dst_path, root_path="/", **kw):
    """umount all pathes in reverse given order"""
    reversed_pathes = list(reversed(pathes)) # we MUST have a list, not iterator
    _process_pathes("umount %(dst)s", reversed_pathes, dst_path, root_path, **kw)