]>
git.saurik.com Git - cydia.git/blob - setnsfpn.cpp
1 /* Cydia - iPhone UIKit Front-End for Debian APT
2 * Copyright (C) 2008-2015 Jay Freeman (saurik)
5 /* GNU General Public License, Version 3 {{{ */
7 * Cydia is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
12 * Cydia is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
30 #define _syscall(expr) ({ typeof(expr) _value; for (;;) { \
32 if ((long) _value != -1) \
34 if (errno != EINTR) { \
40 extern "C" int __getdirentries64(int, char *, int, long *);
66 File::operator int() const {
70 static int setnsfpn(const char *path
, size_t before
, Recurse recurse
) {
71 File
fd(_syscall(open_dprotected_np(path
, O_RDONLY
| O_SYMLINK
, 0, O_DP_GETRAWENCRYPTED
)));
73 if (recurse
== RecurseMaybe
) {
75 _syscall(fstat(fd
, &stat
));
76 switch (stat
.st_mode
& S_IFMT
) {
91 int mode(_syscall(fcntl(fd
, F_GETPROTECTIONCLASS
)));
95 if (recurse
== RecurseYes
)
96 for (long address(0);;) {
98 int size(_syscall(__getdirentries64(fd
, buffer
, sizeof(buffer
), &address
)));
102 const char *next(buffer
), *stop(next
+ size
);
103 while (next
!= stop
) {
104 const dirent
*dir(reinterpret_cast<const dirent
*>(next
));
105 const char *name(dir
->d_name
);
106 size_t after(strlen(name
));
108 if (dir
->d_ino
== 0);
109 else if (after
== 1 && name
[0] == '.');
110 else if (after
== 2 && name
[0] == '.' && name
[1] == '.');
112 size_t both(before
+ 1 + after
);
114 memcpy(sub
, path
, before
);
116 memcpy(sub
+ before
+ 1, name
, after
);
119 switch (dir
->d_type
) {
126 if (setnsfpn(sub
, both
, RecurseYes
) != 0)
130 if (setnsfpn(sub
, both
, RecurseNo
) != 0)
136 next
+= dir
->d_reclen
;
140 _syscall(fcntl(fd
, F_SETPROTECTIONCLASS
, 4));
144 int main(int argc
, const char *argv
[]) {
145 return setnsfpn(argv
[1], strlen(argv
[1]), RecurseMaybe
);