def make_dir_writable(directory): """Context-manager that sets write permission on a directory. This assumes that the directory belongs to you. If the u+w permission wasn't set, it gets set in the context, and restored to what it was when leaving the context. u+x also gets set on all the directories leading to that path. """ uid = os.getuid() try: sb = directory.stat() except OSError: pass else: if sb.st_uid != uid or sb.st_mode & 0o700 == 0o700: yield return # These are the permissions to be restored, in reverse order restore_perms = [] try: # Add u+x to all directories up to the target path = Path('/') for c in directory.components[1:-1]: path = path / c sb = path.stat() if sb.st_uid == uid and not sb.st_mode & 0o100: logging.debug("Temporarily setting u+x on %s", path) restore_perms.append((path, sb.st_mode)) path.chmod(sb.st_mode | 0o700) # Add u+wx to the target sb = directory.stat() if sb.st_uid == uid and sb.st_mode & 0o700 != 0o700: logging.debug("Temporarily setting u+wx on %s", directory) restore_perms.append((directory, sb.st_mode)) directory.chmod(sb.st_mode | 0o700) yield finally: for path, mod in reversed(restore_perms): path.chmod(mod)
def extract_trace(self, target): """Extracts the trace database to the specified path. It is up to the caller to remove that file once done. """ target = Path(target) if self.version == 1: member = self.tar.getmember('METADATA/trace.sqlite3') elif self.version == 2: try: member = self.tar.getmember('METADATA/trace.sqlite3.gz') except KeyError: member = self.tar.getmember('METADATA/trace.sqlite3') else: assert False member = copy.copy(member) member.name = str(target.components[-1]) self.tar.extract(member, path=str(Path.cwd() / target.parent)) target.chmod(0o644) assert target.is_file()