def truncate(self, path, length, fh=None): logging.debug("truncate: %s", repr((path, length, fh))) f = None if fh == None: #print (" closed file") src_path = self.getSource(path) if not os.path.exists(src_path): raise fuse.FuseOSError(errno.ENOENT) if os.path.isdir(src_path): raise fuse.FuseOSError(errno.EISDIR) f = File(src_path, False) else: #print (" file handle ", fh) if fh not in self.file_handles: raise fuse.FuseOSError(errno.ENOENT) f = self.file[fh] if f.is_dir: raise fuse.FuseOSError(errno.EISDIR) self.copyOnWrite(f) #print ("truncate file ", repr (f.src_path)) os.truncate(f.src_path, length)
def Read(self, path, length=None, offset=0, fh=None): """Reads data from a file. Args: path: The path to the file to read. length: How many bytes to read. offset: Offset in bytes from which reading should start. fh: A file handler. Not used. Returns: A string containing the file contents requested. Raises: FuseOSError: If we try and read a directory or if we try and read an object that doesn't support reading. """ if self._IsDir(path): raise fuse.FuseOSError(errno.EISDIR) fd = aff4.FACTORY.Open(self.root.Add(path), token=self.token) # If the object has Read() and Seek() methods, let's use them. if all((hasattr(fd, "Read"), hasattr(fd, "Seek"), callable(fd.Read), callable(fd.Seek))): # By default, read the whole file. if length is None: length = fd.Get(fd.Schema.SIZE) fd.Seek(offset) return fd.Read(length) else: # If we don't have Read/Seek methods, we probably can't read this object. raise fuse.FuseOSError(errno.EIO)
def readdir(self, path, fh): self.logger.info('readdir %s', path) try: cache_entry = self.cache.get_entry(path) except FileNotFoundError as e: self.logger.error('file not found error: %s', path) raise fuse.FuseOSError(errno.ENOENT) if cache_entry.metadata['is_dir'] is False: self.logger.error('%s not a directory', path) raise fuse.FuseOSError(errno.ENOTDIR) files = ['.', '..'] if not 'contents' in cache_entry.metadata: # cache entry might not be full, fetching info self.logger.info('setting metadata cache dirty: %s', cache_entry.path) cache_entry.dirty = True for content in cache_entry.metadata['contents']: basename = os.path.basename(content['path']) files.append(basename) return files
def open(self, path, flags): # Only support 'READ ONLY' flag access_flags = os.O_RDONLY | os.O_WRONLY | os.O_RDWR fh = 0 if flags & access_flags != os.O_RDONLY: raise fuse.FuseOSError(errno.EACCES) else: cur_path, hide_raw = self.get_path(path) if len(cur_path) == 6: uid, gid, pid = fuse.fuse_get_context() username = self.get_username(uid) files = get_datasets(username, cur_path[1], cur_path[2], cur_path[3], cur_path[4], self.datapath, hide_raw) fname = next((f[1] for f in files if f[0] == cur_path[5]), None) if fname: self.gzfile = None fh = os.open(fname, flags) elif cur_path[5].endswith('ugz'): # Check to see if we're being asked about a gzipped file fn = cur_path[5][:-3] + 'gz' fname = next((f[1] for f in files if f[0] == fn), None) if fname: self.gzfile = gzip.open(fname, 'r') fh = self.gzfile.fileno() else: raise fuse.FuseOSError(errno.ENOENT) else: raise fuse.FuseOSError(errno.ENOENT) elif len(cur_path) == 2 and cur_path[1] == 'README.txt': fh = os.open(self.readme_fname, flags) return fh
def open(self, path, flags): flags = 32768 - flags self.logger.info('open %s %d', path, flags) if flags == os.O_RDWR: self.logger.info('invalid flags: O_RDWR') raise fuse.FuseOSError(errno.EINVAL) if flags == os.O_WRONLY: # if it O_WRONLY, let self.create do its thing self.logger.info('valid flags: O_WRONLY') return self.create(path, 0444) elif flags != os.O_RDONLY: # if there is no O_WRONLY / O_RD_ONLY self.logger.error('invalid flags: not O_RDONLY or O_WRONLY') raise fuse.FuseOSError(errno.EINVAL) # in case of O_RDONLY self.logger.info('valid flags: O_RDONLY') try: cache_entry = self.cache.get_entry(path, self.client) except FileNotFoundError as e: self.logger.error('file not found error: %s', path) raise fuse.FuseOSError(errno.ENOENT) try: fd = self.download_manager.open_file(path) self.cache.set_entry(path, cache_entry) return fd except Exception as e: self.logger.error('WTFF: %s', str(e)) raise fuse.FuseOSError(errno.EACCES)
def chmod(self, path, mode): try: self.box.root[path] = (mode, self.box.root[path].item) except NotDirectory: raise fuse.FuseOSError(errno.ENOTDIR) except NoChild: raise fuse.FuseOSError(errno.ENOENT)
def _getPath(self, path): """ Given a fuse path, return the associated resource. :param path: path within the fuse. :returns: a Girder resource dictionary. """ # If asked about a file in top level directory or the top directory, # return that it doesn't exist. Other methods should handle '', # '/user', and 'collection' before calling this method. if '/' not in path.rstrip('/')[1:]: raise fuse.FuseOSError(errno.ENOENT) try: # We can't filter the resource, since that removes files' # assetstore information and users' size information. resource = path_util.lookUpPath(path.rstrip('/'), filter=False, force=True) except (path_util.NotFoundException, AccessException): raise fuse.FuseOSError(errno.ENOENT) except ValidationException: raise fuse.FuseOSError(errno.EROFS) except Exception: logger.exception('ServerFuse server internal error') raise fuse.FuseOSError(errno.EROFS) return resource # {model, document}
def getattr(self, path, fh=None): uid, gid, pid = fuse.fuse_get_context() if fh: fs = os.fstat(fh) at = fs.st_atime ct = fs.st_ctime mt = fs.st_mtime sz = fs.st_size mode = stat.S_IFREG | 0444 nlink = 1 # TODO: get the uncompressed size for gzip files. else: fn = path.split('/')[-1] is_dir = '%' in fn or not bool(os.path.splitext(fn)[1]) at = ct = mt = int(time.time()) if is_dir: sz = 0 mode = stat.S_IFDIR | 0555 nlink = 2 else: mode = stat.S_IFREG | 0444 nlink = 1 username = self.get_username(uid) cur_path, hide_raw = self.get_path(path) sz = 1 if len(cur_path) == 6: files = get_datasets(username, cur_path[1], cur_path[2], cur_path[3], cur_path[4], self.datapath, hide_raw) fname = next((f[1] for f in files if f[0] == cur_path[5]), None) if fname: sz = os.path.getsize(fname) ts = os.path.getmtime(fname) elif cur_path[5].endswith('ugz'): # Check to see if we're being asked about a gzipped file fn = cur_path[5][:-3] + 'gz' fname = next((f[1] for f in files if f[0] == fn), None) if fname: ts = os.path.getmtime(fname) # Apparently there's no way to get the uncompressed size except by reading the last four bytes. # TODO: consider saving this (as well as the timestamp) in the db. with open(fname, 'r') as fp: fp.seek(-4, 2) sz = struct.unpack('<I', fp.read())[0] else: raise fuse.FuseOSError(errno.ENOENT) else: raise fuse.FuseOSError(errno.ENOENT) return { 'st_atime': at, 'st_ctime': ct, 'st_gid': gid, 'st_mode': mode, 'st_mtime': mt, 'st_nlink': nlink, 'st_size': sz, 'st_uid': uid }
def read(self, path, size, offset, fh): f = self.traverse(path) if f is None: raise fuse.FuseOSError(errno.ENOENT) if f.dir(): raise fuse.FuseOSError(errno.EISDIR) return f.read(size, offset)
def opendir(self, path): try: entry = self._get_child(path) except FetchError: raise fuse.FuseOSError(errno.EIO) if not isinstance(entry.item, Directory): raise fuse.FuseOSError(errno.ENOTDIR) return self.to_fd(*entry)
def rename(self, old, new): try: self.box.root[new] = self.box.root[old] del self.box.root[old] except NotDirectory: raise fuse.FuseOSError(errno.ENOTDIR) except NoChild: raise fuse.FuseOSError(errno.ENOENT)
def readdir(self, path, fh): f = self.traverse(path) if f is None: raise fuse.FuseOSError(errno.EOENT) if not f.dir(): raise fuse.FuseOSError(errno.ENOTDIR) return f.readdir()
def access(self, path, amode): if amode & os.W_OK: raise fuse.FuseOSError(EACCES) obj = self._getpath(path) if not obj.exist: raise fuse.FuseOSError(ENOENT) elif (obj.stat.st_mode & amode) != amode: raise fuse.FuseOSError(EACCES) return 0
def _create(self, path, mode, obj): try: self.box.root[path] = (mode, obj) except NoChild: raise fuse.FuseOSError(errno.ENOENT) except NotDirectory: raise fuse.FuseOSError(errno.ENOTDIR) return self.to_fd(mode, obj)
def unlink(self, path): path = Path(path) (directory_mode, directory) = self._get_child(path[:-1]) if not isinstance(directory, Directory): raise fuse.FuseOSError(errno.ENOTDIR) try: del directory[path[-1]] except NoChild: raise fuse.FuseOSError(errno.ENOENT)
def open(self, path, flags): try: entry = self._get_child(path, File) except FetchError: raise fuse.FuseOSError(errno.EIO) if not self.box.is_writable and flags & (os.O_WRONLY | os.O_RDWR): raise fuse.FuseOSError(errno.EROFS) return self.to_fd(*entry)
def getattr(self, path, fh=None): logger.debug("getattr path={}".format(path)) try: entry = self._getPath(path) if entry: return entry.getAttr() except Exception as e: logger.exception("Error in getattr(%s)", path) raise fuse.FuseOSError(EHOSTUNREACH) raise fuse.FuseOSError(ENOENT)
def access(self, path, amode): logging.debug("access: %s", repr((path, amode))) src_path = self.getSource(path) if not os.path.lexists(src_path): raise fuse.FuseOSError(errno.ENOENT) if os.access(src_path, amode, follow_symlinks=False): return 0 raise fuse.FuseOSError(errno.EACCES)
def mkdir(self, path, mode): if path == '/': raise fuse.FuseOSError(errno.EEXIST) _, *path = path.split('/') if len(path) != 1: raise fuse.FuseOSError(errno.EACCES) with self._db.cursor() as c: if not c.tags.new(path[0]): raise fuse.FuseOSError(errno.EEXIST)
def access(self, path, amode): try: (mode, child) = self._get_child(path) except FetchError as e: mode = e.mode if amode & posix.W_OK and not self.box.is_writable: raise fuse.FuseOSError(errno.EACCES) if amode & posix.X_OK: if not mode & stat.S_IXUSR and not mode & stat.S_IFDIR: raise fuse.FuseOSError(errno.EACCES)
def symlink(self, target, source): target = Path(target) try: (target_directory_mode, target_directory) = self._get_child(target[:-1]) except FetchError: raise fuse.FuseOSError(errno.EIO) if not isinstance(target_directory, Directory): raise fuse.FuseOSError(errno.ENOTDIR) target_directory[target[-1]] = (stat.S_IFLNK, Symlink(self.box.storage, target=source))
def _get_child(self, path, cls=None): """Get the mode and child of path. Also check that child is instance of cls.""" try: entry = self.box.root[path] except NotDirectory: raise fuse.FuseOSError(errno.ENOTDIR) except NoChild: raise fuse.FuseOSError(errno.ENOENT) if cls is not None and not isinstance(entry.item, cls): raise fuse.FuseOSError(errno.EINVAL) return entry
def unlink(self, path): logging.debug("unlink: %s", repr(path)) src_path = self.getSource(path) if not os.path.lexists(src_path): raise fuse.FuseOSError(errno.ENOENT) if not os.path.islink(src_path) and os.path.isdir(src_path): raise fuse.FuseOSError(errno.EISDIR) f = File(src_path, False) self.copyOnWrite(f, use_rename=True)
def as_node(node: Node_Like) -> 'core.Node': if node is None: raise fuse.FuseOSError(errno.ENOENT) elif isinstance(node, core.Node): return node elif isinstance(node, bytes) or isinstance(node, str): return nodetypes.BlobFile(as_bytes(node)) elif isinstance(node, dict): return nodetypes.DictDir(node) elif util.is_iterable(node) or util.is_async_iterable(node): return nodetypes.GeneratorFile(node) raise fuse.FuseOSError(errno.EIO)
def flush(self, path, fh): logging.debug("flush: %s", repr((path, fh))) if fh not in self.file_handles: raise fuse.FuseOSError(errno.ENOENT) f = self.file_handles[fh] if f.file == None: raise fuse.FuseOSError(errno.ENOENT) f.file.flush() return 0
def getattr_related(self, path, subpath): gallery_ID, rest = split_path(subpath) if type(try_convert(gallery_ID)) is not int: raise fuse.FuseOSError(errno.ENOENT) ctx = {'path': path, 'ctime': now()} galleries = self.fetch_json(RELATED_URL.format(gallery_ID), self.json_to_galleries, ctx) self.fs['related'][int(gallery_ID)] = galleries try: dig(galleries, rest) except (KeyError, AttributeError, TypeError): raise fuse.FuseOSError(errno.ENOENT) return self.attrs[path]
def symlink(self, path0, source): if path0 == '/': raise fuse.FuseOSError(errno.EEXIST) _, *path = path0.split('/') if len(path) == 1: with self._db.cursor() as c: if c.tags.exists(path[0]): raise fuse.FuseOSError(errno.EEXIST) if source.startswith('sel:'): source = compile_selection(source) if len(path) != 1: raise fuse.FuseOSError(errno.EACCES) with self._db.cursor() as c: if not c.selections.new(path[0], source): raise fuse.FuseOSError(errno.EEXIST) else: if len(path) == 1: raise fuse.FuseOSError(errno.EACCES) if len(path) != 2: raise fuse.FuseOSError(errno.ENOENT) source = os.path.normpath(os.path.join(path0, source)) with self._db.cursor() as c: if not c.files.new(path[1], source): raise fuse.FuseOSError(errno.EEXIST) if path[0] != '__ALL__' and not c.files.add_tag(path[1], path[0]): raise fuse.FuseOSError(errno.EBUSY)
def rmdir(self, path): if path == '/': raise fuse.FuseOSError(errno.EINVAL) _, *path = path.split('/') if len(path) != 1: raise fuse.FuseOSError(errno.ENOTDIR) if path[0] == '__ALL__': raise fuse.FuseOSError(errno.EACCES) with self._db.cursor() as c: if not c.tags.remove(path[0]): raise fuse.FuseOSError(errno.ENOENT)
def read(self): req = SESSION.get(self.url, timeout=CONFIG['timeout']) try: req.raise_for_status() except requests.exceptions.HTTPError: self.stat.setmode(0o000, True) self.init = 2 self._readable = False if req.status_code == 403: raise fuse.FuseOSError(EACCES) elif req.status_code == 404: self.exist = False raise fuse.FuseOSError(ENOENT) else: raise fuse.FuseOSError(EIO) lm = req.headers.get('Last-Modified') if lm: self.stat.settime(time.mktime(parsedate(lm))) else: self.stat.settime(time.time()) try: cwd, listing = parse_dir(req.content) except Exception: logging.exception('failed to parse listing: ' + self.url) listing = [] content = ['.', '..'] objmap = {} for name, modified, size, description in listing: fpath = os.path.join(self.path, name) if name[-1] == '/': fileobj = Directory(self.baseurl, fpath) fpath = fpath.rstrip('/') else: fileobj = File(self.baseurl, fpath) if size is None: fileobj.get_stat() else: fileobj.stat.st_size = size if modified: fileobj.stat.settime(calendar.timegm(modified)) else: fileobj.stat.settime(self.stat.st_mtime) fileobj.init = fileobj.init or 1 content.append(name.rstrip('/')) objmap[fpath] = fileobj self.content = content self.stat.st_nlink = len(content) self.init = 2 self._readable = True return objmap
def unlink(self, path): if path == '/': raise fuse.FuseOSError(errno.EISDIR) _, *path = path.split('/') if len(path) == 1: raise fuse.FuseOSError(errno.EISDIR) if len(path) != 2: raise fuse.FuseOSError(errno.ENOENT) with self._db.cursor() as c: if not (c.files.remove(path[1]) if path[0] == '__ALL__' else c.files.remove_tag(path[1], path[0])): raise fuse.FuseOSError(errno.ENOENT)