blob: 5d57b47a4a8cfeb3af73914e2684bd5548fbff37 [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);
Dees Troyae95d1a2014-09-16 19:05:51 +000074 if (!sehandle) {
75 LOGINFO("Unable to open /file_contexts\n");
76 return 0;
77 }
bigbiff bigbiff731df792014-02-20 18:26:13 -050078 if (TWFunc::Path_Exists(dir)) {
79 fixContextsRecursively(dir, 0);
80 }
81 selabel_close(sehandle);
82 return 0;
83}
84
85int fixPermissions::fixContextsRecursively(string name, int level) {
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040086 DIR *d;
87 struct dirent *de;
88 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -050089 string path;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -050090
bigbiff bigbiff731df792014-02-20 18:26:13 -050091 if (!(d = opendir(name.c_str())))
92 return -1;
93 if (!(de = readdir(d)))
94 return -1;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -050095
bigbiff bigbiff731df792014-02-20 18:26:13 -050096 do {
97 if (de->d_type == DT_DIR) {
98 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
99 continue;
100 path = name + "/" + de->d_name;
101 restorecon(path, &sb);
102 fixContextsRecursively(path, level + 1);
103 }
104 else {
105 path = name + "/" + de->d_name;
106 restorecon(path, &sb);
107 }
108 } while (de = readdir(d));
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500109 closedir(d);
110 return 0;
111}
112
113int fixPermissions::fixDataInternalContexts(void) {
114 DIR *d;
115 struct dirent *de;
116 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500117 string dir, androiddir;
118 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
Dees Troyae95d1a2014-09-16 19:05:51 +0000119 if (!sehandle) {
120 LOGINFO("Unable to open /file_contexts\n");
121 return 0;
122 }
bigbiff bigbiff731df792014-02-20 18:26:13 -0500123 if (TWFunc::Path_Exists("/data/media/0"))
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500124 dir = "/data/media/0";
bigbiff bigbiff731df792014-02-20 18:26:13 -0500125 else
126 dir = "/data/media";
Ethan Yonker5eac2222014-06-11 12:22:55 -0500127 if (!TWFunc::Path_Exists(dir)) {
128 LOGINFO("fixDataInternalContexts: '%s' does not exist!\n", dir.c_str());
129 return 0;
130 }
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500131 LOGINFO("Fixing %s contexts\n", dir.c_str());
bigbiff bigbiff731df792014-02-20 18:26:13 -0500132 restorecon(dir, &sb);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500133 d = opendir(dir.c_str());
134
135 while (( de = readdir(d)) != NULL) {
136 stat(de->d_name, &sb);
137 string f;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500138 f = dir + "/" + de->d_name;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500139 restorecon(f, &sb);
140 }
141 closedir(d);
bigbiff bigbiff731df792014-02-20 18:26:13 -0500142
143 androiddir = dir + "/Android/";
144 if (TWFunc::Path_Exists(androiddir)) {
145 fixContextsRecursively(androiddir, 0);
146 }
147 selabel_close(sehandle);
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400148 return 0;
149}
150#endif
151
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400152int fixPermissions::fixPerms(bool enable_debug, bool remove_data_for_missing_apps) {
153 packageFile = "/data/system/packages.xml";
154 debug = enable_debug;
155 remove_data = remove_data_for_missing_apps;
Dees_Troy201d76b2012-11-16 17:12:02 +0000156 multi_user = TWFunc::Path_Exists("/data/user");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400157
158 if (!(TWFunc::Path_Exists(packageFile))) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000159 gui_print("Can't check permissions\n");
160 gui_print("after Factory Reset.\n");
161 gui_print("Please boot rom and try\n");
162 gui_print("again after you reboot into\n");
163 gui_print("recovery.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400164 return -1;
165 }
166
Dees_Troy2673cec2013-04-02 20:22:16 +0000167 gui_print("Fixing permissions...\nLoading packages...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400168 if ((getPackages()) != 0) {
169 return -1;
170 }
Dees_Troy32f2ca82013-02-02 17:03:12 +0000171
Dees_Troy2673cec2013-04-02 20:22:16 +0000172 gui_print("Fixing /system/app permissions...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400173 if ((fixSystemApps()) != 0) {
174 return -1;
175 }
176
grimsrudcbec59f2013-07-29 15:46:22 +0200177 gui_print("Fixing /data/app permissions...\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400178 if ((fixDataApps()) != 0) {
179 return -1;
180 }
181
Dees_Troy201d76b2012-11-16 17:12:02 +0000182 if (multi_user) {
183 DIR *d = opendir("/data/user");
184 string new_path, user_id;
185
186 if (d == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000187 LOGERR("Error opening '/data/user'\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000188 return -1;
189 }
190
191 if (d) {
192 struct dirent *p;
193 while ((p = readdir(d))) {
194 if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
195 continue;
196
197 new_path = "/data/user/";
198 new_path.append(p->d_name);
199 user_id = "u";
200 user_id += p->d_name;
201 user_id += "_";
202 if (p->d_type == DT_LNK) {
203 char link[512], realPath[512];
204 strcpy(link, new_path.c_str());
205 memset(realPath, 0, sizeof(realPath));
206 while (readlink(link, realPath, sizeof(realPath)) > 0) {
207 strcpy(link, realPath);
208 memset(realPath, 0, sizeof(realPath));
209 }
210 new_path = link;
211 } else if (p->d_type != DT_DIR) {
212 continue;
213 } else {
214 new_path.append("/");
215 // We're probably going to need to fix permissions on multi user but
216 // it will have to wait for another time. Need to figure out where
217 // the uid and gid is stored for other users.
218 continue;
219 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000220 gui_print("Fixing %s permissions...\n", new_path.c_str());
Dees_Troy201d76b2012-11-16 17:12:02 +0000221 if ((fixDataData(new_path)) != 0) {
222 closedir(d);
223 return -1;
224 }
225 }
226 closedir(d);
227 }
228 } else {
grimsrudcbec59f2013-07-29 15:46:22 +0200229 gui_print("Fixing /data/data permissions...\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000230 if ((fixDataData("/data/data/")) != 0) {
231 return -1;
232 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400233 }
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400234 #ifdef HAVE_SELINUX
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500235 gui_print("Fixing /data/data/ contexts.\n");
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400236 fixDataDataContexts();
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500237 fixDataInternalContexts();
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400238 #endif
Dees_Troy2673cec2013-04-02 20:22:16 +0000239 gui_print("Done fixing permissions.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400240 return 0;
241}
242
243int fixPermissions::pchown(string fn, int puid, int pgid) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000244 LOGINFO("Fixing %s, uid: %d, gid: %d\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400245 if (chown(fn.c_str(), puid, pgid) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000246 LOGERR("Unable to chown '%s' %i %i\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400247 return -1;
248 }
249 return 0;
250}
251
252int fixPermissions::pchmod(string fn, string mode) {
253 long mask = 0;
Dees_Troy2673cec2013-04-02 20:22:16 +0000254 LOGINFO("Fixing %s, mode: %s\n", fn.c_str(), mode.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400255 for ( std::string::size_type n = 0; n < mode.length(); ++n) {
256 if (n == 0) {
257 if (mode[n] == '0')
258 continue;
259 else if (mode[n] == '1')
260 mask = S_ISVTX;
261 else if (mode[n] == '2')
262 mask = S_ISGID;
263 }
264 else if (n == 1) {
265 if (mode[n] == '7') {
266 mask |= S_IRWXU;
267 }
268 if (mode[n] == '6') {
269 mask |= S_IRUSR;
270 mask |= S_IWUSR;
271 }
272 if (mode[n] == '5') {
273 mask |= S_IRUSR;
274 mask |= S_IXUSR;
275 }
276 if (mode[n] == '4')
277 mask |= S_IRUSR;
278 if (mode[n] == '3') {
279 mask |= S_IWUSR;
280 mask |= S_IRUSR;
281 }
282 if (mode[n] == '2')
283 mask |= S_IWUSR;
284 if (mode[n] == '1')
285 mask |= S_IXUSR;
286 }
287 else if (n == 2) {
288 if (mode[n] == '7') {
289 mask |= S_IRWXG;
290 }
291 if (mode[n] == '6') {
292 mask |= S_IRGRP;
293 mask |= S_IWGRP;
294 }
295 if (mode[n] == '5') {
296 mask |= S_IRGRP;
297 mask |= S_IXGRP;
298 }
299 if (mode[n] == '4')
300 mask |= S_IRGRP;
301 if (mode[n] == '3') {
302 mask |= S_IWGRP;
303 mask |= S_IXGRP;
304 }
305 if (mode[n] == '2')
306 mask |= S_IWGRP;
307 if (mode[n] == '1')
308 mask |= S_IXGRP;
309 }
310 else if (n == 3) {
311 if (mode[n] == '7') {
312 mask |= S_IRWXO;
313 }
314 if (mode[n] == '6') {
315 mask |= S_IROTH;
316 mask |= S_IWOTH;
317 }
318 if (mode[n] == '5') {
319 mask |= S_IROTH;
320 mask |= S_IXOTH;
321 }
322 if (mode[n] == '4')
323 mask |= S_IROTH;
324 if (mode[n] == '3') {
325 mask |= S_IWOTH;
326 mask |= S_IXOTH;
327 }
328 if (mode[n] == '2')
Dees_Troy6480ce02012-10-10 10:26:54 -0400329 mask |= S_IWOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400330 if (mode[n] == '1')
Dees_Troy6480ce02012-10-10 10:26:54 -0400331 mask |= S_IXOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400332 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500333 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400334
335 if (chmod(fn.c_str(), mask) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000336 LOGERR("Unable to chmod '%s' %l\n", fn.c_str(), mask);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400337 return -1;
338 }
339
340 return 0;
341}
342
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400343int fixPermissions::fixSystemApps() {
344 temp = head;
345 while (temp != NULL) {
346 if (TWFunc::Path_Exists(temp->codePath)) {
bigbiff bigbiffa886ea62014-04-02 20:38:53 -0400347 if (temp->appDir.compare("/system/app") == 0 || temp->appDir.compare("/system/priv-app") == 0) {
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400348 if (debug) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000349 LOGINFO("Looking at '%s'\n", temp->codePath.c_str());
350 LOGINFO("Fixing permissions on '%s'\n", temp->pkgName.c_str());
351 LOGINFO("Directory: '%s'\n", temp->appDir.c_str());
352 LOGINFO("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400353 }
354 if (pchown(temp->codePath, 0, 0) != 0)
355 return -1;
356 if (pchmod(temp->codePath, "0644") != 0)
357 return -1;
358 }
359 } else {
360 //Remove data directory since app isn't installed
361 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
362 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000363 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 -0500364 if (TWFunc::removeDir(temp->dDir, false) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000365 LOGINFO("Unable to removeDir '%s'\n", temp->dDir.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400366 return -1;
367 }
368 }
369 }
370 temp = temp->next;
371 }
372 return 0;
373}
374
375int fixPermissions::fixDataApps() {
376 bool fix = false;
377 int new_gid = 0;
378 string perms = "0000";
379
380 temp = head;
381 while (temp != NULL) {
382 if (TWFunc::Path_Exists(temp->codePath)) {
383 if (temp->appDir.compare("/data/app") == 0 || temp->appDir.compare("/sd-ext/app") == 0) {
384 fix = true;
385 new_gid = 1000;
386 perms = "0644";
387 } else if (temp->appDir.compare("/data/app-private") == 0 || temp->appDir.compare("/sd-ext/app-private") == 0) {
388 fix = true;
389 new_gid = temp->gid;
390 perms = "0640";
391 } else
392 fix = false;
393 if (fix) {
394 if (debug) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000395 LOGINFO("Looking at '%s'\n", temp->codePath.c_str());
396 LOGINFO("Fixing permissions on '%s'\n", temp->pkgName.c_str());
397 LOGINFO("Directory: '%s'\n", temp->appDir.c_str());
398 LOGINFO("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400399 }
400 if (pchown(temp->codePath, 1000, new_gid) != 0)
401 return -1;
402 if (pchmod(temp->codePath, perms) != 0)
403 return -1;
404 }
405 } else {
406 //Remove data directory since app isn't installed
407 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
408 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000409 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 -0500410 if (TWFunc::removeDir(temp->dDir, false) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000411 LOGINFO("Unable to removeDir '%s'\n", temp->dDir.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400412 return -1;
413 }
414 }
415 }
416 temp = temp->next;
417 }
418 return 0;
419}
420
421int fixPermissions::fixAllFiles(string directory, int gid, int uid, string file_perms) {
422 vector <string> files;
423 string file;
424
425 files = listAllFiles(directory);
426 for (unsigned i = 0; i < files.size(); ++i) {
427 file = directory + "/";
428 file.append(files.at(i));
429 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000430 LOGINFO("Looking at file '%s'\n", file.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400431 if (pchmod(file, file_perms) != 0)
432 return -1;
433 if (pchown(file, uid, gid) != 0)
434 return -1;
435 }
436 return 0;
437}
438
Dees_Troy201d76b2012-11-16 17:12:02 +0000439int fixPermissions::fixDataData(string dataDir) {
440 string directory, dir;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400441
442 temp = head;
443 while (temp != NULL) {
Dees_Troy201d76b2012-11-16 17:12:02 +0000444 dir = dataDir + temp->dDir;
445 if (TWFunc::Path_Exists(dir)) {
446 vector <string> dataDataDirs = listAllDirectories(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400447 for (unsigned n = 0; n < dataDataDirs.size(); ++n) {
Dees_Troy201d76b2012-11-16 17:12:02 +0000448 directory = dir + "/";
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400449 directory.append(dataDataDirs.at(n));
450 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000451 LOGINFO("Looking at data directory: '%s'\n", directory.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400452 if (dataDataDirs.at(n) == ".") {
Dees_Troy201d76b2012-11-16 17:12:02 +0000453 if (pchmod(directory, "0755") != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400454 return -1;
455 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
456 return -1;
457 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
458 return -1;
459 }
460 else if (dataDataDirs.at(n) == "..") {
461 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000462 LOGINFO("Skipping ..\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400463 continue;
464 }
465 else if (dataDataDirs.at(n) == "lib") {
466 if (pchmod(directory.c_str(), "0755") != 0)
467 return -1;
468 if (pchown(directory.c_str(), 1000, 1000) != 0)
469 return -1;
470 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
471 return -1;
472 }
473 else if (dataDataDirs.at(n) == "shared_prefs") {
474 if (pchmod(directory.c_str(), "0771") != 0)
475 return -1;
476 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
477 return -1;
478 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
479 return -1;
480 }
481 else if (dataDataDirs.at(n) == "databases") {
482 if (pchmod(directory.c_str(), "0771") != 0)
483 return -1;
484 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
485 return -1;
486 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
487 return -1;
488 }
489 else if (dataDataDirs.at(n) == "cache") {
490 if (pchmod(directory.c_str(), "0771") != 0)
491 return -1;
492 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
493 return -1;
494 if (fixAllFiles(directory, temp->uid, temp->gid, "0600") != 0)
495 return -1;
496 }
497 else {
498 if (pchmod(directory.c_str(), "0771") != 0)
499 return -1;
500 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
501 return -1;
502 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
503 return -1;
504 }
505 }
506 }
507 temp = temp->next;
508 }
509 return 0;
510}
511
512vector <string> fixPermissions::listAllDirectories(string path) {
513 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400514 vector <string> dirs;
515
516 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000517 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400518 return dirs;
519 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000520 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400521 while (entry != NULL) {
522 if (entry->d_type == DT_DIR)
523 dirs.push_back(entry->d_name);
524 entry = readdir(dir);
525 }
526 closedir(dir);
527 return dirs;
528}
529
530vector <string> fixPermissions::listAllFiles(string path) {
531 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400532 vector <string> files;
533
534 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000535 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400536 return files;
537 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000538 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400539 while (entry != NULL) {
540 if (entry->d_type == DT_REG)
541 files.push_back(entry->d_name);
542 entry = readdir(dir);
543 }
544 closedir(dir);
545 return files;
546}
547
548int fixPermissions::getPackages() {
549 int len = 0;
550 bool skiploop = false;
551 vector <string> skip;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400552 string name;
553 head = NULL;
554
555 skip.push_back("/system/framework/framework-res.apk");
556 skip.push_back("/system/framework/com.htc.resources.apk");
557
558 ifstream xmlFile(packageFile.c_str());
559 xmlFile.seekg(0, ios::end);
560 len = (int) xmlFile.tellg();
561 xmlFile.seekg(0, ios::beg);
562 char xmlBuf[len + 1];
563 xmlFile.read(&xmlBuf[0], len);
564 xmlBuf[len] = '\0';
565 xml_document<> pkgDoc;
Dees_Troy34614eb2013-04-05 12:02:14 -0500566 LOGINFO("parsing package, %i...\n", len);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400567 pkgDoc.parse<parse_full>(&xmlBuf[0]);
568
569 xml_node<> * pkgNode = pkgDoc.first_node("packages");
Dees_Troy34614eb2013-04-05 12:02:14 -0500570 if (pkgNode == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000571 LOGERR("No packages found to fix.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400572 return -1;
573 }
Dees_Troy34614eb2013-04-05 12:02:14 -0500574 xml_node <> * next = pkgNode->first_node("package");
575 if (next == NULL) {
576 LOGERR("No package found to fix.\n");
577 return -1;
578 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400579
580 //Get packages
581 while (next->first_attribute("name") != NULL) {
582 package* temp = new package;
583 for (unsigned n = 0; n < skip.size(); ++n) {
584 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
585 skiploop = true;
586 break;
587 }
588 }
589
590 if (skiploop == true) {
591 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000592 LOGINFO("Skipping package %s\n", next->first_attribute("codePath")->value());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400593 free(temp);
594 next = next->next_sibling();
595 skiploop = false;
596 continue;
597 }
598 name.append((next->first_attribute("name")->value()));
599 temp->pkgName = next->first_attribute("name")->value();
600 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000601 LOGINFO("Loading pkg: %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000602 if (next->first_attribute("codePath") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000603 LOGINFO("Problem with codePath on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000604 } else {
605 temp->codePath = next->first_attribute("codePath")->value();
606 temp->app = basename(next->first_attribute("codePath")->value());
607 temp->appDir = dirname(next->first_attribute("codePath")->value());
608 }
609 temp->dDir = name;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400610 if ( next->first_attribute("sharedUserId") != NULL) {
611 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
612 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
613 }
614 else {
Dees_Troy201d76b2012-11-16 17:12:02 +0000615 if (next->first_attribute("userId") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000616 LOGINFO("Problem with userID on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000617 } else {
618 temp->uid = atoi(next->first_attribute("userId")->value());
619 temp->gid = atoi(next->first_attribute("userId")->value());
620 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400621 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400622 temp->next = head;
623 head = temp;
Dees_Troy201d76b2012-11-16 17:12:02 +0000624 if (next->next_sibling("package") == NULL)
625 break;
626 name.clear();
627 next = next->next_sibling("package");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400628 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500629 //Get updated packages
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400630 next = pkgNode->first_node("updated-package");
631 if (next != NULL) {
632 while (next->first_attribute("name") != NULL) {
633 package* temp = new package;
634 for (unsigned n = 0; n < skip.size(); ++n) {
635 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
636 skiploop = true;
637 break;
638 }
639 }
640
641 if (skiploop == true) {
642 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000643 LOGINFO("Skipping package %s\n", next->first_attribute("codePath")->value());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400644 free(temp);
645 next = next->next_sibling();
646 skiploop = false;
647 continue;
648 }
649 name.append((next->first_attribute("name")->value()));
650 temp->pkgName = next->first_attribute("name")->value();
651 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000652 LOGINFO("Loading pkg: %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000653 if (next->first_attribute("codePath") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000654 LOGINFO("Problem with codePath on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000655 } else {
656 temp->codePath = next->first_attribute("codePath")->value();
657 temp->app = basename(next->first_attribute("codePath")->value());
658 temp->appDir = dirname(next->first_attribute("codePath")->value());
659 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400660
Dees_Troy201d76b2012-11-16 17:12:02 +0000661 temp->dDir = name;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400662 if ( next->first_attribute("sharedUserId") != NULL) {
663 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
664 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
665 }
666 else {
Dees_Troy201d76b2012-11-16 17:12:02 +0000667 if (next->first_attribute("userId") == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000668 LOGINFO("Problem with userID on %s\n", next->first_attribute("name")->value());
Dees_Troy201d76b2012-11-16 17:12:02 +0000669 } else {
670 temp->uid = atoi(next->first_attribute("userId")->value());
671 temp->gid = atoi(next->first_attribute("userId")->value());
672 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400673 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400674 temp->next = head;
675 head = temp;
Dees_Troy201d76b2012-11-16 17:12:02 +0000676 if (next->next_sibling("package") == NULL)
677 break;
678 name.clear();
679 next = next->next_sibling("package");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400680 }
681 }
682 return 0;
683}