-
Notifications
You must be signed in to change notification settings - Fork 1
/
varsfs.py
161 lines (120 loc) · 3.37 KB
/
varsfs.py
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
148
149
150
151
152
153
154
155
156
157
158
#import logging
import os
import resource
import subprocess
from errno import ENOENT, EPERM
from stat import S_IFDIR, S_IFREG
from time import time
from fuse import FUSE, FuseOSError, Operations, LoggingMixIn
class FileNode:
def __init__(self):
self.name = ""
self.getter_fn = None
self.setter_fn = None
self.attrs = None
self.fd = None
##
#
class Helpers:
started_at = 0
@staticmethod
def get_pid(varname):
return '%d' % os.getpid()
@staticmethod
def get_user(varname):
return os.environ['LOGNAME']
@staticmethod
def get_uptime(varname):
return '%f' % (time() - Helpers.started_at)
@staticmethod
def get_no_file(varname):
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
return '%d\t%d' % (soft, hard)
@staticmethod
def get_fd_count(varname):
out = subprocess.check_output('ls /proc/self/fd |wc -l', shell=True)
return out
##
#
#class VarsFS(LoggingMixIn, Operations):
class VarsFS(Operations):
def __init__(self, mountpoint):
self.mountpoint = mountpoint
self.files = {}
self.fd = 3
self.uid = os.getuid()
now = time()
Helpers.started_at = time()
root = FileNode()
root.name = '/'
root.attrs = dict(st_mode=(S_IFDIR | 0o755), st_ctime=now,
st_mtime=now, st_atime=now, st_nlink=2,
st_uid=self.uid)
self.files[''] = root
def __create_defaults(self):
self.Add('uptime', Helpers.get_uptime)
self.Add('user', Helpers.get_user)
self.Add('pid', Helpers.get_pid)
self.Add('file-limits', Helpers.get_no_file)
self.Add('fd-count', Helpers.get_fd_count)
def Add(self, varname, getter_fn, setter_fn=None):
f = FileNode()
f.name = varname
f.getter_fn = getter_fn
f.setter_fn = setter_fn
mode = 0o664
if setter_fn is None:
mode = 0o444
f.attrs = dict(st_mode=(S_IFREG | mode), st_nlink=1,
st_size=0, st_ctime=time(), st_mtime=time(),
st_atime=time(), st_uid=self.uid)
self.files[varname] = f
def getattr(self, path, fh=None):
p = path[1:]
if p not in self.files:
raise FuseOSError(ENOENT)
if self.files[p].getter_fn is not None:
self.files[p].attrs['st_size'] = len(self.files[p].getter_fn(p))
return self.files[p].attrs
def open(self, path, flags):
p = path[1:]
if self.files[p].fd is None:
self.fd += 1
self.files[p].fd = self.fd
return self.files[p].fd
def read(self, path, size, offset, fh):
p = path[1:]
try:
if self.files[p].getter_fn is None:
raise FuseOSError(EPERM)
return self.files[p].getter_fn(p)
except KeyError:
raise FuseOSError(ENOENT)
def readdir(self, path, fh):
return ['.', '..'] + [x for x in self.files if x != '']
#def statfs(self, path):
# return dict(f_bsize=512, f_blocks=4096, f_bavail=2048)
def write(self, path, data, offset, fh):
p = path[1:]
try:
if self.files[p].setter_fn is None:
raise FuseOSError(EPERM)
self.files[p].setter_fn(p, data)
return len(data)
except KeyError:
raise FuseOSError(ENOENT)
def truncate(self, path, length, fh=None):
pass
def Run(self, foreground=True):
#logging.basicConfig(level=logging.DEBUG)
self.__create_defaults()
if foreground:
fuse = FUSE(self, self.mountpoint, foreground=foreground, nothreads=True)
else:
import threading
def fn():
#print "New thread"
fuse = FUSE(self, self.mountpoint, foreground=True, nothreads=True)
t = threading.Thread(target=fn)
t.setDaemon(True)
t.start()