Update files.cpp in libutils

This commit is contained in:
topjohnwu 2020-04-02 02:17:45 -07:00
parent dbfde74c1e
commit 9820296e92
4 changed files with 132 additions and 158 deletions

View File

@ -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);

View File

@ -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{};

View File

@ -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);

View File

@ -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);
}