]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
edit-util: make original_path and comment_paths work together
authorMike Yuan <me@yhndnzj.com>
Thu, 6 Apr 2023 17:41:24 +0000 (01:41 +0800)
committerMike Yuan <me@yhndnzj.com>
Fri, 7 Apr 2023 08:10:57 +0000 (16:10 +0800)
src/shared/edit-util.c

index f1eb7987f48c52f54386971be8338e35eca6c887..097ef6a7919cb03a96e1da83e067fde3a9a9caaa 100644 (file)
 #include "mkdir-label.h"
 #include "path-util.h"
 #include "process-util.h"
-#include "selinux-util.h"
-#include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
-#include "tmpfile-util.h"
+#include "tmpfile-util-label.h"
 
 void edit_file_context_done(EditFileContext *context) {
         int r;
@@ -103,6 +101,9 @@ int edit_files_add(
 
 static int create_edit_temp_file(EditFile *e) {
         _cleanup_(unlink_and_freep) char *temp = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        const char *source;
+        bool has_original, has_target;
         unsigned line = 1;
         int r;
 
@@ -114,62 +115,35 @@ static int create_edit_temp_file(EditFile *e) {
         if (e->temp)
                 return 0;
 
-        r = tempfn_random(e->path, NULL, &temp);
+        r = mkdir_parents_label(e->path, 0755);
         if (r < 0)
-                return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", e->path);
+                return log_error_errno(r, "Failed to create parent directories for '%s': %m", e->path);
 
-        r = mkdir_parents_label(e->path, 0755);
+        r = fopen_temporary_label(e->path, e->path, &f, &temp);
         if (r < 0)
-                return log_error_errno(r, "Failed to create parent directories for \"%s\": %m", e->path);
+                return log_error_errno(r, "Failed to create temporary file for '%s': %m", e->path);
 
-        if (!e->original_path && !e->comment_paths) {
-                r = mac_selinux_create_file_prepare(e->path, S_IFREG);
-                if (r < 0)
-                        return r;
+        if (fchmod(fileno(f), 0644) < 0)
+                return log_error_errno(errno, "Failed to change mode of temporary file '%s': %m", temp);
 
-                r = touch(temp);
-                mac_selinux_create_file_clear();
-                if (r < 0)
-                        return log_error_errno(r, "Failed to create temporary file \"%s\": %m", temp);
-        }
+        has_original = e->original_path && access(e->original_path, F_OK) >= 0;
+        has_target = access(e->path, F_OK) >= 0;
 
-        if (e->original_path) {
-                r = mac_selinux_create_file_prepare(e->path, S_IFREG);
-                if (r < 0)
-                        return r;
-
-                r = copy_file(e->original_path, temp, 0, 0644, COPY_REFLINK);
-                if (r == -ENOENT) {
-                        r = touch(temp);
-                        mac_selinux_create_file_clear();
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to create temporary file \"%s\": %m", temp);
-                } else {
-                        mac_selinux_create_file_clear();
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", e->path);
-                }
-        }
+        if (has_original)
+                source = e->original_path;
+        else if (has_target)
+                source = e->path;
+        else
+                source = NULL;
 
         if (e->comment_paths) {
-                _cleanup_free_ char *target_contents = NULL;
-                _cleanup_fclose_ FILE *f = NULL;
+                _cleanup_free_ char *source_contents = NULL;
 
-                r = mac_selinux_create_file_prepare(e->path, S_IFREG);
-                if (r < 0)
-                        return r;
-
-                f = fopen(temp, "we");
-                mac_selinux_create_file_clear();
-                if (!f)
-                        return log_error_errno(errno, "Failed to open temporary file \"%s\": %m", temp);
-
-                if (fchmod(fileno(f), 0644) < 0)
-                        return log_error_errno(errno, "Failed to change mode of temporary file \"%s\": %m", temp);
-
-                r = read_full_file(e->path, &target_contents, NULL);
-                if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to read target file \"%s\": %m", e->path);
+                if (source) {
+                        r = read_full_file(source, &source_contents, NULL);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to read source file '%s': %m", source);
+                }
 
                 fprintf(f,
                         "### Editing %s\n"
@@ -180,41 +154,47 @@ static int create_edit_temp_file(EditFile *e) {
                         "%s\n",
                         e->path,
                         e->context->marker_start,
-                        strempty(target_contents),
-                        target_contents && endswith(target_contents, "\n") ? "" : "\n",
+                        strempty(source_contents),
+                        source_contents && endswith(source_contents, "\n") ? "" : "\n",
                         e->context->marker_end);
 
                 line = 4; /* Start editing at the contents area */
 
-                /* Add a comment with the contents of the original files */
                 STRV_FOREACH(path, e->comment_paths) {
-                        _cleanup_free_ char *contents = NULL;
+                        _cleanup_free_ char *comment = NULL;
 
-                        /* Skip the file that's being edited, already processed in above */
-                        if (path_equal(*path, e->path))
+                        /* Skip the file which is being edited and the source file (can be the same) */
+                        if (PATH_IN_SET(*path, e->path, source))
                                 continue;
 
-                        r = read_full_file(*path, &contents, NULL);
+                        r = read_full_file(*path, &comment, NULL);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to read original file \"%s\": %m", *path);
+                                return log_error_errno(r, "Failed to read comment file '%s': %m", *path);
 
                         fprintf(f, "\n\n### %s", *path);
-                        if (!isempty(contents)) {
-                                _cleanup_free_ char *commented_contents = NULL;
 
-                                commented_contents = strreplace(strstrip(contents), "\n", "\n# ");
-                                if (!commented_contents)
+                        if (!isempty(comment)) {
+                                _cleanup_free_ char *c = NULL;
+
+                                c = strreplace(strstrip(comment), "\n", "\n# ");
+                                if (!c)
                                         return log_oom();
 
-                                fprintf(f, "\n# %s", commented_contents);
+                                fprintf(f, "\n# %s", c);
                         }
                 }
-
-                r = fflush_and_check(f);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to create temporary file \"%s\": %m", temp);
+        } else if (source) {
+                r = copy_file_fd(source, fileno(f), COPY_REFLINK);
+                if (r < 0) {
+                        assert(r != -ENOENT);
+                        return log_error_errno(r, "Failed to copy file '%s' to temporary file '%s': %m", source, temp);
+                }
         }
 
+        r = fflush_and_check(f);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write to temporary file '%s': %m", temp);
+
         e->temp = TAKE_PTR(temp);
         e->line = line;