mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-30 21:07:39 +00:00
Update files.cpp in libutils
This commit is contained in:
parent
dbfde74c1e
commit
9820296e92
@ -107,7 +107,7 @@ void RootFSInit::setup_rootfs() {
|
||||
if (access("/overlay.d", F_OK) == 0) {
|
||||
LOGD("Merge overlay.d\n");
|
||||
load_overlay_rc("/overlay.d");
|
||||
mv_f("/overlay.d", "/");
|
||||
mv_path("/overlay.d", "/");
|
||||
}
|
||||
|
||||
// Patch init.rc
|
||||
@ -120,10 +120,7 @@ void RootFSInit::setup_rootfs() {
|
||||
// Create hardlink mirror of /sbin to /root
|
||||
mkdir("/root", 0750);
|
||||
clone_attr("/sbin", "/root");
|
||||
int rootdir = xopen("/root", O_RDONLY | O_CLOEXEC);
|
||||
int sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
|
||||
link_dir(sbin, rootdir);
|
||||
close(sbin);
|
||||
link_path("/sbin", "/root");
|
||||
|
||||
// Dump magiskinit as magisk
|
||||
int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
|
||||
|
@ -18,42 +18,44 @@ ssize_t fd_path(int fd, char *path, size_t size) {
|
||||
}
|
||||
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size) {
|
||||
ssize_t len = fd_path(dirfd, path, size);
|
||||
if (len < 0)
|
||||
if (fd_path(dirfd, path, size) < 0)
|
||||
return -1;
|
||||
auto len = strlen(path);
|
||||
path[len] = '/';
|
||||
strlcpy(&path[len + 1], name, size - len - 1);
|
||||
strlcpy(path + len + 1, name, size - len - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdirs(const char *pathname, mode_t mode) {
|
||||
char *path = strdup(pathname), *p;
|
||||
int mkdirs(string path, mode_t mode) {
|
||||
errno = 0;
|
||||
for (p = path + 1; *p; ++p) {
|
||||
for (char *p = path.data() + 1; *p; ++p) {
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
if (mkdir(path, mode) == -1) {
|
||||
if (mkdir(path.data(), mode) == -1) {
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
if (mkdir(path, mode) == -1) {
|
||||
if (mkdir(path.data(), mode) == -1) {
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
}
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void post_order_walk(int dirfd, function<int(int, dirent *)> &&fn) {
|
||||
#define SKIP_DOTS {\
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv) \
|
||||
continue;\
|
||||
}
|
||||
|
||||
static void post_order_walk(int dirfd, const function<int(int, dirent *)> &&fn) {
|
||||
auto dir = xopen_dir(dirfd);
|
||||
if (!dir) return;
|
||||
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
SKIP_DOTS
|
||||
if (entry->d_type == DT_DIR)
|
||||
post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), std::move(fn));
|
||||
fn(dirfd, entry);
|
||||
@ -77,158 +79,127 @@ void frm_rf(int dirfd) {
|
||||
post_order_walk(dirfd, remove_at);
|
||||
}
|
||||
|
||||
/* This will only on the same file system */
|
||||
void mv_f(const char *source, const char *destination) {
|
||||
struct stat st;
|
||||
xlstat(source, &st);
|
||||
int src, dest;
|
||||
struct file_attr a;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
xmkdirs(destination, st.st_mode & 0777);
|
||||
src = xopen(source, O_RDONLY | O_CLOEXEC);
|
||||
dest = xopen(destination, O_RDONLY | O_CLOEXEC);
|
||||
fclone_attr(src, dest);
|
||||
mv_dir(src, dest);
|
||||
close(src);
|
||||
close(dest);
|
||||
void mv_path(const char *src, const char *dest) {
|
||||
file_attr a;
|
||||
getattr(src, &a);
|
||||
if (S_ISDIR(a.st.st_mode)) {
|
||||
xmkdirs(dest, 0);
|
||||
setattr(dest, &a);
|
||||
mv_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
|
||||
} else{
|
||||
getattr(source, &a);
|
||||
xrename(source, destination);
|
||||
setattr(destination, &a);
|
||||
xrename(src, dest);
|
||||
}
|
||||
rmdir(source);
|
||||
rmdir(src);
|
||||
}
|
||||
|
||||
/* This will only on the same file system */
|
||||
void mv_dir(int src, int dest) {
|
||||
struct dirent *entry;
|
||||
DIR *dir;
|
||||
int newsrc, newdest;
|
||||
struct file_attr a;
|
||||
|
||||
dir = xfdopendir(src);
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
getattrat(src, entry->d_name, &a);
|
||||
auto dir = xopen_dir(src);
|
||||
run_finally f([&]{ close(dest); });
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
SKIP_DOTS
|
||||
switch (entry->d_type) {
|
||||
case DT_DIR:
|
||||
xmkdirat(dest, entry->d_name, a.st.st_mode & 0777);
|
||||
newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
fsetattr(newdest, &a);
|
||||
mv_dir(newsrc, newdest);
|
||||
close(newsrc);
|
||||
close(newdest);
|
||||
unlinkat(src, entry->d_name, AT_REMOVEDIR);
|
||||
break;
|
||||
if (faccessat(dest, entry->d_name, F_OK, 0) == 0) {
|
||||
// Destination folder exists, needs recursive move
|
||||
int newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
int newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
mv_dir(newsrc, newdest);
|
||||
unlinkat(src, entry->d_name, AT_REMOVEDIR);
|
||||
break;
|
||||
}
|
||||
// Else fall through
|
||||
case DT_LNK:
|
||||
case DT_REG:
|
||||
renameat(src, entry->d_name, dest, entry->d_name);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cp_afc(const char *source, const char *destination) {
|
||||
int src, dest;
|
||||
struct file_attr a;
|
||||
getattr(source, &a);
|
||||
void cp_afc(const char *src, const char *dest) {
|
||||
file_attr a;
|
||||
getattr(src, &a);
|
||||
|
||||
if (S_ISDIR(a.st.st_mode)) {
|
||||
xmkdirs(destination, a.st.st_mode & 0777);
|
||||
src = xopen(source, O_RDONLY | O_CLOEXEC);
|
||||
dest = xopen(destination, O_RDONLY | O_CLOEXEC);
|
||||
clone_dir(src, dest);
|
||||
close(src);
|
||||
close(dest);
|
||||
xmkdirs(dest, 0);
|
||||
clone_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
|
||||
} else{
|
||||
unlink(destination);
|
||||
unlink(dest);
|
||||
if (S_ISREG(a.st.st_mode)) {
|
||||
src = xopen(source, O_RDONLY);
|
||||
dest = xopen(destination, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
xsendfile(dest, src, nullptr, a.st.st_size);
|
||||
close(src);
|
||||
close(dest);
|
||||
int sfd = xopen(src, O_RDONLY | O_CLOEXEC);
|
||||
int dfd = xopen(dest, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
|
||||
xsendfile(dfd, sfd, nullptr, a.st.st_size);
|
||||
close(sfd);
|
||||
close(dfd);
|
||||
} else if (S_ISLNK(a.st.st_mode)) {
|
||||
char buf[PATH_MAX];
|
||||
xreadlink(source, buf, sizeof(buf));
|
||||
xsymlink(buf, destination);
|
||||
char buf[4096];
|
||||
xreadlink(src, buf, sizeof(buf));
|
||||
xsymlink(buf, dest);
|
||||
}
|
||||
}
|
||||
setattr(destination, &a);
|
||||
setattr(dest, &a);
|
||||
}
|
||||
|
||||
void clone_dir(int src, int dest, bool overwrite) {
|
||||
struct dirent *entry;
|
||||
DIR *dir;
|
||||
int srcfd, destfd, newsrc, newdest;
|
||||
char buf[PATH_MAX];
|
||||
struct file_attr a;
|
||||
|
||||
dir = xfdopendir(src);
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
if (struct stat st; !overwrite &&
|
||||
fstatat(dest, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)
|
||||
continue;
|
||||
void clone_dir(int src, int dest) {
|
||||
auto dir = xopen_dir(src);
|
||||
run_finally f([&]{ close(dest); });
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
SKIP_DOTS
|
||||
file_attr a;
|
||||
getattrat(src, entry->d_name, &a);
|
||||
switch (entry->d_type) {
|
||||
case DT_DIR:
|
||||
xmkdirat(dest, entry->d_name, a.st.st_mode & 0777);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
clone_dir(newsrc, newdest, overwrite);
|
||||
close(newsrc);
|
||||
close(newdest);
|
||||
break;
|
||||
case DT_REG:
|
||||
destfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
|
||||
srcfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
xsendfile(destfd, srcfd, nullptr, a.st.st_size);
|
||||
fsetattr(destfd, &a);
|
||||
close(destfd);
|
||||
close(srcfd);
|
||||
break;
|
||||
case DT_LNK:
|
||||
xreadlinkat(src, entry->d_name, buf, sizeof(buf));
|
||||
xsymlinkat(buf, dest, entry->d_name);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
break;
|
||||
case DT_DIR: {
|
||||
xmkdirat(dest, entry->d_name, 0);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
int dst = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
clone_dir(sfd, dst);
|
||||
break;
|
||||
}
|
||||
case DT_REG: {
|
||||
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
int dfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
|
||||
xsendfile(dfd, sfd, nullptr, a.st.st_size);
|
||||
fsetattr(dfd, &a);
|
||||
close(dfd);
|
||||
close(sfd);
|
||||
break;
|
||||
}
|
||||
case DT_LNK: {
|
||||
char buf[4096];
|
||||
xreadlinkat(src, entry->d_name, buf, sizeof(buf));
|
||||
xsymlinkat(buf, dest, entry->d_name);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void link_path(const char *src, const char *dest) {
|
||||
link_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
|
||||
}
|
||||
|
||||
void link_dir(int src, int dest) {
|
||||
struct dirent *entry;
|
||||
DIR *dir;
|
||||
int newsrc, newdest;
|
||||
struct file_attr a;
|
||||
|
||||
dir = xfdopendir(src);
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
auto dir = xopen_dir(src);
|
||||
run_finally f([&]{ close(dest); });
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
SKIP_DOTS
|
||||
if (entry->d_type == DT_DIR) {
|
||||
file_attr a;
|
||||
getattrat(src, entry->d_name, &a);
|
||||
xmkdirat(dest, entry->d_name, a.st.st_mode & 0777);
|
||||
xmkdirat(dest, entry->d_name, 0);
|
||||
setattrat(dest, entry->d_name, &a);
|
||||
newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
link_dir(newsrc, newdest);
|
||||
close(newsrc);
|
||||
close(newdest);
|
||||
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
int dfd = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
link_dir(sfd, dfd);
|
||||
} else {
|
||||
xlinkat(src, entry->d_name, dest, entry->d_name, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getattr(const char *path, struct file_attr *a) {
|
||||
int getattr(const char *path, file_attr *a) {
|
||||
if (xlstat(path, &a->st) == -1)
|
||||
return -1;
|
||||
char *con;
|
||||
@ -239,13 +210,13 @@ int getattr(const char *path, struct file_attr *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getattrat(int dirfd, const char *name, struct file_attr *a) {
|
||||
int getattrat(int dirfd, const char *name, file_attr *a) {
|
||||
char path[4096];
|
||||
fd_pathat(dirfd, name, path, sizeof(path));
|
||||
return getattr(path, a);
|
||||
}
|
||||
|
||||
int fgetattr(int fd, struct file_attr *a) {
|
||||
int fgetattr(int fd, file_attr *a) {
|
||||
if (xfstat(fd, &a->st) < 0)
|
||||
return -1;
|
||||
char *con;
|
||||
@ -256,7 +227,7 @@ int fgetattr(int fd, struct file_attr *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setattr(const char *path, struct file_attr *a) {
|
||||
int setattr(const char *path, file_attr *a) {
|
||||
if (chmod(path, a->st.st_mode & 0777) < 0)
|
||||
return -1;
|
||||
if (chown(path, a->st.st_uid, a->st.st_gid) < 0)
|
||||
@ -266,13 +237,13 @@ int setattr(const char *path, struct file_attr *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setattrat(int dirfd, const char *name, struct file_attr *a) {
|
||||
int setattrat(int dirfd, const char *name, file_attr *a) {
|
||||
char path[4096];
|
||||
fd_pathat(dirfd, name, path, sizeof(path));
|
||||
return setattr(path, a);
|
||||
}
|
||||
|
||||
int fsetattr(int fd, struct file_attr *a) {
|
||||
int fsetattr(int fd, file_attr *a) {
|
||||
if (fchmod(fd, a->st.st_mode & 0777) < 0)
|
||||
return -1;
|
||||
if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0)
|
||||
@ -282,16 +253,16 @@ int fsetattr(int fd, struct file_attr *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clone_attr(const char *source, const char *target) {
|
||||
struct file_attr a;
|
||||
getattr(source, &a);
|
||||
setattr(target, &a);
|
||||
void clone_attr(const char *src, const char *dest) {
|
||||
file_attr a;
|
||||
getattr(src, &a);
|
||||
setattr(dest, &a);
|
||||
}
|
||||
|
||||
void fclone_attr(int sourcefd, int targetfd) {
|
||||
struct file_attr a;
|
||||
fgetattr(sourcefd, &a);
|
||||
fsetattr(targetfd, &a);
|
||||
void fclone_attr(int src, int dest) {
|
||||
file_attr a;
|
||||
fgetattr(src, &a);
|
||||
fsetattr(dest, &a);
|
||||
}
|
||||
|
||||
void *__mmap(const char *filename, size_t *size, bool rw) {
|
||||
@ -337,7 +308,7 @@ void write_zero(int fd, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn) {
|
||||
void file_readline(bool trim, const char *file, const function<bool(string_view)> &fn) {
|
||||
FILE *fp = xfopen(file, "re");
|
||||
if (fp == nullptr)
|
||||
return;
|
||||
@ -361,7 +332,7 @@ void file_readline(bool trim, const char *file, const std::function<bool(std::st
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void parse_prop_file(const char *file, const function<bool (string_view, string_view)> &fn) {
|
||||
void parse_prop_file(const char *file, const function<bool(string_view, string_view)> &&fn) {
|
||||
file_readline(true, file, [&](string_view line_view) -> bool {
|
||||
char *line = (char *) line_view.data();
|
||||
if (line[0] == '#')
|
||||
@ -374,7 +345,7 @@ void parse_prop_file(const char *file, const function<bool (string_view, string_
|
||||
});
|
||||
}
|
||||
|
||||
void parse_mnt(const char *file, const function<bool (mntent*)> &fn) {
|
||||
void parse_mnt(const char *file, const function<bool(mntent*)> &fn) {
|
||||
auto fp = sFILE(setmntent(file, "re"), endmntent);
|
||||
if (fp) {
|
||||
mntent mentry{};
|
||||
|
@ -41,20 +41,21 @@ struct raw_file {
|
||||
|
||||
ssize_t fd_path(int fd, char *path, size_t size);
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
||||
int mkdirs(const char *pathname, mode_t mode);
|
||||
int mkdirs(std::string path, mode_t mode);
|
||||
void rm_rf(const char *path);
|
||||
void mv_f(const char *source, const char *destination);
|
||||
void mv_path(const char *src, const char *dest);
|
||||
void mv_dir(int src, int dest);
|
||||
void cp_afc(const char *source, const char *destination);
|
||||
void cp_afc(const char *src, const char *dest);
|
||||
void link_path(const char *src, const char *dest);
|
||||
void link_dir(int src, int dest);
|
||||
int getattr(const char *path, struct file_attr *a);
|
||||
int getattrat(int dirfd, const char *name, struct file_attr *a);
|
||||
int fgetattr(int fd, struct file_attr *a);
|
||||
int setattr(const char *path, struct file_attr *a);
|
||||
int setattrat(int dirfd, const char *name, struct file_attr *a);
|
||||
int fsetattr(int fd, struct file_attr *a);
|
||||
void fclone_attr(int sourcefd, int targetfd);
|
||||
void clone_attr(const char *source, const char *target);
|
||||
int getattr(const char *path, file_attr *a);
|
||||
int getattrat(int dirfd, const char *name, file_attr *a);
|
||||
int fgetattr(int fd, file_attr *a);
|
||||
int setattr(const char *path, file_attr *a);
|
||||
int setattrat(int dirfd, const char *name, file_attr *a);
|
||||
int fsetattr(int fd, file_attr *a);
|
||||
void fclone_attr(int src, int dest);
|
||||
void clone_attr(const char *src, const char *dest);
|
||||
void fd_full_read(int fd, void **buf, size_t *size);
|
||||
void full_read(const char *filename, void **buf, size_t *size);
|
||||
void write_zero(int fd, size_t size);
|
||||
@ -64,10 +65,10 @@ static inline void file_readline(const char *file,
|
||||
file_readline(false, file, fn);
|
||||
}
|
||||
void parse_prop_file(const char *file,
|
||||
const std::function<bool(std::string_view, std::string_view)> &fn);
|
||||
const std::function<bool(std::string_view, std::string_view)> &&fn);
|
||||
void *__mmap(const char *filename, size_t *size, bool rw);
|
||||
void frm_rf(int dirfd);
|
||||
void clone_dir(int src, int dest, bool overwrite = true);
|
||||
void clone_dir(int src, int dest);
|
||||
void parse_mnt(const char *file, const std::function<bool(mntent*)> &fn);
|
||||
void backup_folder(const char *dir, std::vector<raw_file> &files);
|
||||
void restore_folder(const char *dir, std::vector<raw_file> &files);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define setmntent __setmntent
|
||||
#define endmntent __endmntent
|
||||
#define hasmntopt __hasmntopt
|
||||
#define faccessat __faccessat
|
||||
|
||||
ssize_t __getline(char **lineptr, size_t *n, FILE *stream);
|
||||
ssize_t __getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
|
||||
@ -58,3 +59,7 @@ static inline int __linkat(int olddirfd, const char *oldpath,
|
||||
static inline int __inotify_init1(int flags) {
|
||||
return syscall(__NR_inotify_init1, flags);
|
||||
}
|
||||
|
||||
static inline int __faccessat(int dirfd, const char *pathname, int mode, int flags) {
|
||||
return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user