1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#!/usr/bin/env python
#
# cups.py: a FUSE filesystem for mounting an LDAP directory in Python
# Need python-fuse bindings, and an LDAP server.
# usage: ./cups.py <mountpoint>
# unmount with fusermount -u <mountpoint>
#
import stat
import errno
import fuse
from time import time
from subprocess import Popen, PIPE
fuse.fuse_python_api = (0, 2)
class MyStat(fuse.Stat):
def __init__(self):
self.st_mode = stat.S_IFDIR | 0o755
self.st_ino = 0
self.st_dev = 0
self.st_nlink = 2
self.st_uid = 0
self.st_gid = 0
self.st_size = 4096
self.st_atime = 0
self.st_mtime = 0
self.st_ctime = 0
class CupsFS(fuse.Fuse):
def __init__(self, *args, **kw):
fuse.Fuse.__init__(self, *args, **kw)
# Get our list of printers available.
lpstat = Popen(['lpstat -p'], shell=True, stdout=PIPE)
output = lpstat.communicate()[0]
lines = output.split(b'\n')
lpstat.wait()
self.printers = {}
self.files = {}
self.lastfiles = {}
for line in lines:
words = line.split(b' ')
if len(words) > 2:
self.printers[words[1]] = []
def getattr(self, path):
st = MyStat()
pe = path.split('/')[1:]
st.st_atime = int(time())
st.st_mtime = st.st_atime
st.st_ctime = st.st_atime
if path == '/':
pass
elif pe[-1] in self.printers:
pass
elif pe[-1] in self.lastfiles:
st.st_mode = stat.S_IFREG | 0o666
st.st_nlink = 1
st.st_size = len(self.lastfiles[pe[-1]])
else:
return -errno.ENOENT
return st
def readdir(self, path, offset):
dirents = ['.', '..']
if path == '/':
dirents.extend(list(self.printers.keys()))
else:
dirents.extend(self.printers[path[1:]])
for r in dirents:
yield fuse.Direntry(r)
def mknod(self, path, mode, dev):
pe = path.split('/')[1:] # Path elements 0 = printer 1 = file
self.printers[pe[0]].append(pe[1])
self.files[pe[1]] = ""
self.lastfiles[pe[1]] = ""
return 0
def unlink(self, path):
pe = path.split('/')[1:] # Path elements 0 = printer 1 = file
self.printers[pe[0]].remove(pe[1])
del (self.files[pe[1]])
del (self.lastfiles[pe[1]])
return 0
def read(self, path, size, offset):
pe = path.split('/')[1:] # Path elements 0 = printer 1 = file
return self.lastfiles[pe[1]][offset:offset + size]
def write(self, path, buf, offset):
pe = path.split('/')[1:] # Path elements 0 = printer 1 = file
self.files[pe[1]] += buf
return len(buf)
def release(self, path, flags):
pe = path.split('/')[1:] # Path elements 0 = printer 1 = file
if len(self.files[pe[1]]) > 0:
lpr = Popen(['lpr -P ' + pe[0]], shell=True, stdin=PIPE)
lpr.communicate(input=self.files[pe[1]])
lpr.wait()
self.lastfiles[pe[1]] = self.files[pe[1]]
self.files[pe[1]] = "" # Clear out string
return 0
def open(self, path, flags):
return 0
def truncate(self, path, size):
return 0
def utime(self, path, times):
return 0
def mkdir(self, path, mode):
return 0
def rmdir(self, path):
return 0
def rename(self, pathfrom, pathto):
return 0
def fsync(self, path, isfsyncfile):
return 0
def main():
usage = """
CupsFS: A filesystem to allow printing for applications that can
only print to file.
""" + fuse.Fuse.fusage
server = CupsFS(version="%prog " + fuse.__version__,
usage=usage, dash_s_do='setsingle')
server.parse(errex=1)
server.main()
if __name__ == '__main__':
main()
|