def is_mounted(path): """checks if path is on a mounted path.""" manager = get_manager() if not manager: return False fsi = manager.get_fsi(path)[0] return (fsi is not None)
def chdir(patch, path): """Change the current working directory to path.""" global CWD ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: if not os.path.exists(ap): raise os.error( "[Errno 2] No such file or directory: '/{p}/'".format(p=path)) elif not os.path.isdir(ap): raise os.error("[Errno 20] Not a directory: '{p}'".format(p=path)) else: CWD = ap _org_chdir(ap) # reset paths for p, fs, readonly in manager.get_mounts(): try: fs.cd("/") except: pass else: try: fsi.cd(relpath) CWD = ap except IsFile: raise os.error("[Errno 20] Not a directory: '{p}'".format(p=path)) except OperationFailure: raise os.error( "[Errno 2] No such file or directory: '/{p}/'".format(p=path))
def remove(patch, path): """ Remove (delete) the file path. If path is a directory, OSError is raised; see rmdir() below to remove a directory. This is identical to the unlink() function documented below. On Windows, attempting to remove a file that is in use causes an exception to be raised; on Unix, the directory entry is removed but the storage allocated to the file is not made available until the original file is no longer in use. """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_remove(relpath) elif readonly: raise IOError("[Errno 1] Operation not permitted: '{p}'".format(p=ap)) else: # FSI.remove() works on both files and dirs, we need to check # this before and raise an Exception if required if os.path.isdir(relpath): raise os.error( "OSError: [Errno 21] Is a directory: '{p}'".format(p=ap)) try: return fsi.remove(relpath) except OperationFailure as e: raise os.error(e.message)
def pre_enable(self): # ensure a manager is set manager = mount_ctrl.get_manager() if manager is None: from stashutils import mount_manager # import here to prevent an error manager = mount_manager.MountManager() mount_ctrl.set_manager(manager)
def list_mounts(): """list all mounts""" manager = mount_ctrl.get_manager() if manager is None: manager = mount_manager.MountManager() mount_ctrl.set_manager(manager) mounts = manager.get_mounts() for p, fsi, readonly in mounts: print("{f} on {p}".format(f=fsi.repr(), p=p))
def chmod(patch, path, mode): """Change the mode of path to the numeric mode.""" ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_chmod(relpath, mode) elif readonly: raise IOError("[Errno 1] Operation not permitted: '{p}'".format(p=ap)) else: # we cant do this pass
def access(patch, path, mode): """ Use the real uid/gid to test for access to path. Note that most operations will use the effective uid/gid, therefore this routine can be used in a suid/sgid environment to test if the invoking user has the specified access to path. mode should be F_OK to test the existence of path, or it can be the inclusive OR of one or more of R_OK, W_OK, and X_OK to test permissions. Return True if access is allowed, False if not. See the Unix man page access(2) for more information. """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_access(relpath, mode) else: try: s = fsi.stat(relpath) except OperationFailure: return False if mode == os.F_OK: return True fa_mode = s.st_mode # & 0777 should_read = mode & os.R_OK should_write = mode & os.W_OK should_exec = mode & os.X_OK acc = True if should_read: acc = acc and any(( _stat.S_IRUSR & fa_mode, _stat.S_IRGRP & fa_mode, _stat.S_IROTH & fa_mode, )) if should_write: acc = acc and any(( _stat.S_IWUSR & fa_mode, _stat.S_IWGRP & fa_mode, _stat.S_IWOTH & fa_mode, )) acc = (acc and (not readonly)) if should_exec: acc = acc and any(( _stat.S_IXUSR & fa_mode, _stat.S_IXGRP & fa_mode, _stat.S_IXOTH & fa_mode, )) return acc
def stat(patch, path): """ Perform the equivalent of a stat() system call on the given path. (This function follows symlinks; to stat a symlink use lstat().) """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_stat(relpath) else: try: return fsi.stat(relpath) except OperationFailure: raise os.error( "[Errno 2] No such file or directory: '{p}'".format(p=ap))
def ismount(patch, path): """ Return True if pathname path is a mount point: a point in a file system where a different file system has been mounted. The function checks whether path's parent, path/.., is on a different device than path, or whether path/.. and path point to the same i-node on the same device - this should detect mount points for all Unix and POSIX variants.""" # ^^^ orginal docstring. we can simply ask the manager :) ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_ismount(ap) else: return True
def lstat(patch, path): """ Perform the equivalent of an lstat() system call on the given path. Similar to stat(), but does not follow symbolic links. On platforms that do not support symbolic links, this is an alias for stat(). """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_lstat(relpath) else: # we dont have 'lstat', fallback to stat() try: return fsi.stat(relpath) except OperationFailure: raise os.error( "[Errno 2] No such file or directory: '{p}'".format(p=ap))
def listdir(patch, path): """ Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. It does not include the special entries '.' and '..' even if they are present in the directory. """ ap = os.path.abspath(os.path.join(os.getcwd(), path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_listdir(ap) else: try: return fsi.listdir(relpath) except OperationFailure: raise os.error( "[Errno 2] No such file or directory: '/{p}'".format(p=ap))
def mkdir(patch, path, mode=0777): """ Create a directory named path with numeric mode mode. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out. If the directory already exists, OSError is raised. """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_mkdir(relpath, mode) elif readonly: raise IOError("[Errno 1] Operation not permitted: '{p}'".format(p=ap)) else: # FSI.mkdir() doesnt have a 'mode' argument, we need to ignore this try: return fsi.mkdir(relpath) except OperationFailure as e: raise os.error(e.message)
def rmdir(patch, path): """ Remove (delete) the directory path. Only works when the directory is empty, otherwise, OSError is raised. In order to remove whole directory trees, shutil.rmtree() can be used. """ ap = os.path.abspath(os.path.join(CWD, path)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(ap) if fsi is None: return _org_rmdir(relpath) elif readonly: raise IOError("[Errno 1] Operation not permitted: '{p}'".format(p=ap)) else: # FSI.remove() works on both files and dirs. if os.path.isfile(relpath): raise os.error("[Errno 20] Not a directory: '{p}'".format(p=ap)) try: return fsi.remove(relpath) except OperationFailure as e: raise os.error(e.message)
def open(patch, name, mode="r", buffering=0): """ Open a file, returning an object of the file type described in section File Objects. If the file cannot be opened, IOError is raised. When opening a file, its preferable to use open() instead of invoking the file constructor directly. """ path = os.path.abspath(os.path.join(os.getcwd(), name)) manager = get_manager() fsi, relpath, readonly = manager.get_fsi(path) if fsi is None: return _org_open(relpath, mode, buffering) elif (("w" in mode) or ("a" in mode) or ("+" in mode)) and readonly: raise IOError( "[Errno 1] Operation not permitted: '{p}'".format(p=path)) else: try: return fsi.open(relpath, mode, buffering) except OperationFailure: raise os.error( "[Errno 2] No such file or directory: '{p}'".format(p=path))
def unmount_fsi(self, path, force=False): """unmounts a fsi.""" path = os.path.abspath(path) if not path in self.path2fs: raise MountError("Nothing mounted there.") fsi, readonly = self.path2fs[path] if not force: try: fsi.close() except OperationFailure as e: raise MountError(e.message) del self.path2fs[path] # todo: close files def get_mounts(self): """ returns a list of (path, fsi, readonly) containing all currently mounted filesystems. """ ret = [] for p in self.path2fs: fs, readonly = self.path2fs[p] ret.append((p, fs, readonly)) return ret # install manager if get_manager() is None: set_manager(MountManager())
"-f", "--force", action="store_true", dest="force", help="force unmount; do not call fsi.close()" ) parser.add_argument( "directory", action="store", nargs="?", default=None, help="directory to remove mounted filesystem from", ) ns = parser.parse_args() if not (ns.directory or ("-a" in sys.argv) or ("--all" in sys.argv)): print(_stash.text_color( "Error: no target directory specified!", "red" )) sys.exit(1) manager = mount_ctrl.get_manager() if manager is None: manager = mount_manager.MountManager() mount_ctrl.set_manager(manager) if ns.all: to_unmount = [m[0] for m in manager.get_mounts()] else: to_unmount = [ns.directory] exitcode = 0 for path in to_unmount: if ns.v: print("Unmounting '{p}'...".format(p=path))
help="force unmount; do not call fsi.close()") parser.add_argument( "directory", action="store", nargs="?", default=None, help="directory to remove mounted filesystem from", ) ns = parser.parse_args() if not (ns.directory or ("-a" in sys.argv) or ("--all" in sys.argv)): print(_stash.text_color("Error: no target directory specified!", "red")) sys.exit(1) manager = mount_ctrl.get_manager() if manager is None: manager = mount_manager.MountManager() mount_ctrl.set_manager(manager) if ns.all: to_unmount = [m[0] for m in manager.get_mounts()] else: to_unmount = [ns.directory] exitcode = 0 for path in to_unmount: if ns.v: print("Unmounting '{p}'...".format(p=path))
self.path2fs[path] = (fsi, readonly) def unmount_fsi(self, path, force=False): """unmounts a fsi.""" path = os.path.abspath(path) if not path in self.path2fs: raise MountError("Nothing mounted there.") fsi, readonly = self.path2fs[path] if not force: try: fsi.close() except OperationFailure as e: raise MountError(e.message) del self.path2fs[path] # todo: close files def get_mounts(self): """ returns a list of (path, fsi, readonly) containing all currently mounted filesystems. """ ret = [] for p in self.path2fs: fs, readonly = self.path2fs[p] ret.append((p,fs, readonly)) return ret # install manager if get_manager() is None: set_manager(MountManager())