summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Hector Martin2021-11-17 15:05:46 +0900
committerGravatar Hector Martin2021-11-17 15:58:18 +0900
commit83d301a9e8af048e0be9c7f428ab5aee803025dd (patch)
tree611367b84ab4fd2a718b0a81c5f49f28a2388298
parente7ac67e0b5327e21fa4726c3795011a065c3b89c (diff)
downloadidevicerestore-83d301a9e8af048e0be9c7f428ab5aee803025dd.tar.gz
idevicerestore-83d301a9e8af048e0be9c7f428ab5aee803025dd.tar.bz2
ipsw: Support extracting symlinks as their target name (Monterey)
This already works for zip files, but we need to do a readlink dance for unpacked archives. Signed-off-by: Hector Martin <marcan@marcan.st>
-rw-r--r--src/ipsw.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/src/ipsw.c b/src/ipsw.c
index 7bebd56..1c1ca36 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -629,41 +629,51 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
zip_fclose(zfile);
} else {
char *filepath = build_path(archive->path, infile);
- FILE *f = fopen(filepath, "rb");
- if (!f) {
- error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
- free(filepath);
- ipsw_close(archive);
- return -2;
- }
struct stat fst;
- if (fstat(fileno(f), &fst) != 0) {
- fclose(f);
+ if (lstat(filepath, &fst) != 0) {
error("ERROR: %s: fstat failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
ipsw_close(archive);
return -1;
}
-
size = fst.st_size;
buffer = (unsigned char*)malloc(size+1);
if (buffer == NULL) {
error("ERROR: Out of memory\n");
- fclose(f);
free(filepath);
ipsw_close(archive);
return -1;
}
- if (fread(buffer, 1, size, f) != size) {
+
+ if (S_ISLNK(fst.st_mode)) {
+ if (readlink(filepath, buffer, size) < 0) {
+ error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
+ free(filepath);
+ free(buffer);
+ ipsw_close(archive);
+ return -1;
+ }
+ } else {
+ FILE *f = fopen(filepath, "rb");
+ if (!f) {
+ error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
+ free(filepath);
+ free(buffer);
+ ipsw_close(archive);
+ return -2;
+ }
+ if (fread(buffer, 1, size, f) != size) {
+ fclose(f);
+ error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
+ free(filepath);
+ free(buffer);
+ ipsw_close(archive);
+ return -1;
+ }
fclose(f);
- error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
- free(filepath);
- ipsw_close(archive);
- return -1;
}
buffer[size] = '\0';
- fclose(f);
free(filepath);
}
ipsw_close(archive);