def _first_accessible_path(paths): """Find the first path that is accessible, creating it if necessary.""" for path in paths: try: # Ensure the user has access, creating the directory if necessary. path = sup.canonicalize_path(path) if os.path.exists(path): if can_access(path): return path else: # The path doesn't exist so create it and adjust permissions # and group as needed (e.g., shared ``$tempdir``). prefix = os.path.sep parts = path.strip(os.path.sep).split(os.path.sep) for part in parts: prefix = os.path.join(prefix, part) if not os.path.exists(prefix): break parent = os.path.dirname(prefix) gid = os.stat(parent).st_gid mkdirp(path, group=gid, default_perms='parents') if can_access(path): return path except OSError as e: tty.debug('OSError while checking stage path %s: %s' % ( path, str(e))) return None
def _create_stage_root(path): """Create the stage root directory and ensure appropriate access perms.""" assert path.startswith(os.path.sep) and len(path.strip()) > 1 curr_dir = os.path.sep parts = path.strip(os.path.sep).split(os.path.sep) for i, part in enumerate(parts): curr_dir = os.path.join(curr_dir, part) if not os.path.exists(curr_dir): rest = os.path.join(os.path.sep, *parts[i + 1:]) user_parts = rest.partition(os.path.sep + getpass.getuser()) if len(user_parts[0]) > 0: # Ensure access controls of subdirs created above `$user` # inherit from the parent and share the group. stats = os.stat(os.path.dirname(curr_dir)) curr_dir = ''.join([curr_dir, user_parts[0]]) mkdirp(curr_dir, group=stats.st_gid, mode=stats.st_mode) user_subdirs = ''.join(user_parts[1:]) if len(user_subdirs) > 0: # Ensure access controls of subdirs from `$user` on down are # restricted to the user. curr_dir = ''.join([curr_dir, user_subdirs]) mkdirp(curr_dir, mode=stat.S_IRWXU) assert os.getuid() == os.stat(curr_dir).st_uid break if not can_access(path): raise OSError(errno.EACCES, 'Cannot access %s: Permission denied' % curr_dir)
def _create_stage_root(path): """Create the stage root directory and ensure appropriate access perms.""" assert path.startswith(os.path.sep) and len(path.strip()) > 1 err_msg = 'Cannot create stage root {0}: Access to {1} is denied' user_uid = os.getuid() # Obtain lists of ancestor and descendant paths of the $user node, if any. group_paths, user_node, user_paths = partition_path( path, getpass.getuser()) for p in group_paths: if not os.path.exists(p): # Ensure access controls of subdirs created above `$user` inherit # from the parent and share the group. par_stat = os.stat(os.path.dirname(p)) mkdirp(p, group=par_stat.st_gid, mode=par_stat.st_mode) p_stat = os.stat(p) if par_stat.st_gid != p_stat.st_gid: tty.warn( "Expected {0} to have group {1}, but it is {2}".format( p, par_stat.st_gid, p_stat.st_gid)) if par_stat.st_mode & p_stat.st_mode != par_stat.st_mode: tty.warn( "Expected {0} to support mode {1}, but it is {2}".format( p, par_stat.st_mode, p_stat.st_mode)) if not can_access(p): raise OSError(errno.EACCES, err_msg.format(path, p)) # Add the path ending with the $user node to the user paths to ensure paths # from $user (on down) meet the ownership and permission requirements. if user_node: user_paths.insert(0, user_node) for p in user_paths: # Ensure access controls of subdirs from `$user` on down are # restricted to the user. if not os.path.exists(p): mkdirp(p, mode=stat.S_IRWXU) p_stat = os.stat(p) if p_stat.st_mode & stat.S_IRWXU != stat.S_IRWXU: tty.error( "Expected {0} to support mode {1}, but it is {2}".format( p, stat.S_IRWXU, p_stat.st_mode)) raise OSError(errno.EACCES, err_msg.format(path, p)) else: p_stat = os.stat(p) if user_uid != p_stat.st_uid: tty.warn( "Expected user {0} to own {1}, but it is owned by {2}".format( user_uid, p, p_stat.st_uid))
def create_stage_root(path): # type: (str) -> None """Create the stage root directory and ensure appropriate access perms.""" assert os.path.isabs(path) and len(path.strip()) > 1 err_msg = 'Cannot create stage root {0}: Access to {1} is denied' user_uid = getuid() # Obtain lists of ancestor and descendant paths of the $user node, if any. group_paths, user_node, user_paths = partition_path( path, getpass.getuser()) for p in group_paths: if not os.path.exists(p): # Ensure access controls of subdirs created above `$user` inherit # from the parent and share the group. par_stat = os.stat(os.path.dirname(p)) mkdirp(p, group=par_stat.st_gid, mode=par_stat.st_mode) p_stat = os.stat(p) if par_stat.st_gid != p_stat.st_gid: tty.warn( "Expected {0} to have group {1}, but it is {2}".format( p, par_stat.st_gid, p_stat.st_gid)) if par_stat.st_mode & p_stat.st_mode != par_stat.st_mode: tty.warn( "Expected {0} to support mode {1}, but it is {2}".format( p, par_stat.st_mode, p_stat.st_mode)) if not can_access(p): raise OSError(errno.EACCES, err_msg.format(path, p)) # Add the path ending with the $user node to the user paths to ensure paths # from $user (on down) meet the ownership and permission requirements. if user_node: user_paths.insert(0, user_node) for p in user_paths: # Ensure access controls of subdirs from `$user` on down are # restricted to the user. owner_uid = get_owner_uid(p) if user_uid != owner_uid: tty.warn( "Expected user {0} to own {1}, but it is owned by {2}".format( user_uid, p, owner_uid)) spack_src_subdir = os.path.join(path, _source_path_subdir) # When staging into a user-specified directory with `spack stage -p <PATH>`, we need # to ensure the `spack-src` subdirectory exists, as we can't rely on it being # created automatically by spack. It's not clear why this is the case for `spack # stage -p`, but since `mkdirp()` is idempotent, this should not change the behavior # for any other code paths. if not os.path.isdir(spack_src_subdir): mkdirp(spack_src_subdir, mode=stat.S_IRWXU)
def _first_accessible_path(paths): """Find the first path that is accessible, creating it if necessary.""" for path in paths: try: # Ensure the user has access, creating the directory if necessary. if os.path.exists(path): if can_access(path): return path else: # Now create the stage root with the proper group/perms. _create_stage_root(path) return path except OSError as e: tty.debug('OSError while checking stage path %s: %s' % (path, str(e))) return None
def _first_accessible_path(paths): """Find a tmp dir that exists that we can access.""" for path in paths: try: # try to create the path if it doesn't exist. path = canonicalize_path(path) mkdirp(path) # ensure accessible if not can_access(path): continue # return it if successful. return path except OSError: tty.debug('OSError while checking temporary path: %s' % path) continue return None
def _first_accessible_path(paths): """Find a tmp dir that exists that we can access.""" for path in paths: try: # try to create the path if it doesn't exist. path = canonicalize_path(path) mkdirp(path) # ensure accessible if not can_access(path): continue # return it if successful. return path except OSError: tty.debug('OSError while checking temporary path: %s' % path) continue return None
def ensure_access(file): """Ensure we can access a directory and die with an error if we can't.""" if not can_access(file): tty.die("Insufficient permissions for %s" % file)
def _can_revert_update(scope_dir, cfg_file, bkp_file): dir_ok = fs.can_write_to_dir(scope_dir) cfg_ok = not os.path.exists(cfg_file) or fs.can_access(cfg_file) bkp_ok = fs.can_access(bkp_file) return dir_ok and cfg_ok and bkp_ok
def _can_update_config_file(scope_dir, cfg_file): dir_ok = fs.can_write_to_dir(scope_dir) cfg_ok = fs.can_access(cfg_file) return dir_ok and cfg_ok
def ensure_access(file=spack.paths.stage_path): """Ensure we can access a directory and die with an error if we can't.""" if not can_access(file): tty.die("Insufficient permissions for %s" % file)