Refactor directory parse/creation logic
authorTJ <hacker@iam.tj>
Fri, 13 Nov 2015 20:27:57 +0000 (20:27 +0000)
committerTJ <hacker@iam.tj>
Fri, 13 Nov 2015 20:27:57 +0000 (20:27 +0000)
installshield_main.c

index 40bb743..ed458b3 100644 (file)
@@ -47,7 +47,7 @@ headers_decode(int z_fd)
                printf("CRC32               %08x\n", header->__crc32);
                printf("File size           %08x\n", header->file_bytes);
                printf("Payload size        %08x\n", header->payload_bytes);
-        printf("Directories offset  %08x\n", header->directories_offset);
+               printf("Directories offset  %08x\n", header->directories_offset);
                printf("Directories size    %08x\n", header->directories_bytes);
                printf("Directories entries     %04x\n", header->directories_entries);
                printf("Files offset        %08x\n", header->files_offset);
@@ -90,79 +90,57 @@ headers_decode(int z_fd)
 
                                        printf(" \"%s\\%s\"\n", dirents[q->dir_index].entry->name, q->name);
 
+                                       char *dir_name = strdup(dirents[q->dir_index].entry->name);
+                                       for (char *p = dir_name; *p; ++p)
+                                               if (*p == '\\') *p = '/';
+                                       printf("Parsing '%s' (%d bytes)\n", dir_name, strlen(dir_name));
+
                                        int dir_fd = AT_FDCWD;
                                        int dir_fd_last = dir_fd;
                                        if (extract) {
-                                               char *dir = dirents[q->dir_index].entry->name;
-
-                                               for (char *sep = dir;; ++sep) {
-                                                       if (*sep == '\\' || *sep == 0) {
-                                                               char temp = *sep;
-                                                               *sep = 0;
-
-                                                               if (strlen(dir) > 0) {
-                                                                       int ret;
-
-                                                                       if (debug)
-                                                                               printf("Creating directory '%s': ", dir);
-
-                                                                       if (!dirents[q->dir_index].created && mkdirat(dir_fd, dir, 0755) != 0) {
-                                                                               if (errno != EEXIST) {
-                                                                                       *sep = temp;
-                                                                                       fprintf(stderr, "Error %d: cannot create directory %s\n", errno,  dir);
+                                               if (!dirents[q->dir_index].created) {
+                                                       char *component = dir_name;
+                                                       bool last_component = false;
+                                                       for (char *sep = dir_name;; ++sep) {
+                                                               if (*sep == '/' || *sep == 0) {
+                                                                       if (*sep == 0)
+                                                                               last_component = true;
+                                                                       char temp = *sep;
+                                                                       *sep = 0;
+                                                                       if (strlen(component) > 0) {
+                                                                               if (debug) printf("Component: '%s' %d bytes @ %p\n", component, strlen(component), component);
+                                                                               int ret = mkdirat(dir_fd, component, 0755);
+                                                                               if (ret == 0 || (ret == -1 && errno == EEXIST)) {
+                                                                                       if (debug)
+                                                                                               printf("Directory '%s' %s\n", component, ret == 0 ? "created" : "already exists");
+                                                                                       dir_fd_last = dir_fd;
+                                                                                       dir_fd = openat(dir_fd_last, component, O_DIRECTORY);
+                                                                                       close(dir_fd_last);
+                                                                                       if (dir_fd == -1) {
+                                                                                               fprintf(stderr, "Error %d: cannot open directory '%s': ", errno, component);
+                                                                                               perror(NULL);
+                                                                                               *sep = temp;
+                                                                                               break; // cannot continue if unable to open a path component
+                                                                                       } else if (last_component == true) {
+                                                                                               dirents[q->dir_index].created = true;
+                                                                                       }
+                                                                               } else {
+                                                                                       fprintf(stderr, "Error %d: cannot create directory '%s': ", errno, component);
                                                                                        perror(NULL);
-                                                                                       goto dir_create_abort;
+                                                                                       *sep = temp;
+                                                                                       break; // leave the for() loop immediately
                                                                                }
-                                                                               if (debug)
-                                                                                       printf("Directory already exists: %s\n", dir);
-                                                                       }
-
-                                                                       dir_fd_last = dir_fd;
-                                                                       if (debug)
-                                                                               printf("Opening directory '%s'\n", dir);
-                                                                       if ((dir_fd = openat(dir_fd_last, dir, O_DIRECTORY)) == -1) {
-                                                                               *sep = temp;
-                                                                               fprintf(stderr, "Error %d: cannot open directory %s\n", errno, dir);
-                                                                               perror(NULL);
-                                                                               goto dir_create_abort;
-                                                                       }
-
-                                                                       if (debug)
-                                                                               printf("%s\n", "");
-
-                                                                       if (dir_fd_last != AT_FDCWD) close(dir_fd_last);
-dir_exists:
+                                                                       } // strlen()
                                                                        *sep = temp;
-                                                                       dir = sep + 1;
-                                                               }
-                                                       }
-                                                       if (*sep == 0) break;
-                                               }
-                                               close(dir_fd);
-                                               dir_fd = AT_FDCWD;
-                                               dirents[q->dir_index].created = true;
-                                               goto dir_create_done;
-
-dir_create_abort:
-                                               if (debug)
-                                                       printf("%s", "\n");
-                                               if (dir_fd_last != AT_FDCWD) {
-                                                       close(dir_fd_last);
-                                                       dir_fd_last = AT_FDCWD;
-                                               }
-                                               if (dir_fd != AT_FDCWD) {
-                                                       close(dir_fd);
-                                                       dir_fd = AT_FDCWD;
-                                               }
-
+                                                                       component = sep + 1;
+                                                                       if (last_component) break;
+                                                               } // separator
+                                                       } // for()
+                                                       if (dir_fd < 0)
+                                                               dir_fd = AT_FDCWD;
+                                               } // .created == false
                                        }
-dir_create_done:
-                                       if (NULL);
-                                       char *dir_name = strdup(dirents[q->dir_index].entry->name);
-                                       for (char *p = dir_name; *p; ++p)
-                                               if (*p == '\\') *p = '/';
-
-                                       if (dir_fd == AT_FDCWD && (dir_fd = openat(AT_FDCWD, dir_name, O_DIRECTORY)) != -1) {
+                                       if ((dir_fd = openat(AT_FDCWD, dir_name, O_DIRECTORY)) != -1) {
 
                                                unsigned int z_filename_len = strlen(q->name) + 4;
                                                char z_filename[z_filename_len];
@@ -170,7 +148,7 @@ dir_create_done:
                                                strncat(z_filename, ".z", 2);
 
                                                if (debug)
-                                                       printf(" Creating payload file \"%s/%s\"\n", dir_name,  z_filename);
+                                                       printf(" Creating payload file '%s/%s'\n", dir_name,  z_filename);
 
                                                if ((offset = lseek(z_fd, q->payload_offset, SEEK_SET)) == q->payload_offset) {
                                                        void *buffer;
@@ -187,14 +165,15 @@ dir_create_done:
                                                                }
                                                                free(buffer);
                                                        }
-                                               } else
+                                               } else {
                                                        fprintf(stderr, "Error %d: failed to create %s\n", errno, z_filename);
+                                               }
                                                close(dir_fd);
                                        } else {
-                                               fprintf(stderr, "Error %d: cannot open directory at %d %s\n", errno, dir_fd, dir_name);
+                                               fprintf(stderr, "Error %d: cannot open directory at (%d) '%s': ", errno, dir_fd, dir_name);
                                                perror(NULL);
                                        }
-
+                                       free(dir_name);
                                        q = (void *)q + q->entry_bytes;
                                }
                                free(fileent);