def open(self, inode, flags, ctx=None): if not self.allow_damaged_files: item = self.get_item(inode) if 'chunks_healthy' in item: # Processed archive items don't carry the path anymore; for converting the inode # to the path we'd either have to store the inverse of the current structure, # or search the entire archive. So we just don't print it. It's easy to correlate anyway. logger.warning('File has damaged (all-zero) chunks. Try running borg check --repair. ' 'Mount with allow_damaged_files to read damaged files.') raise llfuse.FUSEError(errno.EIO) return inode
def lookup(self, parent_inode, name, ctx=None): name = fsdecode(name) self.dolog('[>] lookup for %d [%s]' % (parent_inode, name)) n = self.findinode(parent_inode) dirmode = n.stattype() if not (dirmode == 'd'): print("Wrong dir") d = n.readdir() if d is None: raise llfuse.FUSEError(errno.ENOENT) r = {} for i in d: r[i.name()] = i if name in r: e = r[name] attr = self._getattr(e) self.registerinode(attr.st_ino, e) return attr print("Cannot find %s" % (name)) raise llfuse.FUSEError(errno.ENOENT)
def lookup(self, parent_inode, name, ctx=None): self.check_pending_archive(parent_inode) if name == b'.': inode = parent_inode elif name == b'..': inode = self.parent[parent_inode] else: inode = self.contents[parent_inode].get(name) if not inode: raise llfuse.FUSEError(errno.ENOENT) return self.getattr(inode)
def do_os(func, *args, **kwargs): """Do low level OS call and handle errors. This function wraps any raised OSErrors for the FUSE library. Call anything that could raise an OSError using this! """ try: return func(*args, **kwargs) except OSError as err: raise llfuse.FUSEError(err.errno)
def read(self, fh, offset, length): try: entry = self.inodes[fh] except KeyError: raise llfuse.FUSEError(errno.ENOENT) if offset > entry.size: return bytes() i = entry.offset + offset j = i + min(entry.size - offset, length) return self.data[i:j]
def _remove(self, inode_p, name, entry): log.debug("_remove") if inodestruct.r_inode.getInodeByID(entry.st_ino).fileTable: log.debug( "child of this is : " + str(inodestruct.r_inode.getInodeByID(entry.st_ino).fileTable)) raise llfuse.FUSEError(errno.ENOTEMPTY) log.debug("delete from inode# : " + str(inode_p)) log.debug("delete inode# : " + str(entry.st_ino)) inodestruct.r_inode.getInodeByID(inode_p).rmInode( name=name.decode("utf-8"))
def read(self, inode, offset, length): self.logger.debug("read: %s %s %s", inode, offset, length) try: grid_out = self.gridfs.get(inode) except gridfs.errors.NoFile: msg = "Read of inode (%s) fails. Gridfs object not found" self.logger.error(msg, inode) raise llfuse.FUSEError(errno.EIO) grid_out.seek(offset) return grid_out.read(length)
def lookup(self, parrent_ino, name): if name == '.': return self.entrycache[parrent_ino] if name == '..': parent = self.nodecache[parrent_ino].parent return self.entrycache[parent.inode] else: try: node = self.nodecache[parrent_ino].children_as_dict[name] return self.entrycache[node.inode] except KeyError: raise llfuse.FUSEError(errno.ENOENT)
def _notify(self, name): if name in self._tried_open_files and time( ) - self._last_notification > self._notif_max_wait_sec: title = 'Cannot access %s' % name fullname = os.path.join(self._mountpoint, name) text = 'In order to access\n<i>%s</i>,\nyou must mount <b>%s</b>.' % ( fullname, self._name) self._notify_object.Notify(self._notif_app_name, self._notif_id, self._notif_icon, title, text, '', {}, self._notif_time_sec * 1000) self._last_notification = time() raise llfuse.FUSEError(errno.EPERM)
def lookup_create(self, name): try: name = name.decode() except UnicodeDecodeError: raise llfuse.FUSEError(errno.ENOENT) for name in slash_variations(name): c = self.api.db.cursor() r = c.execute( "select id from torrent_entry_group " "where name = ? and series_id = ? and not deleted", (name, self.id)).fetchone() if not r: continue id = r[0] link = yatfs_fs.StaticSymlink( ("../../../../group/by-id/%d" % id).encode()) link.entry_timeout = 3600 link.attr_timeout = 86400 return link else: raise llfuse.FUSEError(errno.ENOENT)
def opendir(self, inode): #print "opendir: inode", inode if inode in self.inodes: p = self.inodes[inode] else: raise llfuse.FUSEError(errno.ENOENT) if not isinstance(p, Directory): raise llfuse.FUSEError(errno.ENOTDIR) fh = self._filehandles_counter self._filehandles_counter += 1 if p.parent_inode in self.inodes: parent = self.inodes[p.parent_inode] else: parent = None self._filehandles[fh] = FileHandle(fh, [('.', p), ('..', parent)] + list(p.items())) return fh
def lookup_create(self, name): try: name = name.decode() except UnicodeDecodeError: raise llfuse.FUSEError(errno.ENOENT) id = name.split(".")[-1] try: id = int(id) except ValueError: raise llfuse.FUSEError(errno.ENOENT) c = self.api.db.cursor() r = c.execute("select group_id from torrent_entry where id = ?", (id, )).fetchone() if (not r) or r[0] != self.id: raise llfuse.FUSEError(errno.ENOENT) link = yatfs_fs.StaticSymlink( ("../../../../torrent/by-id/%d" % id).encode()) link.entry_timeout = 3600 link.attr_timeout = 86400 apply_attr(link, self.api, id) return link
def getattr(self, inode: int, ctx: llfuse.RequestContext = None) -> llfuse.EntryAttributes:# {{{ pylint: disable=unused-argument """ get inode attributes """ entry = llfuse.EntryAttributes() stamp: float # root inode attributes if inode == llfuse.ROOT_INODE: entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 stamp = int(time.time() * 1e9) # parameters for inodes inside the tar file elif inode < self.max_inode: tar_inode = self.tar.getmembers()[inode - self.delta] # setting proper mode based on the type of the inode entry.st_mode = 0 if tar_inode.isdir(): entry.st_mode = stat.S_IFDIR elif tar_inode.isreg(): entry.st_mode = stat.S_IFREG elif tar_inode.islnk(): entry.st_mode = stat.S_IFLNK elif tar_inode.issym(): entry.st_mode = stat.S_IFLNK elif tar_inode.isfifo(): entry.st_mode = stat.S_IFIFO elif tar_inode.ischr(): entry.st_mode = stat.S_IFCHR entry.st_mode |= tar_inode.mode # inode size entry.st_size = tar_inode.size # we will use mtime for atime and ctime also stamp = (tar_inode.mtime * 1e9) else: raise llfuse.FUSEError(errno.ENOENT) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode # because this is read-only FS we can set timeouts to large values entry.attr_timeout = 3600 entry.entry_timeout = 3600 return entry
def rename(self, name_old, name_new, src): if not isinstance(src, CollectionDirectoryBase): raise llfuse.FUSEError(errno.EPERM) if name_new in self: ent = src[name_old] tgt = self[name_new] if isinstance(ent, FuseArvadosFile) and isinstance(tgt, FuseArvadosFile): pass elif isinstance(ent, CollectionDirectoryBase) and isinstance(tgt, CollectionDirectoryBase): if len(tgt) > 0: raise llfuse.FUSEError(errno.ENOTEMPTY) elif isinstance(ent, CollectionDirectoryBase) and isinstance(tgt, FuseArvadosFile): raise llfuse.FUSEError(errno.ENOTDIR) elif isinstance(ent, FuseArvadosFile) and isinstance(tgt, CollectionDirectoryBase): raise llfuse.FUSEError(errno.EISDIR) with llfuse.lock_released: self.collection.rename(name_old, name_new, source_collection=src.collection, overwrite=True) self.flush() src.flush()
def get_bytes(self, pos, size): have_data = self.read_mapfile(pos, size) if not have_data: self.process.recover_bytes(pos, size) if not self.read_mapfile(pos, size): raise llfuse.FUSEError(errno.EIO) with open(self.image, 'rb') as f: assert pos == f.seek(pos, io.SEEK_SET) data = f.read(size) assert len(data) == size return data
def opendir(self, inode, ctx=None): _logger.debug("arv-mount opendir: inode %i", inode) if inode in self.inodes: p = self.inodes[inode] else: raise llfuse.FUSEError(errno.ENOENT) if not isinstance(p, Directory): raise llfuse.FUSEError(errno.ENOTDIR) fh = next(self._filehandles_counter) if p.parent_inode in self.inodes: parent = self.inodes[p.parent_inode] else: raise llfuse.FUSEError(errno.EIO) # update atime self.inodes.touch(p) self._filehandles[fh] = DirectoryHandle(fh, p, [('.', p), ('..', parent)] + listitems(p)) return fh
def setxattr(self, id_, name, value): log.debug('setxattr(%d, %r, %r): start', id_, name, value) # Handle S3QL commands if id_ == CTRL_INODE: if name == b's3ql_flushcache!': self.cache.clear() elif name == b'copy': self.copy_tree(*pickle.loads(value)) elif name == b'upload-meta': if self.upload_event is not None: self.upload_event.set() else: raise llfuse.FUSEError(errno.ENOTTY) elif name == b'lock': self.lock_tree(*pickle.loads(value)) elif name == b'rmtree': self.remove_tree(*pickle.loads(value)) elif name == b'logging': update_logging(*pickle.loads(value)) elif name == b'cachesize': self.cache.max_size = pickle.loads(value) else: raise llfuse.FUSEError(errno.EINVAL) # http://code.google.com/p/s3ql/issues/detail?id=385 elif name in (b'system.posix_acl_access', b'system.posix_acl_default'): raise FUSEError(ACL_ERRNO) else: if self.failsafe or self.inodes[id_].locked: raise FUSEError(errno.EPERM) if len(value) > deltadump.MAX_BLOB_SIZE: raise FUSEError(errno.EINVAL) self.db.execute( 'INSERT OR REPLACE INTO ext_attributes (inode, name_id, value) ' 'VALUES(?, ?, ?)', (id_, self._add_name(name), value)) self.inodes[id_].ctime = time.time()
def _yarp_parse_classname(self, cell_relative_offset): if not self._yarp_is_key(cell_relative_offset): raise llfuse.FUSEError(errno.EBADF) buf = self._yarp_get_cell(cell_relative_offset) key_node = RegistryRecords.KeyNode(buf) classname_length = key_node.get_classname_length() if classname_length == 0: return b'' buf_classname = self._yarp_get_cell(key_node.get_classname_offset()) return buf_classname[:classname_length]
def opendir(self, inode, ctx): """ """ if inode == llfuse.ROOT_INODE: return inode elif inode < self.max_inode: idx = inode - self.delta if self.tar.getmembers()[idx].isdir(): return inode raise llfuse.FUSEError(errno.ENOENT)
def unlink(self, id_p, name, ctx): log.debug('started with %d, %r', id_p, name) if self.failsafe: raise FUSEError(errno.EPERM) inode = self._lookup(id_p, name, ctx) if stat.S_ISDIR(inode.mode): raise llfuse.FUSEError(errno.EISDIR) self._remove(id_p, name, inode.id) self.forget([(inode.id, 1)])
def lookup(self, parent_inode, name, ctx=None): name = fsdecode(name) log.debug("lookup in %d for %s" % (parent_inode, name)) if name == '.': inode = parent_inode if name == '..': if parent_inode == llfuse.ROOT_INODE: inode = parent_inode else: try: parent_name = dirname(self._inodes_mapping[parent_inode]) inode = self._pathes_mapping[parent_name] except KeyError: raise llfuse.FUSEError(errno.ENOENT) else: try: parent_name = self._inodes_mapping[parent_inode] inode = self._get_inode_from_path( os.path.join(parent_name, name)) except KeyError: raise llfuse.FUSEError(errno.ENOENT) return self.getattr(inode)
def mkdir(self, name): try: with llfuse.lock_released: self.api.collections().create( body={ "owner_uuid": self.project_uuid, "name": name, "manifest_text": "" }).execute(num_retries=self.num_retries) self.invalidate() except apiclient_errors.Error as error: _logger.error(error) raise llfuse.FUSEError(errno.EEXIST)
def listxattr(self, inode, ctx): try: entry = self.inodes[inode] except KeyError: raise llfuse.FUSEError(errno.ENOENT) else: if type(entry) is Dir: return [] else: return ['user.u4pak.sha1', 'user.u4pak.compressed_size', 'user.u4pak.compression_method', 'user.u4pak.compression_block_size', 'user.u4pak.encrypted']
def _remove(self, inode_p, name, entry): if self.get_row( "SELECT COUNT(inode) FROM contents WHERE parent_inode=?", (entry.st_ino, ))[0] > 0: raise llfuse.FUSEError(errno.ENOTEMPTY) self.cursor.execute( "DELETE FROM contents WHERE name=? AND parent_inode=?", (name, inode_p)) if entry.st_nlink == 1 and entry.st_ino not in self.inode_open_count: self.cursor.execute("DELETE FROM inodes WHERE id=?", (entry.st_ino, ))
def readdir(self, fh, off): _logger.debug("arv-mount readdir: fh %i off %i", fh, off) if fh in self._filehandles: handle = self._filehandles[fh] else: raise llfuse.FUSEError(errno.EBADF) e = off while e < len(handle.entries): if handle.entries[e][1].inode in self.inodes: yield (handle.entries[e][0].encode(self.inodes.encoding), self.getattr(handle.entries[e][1].inode), e+1) e += 1
def opendir(self, inode): _logger.debug("arv-mount opendir: inode %i", inode) if inode in self.inodes: p = self.inodes[inode] else: raise llfuse.FUSEError(errno.ENOENT) if not isinstance(p, Directory): raise llfuse.FUSEError(errno.ENOTDIR) fh = self._filehandles_counter self._filehandles_counter += 1 if p.parent_inode in self.inodes: parent = self.inodes[p.parent_inode] else: raise llfuse.FUSEError(errno.EIO) # update atime p._atime = time.time() self._filehandles[fh] = FileHandle(fh, [('.', p), ('..', parent)] + list(p.items())) return fh
def _replace(self, inode_p_old, name_old, inode_p_new, name_new, entry_old, entry_new): if self.get_row("SELECT COUNT(inode) FROM contents WHERE parent_inode=?", (entry_new.st_ino))[0] > 0: raise llfuse.FUSEError(errno.ENOTEMPTY) self.cursor.execute("UPDATE contents SET inode=? WHERE name=? AND parent_inode=?", (entry_old.st_ino, name_new, inode_p_new)) self.db.execute('DELETE FROM contents WHERE name=? AND parent_inode=?', (name_old, inode_p_old)) if entry_new.st_nlink == 1 and entry_new.st_ino not in self.inode_open_count: self.cursor.execute("DELETE FROM inodes WHERE id=?", (entry_new.st_ino,))
def _yarp_parse_data_type(self, cell_relative_offset): if not self._yarp_is_value(cell_relative_offset): raise llfuse.FUSEError(errno.EBADF) buf = self._yarp_get_cell(cell_relative_offset) key_value = RegistryRecords.KeyValue(buf) data_type = key_value.get_data_type() if data_type in Registry.ValueTypes.keys(): data_type_str = Registry.ValueTypes[data_type] else: data_type_str = hex(data_type) return data_type_str.encode(self._yarp_encoding)
def _replace(self, id_p_old, name_old, id_p_new, name_new, id_old, id_new): now_ns = time_ns() if self.db.has_val("SELECT 1 FROM contents WHERE parent_inode=?", (id_new, )): log.info("Attempted to overwrite entry with children: %s", get_path(id_p_new, self.db, name_new)) raise llfuse.FUSEError(errno.EINVAL) # Replace target name_id_new = self.db.get_val('SELECT id FROM names WHERE name=?', (name_new, )) self.db.execute( "UPDATE contents SET inode=? WHERE name_id=? AND parent_inode=?", (id_old, name_id_new, id_p_new)) # Delete old name name_id_old = self._del_name(name_old) self.db.execute( 'DELETE FROM contents WHERE name_id=? AND parent_inode=?', (name_id_old, id_p_old)) inode_new = self.inodes[id_new] inode_new.refcount -= 1 inode_new.ctime_ns = now_ns inode_p_old = self.inodes[id_p_old] inode_p_old.ctime_ns = now_ns inode_p_old.mtime_ns = now_ns inode_p_new = self.inodes[id_p_new] inode_p_new.ctime_ns = now_ns inode_p_new.mtime_ns = now_ns if inode_new.refcount == 0 and id_new not in self.open_inodes: self.cache.remove( id_new, 0, int(math.ceil(inode_new.size / self.max_obj_size))) # Since the inode is not open, it's not possible that new blocks # get created at this point and we can safely delete the inode self.db.execute( 'UPDATE names SET refcount = refcount - 1 WHERE ' 'id IN (SELECT name_id FROM ext_attributes WHERE inode=?)', (id_new, )) self.db.execute('DELETE FROM names WHERE refcount=0') self.db.execute('DELETE FROM ext_attributes WHERE inode=?', (id_new, )) self.db.execute('DELETE FROM symlink_targets WHERE inode=?', (id_new, )) del self.inodes[id_new]
def test_copy(): for obj in (llfuse.SetattrFields(), llfuse.RequestContext(), llfuse.lock, llfuse.lock_released): pytest.raises(PicklingError, copy, obj) for (inst, attr) in ((llfuse.EntryAttributes(), 'st_mode'), (llfuse.StatvfsData(), 'f_files')): setattr(inst, attr, 42) inst_copy = copy(inst) assert getattr(inst, attr) == getattr(inst_copy, attr) inst = llfuse.FUSEError(10) assert inst.errno == copy(inst).errno