blob: 0648eb69a209a47c5eeb450d5c5c30fffa64e227 [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
thata3d31fb2014-12-21 22:27:40 +010044static const mode_t kMode_0600 = 0600; // S_IRUSR | S_IWUSR
45static const mode_t kMode_0640 = 0640; // S_IRUSR | S_IWUSR | S_IRGRP
46static const mode_t kMode_0644 = 0644; // S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
47static const mode_t kMode_0660 = 0660; // S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
48static const mode_t kMode_0755 = 0755; // S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
49static const mode_t kMode_0771 = 0771; // S_IRWXU | S_IRWXG | S_IXOTH
50
51fixPermissions::fixPermissions() : head(NULL) {
52}
53
54fixPermissions::~fixPermissions() {
55 deletePackages();
56}
57
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040058#ifdef HAVE_SELINUX
bigbiff bigbiff731df792014-02-20 18:26:13 -050059struct selabel_handle *sehandle;
60struct selinux_opt selinux_options[] = {
61 { SELABEL_OPT_PATH, "/file_contexts" }
62};
63
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040064int fixPermissions::restorecon(string entry, struct stat *sb) {
65 char *oldcontext, *newcontext;
thata3d31fb2014-12-21 22:27:40 +010066
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040067 if (lgetfilecon(entry.c_str(), &oldcontext) < 0) {
68 LOGINFO("Couldn't get selinux context for %s\n", entry.c_str());
69 return -1;
70 }
71 if (selabel_lookup(sehandle, &newcontext, entry.c_str(), sb->st_mode) < 0) {
72 LOGINFO("Couldn't lookup selinux context for %s\n", entry.c_str());
73 return -1;
74 }
bigbiff bigbiff731df792014-02-20 18:26:13 -050075 if (strcmp(oldcontext, newcontext) != 0) {
76 LOGINFO("Relabeling %s from %s to %s\n", entry.c_str(), oldcontext, newcontext);
77 if (lsetfilecon(entry.c_str(), newcontext) < 0) {
78 LOGINFO("Couldn't label %s with %s: %s\n", entry.c_str(), newcontext, strerror(errno));
79 }
bigbiff bigbiff872a3b92013-10-18 20:50:25 -040080 }
81 freecon(oldcontext);
82 freecon(newcontext);
83 return 0;
84}
85
86int fixPermissions::fixDataDataContexts(void) {
bigbiff bigbiff731df792014-02-20 18:26:13 -050087 string dir = "/data/data/";
88 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
Dees Troyae95d1a2014-09-16 19:05:51 +000089 if (!sehandle) {
90 LOGINFO("Unable to open /file_contexts\n");
91 return 0;
92 }
bigbiff bigbiff731df792014-02-20 18:26:13 -050093 if (TWFunc::Path_Exists(dir)) {
94 fixContextsRecursively(dir, 0);
95 }
96 selabel_close(sehandle);
97 return 0;
98}
99
100int fixPermissions::fixContextsRecursively(string name, int level) {
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400101 DIR *d;
102 struct dirent *de;
103 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500104 string path;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500105
bigbiff bigbiff731df792014-02-20 18:26:13 -0500106 if (!(d = opendir(name.c_str())))
107 return -1;
108 if (!(de = readdir(d)))
109 return -1;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500110
bigbiff bigbiff731df792014-02-20 18:26:13 -0500111 do {
112 if (de->d_type == DT_DIR) {
113 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
114 continue;
115 path = name + "/" + de->d_name;
116 restorecon(path, &sb);
117 fixContextsRecursively(path, level + 1);
118 }
119 else {
120 path = name + "/" + de->d_name;
121 restorecon(path, &sb);
122 }
thata3d31fb2014-12-21 22:27:40 +0100123 } while ((de = readdir(d)));
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500124 closedir(d);
125 return 0;
126}
127
128int fixPermissions::fixDataInternalContexts(void) {
129 DIR *d;
130 struct dirent *de;
131 struct stat sb;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500132 string dir, androiddir;
133 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
Dees Troyae95d1a2014-09-16 19:05:51 +0000134 if (!sehandle) {
135 LOGINFO("Unable to open /file_contexts\n");
136 return 0;
137 }
thata3d31fb2014-12-21 22:27:40 +0100138 // TODO: what about /data/media/1 etc.?
bigbiff bigbiff731df792014-02-20 18:26:13 -0500139 if (TWFunc::Path_Exists("/data/media/0"))
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500140 dir = "/data/media/0";
bigbiff bigbiff731df792014-02-20 18:26:13 -0500141 else
142 dir = "/data/media";
Ethan Yonker5eac2222014-06-11 12:22:55 -0500143 if (!TWFunc::Path_Exists(dir)) {
144 LOGINFO("fixDataInternalContexts: '%s' does not exist!\n", dir.c_str());
145 return 0;
146 }
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500147 LOGINFO("Fixing %s contexts\n", dir.c_str());
bigbiff bigbiff731df792014-02-20 18:26:13 -0500148 restorecon(dir, &sb);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500149 d = opendir(dir.c_str());
150
151 while (( de = readdir(d)) != NULL) {
152 stat(de->d_name, &sb);
153 string f;
bigbiff bigbiff731df792014-02-20 18:26:13 -0500154 f = dir + "/" + de->d_name;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500155 restorecon(f, &sb);
156 }
157 closedir(d);
bigbiff bigbiff731df792014-02-20 18:26:13 -0500158
159 androiddir = dir + "/Android/";
160 if (TWFunc::Path_Exists(androiddir)) {
161 fixContextsRecursively(androiddir, 0);
162 }
163 selabel_close(sehandle);
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400164 return 0;
165}
166#endif
167
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400168int fixPermissions::fixPerms(bool enable_debug, bool remove_data_for_missing_apps) {
thata3d31fb2014-12-21 22:27:40 +0100169 string packageFile = "/data/system/packages.xml";
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400170 debug = enable_debug;
171 remove_data = remove_data_for_missing_apps;
thata3d31fb2014-12-21 22:27:40 +0100172 bool multi_user = TWFunc::Path_Exists("/data/user");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400173
174 if (!(TWFunc::Path_Exists(packageFile))) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000175 gui_print("Can't check permissions\n");
176 gui_print("after Factory Reset.\n");
177 gui_print("Please boot rom and try\n");
178 gui_print("again after you reboot into\n");
179 gui_print("recovery.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400180 return -1;
181 }
182
Dees_Troy2673cec2013-04-02 20:22:16 +0000183 gui_print("Fixing permissions...\nLoading packages...\n");
thata3d31fb2014-12-21 22:27:40 +0100184 if ((getPackages(packageFile)) != 0) {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400185 return -1;
186 }
Dees_Troy32f2ca82013-02-02 17:03:12 +0000187
thata3d31fb2014-12-21 22:27:40 +0100188 gui_print("Fixing app permissions...\n");
189 if (fixApps() != 0) {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400190 return -1;
191 }
192
Dees_Troy201d76b2012-11-16 17:12:02 +0000193 if (multi_user) {
194 DIR *d = opendir("/data/user");
195 string new_path, user_id;
196
197 if (d == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000198 LOGERR("Error opening '/data/user'\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000199 return -1;
200 }
201
202 if (d) {
203 struct dirent *p;
204 while ((p = readdir(d))) {
205 if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
206 continue;
207
208 new_path = "/data/user/";
209 new_path.append(p->d_name);
210 user_id = "u";
211 user_id += p->d_name;
212 user_id += "_";
213 if (p->d_type == DT_LNK) {
214 char link[512], realPath[512];
215 strcpy(link, new_path.c_str());
216 memset(realPath, 0, sizeof(realPath));
217 while (readlink(link, realPath, sizeof(realPath)) > 0) {
218 strcpy(link, realPath);
219 memset(realPath, 0, sizeof(realPath));
220 }
221 new_path = link;
222 } else if (p->d_type != DT_DIR) {
223 continue;
224 } else {
225 new_path.append("/");
226 // We're probably going to need to fix permissions on multi user but
227 // it will have to wait for another time. Need to figure out where
228 // the uid and gid is stored for other users.
229 continue;
230 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000231 gui_print("Fixing %s permissions...\n", new_path.c_str());
Dees_Troy201d76b2012-11-16 17:12:02 +0000232 if ((fixDataData(new_path)) != 0) {
233 closedir(d);
234 return -1;
235 }
236 }
237 closedir(d);
238 }
239 } else {
grimsrudcbec59f2013-07-29 15:46:22 +0200240 gui_print("Fixing /data/data permissions...\n");
Dees_Troy201d76b2012-11-16 17:12:02 +0000241 if ((fixDataData("/data/data/")) != 0) {
242 return -1;
243 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400244 }
thata3d31fb2014-12-21 22:27:40 +0100245 gui_print("Done fixing permissions.\n");
246 return 0;
247}
248
249int fixPermissions::fixContexts()
250{
251#ifdef HAVE_SELINUX
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500252 gui_print("Fixing /data/data/ contexts.\n");
bigbiff bigbiff872a3b92013-10-18 20:50:25 -0400253 fixDataDataContexts();
bigbiff bigbiff6b600f92014-01-05 18:13:43 -0500254 fixDataInternalContexts();
thata3d31fb2014-12-21 22:27:40 +0100255 gui_print("Done fixing contexts.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400256 return 0;
thata3d31fb2014-12-21 22:27:40 +0100257#endif
258 gui_print("Not fixing SELinux contexts; support not compiled in.\n");
259 return -1;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400260}
261
262int fixPermissions::pchown(string fn, int puid, int pgid) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000263 LOGINFO("Fixing %s, uid: %d, gid: %d\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400264 if (chown(fn.c_str(), puid, pgid) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000265 LOGERR("Unable to chown '%s' %i %i\n", fn.c_str(), puid, pgid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400266 return -1;
267 }
268 return 0;
269}
270
thata3d31fb2014-12-21 22:27:40 +0100271int fixPermissions::pchmod(string fn, mode_t mode) {
272 LOGINFO("Fixing %s, mode: %o\n", fn.c_str(), mode);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400273
thata3d31fb2014-12-21 22:27:40 +0100274 if (chmod(fn.c_str(), mode) != 0) {
275 LOGERR("Unable to chmod '%s' %o\n", fn.c_str(), mode);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400276 return -1;
277 }
278
279 return 0;
280}
281
thata3d31fb2014-12-21 22:27:40 +0100282int fixPermissions::fixApps() {
283 package* temp = head;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400284 while (temp != NULL) {
thata3d31fb2014-12-21 22:27:40 +0100285 struct stat st;
286 if (stat(temp->codePath.c_str(), &st) == 0) {
287 int new_uid = 0;
288 int new_gid = 0;
289 mode_t perms = 0;
290 bool fix = false;
bigbiff bigbiffa886ea62014-04-02 20:38:53 -0400291 if (temp->appDir.compare("/system/app") == 0 || temp->appDir.compare("/system/priv-app") == 0) {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400292 fix = true;
thata3d31fb2014-12-21 22:27:40 +0100293 new_uid = 0;
294 new_gid = 0;
295 perms = kMode_0644;
296 } else if (temp->appDir.compare("/data/app") == 0 || temp->appDir.compare("/sd-ext/app") == 0) {
297 fix = true;
298 new_uid = 1000;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400299 new_gid = 1000;
thata3d31fb2014-12-21 22:27:40 +0100300 perms = kMode_0644;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400301 } else if (temp->appDir.compare("/data/app-private") == 0 || temp->appDir.compare("/sd-ext/app-private") == 0) {
302 fix = true;
thata3d31fb2014-12-21 22:27:40 +0100303 new_uid = 1000;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400304 new_gid = temp->gid;
thata3d31fb2014-12-21 22:27:40 +0100305 perms = kMode_0640;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400306 } else
307 fix = false;
308 if (fix) {
309 if (debug) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000310 LOGINFO("Looking at '%s'\n", temp->codePath.c_str());
311 LOGINFO("Fixing permissions on '%s'\n", temp->pkgName.c_str());
312 LOGINFO("Directory: '%s'\n", temp->appDir.c_str());
313 LOGINFO("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400314 }
thata3d31fb2014-12-21 22:27:40 +0100315 if (S_ISDIR(st.st_mode)) {
316 // Android 5.0 introduced codePath pointing to a directory instead of the apk itself
317 // TODO: check what this should do
318 if (fixDir(temp->codePath, new_uid, new_gid, kMode_0755, new_uid, new_gid, perms) != 0)
319 return -1;
320 } else {
321 if (pchown(temp->codePath, new_uid, new_gid) != 0)
322 return -1;
323 if (pchmod(temp->codePath, perms) != 0)
324 return -1;
325 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400326 }
thata3d31fb2014-12-21 22:27:40 +0100327 } else if (remove_data) {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400328 //Remove data directory since app isn't installed
thata3d31fb2014-12-21 22:27:40 +0100329 string datapath = "/data/data/" + temp->dDir;
330 if (TWFunc::Path_Exists(datapath) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400331 if (debug)
thata3d31fb2014-12-21 22:27:40 +0100332 LOGINFO("Looking at '%s', removing data dir: '%s', appDir: '%s'", temp->codePath.c_str(), datapath.c_str(), temp->appDir.c_str());
333 if (TWFunc::removeDir(datapath, false) != 0) {
334 LOGINFO("Unable to removeDir '%s'\n", datapath.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400335 return -1;
336 }
337 }
338 }
339 temp = temp->next;
340 }
341 return 0;
342}
343
thata3d31fb2014-12-21 22:27:40 +0100344int fixPermissions::fixAllFiles(string directory, int uid, int gid, mode_t file_perms) {
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400345 vector <string> files;
346 string file;
347
348 files = listAllFiles(directory);
349 for (unsigned i = 0; i < files.size(); ++i) {
350 file = directory + "/";
351 file.append(files.at(i));
352 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000353 LOGINFO("Looking at file '%s'\n", file.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400354 if (pchmod(file, file_perms) != 0)
355 return -1;
356 if (pchown(file, uid, gid) != 0)
357 return -1;
358 }
359 return 0;
360}
361
thata3d31fb2014-12-21 22:27:40 +0100362int fixPermissions::fixDir(const string& dir, int diruid, int dirgid, mode_t dirmode, int fileuid, int filegid, mode_t filemode)
363{
364 if (pchmod(dir.c_str(), dirmode) != 0)
365 return -1;
366 if (pchown(dir.c_str(), diruid, dirgid) != 0)
367 return -1;
368 if (fixAllFiles(dir, fileuid, filegid, filemode) != 0)
369 return -1;
370 return 0;
371}
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400372
thata3d31fb2014-12-21 22:27:40 +0100373int fixPermissions::fixDataData(string dataDir) {
374 package* temp = head;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400375 while (temp != NULL) {
thata3d31fb2014-12-21 22:27:40 +0100376 string dir = dataDir + temp->dDir;
Dees_Troy201d76b2012-11-16 17:12:02 +0000377 if (TWFunc::Path_Exists(dir)) {
378 vector <string> dataDataDirs = listAllDirectories(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400379 for (unsigned n = 0; n < dataDataDirs.size(); ++n) {
thata3d31fb2014-12-21 22:27:40 +0100380 string directory = dir + "/";
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400381 directory.append(dataDataDirs.at(n));
382 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000383 LOGINFO("Looking at data directory: '%s'\n", directory.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400384 if (dataDataDirs.at(n) == ".") {
thata3d31fb2014-12-21 22:27:40 +0100385 if (fixDir(directory, temp->uid, temp->gid, kMode_0755, temp->uid, temp->gid, kMode_0755) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400386 return -1;
387 }
388 else if (dataDataDirs.at(n) == "..") {
389 if (debug)
Dees_Troy2673cec2013-04-02 20:22:16 +0000390 LOGINFO("Skipping ..\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400391 continue;
392 }
thata3d31fb2014-12-21 22:27:40 +0100393 // TODO: when any of these fails, do we really want to stop everything?
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400394 else if (dataDataDirs.at(n) == "lib") {
thata3d31fb2014-12-21 22:27:40 +0100395 if (fixDir(directory, 1000, 1000, kMode_0755, 1000, 1000, kMode_0755) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400396 return -1;
397 }
398 else if (dataDataDirs.at(n) == "shared_prefs") {
thata3d31fb2014-12-21 22:27:40 +0100399 if (fixDir(directory, temp->uid, temp->gid,kMode_0771, temp->uid, temp->gid, kMode_0660) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400400 return -1;
401 }
402 else if (dataDataDirs.at(n) == "databases") {
thata3d31fb2014-12-21 22:27:40 +0100403 if (fixDir(directory, temp->uid, temp->gid,kMode_0771, temp->uid, temp->gid, kMode_0660) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400404 return -1;
405 }
406 else if (dataDataDirs.at(n) == "cache") {
thata3d31fb2014-12-21 22:27:40 +0100407 if (fixDir(directory, temp->uid, temp->gid,kMode_0771, temp->uid, temp->gid, kMode_0600) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400408 return -1;
409 }
410 else {
thata3d31fb2014-12-21 22:27:40 +0100411 if (fixDir(directory, temp->uid, temp->gid,kMode_0771, temp->uid, temp->gid, kMode_0755) != 0)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400412 return -1;
413 }
414 }
415 }
416 temp = temp->next;
417 }
418 return 0;
419}
420
thata3d31fb2014-12-21 22:27:40 +0100421// TODO: merge to listAllDirEntries(path, type)
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400422vector <string> fixPermissions::listAllDirectories(string path) {
423 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400424 vector <string> dirs;
425
426 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000427 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400428 return dirs;
429 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000430 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400431 while (entry != NULL) {
432 if (entry->d_type == DT_DIR)
433 dirs.push_back(entry->d_name);
434 entry = readdir(dir);
435 }
436 closedir(dir);
437 return dirs;
438}
439
440vector <string> fixPermissions::listAllFiles(string path) {
441 DIR *dir = opendir(path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400442 vector <string> files;
443
444 if (dir == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000445 LOGERR("Error opening '%s'\n", path.c_str());
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400446 return files;
447 }
Dees_Troy201d76b2012-11-16 17:12:02 +0000448 struct dirent *entry = readdir(dir);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400449 while (entry != NULL) {
450 if (entry->d_type == DT_REG)
451 files.push_back(entry->d_name);
452 entry = readdir(dir);
453 }
454 closedir(dir);
455 return files;
456}
457
thata3d31fb2014-12-21 22:27:40 +0100458void fixPermissions::deletePackages() {
459 while (head) {
460 package* temp = head;
461 head = temp->next;
462 delete temp;
463 }
464}
465
466int fixPermissions::getPackages(const string& packageFile) {
467 deletePackages();
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400468 head = NULL;
469
thata3d31fb2014-12-21 22:27:40 +0100470 // TODO: simply skip all packages in /system/framework? or why are these excluded?
471 vector <string> skip;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400472 skip.push_back("/system/framework/framework-res.apk");
473 skip.push_back("/system/framework/com.htc.resources.apk");
474
475 ifstream xmlFile(packageFile.c_str());
476 xmlFile.seekg(0, ios::end);
thata3d31fb2014-12-21 22:27:40 +0100477 int len = (int) xmlFile.tellg();
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400478 xmlFile.seekg(0, ios::beg);
thata3d31fb2014-12-21 22:27:40 +0100479 vector<char> xmlBuf(len + 1);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400480 xmlFile.read(&xmlBuf[0], len);
481 xmlBuf[len] = '\0';
482 xml_document<> pkgDoc;
thata3d31fb2014-12-21 22:27:40 +0100483 LOGINFO("Parsing packages.xml, size=%i...\n", len);
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400484 pkgDoc.parse<parse_full>(&xmlBuf[0]);
485
486 xml_node<> * pkgNode = pkgDoc.first_node("packages");
Dees_Troy34614eb2013-04-05 12:02:14 -0500487 if (pkgNode == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000488 LOGERR("No packages found to fix.\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400489 return -1;
490 }
thata3d31fb2014-12-21 22:27:40 +0100491
492 // Get packages
493 for (xml_node<>* node = pkgNode->first_node(); node; node = node->next_sibling()) {
494 if (node->type() != node_element)
495 continue;
496 string elementName = node->name();
497 // we want <package> and <updated-package>
498 if (!(elementName == "package" || elementName == "updated-package"))
499 continue;
500
501 xml_attribute<>* attName = node->first_attribute("name");
502 if (!attName)
503 continue;
504 string name = attName->value();
505
506 xml_attribute<>* attCodePath = node->first_attribute("codePath");
507 if (!attCodePath)
508 {
509 LOGINFO("No codePath on %s, skipping.\n", name.c_str());
510 continue;
511 }
512 string codePath = attCodePath->value();
513
514 bool doskip = std::find(skip.begin(), skip.end(), codePath) != skip.end();
515 if (doskip) {
516 if (debug)
517 LOGINFO("Skipping package %s\n", codePath.c_str());
518 continue;
519 }
520
521 if (debug)
522 LOGINFO("Loading pkg: %s\n", name.c_str());
523
524 package* temp = new package;
525 temp->pkgName = name;
526 temp->codePath = codePath;
527 temp->appDir = codePath;
528 temp->dDir = name;
529 xml_attribute<>* attUserId = node->first_attribute("userId");
530 if (!attUserId)
531 attUserId = node->first_attribute("sharedUserId");
532 if (!attUserId) {
533 LOGINFO("Problem with userID on %s\n", name.c_str());
534 } else {
535 temp->uid = atoi(attUserId->value());
536 temp->gid = atoi(attUserId->value());
537 }
538 temp->next = head;
539 head = temp;
540 }
541
542 if (head == NULL) {
Dees_Troy34614eb2013-04-05 12:02:14 -0500543 LOGERR("No package found to fix.\n");
544 return -1;
545 }
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400546
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400547 return 0;
548}