def readdir(self, path, offset): path_components = Tree._path_dissect(path) try: t = Tree._find_path(self.tree.inodes, path_components) except (TypeError, KeyError): raise OSError(2, 'No such file or directory', path) for k in t: yield fuse.Direntry(k)
def fsync(self, isfsyncfile): self._fflush() if isfsyncfile and hasattr(os, 'fdatasync'): os.fdatasync(self.fd) else: os.fsync(self.fd) block_list = splitFile(CACHE_DIR + self.path) # get list of blocks pos = self.file.tell() self.file.seek(0, 2) self.finode.size = self.file.tell() self.file.seek(pos, 0) # return back to the current pos # the file already exists if len(self.log_changes) > 0: # (@WARNING: do not know how to deal with intersections) x, y = self.log_changes.pop() tmp = Set(range(x, y + 1)) upd = len(self.log_changes) # start uploading from the end block_order = [] self.update_pending = [ ] # list to store blocks that need update for i in range(0, upd): x, y = self.log_changes.pop() t = Set(range(x, y + 1)) tmp = tmp | (t.difference(tmp) ) # expand the set with t - tmp for i in tmp: block_order.append( i) # set --> list to perform order operation block_order.sort() # sort block order for i in block_order: if i < len(block_list): self.update_pending.append( block_list[i] ) # fill updated blocks to the array for uploading new_block_id_list = upload_to_vk( self.update_pending) # upload updated blocks to the vk for i in block_order: if i < len( block_list ): # if once block had been updated before this part of file was cut -> do not upload self.finode.blocks[1][i] = new_block_id_list[i] # the file has just been created with zero bytes length else: new_block_id_list = upload_to_vk(block_list) self.finode.blocks[1] = new_block_id_list path_components = Tree._path_dissect(self.path) Tree._find_path( self.tree.inodes, path_components[:-1])[path_components[-1]] = self.finode
def rmdir(self, path): path_components = Tree._path_dissect(path) sub = self.tree.inodes for i in path_components[:-1]: sub = sub[i] del sub[path_components[-1]] try: shutil.rmtree(CACHE_DIR + path) except OSError: pass
def rename(self, path, path1): path_components = Tree._path_dissect(path) new_name = path1.strip('/').split('/')[-1] sub = self.tree.inodes for i in path_components[:-1]: sub = sub[i] old = sub.pop(path_components[-1]) self.tree._find_path(self.tree.inodes, path_components[:-1])[new_name] = old os.rename(CACHE_DIR + path, CACHE_DIR + path1) cache.set(old.id, (old.size, path1))
def flush(self): self._fflush() # cf. xmp_flush() in fusexmp_fh.c # block_list = splitFile(CACHE_DIR + self.path) # get list of blocks # change inode size pos = self.file.tell() self.file.seek(0, 2) self.finode.size = self.file.tell() self.file.seek(pos, 0) # return back to the current pos path_components = Tree._path_dissect(self.path) Tree._find_path( self.tree.inodes, path_components[:-1])[path_components[-1]] = self.finode # # the file already exists # if len(self.log_changes) > 0: # # (@WARNING: do not know how to deal with intersections) # x, y = self.log_changes.pop() # tmp = Set(range(x, y + 1)) # upd = len(self.log_changes) # start uploading from the end # block_order = [] # self.update_pending = [] # list to store blocks that need update # for i in range(0, upd): # x, y = self.log_changes.pop() # t = Set(range(x, y + 1)) # tmp = tmp | (t.difference(tmp)) # expand the set with t - tmp # for i in tmp: # block_order.append(i) # set --> list to perform order operation # block_order.sort() # sort block order # for i in block_order: # if i < len(block_list): # self.update_pending.append(block_list[i]) # fill updated blocks to the array for uploading # new_block_id_list = upload_to_vk(self.update_pending) # upload updated blocks to the vk # for i in block_order: # if i < len(block_list): # if once block had been updated before this part of file was cut -> do not upload # self.finode.blocks[1][i] = new_block_id_list[i] # # the file has just been created with zero bytes length # else: # new_block_id_list = upload_to_vk(block_list) # self.finode.blocks[1] = new_block_id_list os.close(os.dup(self.fd))
def truncate(self, path, len): path_components = Tree._path_dissect(path) try: t = Tree._find_path(self.tree.inodes, path_components) except (TypeError, KeyError): raise OSError(2, 'No such file or directory', path) if isinstance(t, Inode): if 0 < len <= t.size: # Assuming that tree branch mirrors in cache dir f = open(CACHE_DIR + path, "a") f.truncate(len) f.close() # clear respective blocks in Inode t.size = len blocks = t.size / BLOCK_SIZE if t.size % BLOCK_SIZE != 0: blocks += 1 t.blocks = t.blocks[:blocks]
def __init__(self, path, flags, *mode, **kwargs): """ initialize file for a folder if no file with such name exists, then we have to create one. all files are stored in cache (/var/cache/snfs/...) after fsdestroy all cache should be removed (task pending) """ try: self.tree = kwargs['tree'] except KeyError: pass self.path = path self.mode = mode # remember the state self.log_changes = [] path_components = Tree._path_dissect(self.path) if not os.path.exists(CACHE_DIR + self.path): try: finode = Tree._find_path(self.tree.inodes, path_components) if finode.size > 0: download_from_vk(blocks=finode.blocks[1], size=finode.size, fullpath=self.path) else: open(CACHE_DIR + self.path, 'a').close() self.finode = finode nodes_to_delete = cache.set(self.finode.id, (self.finode.size, self.path)) for p in nodes_to_delete: try: os.remove(CACHE_DIR + p) except OSError: pass except (TypeError, KeyError): if flag2mode(flags) in ['a', 'w+']: finode = Inode(size=0, blocks={1: [], 2: [], 3: []}) Tree._find_path( self.tree.inodes, path_components[:-1])[path_components[-1]] = finode open(CACHE_DIR + self.path, 'a').close() self.finode = finode nodes_to_delete = cache.set( self.finode.id, (self.finode.size, self.path)) for p in nodes_to_delete: try: os.remove(CACHE_DIR + p) except OSError: pass else: raise OSError(2, 'No such file or directory', path) else: self.finode = Tree._find_path(self.tree.inodes, path_components) try: cache.get(self.finode.id) except KeyError: pass self.file = os.fdopen(os.open(CACHE_DIR + path, flags, *mode), flag2mode(flags)) self.fd = self.file.fileno()
def access(self, path, mode): path_components = Tree._path_dissect(path) try: Tree._find_path(self.tree.inodes, path_components) except (TypeError, KeyError): return -EACCES