def utime(self, path, times): ''' Set the times (atime, mtime, and ctime) of a file. Returns: True upon successful modification, otherwise an errno code is returned. ''' self._debug('opcode: utime | path: %s' % (path)) context = self.GetContext() file_stat = tsumufs.getManager(path).statFile(path) self._debug('context: %s' % repr(context)) self._debug('file: uid=%d, gid=%d, mode=%o' % (file_stat.st_uid, file_stat.st_gid, file_stat.st_mode)) # Use 0 values as a workaroud to simulate a change on the fs # without updating any document revision. if times == (0, 0): return 0 try: if tsumufs.getManager(path).utime(path, times): tsumufs.syncLog.addMetadataChange(path, times=True) return 0 except OSError, e: self._debug('utime: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def access(self, path, mode): ''' Test for access to a path. Returns: True upon successful check, otherwise an errno code is returned. ''' self._debug('opcode: access | path: %s | mode: %o' % (path, mode)) context = self.GetContext() self._debug('uid: %s, gid: %s, pid: %s' % (repr(context['uid']), repr(context['gid']), repr(context['pid']))) try: tsumufs.getManager(path).access(context['uid'], path, mode) return 0 except OSError, e: self._debug('access: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def mkdir(self, path, mode): ''' Creates a new directory with the specified mode. Returns: 0 on successful creation, othewrise a negative errno code is returned. ''' self._debug('opcode: mkdir | path: %s | mode: %o' % (path, mode)) context = self.GetContext() parent = os.path.dirname(path) tsumufs.getManager(parent).access(context['uid'], parent, os.W_OK|os.X_OK) try: if tsumufs.getManager(path).makeDir(path, mode &~ tsumufs.defaultModeMask, context['uid'], context['gid']): tsumufs.syncLog.addNew('dir', filename=path) return 0 except OSError, e: self._debug('mkdir: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def unlink(self, path): ''' Callback to unlink a file on disk. Returns: True on successful unlink, or an errno code on error. ''' self._debug('opcode: unlink | path: %s' % path) try: context = self.GetContext() tsumufs.getManager(os.path.dirname(path)).access(context['uid'], os.path.dirname(path), os.W_OK) if tsumufs.getManager(path).removeCachedFile(path, removeperm=True): tsumufs.syncLog.addUnlink(path, 'file') return 0 except OSError, e: self._debug('unlink: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def chown(self, path, newuid, newgid): ''' Change the owner and/or group of a file. Returns: True on successful change, otherwise errno code is returned. ''' self._debug('opcode: chown | path: %s | uid: %d | gid: %d' % (path, newuid, newgid)) context = self.GetContext() file_stat = tsumufs.getManager(path).statFile(path) if context['uid'] != 0: if newuid != -1 and context['uid'] != newuid: raise OSError(errno.EPERM, os.strerror(errno.EPERM)) if (file_stat.st_uid != context['uid']) and (newgid != -1): if newgid not in tsumufs.getGidsForUid(context['uid']): raise OSError(errno.EPERM, os.strerror(errno.EPERM)) try: if tsumufs.getManager(path).chown(path, newuid, newgid): tsumufs.syncLog.addMetadataChange(path, uid=True, gid=True) return 0 except OSError, e: self._debug('chown: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def getxattr(self, path, name, size): ''' Callback that is called to get a specific extended attribute size or value by name. Returns: The size of the value (including the null terminator) if size is set to 0. The string the extended attribute contains if size > 0 -EOPNOTSUPP if the name is invalid. ''' self._debug('opcode: getxattr | path: %s | name: %s | size: %d' % (path, name, size)) name = name.lower() try: if name.startswith("security."): return -errno.ENODATA xattr = tsumufs.getManager(path).getxattr(path, name) if size == 0: # Caller just wants the size of the value. return len(xattr) else: return xattr except OSError, e: self._debug('getxattr: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def getattr(self, path): ''' Callback which is called into when a stat() is performed on the user side of things. Returns: A stat result object, the same as an os.lstat() call. Raises: None ''' self._debug('opcode: getattr (%d) | self: %s | path: %s' % (self.GetContext()['pid'], repr(self), path)) try: result = tsumufs.getManager(path).statFile(path) self._debug('Returning (%d, %d, %o)' % (result.st_uid, result.st_gid, result.st_mode)) return result except OSError, e: self._debug('getattr: Caught OSError: %d: %s' % (e.errno, e.strerror)) return -e.errno
def removexattr(self, path, name): ''' Callback that is called into when a setxattr() call is performed. This removes an extended attribute, if that attribute is non-readonly. If the attribute isn't a valid name, or is read-only, this method returns -errno.EOPNOTSUPP. Returns: None, or -EOPNOTSUPP on error. ''' self._debug('opcode: removexattr | path: %s | name: %s' % (path, name)) mode = tsumufs.getManager(path).statFile(path).st_mode if path == '/': type_ = 'root' elif stat.S_ISDIR(mode): type_ = 'dir' else: type_ = 'file' try: return tsumufs.ExtendedAttributes.removeXAttr(type_, path, name) except KeyError, e: self._debug('Request for extended attribute that is not present in the ' 'dictionary: <%s, %s, %s>' % (repr(type_), repr(path), repr(name)))
def rename(self, old, new): ''' Renames a file from old to new, possibly changing it's path as well as its filename. Returns: True on successful rename, or errno code on error. ''' self._debug('opcode: rename | old: %s | new: %s' % (old, new)) try: context = self.GetContext() # According to the rename(2) man page, EACCES is raised when: # # Write permission is denied for the directory containing oldpath or # newpath, or, search permission is denied for one of the directories in # the path prefix of oldpath or newpath, or oldpath is a directory and # does not allow write permission (needed to update the .. entry). # # Otherwise the rename is allowed. It doesn't care about permissions on # the file itself. # So, do this: # 1. Stat old. If dir and not W_OK, EACCES # 2. Verify X_OK | W_OK on dirname(old) and dirname(new) old_stat = tsumufs.getManager(old).statFile(old) if stat.S_ISDIR(old_stat.st_mode): tsumufs.getManager(old).access(context['uid'], old, os.W_OK) tsumufs.getManager(os.path.dirname(old)).access(context['uid'], os.path.dirname(old), os.X_OK | os.W_OK) tsumufs.getManager(os.path.dirname(new)).access(context['uid'], os.path.dirname(new), os.X_OK | os.W_OK) # Restore the real file path if old has been acceded via # a view virtual folder. if tsumufs.viewsManager.isAnyViewPath(old): old = tsumufs.viewsManager.realFilePath(old) if tsumufs.getManager(new).rename(old, new): tsumufs.syncLog.addRename(old, new) return 0 except OSError, e: self._debug('rename: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def rmdir(self, path): ''' Removes a directory from disk. Returns: True on successful unlink, or errno code on error. ''' self._debug('opcode: rmdir | path: %s' % path) try: context = self.GetContext() tsumufs.getManager(path).access(context['uid'], path, os.W_OK) if tsumufs.getManager(path).removeCachedFile(path, removeperm=True): tsumufs.syncLog.addUnlink(path, 'dir') return 0 except OSError, e: self._debug('rmdir: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def mknod(self, path, mode, dev): ''' Creates a special device file with the specified mode and device number. Returns: True on successful creation, otherwise an errno code is returned. ''' self._debug('opcode: mknod | path: %s | mode: %d | dev: %s' % (path, mode, dev)) context = self.GetContext() if mode & (stat.S_IFCHR | stat.S_IFBLK): if context['uid'] != 0: raise OSError(errno.EPERM) parent = os.path.dirname(path) tsumufs.getManager(parent).access(context['uid'], parent, os.W_OK|os.X_OK) try: if tsumufs.getManager(path).makeNode(path, mode &~ tsumufs.defaultModeMask, dev): if mode & stat.S_IFREG: tsumufs.syncLog.addNew('file', filename=path) elif mode & stat.S_IFCHR: tsumufs.syncLog.addNew('dev', filename=path, dev_type='char') elif mode & stat.S_IFBLK: tsumufs.syncLog.addNew('dev', filename=path, dev_type='block') elif mode & stat.S_IFIFO: tsumufs.syncLog.addNew('fifo', filename=path) return 0 except OSError, e: self._debug('mknod: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def symlink(self, src, dest): ''' Creates a symlink pointing to src as a file called dest. Returns: True on successful link creation, or errno code on error. ''' self._debug('opcode: symlink | src: %s | dest: %s' % (src, dest)) try: context = self.GetContext() parent = os.path.dirname(dest) tsumufs.getManager(parent).access(context['uid'], parent, os.W_OK | os.X_OK) if tsumufs.getManager(dest).makeSymlink(src, dest, context['uid'], context['gid']): tsumufs.syncLog.addNew('symlink', filename=dest) return 0 except OSError, e: self._debug('symlink: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def readlink(self, path): ''' Reads the value of a symlink. Returns: The string representation of the file the symlink points to, or a negative errno code on error. ''' self._debug('opcode: readlink | path: %s' % path) try: context = self.GetContext() tsumufs.getManager(path).access(context['uid'], path, os.R_OK) retval = tsumufs.getManager(path).readLink(path) self._debug('Returning: %s' % retval) return retval except OSError, e: self._debug('readlink: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def opendir(self, path): ''' Test for access to a directory path. Returns: True upon successful check, otherwise an errno code is returned. ''' self._debug('opcode: opendir | path: %s' % path) context = self.GetContext() self._debug('uid: %s, gid: %s, pid: %s' % (repr(context['uid']), repr(context['gid']), repr(context['pid']))) try: tsumufs.getManager(path).access(context['uid'], path, os.R_OK | os.X_OK) return 0 except OSError, e: self._debug('opendir: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def chmod(self, path, mode): ''' Changes the mode of a file. Returns: True on successful mode change, or errno code on error. ''' self._debug('opcode: chmod | path: %s | mode: %o' % (path, mode)) context = self.GetContext() file_stat = tsumufs.getManager(path).statFile(path) self._debug('context: %s' % repr(context)) self._debug('file: uid=%d, gid=%d, mode=%o' % (file_stat.st_uid, file_stat.st_gid, file_stat.st_mode)) if ((file_stat.st_uid != context['uid']) and (context['uid'] != 0)): self._debug('chmod: user not owner, and user not root -- EPERM') return -errno.EPERM tsumufs.getManager(path).access(context['uid'], os.path.dirname(path), os.F_OK) try: self._debug('chmod: access granted -- chmoding') if tsumufs.getManager(path).chmod(path, mode &~ tsumufs.defaultModeMask): tsumufs.syncLog.addMetadataChange(path, mode=True) return 0 except OSError, e: self._debug('chmod: Caught OSError: errno %d: %s' % (e.errno, e.strerror)) return -e.errno
def listxattr(self, path, size): ''' Callback method to list the names of valid extended attributes in a file. Returns: The number of variables available if size is 0. A list of key names if size > 0. ''' self._debug('opcode: listxattr | path: %s | size: %d' % (path, size)) keys = tsumufs.getManager(path).listxattr(path) if size == 0: return len(''.join(keys)) + len(keys) return keys
def readdir(self, path, offset): ''' Generator callback that returns a fuse.Direntry object every time it is called. Similar to the C readdir() call. Returns: A generator that yields a fuse.Direntry object, or an errno code on error. ''' self._debug('opcode: readdir | path: %s | offset: %d' % (path, offset)) try: for filename in [ '.', '..' ]: dirent = fuse.Direntry(filename) dirent.type = stat.S_IFDIR dirent.offset = offset yield dirent dociterators = [ tsumufs.getManager(path).getDirents(path) ] if path == tsumufs.viewsPoint: # Append the root directories of views dociterators.append(tsumufs.viewsManager.getRootDirs()) for dociterator in dociterators: for doc in dociterator: dirent = fuse.Direntry(str(doc.filename)) dirent.type = stat.S_IFMT(doc.mode) dirent.offset = offset yield dirent except OSError, e: self._debug('readdir: Caught OSError on %s: errno %d: %s' % (filename, e.errno, e.strerror)) yield -e.errno
elif stat.S_ISDIR(mode): type_ = 'dir' else: type_ = 'file' try: return tsumufs.ExtendedAttributes.setXAttr(type_, path, name, value) except KeyError, e: self._debug('Request for extended attribute that is not present in the ' 'dictionary: <%s, %s, %s>' % (repr(type_), repr(path), repr(name))) try: context = self.GetContext() tsumufs.getManager(path).access(context['uid'], path, os.W_OK) if tsumufs.getManager(path).setxattr(path, name, value): tsumufs.syncLog.addMetadataChange(path, xattrs=[name], acls=(name == "system.posix_acl_access")) return 0 except Exception, e: return -errno.EOPNOTSUPP @benchmark def removexattr(self, path, name): ''' Callback that is called into when a setxattr() call is performed. This removes an extended attribute, if that attribute is non-readonly. If the attribute isn't a valid name, or
def __new__(cls, path, *args, **kwargs): kwargs.update(self.GetContext()) klass = tsumufs.getManager(path).getFileClass(path) or tsumufs.FuseFile return klass(path, *args, **kwargs)