diff options
| author | 2012-08-22 22:03:44 +0200 | |
|---|---|---|
| committer | 2012-08-22 22:03:44 +0200 | |
| commit | 05d2bc0ba3d736e2034bd89c810457d6a80ad052 (patch) | |
| tree | 67f1c4e7fc7d8fa55bf60179661c11af668983fe /src | |
| parent | b7bec60c948b7fcfa35ff0ccbc986c650dbfc4d4 (diff) | |
| download | ideviceinstaller-05d2bc0ba3d736e2034bd89c810457d6a80ad052.tar.gz ideviceinstaller-05d2bc0ba3d736e2034bd89c810457d6a80ad052.tar.bz2 | |
Add support for CarrierBundle installation (.ipcc files)
Diffstat (limited to 'src')
| -rw-r--r-- | src/ideviceinstaller.c | 333 | 
1 files changed, 212 insertions, 121 deletions
| diff --git a/src/ideviceinstaller.c b/src/ideviceinstaller.c index 67e06f9..acf2b6b 100644 --- a/src/ideviceinstaller.c +++ b/src/ideviceinstaller.c @@ -212,6 +212,7 @@ static void print_usage(int argc, char **argv)  		 "       -o list_all\t- list all types of apps\n"  		 "       -o xml\t\t- print full output as xml plist\n"  		 "  -i, --install ARCHIVE\tInstall app from package file specified by ARCHIVE.\n" +		 "                       \tARCHIVE can also be a .ipcc file for carrier bundles.\n"  		 "  -u, --uninstall APPID\tUninstall app specified by APPID.\n"  		 "  -g, --upgrade APPID\tUpgrade app specified by APPID.\n"  		 "  -L, --list-archives\tList archived applications, possible options:\n" @@ -525,152 +526,242 @@ run_again:  			goto leave_cleanup;  		} -		/* extract iTunesMetadata.plist from package */ -		char *zbuf = NULL; -		uint32_t len = 0; -		if (zip_f_get_contents(zf, "iTunesMetadata.plist", 0, &zbuf, &len) == 0) { -			meta = plist_new_data(zbuf, len); -		} -		if (zbuf) { -			free(zbuf); -		} +		plist_t client_opts = instproxy_client_options_new(); -		/* we need to get the CFBundleName first */ -		plist_t info = NULL; -		zbuf = NULL; -		len = 0; -		if (zip_f_get_contents(zf, "Info.plist", ZIP_FL_NODIR, &zbuf, &len) < 0) { -			zip_unchange_all(zf); -			zip_close(zf); -			goto leave_cleanup; -		} -		if (memcmp(zbuf, "bplist00", 8) == 0) { -			plist_from_bin(zbuf, len, &info); -		} else { -			plist_from_xml(zbuf, len, &info); -		} -		free(zbuf); +		if ((strlen(appid) > 5) && (strcmp(&appid[strlen(appid)-5], ".ipcc") == 0)) { +			char* ipcc = strdup(appid); +			if ((asprintf(&pkgname, "%s/%s", PKG_PATH, basename(ipcc)) > 0) && pkgname) { +				afc_make_directory(afc, pkgname); +			} -		if (!info) { -			fprintf(stderr, "Could not parse Info.plist!\n"); -			zip_unchange_all(zf); -			zip_close(zf); -			goto leave_cleanup; -		} +			printf("Uploading %s package contents...\n", basename(ipcc)); + +			/* extract the contents of the .ipcc file to PublicStaging/<name>.ipcc directory */ +			zip_uint64_t numzf = zip_get_num_entries(zf, 0); +			zip_uint64_t i = 0; +			for (i = 0; numzf > 0 && i < numzf; i++) { +				const char* zname = zip_get_name(zf, i, 0); +				char* dstpath = NULL; +				if (!zname) continue; +				if (zname[strlen(zname)-1] == '/') { +					// directory +					if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) > 0) && dstpath) { +						afc_make_directory(afc, dstpath);						} +					free(dstpath); +					dstpath = NULL; +				} else { +					// file +					struct zip_file* zfile = zip_fopen_index(zf, i, 0); +					if (!zfile) continue; + +					if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) <= 0) || !dstpath || (afc_file_open(afc, dstpath, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS)) { +						fprintf(stderr, "ERROR: can't open afc://%s for writing\n", dstpath); +						free(dstpath); +						dstpath = NULL; +						zip_fclose(zfile); +						continue; +					} -		char *bundlename = NULL; +					struct zip_stat zs; +					zip_stat_init(&zs); +					if (zip_stat_index(zf, i, 0, &zs) != 0) { +						fprintf(stderr, "ERROR: zip_stat_index %ld failed!\n", i); +						free(dstpath); +						dstpath = NULL; +						zip_fclose(zfile); +						continue; +					} -		plist_t bname = plist_dict_get_item(info, "CFBundleName"); -		if (bname) { -			plist_get_string_val(bname, &bundlename); -		} -		plist_free(info); +					free(dstpath); +					dstpath = NULL; + +					zip_uint64_t zfsize = 0; +					while (zfsize < zs.size) { +						zip_int64_t amount = zip_fread(zfile, buf, sizeof(buf)); +						if (amount == 0) { +							break; +						} + +						if (amount > 0) { +							uint32_t written, total = 0; +							while (total < amount) { +								written = 0; +								if (afc_file_write(afc, af, buf, amount, &written) != +									AFC_E_SUCCESS) { +									fprintf(stderr, "AFC Write error!\n"); +									break; +								} +								total += written; +							} +							if (total != amount) { +								fprintf(stderr, "Error: wrote only %d of %zu\n", total, amount); +								afc_file_close(afc, af); +								zip_fclose(zfile); +								free(dstpath); +								goto leave_cleanup; +							} +						} + +						zfsize += amount; +					} -		if (!bundlename) { -			fprintf(stderr, "Could not determine CFBundleName!\n"); -			zip_unchange_all(zf); -			zip_close(zf); -			goto leave_cleanup; -		} +					afc_file_close(afc, af); +					af = 0; -		char *sinfname = NULL; -	       	if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundlename, bundlename) < 0) { -			fprintf(stderr, "Out of memory!?\n"); -			goto leave_cleanup; -		} -		free(bundlename); +					zip_fclose(zfile); +				} +			} +			free(ipcc); +			printf("done.\n"); -		/* extract .sinf from package */ -		zbuf = NULL; -		len = 0; -		if (zip_f_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { -			sinf = plist_new_data(zbuf, len); -		} -		free(sinfname); -		if (zbuf) { +			instproxy_client_options_add(client_opts, "PackageType", "CarrierBundle", NULL); +		} else { +			/* extract iTunesMetadata.plist from package */ +			char *zbuf = NULL; +			uint32_t len = 0; +			if (zip_f_get_contents(zf, "iTunesMetadata.plist", 0, &zbuf, &len) == 0) { +				meta = plist_new_data(zbuf, len); +			} +			if (zbuf) { +				free(zbuf); +			} + +			/* we need to get the CFBundleName first */ +			plist_t info = NULL; +			zbuf = NULL; +			len = 0; +			if (zip_f_get_contents(zf, "Info.plist", ZIP_FL_NODIR, &zbuf, &len) < 0) { +				zip_unchange_all(zf); +				zip_close(zf); +				goto leave_cleanup; +			} +			if (memcmp(zbuf, "bplist00", 8) == 0) { +				plist_from_bin(zbuf, len, &info); +			} else { +				plist_from_xml(zbuf, len, &info); +			}  			free(zbuf); -		} -		zip_unchange_all(zf); -		zip_close(zf); +			if (!info) { +				fprintf(stderr, "Could not parse Info.plist!\n"); +				zip_unchange_all(zf); +				zip_close(zf); +				goto leave_cleanup; +			} -		/* copy archive to device */ -		f = fopen(appid, "r"); -		if (!f) { -			fprintf(stderr, "fopen: %s: %s\n", appid, strerror(errno)); -			goto leave_cleanup; -		} +			char *bundlename = NULL; -		pkgname = NULL; -		if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { -			fprintf(stderr, "Out of memory!?\n"); -			goto leave_cleanup; -		} +			plist_t bname = plist_dict_get_item(info, "CFBundleName"); +			if (bname) { +				plist_get_string_val(bname, &bundlename); +			} +			plist_free(info); -		printf("Copying '%s' --> '%s'\n", appid, pkgname); +			if (!bundlename) { +				fprintf(stderr, "Could not determine CFBundleName!\n"); +				zip_unchange_all(zf); +				zip_close(zf); +				goto leave_cleanup; +			} -		char **strs = NULL; -		if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { -			if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { -				fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); +			char *sinfname = NULL; +		       	if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundlename, bundlename) < 0) { +				fprintf(stderr, "Out of memory!?\n"); +				goto leave_cleanup;  			} -		} -		if (strs) { -			int i = 0; -			while (strs[i]) { -				free(strs[i]); -				i++; +			free(bundlename); + +			/* extract .sinf from package */ +			zbuf = NULL; +			len = 0; +			if (zip_f_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { +				sinf = plist_new_data(zbuf, len); +			} +			free(sinfname); +			if (zbuf) { +				free(zbuf);  			} -			free(strs); -		} -		if ((afc_file_open(afc, pkgname, AFC_FOPEN_WRONLY, &af) != -			 AFC_E_SUCCESS) || !af) { -			fclose(f); -			fprintf(stderr, "afc_file_open on '%s' failed!\n", pkgname); -			free(pkgname); -			goto leave_cleanup; -		} +			/* copy archive to device */ +			f = fopen(appid, "r"); +			if (!f) { +				fprintf(stderr, "fopen: %s: %s\n", appid, strerror(errno)); +				goto leave_cleanup; +			} -		size_t amount = 0; -		do { -			amount = fread(buf, 1, sizeof(buf), f); -			if (amount > 0) { -				uint32_t written, total = 0; -				while (total < amount) { -					written = 0; -					if (afc_file_write(afc, af, buf, amount, &written) != -						AFC_E_SUCCESS) { -						fprintf(stderr, "AFC Write error!\n"); -						break; -					} -					total += written; +			pkgname = NULL; +			if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { +				fprintf(stderr, "Out of memory!?\n"); +				goto leave_cleanup; +			} + +			printf("Copying '%s' --> '%s'\n", appid, pkgname); + +			char **strs = NULL; +			if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { +				if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { +					fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); +				} +			} +			if (strs) { +				int i = 0; +				while (strs[i]) { +					free(strs[i]); +					i++;  				} -				if (total != amount) { -					fprintf(stderr, "Error: wrote only %d of %zu\n", total, +				free(strs); +			} + +			if ((afc_file_open(afc, pkgname, AFC_FOPEN_WRONLY, &af) != +				 AFC_E_SUCCESS) || !af) { +				fclose(f); +				fprintf(stderr, "afc_file_open on '%s' failed!\n", pkgname); +				free(pkgname); +				goto leave_cleanup; +			} + +			size_t amount = 0; +			do { +				amount = fread(buf, 1, sizeof(buf), f); +				if (amount > 0) { +					uint32_t written, total = 0; +					while (total < amount) { +						written = 0; +						if (afc_file_write(afc, af, buf, amount, &written) != +							AFC_E_SUCCESS) { +							fprintf(stderr, "AFC Write error!\n"); +							break; +						} +						total += written; +					} +					if (total != amount) { +						fprintf(stderr, "Error: wrote only %d of %zu\n", total,  							amount); -					afc_file_close(afc, af); -					fclose(f); -					free(pkgname); -					goto leave_cleanup; +						afc_file_close(afc, af); +						fclose(f); +						free(pkgname); +						goto leave_cleanup; +					}  				}  			} -		} -		while (amount > 0); +			while (amount > 0); -		afc_file_close(afc, af); -		fclose(f); +			afc_file_close(afc, af); +			fclose(f); -		printf("done.\n"); +			printf("done.\n"); -		/* perform installation or upgrade */ -		plist_t client_opts = instproxy_client_options_new(); -		if (sinf) { -			instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); -		} -		if (meta) { -			instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL); +			if (sinf) { +				instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); +			} +			if (meta) { +				instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL); +			}  		} +		zip_unchange_all(zf); +		zip_close(zf); + +		/* perform installation or upgrade */  		if (install_mode) {  			printf("Installing '%s'\n", pkgname);  #ifdef HAVE_LIBIMOBILEDEVICE_1_1 | 
