]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #13727 from keszybz/pstore-greedy-realloc
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 9 Oct 2019 06:01:45 +0000 (15:01 +0900)
committerGitHub <noreply@github.com>
Wed, 9 Oct 2019 06:01:45 +0000 (15:01 +0900)
Use greedy realloc in pstore

src/pstore/pstore.c

index 8ffe523830f302c523f2481a32d0f3f39e95918b..e4618aac0ecc774b2d955128ff81213c92780af9 100644 (file)
@@ -179,9 +179,11 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
         ssize_t wr;
         int r;
 
-        if (isempty(dmesg) || size == 0)
+        if (size == 0)
                 return 0;
 
+        assert(dmesg);
+
         ofd_path = path_join(arg_archivedir, id, "dmesg.txt");
         if (!ofd_path)
                 return log_oom();
@@ -205,7 +207,8 @@ static int write_dmesg(const char *dmesg, size_t size, const char *id) {
 static void process_dmesg_files(PStoreList *list) {
         /* Move files, reconstruct dmesg.txt */
         _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL;
-        size_t dmesg_size = 0;
+        size_t dmesg_size = 0, dmesg_allocated = 0;
+        bool dmesg_bad = false;
         PStoreEntry *pe;
 
         /* Handle each dmesg file: files processed in reverse
@@ -282,33 +285,39 @@ static void process_dmesg_files(PStoreList *list) {
                 /* Now move file from pstore to archive storage */
                 move_file(pe, pe_id);
 
+                if (dmesg_bad)
+                        continue;
+
                 /* If the current record id is NOT the same as the
                  * previous record id, then start a new dmesg.txt file */
-                if (!pe_id || !dmesg_id || !streq(pe_id, dmesg_id)) {
+                if (!streq_ptr(pe_id, dmesg_id)) {
                         /* Encountered a new dmesg group, close out old one, open new one */
-                        if (dmesg) {
-                                (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
-                                dmesg = mfree(dmesg);
-                                dmesg_size = 0;
-                        }
+                        (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
+                        dmesg_size = 0;
 
                         /* now point dmesg_id to storage of pe_id */
                         free_and_replace(dmesg_id, pe_id);
                 }
 
-                /* Reconstruction of dmesg is done as a useful courtesy, do not log errors */
-                dmesg = realloc(dmesg, dmesg_size + strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1);
-                if (dmesg) {
-                        dmesg_size += sprintf(&dmesg[dmesg_size], "%s:\n", pe->dirent.d_name);
-                        if (pe->content) {
-                                memcpy(&dmesg[dmesg_size], pe->content, pe->content_size);
-                                dmesg_size += pe->content_size;
-                        }
+                /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled
+                 * output either. */
+                size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1;
+                if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) {
+                        log_warning_errno(ENOMEM, "Failed to write dmesg file: %m");
+                        dmesg_bad = true;
+                        continue;
+                }
+
+                dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name);
+                if (pe->content) {
+                        memcpy(dmesg + dmesg_size, pe->content, pe->content_size);
+                        dmesg_size += pe->content_size;
                 }
 
                 pe_id = mfree(pe_id);
         }
-        if (dmesg)
+
+        if (!dmesg_bad)
                 (void) write_dmesg(dmesg, dmesg_size, dmesg_id);
 }
 
@@ -359,15 +368,18 @@ static int run(int argc, char *argv[]) {
 
         log_setup_service();
 
-        if (argc > 1)
+        if (argc == 3) {
+                arg_sourcedir = argv[1];
+                arg_archivedir = argv[2];
+        } else if (argc > 1)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "This program takes no arguments.");
+                                       "This program takes zero or two arguments.");
 
         /* Ignore all parse errors */
         (void) parse_config();
 
-        log_debug("Selected storage '%s'.", pstore_storage_to_string(arg_storage));
-        log_debug("Selected Unlink '%d'.", arg_unlink);
+        log_debug("Selected storage: %s.", pstore_storage_to_string(arg_storage));
+        log_debug("Selected unlink: %s.", yes_no(arg_unlink));
 
         if (arg_storage == PSTORE_STORAGE_NONE)
                 /* Do nothing, intentionally, leaving pstore untouched */