diff --git a/gitlib/gitlib.py b/gitlib/gitlib.py index 57d630b..26238a8 100755 --- a/gitlib/gitlib.py +++ b/gitlib/gitlib.py @@ -296,7 +296,10 @@ class OpengnsysGitLibrary: """ self.debug_check_for_untracked_files = True - self.logger.debug(f"Git repository: {self.repo_server}") + if not self.repo_server: + self.logger.error("Git repository not known, we may not have booted correctly? Check ogrepo and oglive kernel arguments.") + else: + self.logger.debug(f"Git repository: {self.repo_server}") def _is_efi(self): """Determina si hemos arrancado con EFI @@ -839,6 +842,7 @@ class OpengnsysGitLibrary: empties_file = open(os.path.join(meta_dir, "empty_directories.jsonl.new"), "w") specials_file = open(os.path.join(meta_dir, "special_files.jsonl.new"), "w") acls_file = open(os.path.join(meta_dir, "acls.jsonl.new"), "w") + perms_file = open(os.path.join(meta_dir, "unix_permissions.jsonl.new"), "w") xattrs_file = open(os.path.join(meta_dir, "xattrs.jsonl.new"), "w") gitignores_file = open(os.path.join(meta_dir, "gitignores.jsonl.new"), "w") filesystems_file = open(os.path.join(meta_dir, "filesystems.json.new"), "w") @@ -947,6 +951,16 @@ class OpengnsysGitLibrary: if not ntfs and os.path.isfile(full_path) and not os.path.islink(full_path): # docs: https://pylibacl.k1024.org/module.html#posix1e.ACL.to_any_text + # Git doesn't preserve setuid, we've got to store it separately + stat_data = os.stat(full_path) + + perms_json = json.dumps({ + "file" : full_path_rel, + "mode" : stat_data.st_mode, + "uid" : stat_data.st_uid, + "gid" : stat_data.st_gid + }) + xattrs = str(xattr.get_all(full_path)) acls = posix1e.ACL(file=full_path) @@ -958,6 +972,7 @@ class OpengnsysGitLibrary: acl_data = str(base64.b64encode(acls.__getstate__()), 'utf-8') acls_json = json.dumps({"file": full_path_rel, "acl" : acl_data }) + perms_file.write(perms_json + "\n") xattrs_file.write(xattrs_json + "\n") acls_file.write(acls_json + "\n") @@ -1016,6 +1031,7 @@ class OpengnsysGitLibrary: specials_file.close() xattrs_file.close() acls_file.close() + perms_file.close() gitignores_file.close() filesystems_file.close() metadata_file.close() @@ -1023,6 +1039,7 @@ class OpengnsysGitLibrary: os.rename(os.path.join(meta_dir, "empty_directories.jsonl.new"), os.path.join(meta_dir, "empty_directories.jsonl")) os.rename(os.path.join(meta_dir, "special_files.jsonl.new"), os.path.join(meta_dir, "special_files.jsonl")) os.rename(os.path.join(meta_dir, "acls.jsonl.new"), os.path.join(meta_dir, "acls.jsonl")) + os.rename(os.path.join(meta_dir, "unix_permissions.jsonl.new"), os.path.join(meta_dir, "unix_permissions.jsonl")) os.rename(os.path.join(meta_dir, "xattrs.jsonl.new"), os.path.join(meta_dir, "xattrs.jsonl")) os.rename(os.path.join(meta_dir, "gitignores.jsonl.new"), os.path.join(meta_dir, "gitignores.jsonl")) os.rename(os.path.join(meta_dir, "filesystems.json.new"), os.path.join(meta_dir, "filesystems.json")) @@ -1084,6 +1101,32 @@ class OpengnsysGitLibrary: self.logger.debug(f"Deleting: {empty_dir_keep}") os.unlink(empty_dir_keep) + if not destructive_only: + self.logger.debug("Processing unix_permissions.jsonl") + with open(os.path.join(meta_dir, "unix_permissions.jsonl"), "r") as acls_file: + for line in acls_file: + perms_data = json.loads(line) + #self.logger.debug(f"Data: {acls_data}") + + perms_file = perms_data['file'] + file_perms = perms_data['mode'] + file_uid = perms_data['uid'] + file_gid = perms_data['gid'] + + if perms_file.startswith("/"): + perms_file = perms_file[1:] + + perms_file_path = os.path.join(path, perms_file) + + if os.path.exists(perms_file_path): + self.logger.debug(f"Applying permissions {file_perms}, owner {file_uid}, group {file_gid} to {perms_file_path}") + # chown clears suid bits, must come first + os.chown(perms_file_path, file_uid, file_gid) + os.chmod(perms_file_path, file_perms) + else: + self.logger.warn(f"Can't apply permissions to {perms_file_path}, file doesn't exist.") + + if not destructive_only: self.logger.debug("Processing acls.jsonl") with open(os.path.join(meta_dir, "acls.jsonl"), "r") as acls_file: @@ -1167,7 +1210,10 @@ class OpengnsysGitLibrary: except FileExistsError as exists: self.logger.debug(f"Exists: {full_path}") + # chown clears suid bit, so even though it's redundant in most cases and already + # done above, set the full perms on the file again anyway. os.chown(full_path, data['uid'], data['gid']) + os.chmod(full_path, file_mode) self.logger.debug("Metadata restoration completed.")