blob: db6e90b52caa2d659e5f5f7ae21454907909d681 [file] [log] [blame]
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001/*
2 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <iostream>
20#include <fstream>
21#include <sstream>
22#include <string>
23#include <vector>
24#include <string.h>
25#include <libgen.h>
26#include <unistd.h>
27#include <sys/stat.h>
28#include <dirent.h>
bigbiff bigbiff84a3f1a2013-12-28 18:32:15 -050029#include <errno.h>
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -040030#include "gui/rapidxml.hpp"
31#include "fixPermissions.hpp"
32#include "twrp-functions.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000033#include "twcommon.h"
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040034#ifdef HAVE_SELINUX
35#include "selinux/selinux.h"
36#include "selinux/label.h"
37#include "selinux/android.h"
38#include "selinux/label.h"
39#endif
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -040040
41using namespace std;
42using namespace rapidxml;
43
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040044#ifdef HAVE_SELINUX
bigbiff bigbiff731df792014-02-20 18:26:13 -050045struct selabel_handle *sehandle;
46struct selinux_opt selinux_options[] = {
47 { SELABEL_OPT_PATH, "/file_contexts" }
48};
49
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040050int fixPermissions::restorecon(string entry, struct stat *sb) {
51 char *oldcontext, *newcontext;
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040052 if (lgetfilecon(entry.c_str(), &oldcontext) < 0) {
53 LOGINFO("Couldn't get selinux context for %s\n", entry.c_str());
54 return -1;
55 }
56 if (selabel_lookup(sehandle, &newcontext, entry.c_str(), sb->st_mode) < 0) {
57 LOGINFO("Couldn't lookup selinux context for %s\n", entry.c_str());
58 return -1;
59 }
bigbiff bigbiff731df792014-02-20 18:26:13 -050060 if (strcmp(oldcontext, newcontext) != 0) {
61 LOGINFO("Relabeling %s from %s to %s\n", entry.c_str(), oldcontext, newcontext);
62 if (lsetfilecon(entry.c_str(), newcontext) < 0) {
63 LOGINFO("Couldn't label %s with %s: %s\n", entry.c_str(), newcontext, strerror(errno));
64 }
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040065 }
66 freecon(oldcontext);
67 freecon(newcontext);
68 return 0;
69}
70
71int fixPermissions::fixDataDataContexts(void) {
bigbiff bigbiff731df792014-02-20 18:26:13 -050072 string dir = "/data/data/";
73 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
74 if (TWFunc::Path_Exists(dir)) {
75 fixContextsRecursively(dir, 0);
76 }
77 selabel_close(sehandle);
78 return 0;
79}
80
81int fixPermissions::fixContextsRecursively(string name, int level) {
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040082 DIR *d;
83 struct dirent *de;
84 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -050085 string path;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -050086
bigbiff bigbiff731df792014-02-20 18:26:13 -050087 if (!(d = opendir(name.c_str())))
88 return -1;
89 if (!(de = readdir(d)))
90 return -1;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -050091
bigbiff bigbiff731df792014-02-20 18:26:13 -050092 do {
93 if (de->d_type == DT_DIR) {
94 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
95 continue;
96 path = name + "/" + de->d_name;
97 restorecon(path, &sb);
98 fixContextsRecursively(path, level + 1);
99 }
100 else {
101 path = name + "/" + de->d_name;
102 restorecon(path, &sb);
103 }
104 } while (de = readdir(d));
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500105 closedir(d);
106 return 0;
107}
108
109int fixPermissions::fixDataInternalContexts(void) {
110 DIR *d;
111 struct dirent *de;
112 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500113 string dir, androiddir;
114 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500115
bigbiff bigbiff731df792014-02-20 18:26:13 -0500116 if (TWFunc::Path_Exists("/data/media/0"))
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500117 dir = "/data/media/0";
bigbiff bigbiff731df792014-02-20 18:26:13 -0500118 else
119 dir = "/data/media";
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500120 LOGINFO("Fixing %s contexts\n", dir.c_str());
bigbiff bigbiff731df792014-02-20 18:26:13 -0500121 restorecon(dir, &sb);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500122 d = opendir(dir.c_str());
123
124 while (( de = readdir(d)) != NULL) {
125 stat(de->d_name, &sb);
126 string f;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500127 f = dir + "/" + de->d_name;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500128 restorecon(f, &sb);
129 }
130 closedir(d);
bigbiff bigbiff731df792014-02-20 18:26:13 -0500131
132 androiddir = dir + "/Android/";
133 if (TWFunc::Path_Exists(androiddir)) {
134 fixContextsRecursively(androiddir, 0);
135 }
136 selabel_close(sehandle);
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400137 return 0;
138}
139#endif
140
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400141int fixPermissions::fixPerms(bool enable_debug, bool remove_data_for_missing_apps) {
142 packageFile = "/data/system/packages.xml";
143 debug = enable_debug;
144 remove_data = remove_data_for_missing_apps;
Dees_Troy201d76b2012-11-16 17:12:02 +0000145 multi_user = TWFunc::Path_Exists("/data/user");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400146
147 if (!(TWFunc::Path_Exists(packageFile))) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000148 gui_print("Can't check permissions\n");
149 gui_print("after Factory Reset.\n");
150 gui_print("Please boot rom and try\n");
151 gui_print("again after you reboot into\n");
152 gui_print("recovery.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400153 return -1;
154 }
155
Dees_Troy2673cec2013-04-02 20:22:16 +0000156 gui_print("Fixing permissions...\nLoading packages...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400157 if ((getPackages()) != 0) {
158 return -1;
159 }
Dees_Troy32f2ca82013-02-02 17:03:12 +0000160
Dees_Troy2673cec2013-04-02 20:22:16 +0000161 gui_print("Fixing /system/app permissions...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400162 if ((fixSystemApps()) != 0) {
163 return -1;
164 }
165
grimsrudcbec59f2013-07-29 15:46:22 +0200166 gui_print("Fixing /data/app permissions...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400167 if ((fixDataApps()) != 0) {
168 return -1;
169 }
170
Dees_Troy201d76b2012-11-16 17:12:02 +0000171 if (multi_user) {
172 DIR *d = opendir("/data/user");
173 string new_path, user_id;
174
175 if (d == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000176 LOGERR("Error opening '/data/user'\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000177 return -1;
178 }
179
180 if (d) {
181 struct dirent *p;
182 while ((p = readdir(d))) {
183 if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
184 continue;
185
186 new_path = "/data/user/";
187 new_path.append(p->d_name);
188 user_id = "u";
189 user_id += p->d_name;
190 user_id += "_";
191 if (p->d_type == DT_LNK) {
192 char link[512], realPath[512];
193 strcpy(link, new_path.c_str());
194 memset(realPath, 0, sizeof(realPath));
195 while (readlink(link, realPath, sizeof(realPath)) > 0) {
196 strcpy(link, realPath);
197 memset(realPath, 0, sizeof(realPath));
198 }
199 new_path = link;
200 } else if (p->d_type != DT_DIR) {
201 continue;
202 } else {
203 new_path.append("/");
204 // We're probably going to need to fix permissions on multi user but
205 // it will have to wait for another time. Need to figure out where
206 // the uid and gid is stored for other users.
207 continue;
208 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000209 gui_print("Fixing %s permissions...\n", new_path.c_str());
Dees_Troy201d76b2012-11-16 17:12:02 +0000210 if ((fixDataData(new_path)) != 0) {
211 closedir(d);
212 return -1;
213 }
214 }
215 closedir(d);
216 }
217 } else {
grimsrudcbec59f2013-07-29 15:46:22 +0200218 gui_print("Fixing /data/data permissions...\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000219 if ((fixDataData("/data/data/")) != 0) {
220 return -1;
221 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400222 }
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400223 #ifdef HAVE_SELINUX
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500224 gui_print("Fixing /data/data/ contexts.\n");
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400225 fixDataDataContexts();
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500226 fixDataInternalContexts();
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400227 #endif
Dees_Troy2673cec2013-04-02 20:22:16 +0000228 gui_print("Done fixing permissions.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400229 return 0;
230}
231
232int fixPermissions::pchown(string fn, int puid, int pgid) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000233 LOGINFO("Fixing %s, uid: %d, gid: %d\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400234 if (chown(fn.c_str(), puid, pgid) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000235 LOGERR("Unable to chown '%s' %i %i\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400236 return -1;
237 }
238 return 0;
239}
240
241int fixPermissions::pchmod(string fn, string mode) {
242 long mask = 0;
Dees_Troy2673cec2013-04-02 20:22:16 +0000243 LOGINFO("Fixing %s, mode: %s\n", fn.c_str(), mode.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400244 for ( std::string::size_type n = 0; n < mode.length(); ++n) {
245 if (n == 0) {
246 if (mode[n] == '0')
247 continue;
248 else if (mode[n] == '1')
249 mask = S_ISVTX;
250 else if (mode[n] == '2')
251 mask = S_ISGID;
252 }
253 else if (n == 1) {
254 if (mode[n] == '7') {
255 mask |= S_IRWXU;
256 }
257 if (mode[n] == '6') {
258 mask |= S_IRUSR;
259 mask |= S_IWUSR;
260 }
261 if (mode[n] == '5') {
262 mask |= S_IRUSR;
263 mask |= S_IXUSR;
264 }
265 if (mode[n] == '4')
266 mask |= S_IRUSR;
267 if (mode[n] == '3') {
268 mask |= S_IWUSR;
269 mask |= S_IRUSR;
270 }
271 if (mode[n] == '2')
272 mask |= S_IWUSR;
273 if (mode[n] == '1')
274 mask |= S_IXUSR;
275 }
276 else if (n == 2) {
277 if (mode[n] == '7') {
278 mask |= S_IRWXG;
279 }
280 if (mode[n] == '6') {
281 mask |= S_IRGRP;
282 mask |= S_IWGRP;
283 }
284 if (mode[n] == '5') {
285 mask |= S_IRGRP;
286 mask |= S_IXGRP;
287 }
288 if (mode[n] == '4')
289 mask |= S_IRGRP;
290 if (mode[n] == '3') {
291 mask |= S_IWGRP;
292 mask |= S_IXGRP;
293 }
294 if (mode[n] == '2')
295 mask |= S_IWGRP;
296 if (mode[n] == '1')
297 mask |= S_IXGRP;
298 }
299 else if (n == 3) {
300 if (mode[n] == '7') {
301 mask |= S_IRWXO;
302 }
303 if (mode[n] == '6') {
304 mask |= S_IROTH;
305 mask |= S_IWOTH;
306 }
307 if (mode[n] == '5') {
308 mask |= S_IROTH;
309 mask |= S_IXOTH;
310 }
311 if (mode[n] == '4')
312 mask |= S_IROTH;
313 if (mode[n] == '3') {
314 mask |= S_IWOTH;
315 mask |= S_IXOTH;
316 }
317 if (mode[n] == '2')
Dees_Troy6480ce02012-10-10 10:26:54 -0400318 mask |= S_IWOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400319 if (mode[n] == '1')
Dees_Troy6480ce02012-10-10 10:26:54 -0400320 mask |= S_IXOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400321 }
322 }
323
324 if (chmod(fn.c_str(), mask) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000325 LOGERR("Unable to chmod '%s' %l\n", fn.c_str(), mask);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400326 return -1;
327 }
328
329 return 0;
330}
331
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400332int fixPermissions::fixSystemApps() {
333 temp = head;
334 while (temp != NULL) {
335 if (TWFunc::Path_Exists(temp->codePath)) {
336 if (temp->appDir.compare("/system/app") == 0) {
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400337 if (debug) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000338 LOGINFO("Looking at '%s'\n", temp->codePath.c_str());
339 LOGINFO("Fixing permissions on '%s'\n", temp->pkgName.c_str());
340 LOGINFO("Directory: '%s'\n", temp->appDir.c_str());
341 LOGINFO("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400342 }
343 if (pchown(temp->codePath, 0, 0) != 0)
344 return -1;
345 if (pchmod(temp->codePath, "0644") != 0)
346 return -1;
347 }
348 } else {
349 //Remove data directory since app isn't installed
350 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
351 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000352 LOGINFO("Looking at '%s', removing data dir: '%s', appDir: '%s'", temp->codePath.c_str(), temp->dDir.c_str(), temp->appDir.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500353 if (TWFunc::removeDir(temp->dDir, false) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000354 LOGINFO("Unable to removeDir '%s'\n", temp->dDir.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400355 return -1;
356 }
357 }
358 }
359 temp = temp->next;
360 }
361 return 0;
362}
363
364int fixPermissions::fixDataApps() {
365 bool fix = false;
366 int new_gid = 0;
367 string perms = "0000";
368
369 temp = head;
370 while (temp != NULL) {
371 if (TWFunc::Path_Exists(temp->codePath)) {
372 if (temp->appDir.compare("/data/app") == 0 || temp->appDir.compare("/sd-ext/app") == 0) {
373 fix = true;
374 new_gid = 1000;
375 perms = "0644";
376 } else if (temp->appDir.compare("/data/app-private") == 0 || temp->appDir.compare("/sd-ext/app-private") == 0) {
377 fix = true;
378 new_gid = temp->gid;
379 perms = "0640";
380 } else
381 fix = false;
382 if (fix) {
383 if (debug) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000384 LOGINFO("Looking at '%s'\n", temp->codePath.c_str());
385 LOGINFO("Fixing permissions on '%s'\n", temp->pkgName.c_str());
386 LOGINFO("Directory: '%s'\n", temp->appDir.c_str());
387 LOGINFO("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400388 }
389 if (pchown(temp->codePath, 1000, new_gid) != 0)
390 return -1;
391 if (pchmod(temp->codePath, perms) != 0)
392 return -1;
393 }
394 } else {
395 //Remove data directory since app isn't installed
396 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
397 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000398 LOGINFO("Looking at '%s', removing data dir: '%s', appDir: '%s'", temp->codePath.c_str(), temp->dDir.c_str(), temp->appDir.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500399 if (TWFunc::removeDir(temp->dDir, false) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000400 LOGINFO("Unable to removeDir '%s'\n", temp->dDir.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400401 return -1;
402 }
403 }
404 }
405 temp = temp->next;
406 }
407 return 0;
408}
409
410int fixPermissions::fixAllFiles(string directory, int gid, int uid, string file_perms) {
411 vector <string> files;
412 string file;
413
414 files = listAllFiles(directory);
415 for (unsigned i = 0; i < files.size(); ++i) {
416 file = directory + "/";
417 file.append(files.at(i));
418 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000419 LOGINFO("Looking at file '%s'\n", file.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400420 if (pchmod(file, file_perms) != 0)
421 return -1;
422 if (pchown(file, uid, gid) != 0)
423 return -1;
424 }
425 return 0;
426}
427
Dees_Troy201d76b2012-11-16 17:12:02 +0000428int fixPermissions::fixDataData(string dataDir) {
429 string directory, dir;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400430
431 temp = head;
432 while (temp != NULL) {
Dees_Troy201d76b2012-11-16 17:12:02 +0000433 dir = dataDir + temp->dDir;
434 if (TWFunc::Path_Exists(dir)) {
435 vector <string> dataDataDirs = listAllDirectories(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400436 for (unsigned n = 0; n < dataDataDirs.size(); ++n) {
Dees_Troy201d76b2012-11-16 17:12:02 +0000437 directory = dir + "/";
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400438 directory.append(dataDataDirs.at(n));
439 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000440 LOGINFO("Looking at data directory: '%s'\n", directory.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400441 if (dataDataDirs.at(n) == ".") {
Dees_Troy201d76b2012-11-16 17:12:02 +0000442 if (pchmod(directory, "0755") != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400443 return -1;
444 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
445 return -1;
446 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
447 return -1;
448 }
449 else if (dataDataDirs.at(n) == "..") {
450 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000451 LOGINFO("Skipping ..\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400452 continue;
453 }
454 else if (dataDataDirs.at(n) == "lib") {
455 if (pchmod(directory.c_str(), "0755") != 0)
456 return -1;
457 if (pchown(directory.c_str(), 1000, 1000) != 0)
458 return -1;
459 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
460 return -1;
461 }
462 else if (dataDataDirs.at(n) == "shared_prefs") {
463 if (pchmod(directory.c_str(), "0771") != 0)
464 return -1;
465 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
466 return -1;
467 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
468 return -1;
469 }
470 else if (dataDataDirs.at(n) == "databases") {
471 if (pchmod(directory.c_str(), "0771") != 0)
472 return -1;
473 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
474 return -1;
475 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
476 return -1;
477 }
478 else if (dataDataDirs.at(n) == "cache") {
479 if (pchmod(directory.c_str(), "0771") != 0)
480 return -1;
481 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
482 return -1;
483 if (fixAllFiles(directory, temp->uid, temp->gid, "0600") != 0)
484 return -1;
485 }
486 else {
487 if (pchmod(directory.c_str(), "0771") != 0)
488 return -1;
489 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
490 return -1;
491 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
492 return -1;
493 }
494 }
495 }
496 temp = temp->next;
497 }
498 return 0;
499}
500
501vector <string> fixPermissions::listAllDirectories(string path) {
502 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400503 vector <string> dirs;
504
505 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000506 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400507 return dirs;
508 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000509 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400510 while (entry != NULL) {
511 if (entry->d_type == DT_DIR)
512 dirs.push_back(entry->d_name);
513 entry = readdir(dir);
514 }
515 closedir(dir);
516 return dirs;
517}
518
519vector <string> fixPermissions::listAllFiles(string path) {
520 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400521 vector <string> files;
522
523 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000524 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400525 return files;
526 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000527 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400528 while (entry != NULL) {
529 if (entry->d_type == DT_REG)
530 files.push_back(entry->d_name);
531 entry = readdir(dir);
532 }
533 closedir(dir);
534 return files;
535}
536
537int fixPermissions::getPackages() {
538 int len = 0;
539 bool skiploop = false;
540 vector <string> skip;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400541 string name;
542 head = NULL;
543
544 skip.push_back("/system/framework/framework-res.apk");
545 skip.push_back("/system/framework/com.htc.resources.apk");
546
547 ifstream xmlFile(packageFile.c_str());
548 xmlFile.seekg(0, ios::end);
549 len = (int) xmlFile.tellg();
550 xmlFile.seekg(0, ios::beg);
551 char xmlBuf[len + 1];
552 xmlFile.read(&xmlBuf[0], len);
553 xmlBuf[len] = '\0';
554 xml_document<> pkgDoc;
Dees_Troy34614eb2013-04-05 12:02:14 -0500555 LOGINFO("parsing package, %i...\n", len);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400556 pkgDoc.parse<parse_full>(&xmlBuf[0]);
557
558 xml_node<> * pkgNode = pkgDoc.first_node("packages");
Dees_Troy34614eb2013-04-05 12:02:14 -0500559 if (pkgNode == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000560 LOGERR("No packages found to fix.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400561 return -1;
562 }
Dees_Troy34614eb2013-04-05 12:02:14 -0500563 xml_node <> * next = pkgNode->first_node("package");
564 if (next == NULL) {
565 LOGERR("No package found to fix.\n");
566 return -1;
567 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400568
569 //Get packages
570 while (next->first_attribute("name") != NULL) {
571 package* temp = new package;
572 for (unsigned n = 0; n < skip.size(); ++n) {
573 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
574 skiploop = true;
575 break;
576 }
577 }
578
579 if (skiploop == true) {
580 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000581 LOGINFO("Skipping package %s\n", next->first_attribute("codePath")->value());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400582 free(temp);
583 next = next->next_sibling();
584 skiploop = false;
585 continue;
586 }
587 name.append((next->first_attribute("name")->value()));
588 temp->pkgName = next->first_attribute("name")->value();
589 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000590 LOGINFO("Loading pkg: %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000591 if (next->first_attribute("codePath") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000592 LOGINFO("Problem with codePath on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000593 } else {
594 temp->codePath = next->first_attribute("codePath")->value();
595 temp->app = basename(next->first_attribute("codePath")->value());
596 temp->appDir = dirname(next->first_attribute("codePath")->value());
597 }
598 temp->dDir = name;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400599 if ( next->first_attribute("sharedUserId") != NULL) {
600 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
601 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
602 }
603 else {
Dees_Troy201d76b2012-11-16 17:12:02 +0000604 if (next->first_attribute("userId") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000605 LOGINFO("Problem with userID on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000606 } else {
607 temp->uid = atoi(next->first_attribute("userId")->value());
608 temp->gid = atoi(next->first_attribute("userId")->value());
609 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400610 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400611 temp->next = head;
612 head = temp;
Dees_Troy201d76b2012-11-16 17:12:02 +0000613 if (next->next_sibling("package") == NULL)
614 break;
615 name.clear();
616 next = next->next_sibling("package");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400617 }
618 //Get updated packages
619 next = pkgNode->first_node("updated-package");
620 if (next != NULL) {
621 while (next->first_attribute("name") != NULL) {
622 package* temp = new package;
623 for (unsigned n = 0; n < skip.size(); ++n) {
624 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
625 skiploop = true;
626 break;
627 }
628 }
629
630 if (skiploop == true) {
631 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000632 LOGINFO("Skipping package %s\n", next->first_attribute("codePath")->value());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400633 free(temp);
634 next = next->next_sibling();
635 skiploop = false;
636 continue;
637 }
638 name.append((next->first_attribute("name")->value()));
639 temp->pkgName = next->first_attribute("name")->value();
640 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000641 LOGINFO("Loading pkg: %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000642 if (next->first_attribute("codePath") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000643 LOGINFO("Problem with codePath on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000644 } else {
645 temp->codePath = next->first_attribute("codePath")->value();
646 temp->app = basename(next->first_attribute("codePath")->value());
647 temp->appDir = dirname(next->first_attribute("codePath")->value());
648 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400649
Dees_Troy201d76b2012-11-16 17:12:02 +0000650 temp->dDir = name;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400651 if ( next->first_attribute("sharedUserId") != NULL) {
652 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
653 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
654 }
655 else {
Dees_Troy201d76b2012-11-16 17:12:02 +0000656 if (next->first_attribute("userId") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000657 LOGINFO("Problem with userID on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000658 } else {
659 temp->uid = atoi(next->first_attribute("userId")->value());
660 temp->gid = atoi(next->first_attribute("userId")->value());
661 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400662 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400663 temp->next = head;
664 head = temp;
Dees_Troy201d76b2012-11-16 17:12:02 +0000665 if (next->next_sibling("package") == NULL)
666 break;
667 name.clear();
668 next = next->next_sibling("package");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400669 }
670 }
671 return 0;
672}