Skip to content

Instantly share code, notes, and snippets.

@yudai09
Last active December 18, 2015 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yudai09/5815238 to your computer and use it in GitHub Desktop.
Save yudai09/5815238 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
# Copyright (C) 2006 Csaba Henk <csaba.henk@creo.hu>
#
# This program can be distributed under the terms of the GNU LGPL.
# See the file COPYING.
#
import os, sys
from errno import *
from stat import *
import fcntl
import fuse
from fuse import Fuse
import re
import datetime
import logging
logging.basicConfig(filename='log.txt',level=logging.DEBUG)
if not hasattr(fuse, '__version__'):
raise RuntimeError, \
"your fuse-py doesn't know of fuse.__version__, probably it's too old."
fuse.fuse_python_api = (0, 2)
# We use a custom file class
fuse.feature_assert('stateful_files', 'has_init')
def flag2mode(flags):
md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
if flags | os.O_APPEND:
m = m.replace('w', 'a', 1)
return m
def time_to_open(path):
year_reg = '([0-9][0-9][0-9][0-9])'
month_reg = '(1[0-2]|0[1-9])'
day_reg = "(1[0-9]|2[0-9]|3[0-1]|0[1-9])"
p = re.compile("/(%s%s%s)/" % (year_reg, month_reg, day_reg))
datelist = p.findall(path)
if len(datelist) == 0:
return True
datelist_int = map((lambda x:int(x[0])),datelist)
date_most_future = max(datelist_int)
now = datetime.datetime.today()
now_int = now.year *10000 + now.month * 100 + now.day
return date_most_future < now_int
class Xmp(Fuse):
def __init__(self, *args, **kw):
Fuse.__init__(self, *args, **kw)
# do stuff to set up your filesystem here, if you want
#import thread
#thread.start_new_thread(self.mythread, ())
self.root = '/'
# self.file_class = self.XmpFile
# def mythread(self):
#
# """
# The beauty of the FUSE python implementation is that with the python interp
# running in foreground, you can have threads
# """
# print "mythread: started"
# while 1:
# time.sleep(120)
# print "mythread: ticking"
def getattr(self, path):
return os.lstat("." + path)
def readlink(self, path):
return os.readlink("." + path)
def readdir(self, path, offset):
for e in os.listdir("." + path):
yield fuse.Direntry(e)
def unlink(self, path):
os.unlink("." + path)
def rmdir(self, path):
os.rmdir("." + path)
def symlink(self, path, path1):
os.symlink(path, "." + path1)
def rename(self, path, path1):
logging.debug(now + ' rename')
if not time_to_open(path):
return -EACCES
os.rename("." + path, "." + path1)
def link(self, path, path1):
os.link("." + path, "." + path1)
def chmod(self, path, mode):
os.chmod("." + path, mode)
def chown(self, path, user, group):
os.chown("." + path, user, group)
def truncate(self, path, len):
f = open("." + path, "a")
f.truncate(len)
f.close()
def mknod(self, path, mode, dev):
os.mknod("." + path, mode, dev)
def mkdir(self, path, mode):
os.mkdir("." + path, mode)
def utime(self, path, times):
os.utime("." + path, times)
def open( self, path, mode ):
logging.debug('open')
if (mode & os.O_WRONLY) == 0:
if not time_to_open(path):
return -EACCES
def fsinit(self):
os.chdir(self.root)
# def read(self, path, size, offset, fh):
def read(self, path, length, offset):
f = open("." + path, "r")
f.seek(offset)
buffer = f.read(length)
return buffer
def write(self, path, buf, offset):
f = open("." + path, "w")
logging.debug("seek")
f.seek(offset)
logging.debug("write")
f.write(buf)
return len(buf)
#def write(self, path, buf, offset):
# def release(self, flags):
def main():
usage = """
Userspace nullfs-alike: mirror the filesystem tree from some point on.
""" + Fuse.fusage
server = Xmp(version="%prog " + fuse.__version__,
usage=usage)
server.parser.add_option(mountopt="root", metavar="PATH", default='/',
help="mirror filesystem from under PATH [default: %default]")
server.parse(values=server, errex=1)
logging.debug(server.root)
try:
if server.fuse_args.mount_expected():
os.chdir(server.root)
except OSError:
print >> sys.stderr, "can't enter root of underlying filesystem"
sys.exit(1)
server.main()
if __name__ == '__main__':
main()
@yudai09
Copy link
Author

yudai09 commented Jun 19, 2013

$ python xmp-2.py -o root=/tmp/fs/ /home/hoge/mnt

directoryの名前が20130626のような形式になっている場合は現在の日付よりも、directoryの日付が新しい場合はその中にあるファイルを読めない。書き込みは可能。

ただし抜け道がある。

@thuydg
Copy link

thuydg commented Jun 19, 2013

[root@localhost fuse]# fusermount -u /usr/local/fuse/
[root@localhost fuse]# python xmp2.py /usr/local/fuse/
[root@localhost fuse]# ls /usr/local/fuse/
bin boot dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux simple.c srv sys testfusepython test.txt tmp usr var
[root@localhost fuse]# mkdir /usr/local/fuse/20130405/
[root@localhost fuse]# touch /usr/local/fuse/20130405/test.txt
[root@localhost fuse]# ls /usr/local/fuse/
20130405 bin boot dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux simple.c srv sys testfusepython test.txt tmp usr var
[root@localhost fuse]# ls /
20130405 bin boot dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux simple.c srv sys testfusepython test.txt tmp usr var
[root@localhost fuse]# cat /usr/local/fuse/20130405/test.txt
[root@localhost fuse]# mkdir /usr/local/fuse/20130705/
[root@localhost fuse]# touch /usr/local/fuse/20130705/test.txt
[root@localhost fuse]# cat /usr/local/fuse/20130405/test.txt
[root@localhost fuse]# cat /usr/local/fuse/20130705/test.txt
cat: /usr/local/fuse/20130705/test.txt: Permission denied
[root@localhost fuse]# cat /20130705/test.txt
[root@localhost fuse]#

@thuydg
Copy link

thuydg commented Jun 19, 2013

動作、確認できました!fuse通過だったらいいんだけど、実際にファイル実態がアクセスされちゃうんだね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment