diff options
| author | 2013-01-11 20:11:11 +0100 | |
|---|---|---|
| committer | 2013-01-11 20:11:11 +0100 | |
| commit | 1641d9a8e82a0c5f1ad6968916fce2e63187c400 (patch) | |
| tree | 4b88991c41592b50018c154bd0da5fd7019b35c9 /src/ideviceinstaller.c | |
| parent | 7b85d07800030beecf2e2386c3c7539d3ad0629c (diff) | |
| download | ideviceinstaller-1641d9a8e82a0c5f1ad6968916fce2e63187c400.tar.gz ideviceinstaller-1641d9a8e82a0c5f1ad6968916fce2e63187c400.tar.bz2 | |
Refactor logic to locate the app directory within an archive
The method to determine the Payload/*.app directory in the archive has not
worked for a couple of use-cases. We now scan the file list in the archive
to locate the directory which should work for all cases.
Diffstat (limited to 'src/ideviceinstaller.c')
| -rw-r--r-- | src/ideviceinstaller.c | 94 |
1 files changed, 64 insertions, 30 deletions
diff --git a/src/ideviceinstaller.c b/src/ideviceinstaller.c index 12577f7..54bd318 100644 --- a/src/ideviceinstaller.c +++ b/src/ideviceinstaller.c | |||
| @@ -176,6 +176,61 @@ static int zip_get_contents(struct zip *zf, const char *filename, int locate_fla | |||
| 176 | return 0; | 176 | return 0; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static int zip_get_app_directory(struct zip* zf, char** path) | ||
| 180 | { | ||
| 181 | int i = 0; | ||
| 182 | int c = zip_get_num_files(zf); | ||
| 183 | int len = 0; | ||
| 184 | const char* name = NULL; | ||
| 185 | |||
| 186 | /* look through all filenames in the archive */ | ||
| 187 | do { | ||
| 188 | /* get filename at current index */ | ||
| 189 | name = zip_get_name(zf, i++, 0); | ||
| 190 | if (name != NULL) { | ||
| 191 | /* check if we have a "Payload/.../" name */ | ||
| 192 | len = strlen(name); | ||
| 193 | if (!strncmp(name, "Payload/", 8) && (len > 8)) { | ||
| 194 | /* locate the second directory delimiter */ | ||
| 195 | const char* p = name + 8; | ||
| 196 | do { | ||
| 197 | if (*p == '/') { | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } while(p++ != NULL); | ||
| 201 | |||
| 202 | /* try next entry if not found */ | ||
| 203 | if (p == NULL) | ||
| 204 | continue; | ||
| 205 | |||
| 206 | len = p - name + 1; | ||
| 207 | |||
| 208 | if (*path != NULL) { | ||
| 209 | free(*path); | ||
| 210 | *path = NULL; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* allocate and copy filename */ | ||
| 214 | *path = (char*)malloc(len + 1); | ||
| 215 | strncpy(*path, name, len); | ||
| 216 | |||
| 217 | /* add terminating null character */ | ||
| 218 | char* t = *path + len; | ||
| 219 | *t = '\0'; | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } while(i < c); | ||
| 224 | |||
| 225 | /* check if the path actually exists */ | ||
| 226 | int zindex = zip_name_locate(zf, *path, 0); | ||
| 227 | if (zindex < 0) { | ||
| 228 | return -1; | ||
| 229 | } | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 179 | static void do_wait_when_needed() | 234 | static void do_wait_when_needed() |
| 180 | { | 235 | { |
| 181 | int i = 0; | 236 | int i = 0; |
| @@ -633,44 +688,23 @@ run_again: | |||
| 633 | free(zbuf); | 688 | free(zbuf); |
| 634 | } | 689 | } |
| 635 | 690 | ||
| 636 | plist_t info = NULL; | 691 | /* determine .app directory in archive */ |
| 637 | zbuf = NULL; | 692 | zbuf = NULL; |
| 638 | len = 0; | 693 | len = 0; |
| 694 | plist_t info = NULL; | ||
| 639 | char filename[256]; | 695 | char filename[256]; |
| 640 | filename[0] = '\0'; | 696 | filename[0] = '\0'; |
| 697 | char* app_directory_name = NULL; | ||
| 641 | 698 | ||
| 642 | /* check for "Payload" directory */ | 699 | if (zip_get_app_directory(zf, &app_directory_name)) { |
| 643 | int zindex = zip_name_locate(zf, "Payload/", 0); | 700 | fprintf(stderr, "Unable to locate app directory in archive!\n"); |
| 644 | if (zindex < 0) { | ||
| 645 | fprintf(stderr, "Unable to locate Payload folder in archive!\n"); | ||
| 646 | zip_unchange_all(zf); | ||
| 647 | zip_close(zf); | ||
| 648 | goto leave_cleanup; | 701 | goto leave_cleanup; |
| 649 | } | 702 | } |
| 650 | 703 | ||
| 651 | /* check for "*.app" directory */ | ||
| 652 | if (meta_dict) { | ||
| 653 | plist_t nm = plist_dict_get_item(meta_dict, "itemName"); | ||
| 654 | plist_t fe = plist_dict_get_item(meta_dict, "fileExtension"); | ||
| 655 | if (nm && (plist_get_node_type(nm) == PLIST_STRING) && fe && (plist_get_node_type(fe) == PLIST_STRING)) { | ||
| 656 | char* val = NULL; | ||
| 657 | plist_get_string_val(nm, &val); | ||
| 658 | if (val) { | ||
| 659 | strcpy(filename, "Payload/"); | ||
| 660 | strcat(filename, val); | ||
| 661 | free(val); | ||
| 662 | val = NULL; | ||
| 663 | plist_get_string_val(fe, &val); | ||
| 664 | strcat(filename, val); | ||
| 665 | strcat(filename, "/"); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | if (filename[0] == '\0') { | ||
| 670 | strcpy(filename, zip_get_name(zf, zindex+1, 0)); | ||
| 671 | } | ||
| 672 | |||
| 673 | /* construct full filename to Info.plist */ | 704 | /* construct full filename to Info.plist */ |
| 705 | strcpy(filename, app_directory_name); | ||
| 706 | free(app_directory_name); | ||
| 707 | app_directory_name = NULL; | ||
| 674 | strcat(filename, "Info.plist"); | 708 | strcat(filename, "Info.plist"); |
| 675 | 709 | ||
| 676 | if (zip_get_contents(zf, filename, 0, &zbuf, &len) < 0) { | 710 | if (zip_get_contents(zf, filename, 0, &zbuf, &len) < 0) { |
| @@ -708,7 +742,7 @@ run_again: | |||
| 708 | } | 742 | } |
| 709 | 743 | ||
| 710 | char *sinfname = NULL; | 744 | char *sinfname = NULL; |
| 711 | if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { | 745 | if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { |
| 712 | fprintf(stderr, "Out of memory!?\n"); | 746 | fprintf(stderr, "Out of memory!?\n"); |
| 713 | goto leave_cleanup; | 747 | goto leave_cleanup; |
| 714 | } | 748 | } |
