Welcome, guest | Sign In | My Account | Store | Cart
#!/usr/bin/env python

import getopt
import sys
import os
import posix
import getpass

# the default root to mount ssh sources
# its a good idea not to place this in ~ directly
DEFAULTMOUNTROOT= os.environ.get ("HOME") + os.sep + "mnt"

class mnt:
    def __init__(self, argv):
        self.read_mountroot_cfg ()
        if not os.path.exists (self.mountroot):
            os.mkdir (self.mountroot)
            print "Creating mountroot in %s" % self.mountroot
        self.argv = argv
        self.uid = os.getuid()
        
    def usage(self, short=True):
        if short:
            print """%s [-u mountpoint] [-p port] [-m mountpoint] <-a|-l|-h|user@host:path>""" % sys.argv[0]
        else:
            print """%s [OPTIONS] SOURCE
        OPTIONS
        -a                            Unmount all sshfs-mounts
        -u <mountpoint>               Unmount mount
        -p <port>                     Use specified port
        -m <mountpoint>               Don't select mountpoint automatically
        -l                            List all mounts
        -h                            This help page
    
        SOURCE is any ssh address. mnt will use the current user if no username
        is given. If the Path is ommitted mnt will mount the home directory.
        Mountpoint is always without directories, see .mntrc
        
        EXAMPLES
        mnt sven@deepblue             
        mnt sven@deepblue:/home
        mnt -m dbroot sven@deepblue:/
        mnt -p 2345 sven@deepblue
        mnt -u deepblue
        mnt -a
        """ % sys.argv[0]

    def _get_mounted_fs (self):
        """ _get_mounted_fs() -> [[source, mountpoint, filesystem, options, p1, p2],...]
        reads mtab and returns a list of mounted sshfs filesystems. """
        try:
            lines = [line.strip("\n").split(" ") for line in open ("/etc/mtab", "r").readlines()]
            return [mount for mount in lines if mount[2]=="fuse.sshfs"]
        except:
            print "Could not read mtab"
        

    def read_mountroot_cfg(self):
        rcfile = os.environ.get ("HOME") + os.sep + ".mntrc"
        if os.path.exists (rcfile):
            try:
                for line in open (rcfile, "r").readlines():
                    if line.startswith ('mountroot='):
                        self.mountroot = line.rsplit ("=")[1].strip("\n")
            except:
                print "Conffile existant but not readable."
        else:
            try:
                self.mountroot = DEFAULTMOUNTROOT
                open (rcfile, "w").writelines ("mountroot=%s" % DEFAULTMOUNTROOT)
                print "Writing default mountroot %s to .mntrc" % DEFAULTMOUNTROOT
            except:
                print "Could not write .mntrc (%s)" % rcfile
    
    def _split_ssh_source (self,source):
        """_split_ssh_source(source) -> (user, host, path)
        split the values of a ssh source, guess the missing parts of user@host:path"""
        try:
            user,hostpart = source.split("@")
        except ValueError:
            user = getpass.getuser()
            try:
                host, path = source.split(":")
            except:
                path = "."
                host = source
        else:
            try:
                host, path = hostpart.split(":")
            except:
                path = "."
                host = hostpart
        return (user, host, path)

    def _get_possible_mountpoint (self, user, host):
        """_get_possible_mountpoint (user, host) -> mountpoint
        guesses a possible free mountpoint and returns it."""
        if not self.mountpoint:
            self.mountpoint = user + "-" + host
        mp = self.mountroot + os.path.sep + self.mountpoint
        return mp

    def do_mount (self,source):
        """do_mount(source)
        mount ssh source as local filesystem by calling sshfs"""
        user, host, path = self._split_ssh_source (source)
        mp = self._get_possible_mountpoint (user, host)
        if not os.path.exists (mp):
            os.mkdir (mp)
        sshfs = "%s@%s:%s" % (user, host, path)
        
        status = os.system ('sshfs -p %d -o uid=%d "%s" "%s"' % (self.port, self.uid, sshfs, mp))
        if status == 0:
           print "%s mounted as %s" % (sshfs, self.mountpoint)
        else:
            os.rmdir (mp)
    
    def do_umount_all(self):
        for src,mp,fs,opts,p1,p2 in self._get_mounted_fs():
            self.do_umount (mp.rsplit (os.path.sep)[-1])
    
    def do_umount (self, mountpoint):
        if os.path.exists (self.mountroot + os.path.sep + mountpoint):
            os.system ("fusermount -u " + self.mountroot + os.path.sep + mountpoint)
            os.rmdir (self.mountroot + os.path.sep + mountpoint)
    
    def do_list(self):
        for src,mp,fs,opts,p1,p2 in self._get_mounted_fs():
            print "%25s mounted on %s" % (src,mp)      
    
    def main(self):
        try:
            opts, args = getopt.getopt(self.argv, "au:lp:m:h", ["all", "unmount", "list", "port", "mountpoint", "help"])            
        except getopt.GetoptError:
            self.usage()
            sys.exit (2)
        
        self.mountpoint=None
        self.port=22
        for opt, arg in opts:
            if opt in ("-u", "--umount"):
                self.do_umount(arg)
                sys.exit(0)
            elif opt in ("-l", "--list"):
                self.do_list()
                sys.exit(0)
            elif opt in ("-h", "--help"):
                self.usage(short=False)
                sys.exit(1)
            elif opt in ("-a", "--all"):
                self.do_umount_all()
                sys.exit(0)
            elif opt in ("-p", "--port"):
                self.port=arg
            elif opt in ("-m", "--mountpoint"):
                self.mountpoint=arg
        self.do_mount (args[0])


if __name__ == '__main__':
    m = mnt(sys.argv[1:])
    m.main()
    

History