#!/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()
