From: TJ Date: Fri, 13 Nov 2015 20:27:57 +0000 (+0000) Subject: Refactor directory parse/creation logic X-Git-Url: https://iam.tj/gitweb/gitweb.cgi?p=installshield_z.git;a=commitdiff_plain;h=daf2864cc7caf4f6856089f4f90fa8df25be883f Refactor directory parse/creation logic --- diff --git a/installshield_main.c b/installshield_main.c index 40bb743..ed458b3 100644 --- a/installshield_main.c +++ b/installshield_main.c @@ -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);