]>
Commit | Line | Data |
---|---|---|
1 | #include "CyteKit/UCPlatform.h" | |
2 | ||
3 | #include <dirent.h> | |
4 | #include <strings.h> | |
5 | ||
6 | #include <sys/stat.h> | |
7 | #include <sys/sysctl.h> | |
8 | #include <sys/types.h> | |
9 | ||
10 | #include <Menes/ObjectHandle.h> | |
11 | ||
12 | void Finish(const char *finish) { | |
13 | if (finish == NULL) | |
14 | return; | |
15 | ||
16 | const char *cydia(getenv("CYDIA")); | |
17 | if (cydia == NULL) | |
18 | return; | |
19 | ||
20 | int fd([[[[NSString stringWithUTF8String:cydia] componentsSeparatedByString:@" "] objectAtIndex:0] intValue]); | |
21 | ||
22 | FILE *fout(fdopen(fd, "w")); | |
23 | fprintf(fout, "finish:%s\n", finish); | |
24 | fclose(fout); | |
25 | } | |
26 | ||
27 | static bool setnsfpn(const char *path) { | |
28 | return system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn %s", path] UTF8String]) == 0; | |
29 | } | |
30 | ||
31 | enum StashStatus { | |
32 | StashDone, | |
33 | StashFail, | |
34 | StashGood, | |
35 | }; | |
36 | ||
37 | static StashStatus MoveStash() { | |
38 | struct stat stat; | |
39 | ||
40 | if (lstat("/var/stash", &stat) == -1) | |
41 | return errno == ENOENT ? StashGood : StashFail; | |
42 | else if (S_ISLNK(stat.st_mode)) | |
43 | return StashGood; | |
44 | else if (!S_ISDIR(stat.st_mode)) | |
45 | return StashFail; | |
46 | ||
47 | if (lstat("/var/db/stash", &stat) == -1) { | |
48 | if (errno == ENOENT) | |
49 | goto move; | |
50 | else return StashFail; | |
51 | } else if (S_ISLNK(stat.st_mode)) | |
52 | // XXX: this is fixable | |
53 | return StashFail; | |
54 | else if (!S_ISDIR(stat.st_mode)) | |
55 | return StashFail; | |
56 | else { | |
57 | if (!setnsfpn("/var/db/stash")) | |
58 | return StashFail; | |
59 | if (system("mv -t /var/stash /var/db/stash/*") != 0) | |
60 | return StashFail; | |
61 | if (rmdir("/var/db/stash") == -1) | |
62 | return StashFail; | |
63 | } move: | |
64 | ||
65 | if (!setnsfpn("/var/stash")) | |
66 | return StashFail; | |
67 | ||
68 | if (rename("/var/stash", "/var/db/stash") == -1) | |
69 | return StashFail; | |
70 | if (symlink("/var/db/stash", "/var/stash") != -1) | |
71 | return StashDone; | |
72 | if (rename("/var/db/stash", "/var/stash") != -1) | |
73 | return StashFail; | |
74 | ||
75 | fprintf(stderr, "/var/stash misplaced -- DO NOT REBOOT\n"); | |
76 | return StashFail; | |
77 | } | |
78 | ||
79 | static bool FixProtections() { | |
80 | const char *path("/var/lib"); | |
81 | mkdir(path, 0755); | |
82 | if (!setnsfpn(path)) { | |
83 | fprintf(stderr, "failed to setnsfpn %s\n", path); | |
84 | return false; | |
85 | } | |
86 | ||
87 | return true; | |
88 | } | |
89 | ||
90 | static void FixPermissions() { | |
91 | DIR *stash(opendir("/var/stash")); | |
92 | if (stash == NULL) | |
93 | return; | |
94 | ||
95 | while (dirent *entry = readdir(stash)) { | |
96 | const char *folder(entry->d_name); | |
97 | if (strlen(folder) != 8) | |
98 | continue; | |
99 | if (strncmp(folder, "_.", 2) != 0) | |
100 | continue; | |
101 | ||
102 | char path[1024]; | |
103 | sprintf(path, "/var/stash/%s", folder); | |
104 | ||
105 | struct stat stat; | |
106 | if (lstat(path, &stat) == -1) | |
107 | continue; | |
108 | if (!S_ISDIR(stat.st_mode)) | |
109 | continue; | |
110 | ||
111 | chmod(path, 0755); | |
112 | } | |
113 | ||
114 | closedir(stash); | |
115 | } | |
116 | ||
117 | #define APPLICATIONS "/Applications" | |
118 | static bool FixApplications() { | |
119 | char target[1024]; | |
120 | ssize_t length(readlink(APPLICATIONS, target, sizeof(target))); | |
121 | if (length == -1) | |
122 | return false; | |
123 | ||
124 | if (length >= sizeof(target)) // >= "just in case" (I'm nervous) | |
125 | return false; | |
126 | target[length] = '\0'; | |
127 | ||
128 | if (strlen(target) != 30) | |
129 | return false; | |
130 | if (memcmp(target, "/var/stash/Applications.", 24) != 0) | |
131 | return false; | |
132 | if (strchr(target + 24, '/') != NULL) | |
133 | return false; | |
134 | ||
135 | struct stat stat; | |
136 | if (lstat(target, &stat) == -1) | |
137 | return false; | |
138 | if (!S_ISDIR(stat.st_mode)) | |
139 | return false; | |
140 | ||
141 | char temp[] = "/var/stash/_.XXXXXX"; | |
142 | if (mkdtemp(temp) == NULL) | |
143 | return false; | |
144 | ||
145 | if (false) undo: { | |
146 | unlink(temp); | |
147 | return false; | |
148 | } | |
149 | ||
150 | if (chmod(temp, 0755) == -1) | |
151 | goto undo; | |
152 | ||
153 | char destiny[strlen(temp) + 32]; | |
154 | sprintf(destiny, "%s%s", temp, APPLICATIONS); | |
155 | ||
156 | if (unlink(APPLICATIONS) == -1) | |
157 | goto undo; | |
158 | ||
159 | if (rename(target, destiny) == -1) { | |
160 | if (symlink(target, APPLICATIONS) == -1) | |
161 | fprintf(stderr, "/Applications damaged -- DO NOT REBOOT\n"); | |
162 | goto undo; | |
163 | } else { | |
164 | bool success; | |
165 | if (symlink(destiny, APPLICATIONS) != -1) | |
166 | success = true; | |
167 | else { | |
168 | fprintf(stderr, "/var/stash/Applications damaged -- DO NOT REBOOT\n"); | |
169 | success = false; | |
170 | } | |
171 | ||
172 | // unneccessary, but feels better (I'm nervous) | |
173 | symlink(destiny, target); | |
174 | ||
175 | [@APPLICATIONS writeToFile:[NSString stringWithFormat:@"%s.lnk", temp] atomically:YES encoding:NSNonLossyASCIIStringEncoding error:NULL]; | |
176 | return success; | |
177 | } | |
178 | } | |
179 | ||
180 | int main(int argc, const char *argv[]) { | |
181 | if (argc < 2 || strcmp(argv[1], "configure") != 0) | |
182 | return 0; | |
183 | ||
184 | NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); | |
185 | ||
186 | bool restart(false); | |
187 | ||
188 | if (kCFCoreFoundationVersionNumber >= 1000) { | |
189 | if (!FixProtections()) | |
190 | return 1; | |
191 | switch (MoveStash()) { | |
192 | case StashDone: | |
193 | restart = true; | |
194 | break; | |
195 | case StashFail: | |
196 | fprintf(stderr, "failed to move stash\n"); | |
197 | return 1; | |
198 | case StashGood: | |
199 | break; | |
200 | } | |
201 | } | |
202 | ||
203 | #define OldCache_ "/var/root/Library/Caches/com.saurik.Cydia" | |
204 | if (access(OldCache_, F_OK) == 0) | |
205 | system("rm -rf " OldCache_); | |
206 | ||
207 | #define NewCache_ "/var/mobile/Library/Caches/com.saurik.Cydia" | |
208 | system("cd /; su -c 'mkdir -p " NewCache_ "' mobile"); | |
209 | if (access(NewCache_ "/lists", F_OK) != 0 && errno == ENOENT) | |
210 | system("cp -at " NewCache_ " /var/lib/apt/lists"); | |
211 | system("chown -R 501.501 " NewCache_); | |
212 | ||
213 | #define OldLibrary_ "/var/lib/cydia" | |
214 | ||
215 | #define NewLibrary_ "/var/mobile/Library/Cydia" | |
216 | system("cd /; su -c 'mkdir -p " NewLibrary_ "' mobile"); | |
217 | ||
218 | #define Cytore_ "/metadata.cb0" | |
219 | ||
220 | #define CYDIA_LIST "/etc/apt/sources.list.d/cydia.list" | |
221 | unlink(CYDIA_LIST); | |
222 | [[NSString stringWithFormat:@ | |
223 | "deb http://apt.saurik.com/ ios/%.2f main\n" | |
224 | "deb http://apt.thebigboss.org/repofiles/cydia/ stable main\n" | |
225 | "deb http://cydia.zodttd.com/repo/cydia/ stable main\n" | |
226 | "deb http://apt.modmyi.com/ stable main\n" | |
227 | , kCFCoreFoundationVersionNumber] writeToFile:@ CYDIA_LIST atomically:YES]; | |
228 | ||
229 | if (access(NewLibrary_ Cytore_, F_OK) != 0 && errno == ENOENT) { | |
230 | if (access(NewCache_ Cytore_, F_OK) == 0) | |
231 | system("mv -f " NewCache_ Cytore_ " " NewLibrary_); | |
232 | else if (access(OldLibrary_ Cytore_, F_OK) == 0) | |
233 | system("mv -f " OldLibrary_ Cytore_ " " NewLibrary_); | |
234 | chown(NewLibrary_ Cytore_, 501, 501); | |
235 | } | |
236 | ||
237 | FixPermissions(); | |
238 | ||
239 | restart |= FixApplications(); | |
240 | ||
241 | if (restart) | |
242 | Finish("restart"); | |
243 | ||
244 | [pool release]; | |
245 | return 0; | |
246 | } |