+#!/usr/bin/python
+
+import fuse
+from fuse import Fuse
+
+from time import time
+
+import stat # for file properties
+import os # for filesystem modes (O_RDONLY, etc)
+import errno # for error number codes (ENOENT, etc)
+ # - note: these must be returned as negatives
+
+fuse.fuse_python_api = (0, 2)
+
+machines = ['moo17', 'remus']
+realpath = "/home/machines/"
+uid = 1000
+
+def dirFromList(list):
+ """
+ Return a properly formatted list of items suitable to a directory listing.
+ ['a', 'b', 'c'] => [('a', 0), ('b', 0), ('c', 0)]
+ """
+ return [(x, 0) for x in list]
+
+def getDepth(path):
+ """
+ Return the depth of a given path, zero-based from root ('/')
+ """
+ if path == '/':
+ return 0
+ else:
+ return path.count('/')
+
+def getParts(path):
+ """
+ Return the slash-separated parts of a given path as a list
+ """
+ if path == '/':
+ return ['/']
+ else:
+ return path[1:].split('/')
+
+class MyStat:
+ def __init__(self):
+ self.st_mode = 0
+ self.st_ino = 0
+ self.st_dev = 0
+ self.st_nlink = 0
+ self.st_uid = uid
+ self.st_gid = 0
+ self.st_size = 0
+ self.st_atime = 0
+ self.st_mtime = 0
+ self.st_ctime = 0
+
+ def toTuple(self):
+ return (self.st_mode, self.st_ino, self.st_dev, self.st_nlink, self.st_uid, self.st_gid, self.st_size, self.st_atime, self.st_mtime, self.st_ctime)
+
+class ConsoleFS(Fuse):
+ """
+ """
+
+ def __init__(self, *args, **kw):
+ Fuse.__init__(self, *args, **kw)
+ print 'Init complete.'
+
+ def mirrorPath(self, path):
+ return realpath + "/".join(getParts(path)[1:])
+
+ def getattr(self, path):
+ """
+ - st_mode (protection bits)
+ - st_ino (inode number)
+ - st_dev (device)
+ - st_nlink (number of hard links)
+ - st_uid (user ID of owner)
+ - st_gid (group ID of owner)
+ - st_size (size of file, in bytes)
+ - st_atime (time of most recent access)
+ - st_mtime (time of most recent content modification)
+ - st_ctime (platform dependent; time of most recent metadata change on Unix,
+ or the time of creation on Windows).
+ """
+
+ print "*** getattr: " + path
+
+ depth = getDepth(path)
+ parts = getParts(path)
+
+ st = MyStat()
+ if path == '/':
+ st.st_mode = stat.S_IFDIR | 0755
+ st.st_nlink = 2
+ elif depth == 1:
+ if parts[-1] in machines:
+ st.st_mode = stat.S_IFDIR | 0755
+ st.st_nlink = 2
+ else:
+ return -errno.ENOENT
+ elif depth == 2 and parts[-1] == '.k5login':
+ st.st_mode = stat.S_IFREG | 0444
+ st.st_nlink = 1
+ st.st_size = 17
+ else:
+ st = os.lstat(self.mirrorPath(path))
+ return st.toTuple()
+
+ def readdir(self, path, offset):
+ print '*** readdir', path, offset
+ if path == '/':
+ for r in ['.', '..']+machines:
+ yield fuse.Direntry(r)
+ elif getDepth(path) == 1:
+ for r in set(os.listdir(self.mirrorPath(path)) + ['.k5login']):
+ yield fuse.Direntry(r)
+ else:
+ for r in os.listdir(self.mirrorPath(path)):
+ yield fuse.Direntry(r)
+
+ def read ( self, path, length, offset ):
+ print '*** read', path, length, offset
+
+ if getDepth(path) < 2:
+ return -errno.ENOENT
+ elif getParts(path)[1:] == ['.k5login']:
+ pass
+ else:
+ fname = self.mirrorPath(path)
+ if not os.path.isfile(fname):
+ return -errno.ENOENT
+ else:
+ f = open(fname)
+ f.seek(offset)
+ return f.read(length)
+
+if __name__ == '__main__':
+ usage="""
+ConsoleFS [mount_path]
+"""
+ server = ConsoleFS()
+ server.flags = 0
+ server.main()