Add dest_size 73/275873/2
authorMateusz Majewski <m.majewski2@samsung.com>
Fri, 3 Jun 2022 11:07:26 +0000 (13:07 +0200)
committerMateusz Majewski <m.majewski2@samsung.com>
Fri, 3 Jun 2022 11:29:55 +0000 (13:29 +0200)
Change-Id: I0510236e0036b9409f632a4109a9e83ace58a6c7

upgrade-apply/main.c
upgrade-apply/ss_brotli_patch/ss_brotli_patch.c
upgrade-apply/ss_brotli_patch/ss_brotli_patch.h

index ce6387fa3ec9f7aac3dbdefdf325de5398929504..4faff68c51662c6473176259c6d1ac1adcd9e713 100644 (file)
@@ -58,6 +58,7 @@ struct parse_result {
                PARSE_MISSING_ARGUMENT,
                PARSE_PATCH_MISTAKE,
                PARSE_BAD_KIND,
+               PARSE_BAD_SIZE,
                PARSE_NO_PARSE,
        } result;
 
@@ -66,6 +67,7 @@ struct parse_result {
        const char *archive_file;
        const char *patch_orig;
        const char *dest_sha1;
+       size_t dest_size;
        enum archive_kind kind;
 };
 
@@ -76,6 +78,7 @@ struct parse_result parse_args(int argc, char **argv)
        const char *archive_file = NULL;
        const char *patch_orig = NULL;
        const char *dest_sha1 = NULL;
+       long long int dest_size = 0;
        enum archive_kind kind = -1;
        bool help = false;
 
@@ -87,6 +90,7 @@ struct parse_result parse_args(int argc, char **argv)
                        {"kind",         required_argument, NULL, 3  },
                        {"patch-orig",   required_argument, NULL, 4  },
                        {"dest-sha1",    required_argument, NULL, 5  },
+                       {"dest-size",    required_argument, NULL, 6  },
                        {"help",         no_argument,       NULL, 'h'},
                        {0}
                };
@@ -136,6 +140,14 @@ struct parse_result parse_args(int argc, char **argv)
                        dest_sha1 = optarg;
                        break;
 
+               case 6: // dest-size
+                       if (dest_size != 0)
+                               return (struct parse_result) { .result = PARSE_REPEATED_ARGUMENT };
+                       dest_size = atoi(optarg);
+                       if (dest_size <= 0 || dest_size > SIZE_MAX)
+                               return (struct parse_result) { .result = PARSE_BAD_SIZE };
+                       break;
+
                case 'h': // help
                        if (help)
                                return (struct parse_result) { .result = PARSE_REPEATED_ARGUMENT };
@@ -174,6 +186,7 @@ struct parse_result parse_args(int argc, char **argv)
                .archive_file = archive_file,
                .patch_orig = patch_orig,
                .dest_sha1 = dest_sha1,
+               .dest_size = dest_size,
                .kind = kind,
        };
 }
@@ -240,7 +253,7 @@ ssize_t gzip_write(__attribute__((unused)) int useless_fd, __attribute__((unused
 void help(char *name)
 {
        fprintf(stderr,
-               "Usage: %s --archive ARCHIVE --archive-file FILE --dest DESTINATION --kind KIND [--patch-orig ORIGIN] [--dest-sha1 SHA1]\n"
+               "Usage: %s --archive ARCHIVE --archive-file FILE --dest DESTINATION --kind KIND [--patch-orig ORIGIN] [--dest-sha1 SHA1] [--dest-size SIZE]\n"
                "\n"
                "Patches a partition using an archive.\n"
                "It will look for a file named FILE in an archive called ARCHIVE; the archive should have an extension\n"
@@ -250,7 +263,9 @@ void help(char *name)
                " - ss_brotli_patch means that the file should be treated as a delta in the (Tizen-specific) ss_brotli_patch\n"
                "   format. In this case, ORIGIN is needed and specifies the partition that a delta is based on.\n"
                "The results will be written to the DESTINATION partition.\n"
-               "If SHA1 is provided (lowercase hexadecimal), it is compared to the one calculated on DESTINATION after writing.\n",
+               "If SHA1 is provided (lowercase hexadecimal), it is compared to the one calculated on DESTINATION after writing.\n"
+               "Additionally, if SIZE is provided, it is used as the destination size; this matters for SHA1 comparision,\n"
+               "and also if ss_brotli_patch is used.\n",
        name);
 }
 
@@ -295,7 +310,7 @@ int apply_raw(const char *dest, TAR *tar)
        return 0;
 }
 
-int check_sha1(const char *dest, const char *sha1)
+int check_sha1(const char *dest, const char *sha1, size_t read_bytes)
 {
        const size_t SHA1_LEN = 20;
        const char HEX_DIGITS[] = "0123456789abcdef";
@@ -314,40 +329,47 @@ int check_sha1(const char *dest, const char *sha1)
        SHA1_CTX context;
        SHA1Init(&context);
 
-       for (;;) {
+       if (read_bytes == 0)
+               read_bytes = SIZE_MAX;
+
+       while (read_bytes > 0) {
                // This size doesn't really matter, so let's just pick a value that is big enough
                // to not use too many syscalls.
                unsigned char buf[1 << 16];
 
-               int r_read = read(dest_fd, buf, sizeof(buf));
+               int r_read = read(dest_fd, buf, read_bytes < sizeof(buf) ? read_bytes : sizeof(buf));
+               read_bytes -= r_read;
                switch (r_read) {
                case -1:
                        fprintf(stderr, "Couldn't read from the destination (errno: %m)\n");
                        return -1;
                case 0:
                        // We read all the data. Let's check the results!
-                       {
-                               unsigned char correct_sha1[SHA1_LEN + 1];
-                               SHA1Final(correct_sha1, &context);
-
-                               char correct_sha1_hex[2 * SHA1_LEN + 1];
-                               for (int i = 0; i < SHA1_LEN; ++i) {
-                                       correct_sha1_hex[2 * i]     = HEX_DIGITS[correct_sha1[i] / 16];
-                                       correct_sha1_hex[2 * i + 1] = HEX_DIGITS[correct_sha1[i] % 16];
-                               }
-                               correct_sha1_hex[sizeof(correct_sha1_hex) - 1] = '\0';
-
-                               if (strcmp(correct_sha1_hex, sha1) != 0) {
-                                       fprintf(stderr, "Malformed or invalid SHA1: correct one is %s\n", correct_sha1_hex);
-                                       return -1;
-                               }
-
-                               return 0;
-                       }
+                       // ... wait, there is no two-layer (switch and while) break in C.
+                       // Ugh, we have to goto instead.
+                       goto while_done;
                }
 
                SHA1Update(&context, buf, r_read);
        }
+while_done:;
+
+       unsigned char correct_sha1[SHA1_LEN + 1];
+       SHA1Final(correct_sha1, &context);
+
+       char correct_sha1_hex[2 * SHA1_LEN + 1];
+       for (int i = 0; i < SHA1_LEN; ++i) {
+               correct_sha1_hex[2 * i]     = HEX_DIGITS[correct_sha1[i] / 16];
+               correct_sha1_hex[2 * i + 1] = HEX_DIGITS[correct_sha1[i] % 16];
+       }
+       correct_sha1_hex[sizeof(correct_sha1_hex) - 1] = '\0';
+
+       if (strcmp(correct_sha1_hex, sha1) != 0) {
+               fprintf(stderr, "Malformed or invalid SHA1: correct one is %s\n", correct_sha1_hex);
+               return -1;
+       }
+
+       return 0;
 }
 
 int main(int argc, char **argv)
@@ -370,6 +392,10 @@ int main(int argc, char **argv)
                fprintf(stderr, "Invalid `kind` parameter (possible: `raw`, `ss_brotli_patch`)\n");
                help(argv[0]);
                return EXIT_FAILURE;
+       case PARSE_BAD_SIZE:
+               fprintf(stderr, "Invalid `dest-size` parameter (it should be a positive number that fits in size_t)\n");
+               help(argv[0]);
+               return EXIT_FAILURE;
        case PARSE_NO_PARSE:
                fprintf(stderr, "Invalid parameters passed\n");
                help(argv[0]);
@@ -447,7 +473,7 @@ int main(int argc, char **argv)
                        break;
 
                case KIND_BROTLI_PATCH:
-                       r = apply_patch_brotli(parsed.patch_orig, parsed.dest, tar);
+                       r = apply_patch_brotli(parsed.patch_orig, parsed.dest, tar, parsed.dest_size);
                        break;
                }
 
@@ -458,7 +484,7 @@ int main(int argc, char **argv)
 
                if (parsed.dest_sha1 != NULL) {
                        fprintf(stderr, "Write successful. Now checking SHA1\n");
-                       if (check_sha1(parsed.dest, parsed.dest_sha1) != 0) {
+                       if (check_sha1(parsed.dest, parsed.dest_sha1, parsed.dest_size) != 0) {
                                fprintf(stderr, "Couldn't check SHA1; you might need to restore from the backup!\n");
                                return EXIT_FAILURE;
                        }
index 50227fc6f7a6bac6d94c1f88b75583296a21dbc4..4821fc4728b8ba343d8ab005d6f4de280fbb97a2 100644 (file)
@@ -142,7 +142,7 @@ static size_t decompress_bytes(struct bs_data *data, size_t keep_offset)
     return PF_OK;
 }
 
-static int open_files(struct bs_data *data, const char *source_file, const char *dest_file, TAR *patch_tar)
+static int open_files(struct bs_data *data, const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size)
 {
     assert(data);
     assert(source_file);
@@ -159,7 +159,7 @@ static int open_files(struct bs_data *data, const char *source_file, const char
 
     data->src_len = get_file_len(data->src_fd);
     data->patch_len = th_get_size(data->patch_tar);
-    data->dest_len = get_file_len(data->dest_fd);
+    data->dest_len = dest_size == 0 ? get_file_len(data->dest_fd) : dest_size;
 
     data->src_ptr = mmap(NULL, data->src_len, PROT_READ, MAP_PRIVATE, data->src_fd, 0);
     if (data->src_ptr == MAP_FAILED) {
@@ -268,7 +268,7 @@ int read_header(struct bs_data *data, uint8_t **buff_out_pos)
     return PF_OK;
 }
 
-int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar)
+int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size)
 {
     assert(source_file);
     assert(dest_file);
@@ -280,7 +280,7 @@ int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patc
 
     init_data(&data);
 
-    if ((result = open_files(&data, source_file, dest_file, patch_tar)) != PF_OK)
+    if ((result = open_files(&data, source_file, dest_file, patch_tar, dest_size)) != PF_OK)
         goto exit;
 
     if ((result = decompress_bytes(&data, 0)) != PF_OK)
index 7c5603c11e36dc44fce831e1b146c48efed87756..fb2fc95a915ed1e13a6d0863f057d98e37ea8b75 100644 (file)
@@ -21,4 +21,4 @@
 
 #include <libtar.h>
 
-extern int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar);
+extern int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size);