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
|
"""
FUSE filesystem on bareos data.
"""
from bareos.bsock import DirectorConsoleJson
import bareos.bsock
from bareos.util import Path
from bareos.fuse.root import Root
import errno
import fuse
import logging
import socket
import stat
import os.path
from pprint import pformat
fuse.fuse_python_api = (0, 2)
class BareosFuse(fuse.Fuse):
def __init__(self, *args, **kw):
self.bsock = None
self.bareos = None
self.restoreclient = None
self.restorejob = None
self.restorepath = '/var/cache/bareosfs/'
super(BareosFuse, self).__init__(*args, **kw)
self.multithreaded = False
def initLogging(self):
self.logger = logging.getLogger()
self.logger.setLevel(logging.DEBUG)
if hasattr(self, "logfile"):
hdlr = logging.FileHandler(self.logfile)
# limit message size
formatter = logging.Formatter('%(asctime)s %(levelname)-7s %(module)s %(funcName)s( %(message).800s )')
hdlr.setFormatter(formatter)
self.logger.addHandler(hdlr)
def parse(self, *args, **kw):
super(BareosFuse, self).parse(*args, **kw)
if self.fuse_args.mount_expected():
options = [ 'address', 'port', 'dirname', 'name', 'password' ]
self.bsockParameter = {}
for i in options:
if hasattr(self, i):
self.bsockParameter[i] = getattr(self,i)
else:
#self.logger.debug( "%s: missing, default: %s" %(i, str(getattr(self,i,None))))
pass
if not hasattr(self, 'password'):
raise bareos.fuse.ParameterMissing("missing parameter password")
else:
password = bareos.bsock.Password(self.password)
self.bsockParameter['password']=password
self.restorepath = os.path.normpath(self.restorepath)
if not os.path.isabs(self.restorepath):
raise bareos.fuse.RestorePathInvalid("restorepath must be an absolute path")
def main(self, *args, **kw):
# use main() instead of fsinit,
# as this prevents FUSE from being started in case of errors.
self.initLogging()
self.logger.debug('start')
if self.fuse_args.mount_expected():
try:
self.bsock = bareos.bsock.BSockJson(**self.bsockParameter)
except socket.error as e:
self.logger.exception(e)
raise bareos.fuse.SocketConnectionRefused(e)
self.bareos = Root(self.bsock, self.restoreclient, self.restorejob, self.restorepath)
super(BareosFuse, self).main(*args, **kw)
self.logger.debug('done')
def getattr(self, path):
if self.bareos:
stat = self.bareos.getattr(Path(path))
if isinstance(stat, fuse.Stat):
self.logger.debug("{path}: dev={stat.st_dev}, ino={stat.st_ino}, mode={stat.st_mode}, nlink={stat.st_nlink}, uid={stat.st_uid}, gid={stat.st_gid}, size={stat.st_size}, atime={stat.st_atime}, ctime={stat.st_ctime}, mtime={stat.st_mtime}".format(path=path, stat=stat))
else:
self.logger.debug("%s: (int) %i" % (path, stat))
return stat
def read(self, path, size, offset):
result = self.bareos.read(Path(path), size, offset)
self.logger.debug("%s: %s" % (path, result))
return result
def readdir(self, path, offset):
entries = self.bareos.readdir(Path(path), offset)
self.logger.debug("%s: %s" % (path, entries))
if not entries:
return -errno.ENOENT
else:
return [fuse.Direntry(f) for f in entries]
def readlink(self, path):
result = self.bareos.readlink(Path(path))
self.logger.debug("%s: %s" % (path, result))
return result
def listxattr(self, path, size):
'''
list extended attributes
'''
keys = self.bareos.listxattr(Path(path))
if size == 0:
# We are asked for size of the attr list, ie. joint size of attrs
# plus null separators.
result = len("".join(keys)) + len(keys)
self.logger.debug("%s: len=%s" % (path, result))
else:
result = keys
self.logger.debug("%s: keys=%s" % (path, ", ".join(keys)))
return result
def getxattr(self, path, key, size):
'''
get value of extended attribute
burpfs exposes some filesystem attributes for the root directory
(e.g. backup number, cache prefix - see FileSystem.xattr_fields_root)
and may also expose several other attributes for each file/directory
in the future (see FileSystem.xattr_fields)
'''
value = self.bareos.getxattr(Path(path), key)
self.logger.debug("%s: %s=%s" % (path, key, str(value)))
if value == None:
result = -errno.ENODATA
elif size == 0:
# we are asked for size of the value
result = len(value)
self.logger.debug("%s: len=%s" % (path, result))
else:
result = value
self.logger.debug("%s: %s=%s" % (path, key, result))
return result
def setxattr(self, path, key, value, flags):
'''
set value of extended attribute
'''
result = self.bareos.setxattr(Path(path), key, value, flags)
self.logger.debug("%s: %s=%s: %s" % (path, key, value, str(result)))
return result
def rename(self, oldpath, newpath):
result = self.bareos.rename(Path(oldpath), Path(newpath))
self.logger.debug("%s => %s: %s" % (oldpath, newpath, result))
return result
|