#!/usr/bin/python """user filesystem implements files for the -f option to ncftpget (and possibly other ncftp-related programs) according to the manpage, the file should have this format: host sphygmomanometer.ncftp.com user gleason pass mypasswd and since we don't want to have to duplicate our existing $HOME/.netrc file, we implement this user filesytem to reformat .netrc to the above it is necessary to create a directory /mnt/fuse/ncftpgetrc writeable by you, or specify another directory when invoking this script, e.g. ./ncftpgetrc.py $HOME/mnt/fuse/ncftpgetrc on invoking this script, it will exit leaving a file for each host specified in $HOME/.netrc under /mnt/fuse/ncftpgetrc/. you can remove this by: fusermount -u /mnt/fuse/ncftpgetrc """ import os, sys, stat, errno, syslog import fuse from fuse import Fuse fuse.fuse_python_api = (0, 2) NCFTPGETRC = { 'source': os.getenv('HOME') + os.path.sep + '.netrc', 'contents': {}, 'mountpoint': '/mnt/fuse/ncftpgetrc', 'stat': None, } INPUT_HEADERS = ['machine', 'login', 'password'] OUTPUT_HEADERS = ['host', 'user', 'pass'] class FuseStat(fuse.Stat): def __init__(self): attributes = ['st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid', 'st_size', 'st_atime', 'st_mtime', 'st_ctime'] from_source = ['st_uid', 'st_gid', 'st_atime', 'st_ctime', 'st_mtime'] initial = dict([[attr, 0] for attr in attributes]) try: if NCFTPGETRC['source']: syslog.syslog(syslog.LOG_INFO, 'stat %s' % NCFTPGETRC['source']) source_stat = os.stat(NCFTPGETRC['source']) for attribute in from_source: initial[attribute] = getattr(source_stat, attribute, 0) except: pass syslog.syslog(syslog.LOG_INFO, 'initial stat: %s' % repr(initial)) for attribute in attributes: setattr(self, attribute, initial[attribute]) class NcftpgetrcFS(Fuse): def getattr(self, path): load_netrc() st = NCFTPGETRC['stat'] = FuseStat() if path == '/': st.st_mode = stat.S_IFDIR | 0755 st.st_nlink = 2 elif path[1:] in NCFTPGETRC['contents'].keys(): st.st_mode = stat.S_IFREG | 0444 st.st_nlink = 1 st.st_size = len(NCFTPGETRC['contents'][path[1:]]) else: return -errno.ENOENT return st def readdir(self, path, offset): load_netrc() syslog.syslog(syslog.LOG_DEBUG, 'readdir %s' % path) ret = ['.', '..'] + sorted(NCFTPGETRC['contents'].keys()) syslog.syslog(syslog.LOG_DEBUG, repr(ret)) for r in ret: yield fuse.Direntry(r) def open(self, path, flags): load_netrc() if not path[1:] in NCFTPGETRC['contents'].keys(): return -errno.ENOENT if (flags & 3) != os.O_RDONLY: return -errno.EACCES return 0 def read(self, path, size, offset): load_netrc() syslog.syslog(syslog.LOG_DEBUG, 'read %d bytes, offset %d, of %s' % ( size, offset, path)) if not path[1:] in NCFTPGETRC['contents'].keys(): return -errno.ENOENT slen = len(NCFTPGETRC['contents'][path[1:]]) if offset < slen: if offset + size > slen: size = slen - offset buf = NCFTPGETRC['contents'][path[1:]][offset:offset + size] else: buf = '' return buf def main(): if len(sys.argv) < 2: sys.argv.append(NCFTPGETRC['mountpoint']) if not os.path.exists(sys.argv[1]): os.mkdir(sys.argv[1], 0700) fusage = 'Userspace ncftpget login database\n\n' + Fuse.fusage syslog.openlog('ncftpgetrc', syslog.LOG_PID, syslog.LOG_KERN) syslog.syslog(syslog.LOG_INFO, 'starting FUSE "ncftpgetrc"') server = NcftpgetrcFS(version = "%prog " + fuse.__version__, usage = fusage, dash_s_do='setsingle') server.parse(values = server, errex = 1) server.main() def readall(filename): input = open(filename) data = input.readlines() input.close() return data def load_netrc(): data = readall(NCFTPGETRC['source']) for line in data: row = line.split() if len(row) == 6 and [row[0], row[2], row[4]] == INPUT_HEADERS: NCFTPGETRC['contents'][row[1]] = ''.join(['%s %s\n' % (OUTPUT_HEADERS[n], row[(n << 1) + 1]) for n in range(len(OUTPUT_HEADERS))]) if __name__=='__main__': main()