Improve builtin selinux implementation
This commit is contained in:
parent
b7e2e972c7
commit
da0a72e8b0
@ -27,15 +27,17 @@ static int is_excl(const char *name) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_getpath(int fd, char *path, size_t size) {
|
ssize_t fd_path(int fd, char *path, size_t size) {
|
||||||
snprintf(path, size, "/proc/self/fd/%d", fd);
|
snprintf(path, size, "/proc/self/fd/%d", fd);
|
||||||
return xreadlink(path, path, size) == -1;
|
return xreadlink(path, path, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_getpathat(int dirfd, const char *name, char *path, size_t size) {
|
int fd_pathat(int dirfd, const char *name, char *path, size_t size) {
|
||||||
if (fd_getpath(dirfd, path, size))
|
ssize_t len = fd_path(dirfd, path, size);
|
||||||
return 1;
|
if (len < 0)
|
||||||
snprintf(path, size, "%s/%s", path, name);
|
return -1;
|
||||||
|
path[len] = '/';
|
||||||
|
strlcpy(&path[len + 1], name, size - len - 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ void rm_rf(const char *path) {
|
|||||||
if (lstat(path, &st) < 0)
|
if (lstat(path, &st) < 0)
|
||||||
return;
|
return;
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
int fd = open(path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
frm_rf(fd);
|
frm_rf(fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -211,7 +213,7 @@ void clone_dir(int src, int dest) {
|
|||||||
case DT_REG:
|
case DT_REG:
|
||||||
destfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
|
destfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC);
|
||||||
srcfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
srcfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
xsendfile(destfd, srcfd, 0, a.st.st_size);
|
xsendfile(destfd, srcfd, nullptr, a.st.st_size);
|
||||||
fsetattr(destfd, &a);
|
fsetattr(destfd, &a);
|
||||||
close(destfd);
|
close(destfd);
|
||||||
close(srcfd);
|
close(srcfd);
|
||||||
@ -263,16 +265,21 @@ int getattr(const char *path, struct file_attr *a) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getattrat(int dirfd, const char *pathname, struct file_attr *a) {
|
int getattrat(int dirfd, const char *name, struct file_attr *a) {
|
||||||
char path[PATH_MAX];
|
char path[4096];
|
||||||
fd_getpathat(dirfd, pathname, path, sizeof(path));
|
fd_pathat(dirfd, name, path, sizeof(path));
|
||||||
return getattr(path, a);
|
return getattr(path, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fgetattr(int fd, struct file_attr *a) {
|
int fgetattr(int fd, struct file_attr *a) {
|
||||||
char path[PATH_MAX];
|
if (xfstat(fd, &a->st) < 0)
|
||||||
fd_getpath(fd, path, sizeof(path));
|
return -1;
|
||||||
return getattr(path, a);
|
char *con;
|
||||||
|
if (fgetfilecon(fd, &con) < 0)
|
||||||
|
return -1;
|
||||||
|
strcpy(a->con, con);
|
||||||
|
freecon(con);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setattr(const char *path, struct file_attr *a) {
|
int setattr(const char *path, struct file_attr *a) {
|
||||||
@ -280,21 +287,25 @@ int setattr(const char *path, struct file_attr *a) {
|
|||||||
return -1;
|
return -1;
|
||||||
if (chown(path, a->st.st_uid, a->st.st_gid) < 0)
|
if (chown(path, a->st.st_uid, a->st.st_gid) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (strlen(a->con) && lsetfilecon(path, a->con) < 0)
|
if (a->con[0] && lsetfilecon(path, a->con) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setattrat(int dirfd, const char *pathname, struct file_attr *a) {
|
int setattrat(int dirfd, const char *name, struct file_attr *a) {
|
||||||
char path[PATH_MAX];
|
char path[4096];
|
||||||
fd_getpathat(dirfd, pathname, path, sizeof(path));
|
fd_pathat(dirfd, name, path, sizeof(path));
|
||||||
return setattr(path, a);
|
return setattr(path, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fsetattr(int fd, struct file_attr *a) {
|
int fsetattr(int fd, struct file_attr *a) {
|
||||||
char path[PATH_MAX];
|
if (fchmod(fd, a->st.st_mode & 0777) < 0)
|
||||||
fd_getpath(fd, path, sizeof(path));
|
return -1;
|
||||||
return setattr(path, a);
|
if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0)
|
||||||
|
return -1;
|
||||||
|
if (a->con[0] && fsetfilecon(fd, a->con) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone_attr(const char *source, const char *target) {
|
void clone_attr(const char *source, const char *target) {
|
||||||
@ -346,17 +357,6 @@ void full_read(const char *filename, void **buf, size_t *size) {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size) {
|
|
||||||
int fd = xopenat(dirfd, filename, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0) {
|
|
||||||
*buf = nullptr;
|
|
||||||
*size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fd_full_read(fd, buf, size);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_zero(int fd, size_t size) {
|
void write_zero(int fd, size_t size) {
|
||||||
char buf[4096] = {0};
|
char buf[4096] = {0};
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -4,12 +4,16 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void (*freecon)(char * con);
|
extern void (*freecon)(char *con);
|
||||||
extern int (*setcon)(const char * con);
|
extern int (*setcon)(const char *con);
|
||||||
extern int (*getfilecon)(const char *path, char ** con);
|
extern int (*getfilecon)(const char *path, char **con);
|
||||||
extern int (*lgetfilecon)(const char *path, char ** con);
|
extern int (*lgetfilecon)(const char *path, char **con);
|
||||||
extern int (*setfilecon)(const char *path, const char * con);
|
extern int (*fgetfilecon)(int fd, char **con);
|
||||||
extern int (*lsetfilecon)(const char *path, const char * con);
|
extern int (*setfilecon)(const char *path, const char *con);
|
||||||
|
extern int (*lsetfilecon)(const char *path, const char *con);
|
||||||
|
extern int (*fsetfilecon)(int fd, const char *con);
|
||||||
|
void getfilecon_at(int dirfd, const char *name, char **con);
|
||||||
|
void setfilecon_at(int dirfd, const char *name, const char *con);
|
||||||
|
|
||||||
void selinux_builtin_impl();
|
void selinux_builtin_impl();
|
||||||
void dload_selinux();
|
void dload_selinux();
|
||||||
|
@ -51,6 +51,7 @@ int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
void *(*start_routine) (void *), void *arg);
|
void *(*start_routine) (void *), void *arg);
|
||||||
int xstat(const char *pathname, struct stat *buf);
|
int xstat(const char *pathname, struct stat *buf);
|
||||||
int xlstat(const char *pathname, struct stat *buf);
|
int xlstat(const char *pathname, struct stat *buf);
|
||||||
|
int xfstat(int fd, struct stat *buf);
|
||||||
int xdup2(int oldfd, int newfd);
|
int xdup2(int oldfd, int newfd);
|
||||||
int xdup3(int oldfd, int newfd, int flags);
|
int xdup3(int oldfd, int newfd, int flags);
|
||||||
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz);
|
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz);
|
||||||
@ -103,8 +104,8 @@ struct file_attr {
|
|||||||
char con[128];
|
char con[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
int fd_getpath(int fd, char *path, size_t size);
|
ssize_t fd_path(int fd, char *path, size_t size);
|
||||||
int fd_getpathat(int dirfd, const char *name, 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(const char *pathname, mode_t mode);
|
||||||
void post_order_walk(int dirfd, void (*fn)(int, struct dirent *));
|
void post_order_walk(int dirfd, void (*fn)(int, struct dirent *));
|
||||||
void rm_rf(const char *path);
|
void rm_rf(const char *path);
|
||||||
@ -115,17 +116,16 @@ void cp_afc(const char *source, const char *destination);
|
|||||||
void link_dir(int src, int dest);
|
void link_dir(int src, int dest);
|
||||||
void clone_dir(int src, int dest);
|
void clone_dir(int src, int dest);
|
||||||
int getattr(const char *path, struct file_attr *a);
|
int getattr(const char *path, struct file_attr *a);
|
||||||
int getattrat(int dirfd, const char *pathname, struct file_attr *a);
|
int getattrat(int dirfd, const char *name, struct file_attr *a);
|
||||||
int fgetattr(int fd, struct file_attr *a);
|
int fgetattr(int fd, struct file_attr *a);
|
||||||
int setattr(const char *path, struct file_attr *a);
|
int setattr(const char *path, struct file_attr *a);
|
||||||
int setattrat(int dirfd, const char *pathname, struct file_attr *a);
|
int setattrat(int dirfd, const char *name, struct file_attr *a);
|
||||||
int fsetattr(int fd, struct file_attr *a);
|
int fsetattr(int fd, struct file_attr *a);
|
||||||
void fclone_attr(int sourcefd, int targetfd);
|
void fclone_attr(int sourcefd, int targetfd);
|
||||||
void clone_attr(const char *source, const char *target);
|
void clone_attr(const char *source, const char *target);
|
||||||
void mmap_ro(const char *filename, void **buf, size_t *size);
|
void mmap_ro(const char *filename, void **buf, size_t *size);
|
||||||
void fd_full_read(int fd, void **buf, size_t *size);
|
void fd_full_read(int fd, void **buf, size_t *size);
|
||||||
void full_read(const char *filename, void **buf, size_t *size);
|
void full_read(const char *filename, void **buf, size_t *size);
|
||||||
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size);
|
|
||||||
void write_zero(int fd, size_t size);
|
void write_zero(int fd, size_t size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -25,6 +25,13 @@ static int stub(const char *, char **ctx) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stub(int, const char *) { return 0; }
|
||||||
|
|
||||||
|
static int stub(int, char **ctx) {
|
||||||
|
*ctx = strdup("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Builtin implementation
|
// Builtin implementation
|
||||||
|
|
||||||
static void __freecon(char *s) {
|
static void __freecon(char *s) {
|
||||||
@ -44,7 +51,10 @@ static int __setcon(const char *ctx) {
|
|||||||
static int __getfilecon(const char *path, char **ctx) {
|
static int __getfilecon(const char *path, char **ctx) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
|
int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
|
||||||
if (rc > 0)
|
if (rc < 0) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
*ctx = strdup(buf);
|
*ctx = strdup(buf);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -52,17 +62,50 @@ static int __getfilecon(const char *path, char **ctx) {
|
|||||||
static int __lgetfilecon(const char *path, char **ctx) {
|
static int __lgetfilecon(const char *path, char **ctx) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
|
int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
|
||||||
if (rc > 0)
|
if (rc < 0) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ctx = strdup(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __fgetfilecon(int fd, char **ctx) {
|
||||||
|
char buf[1024];
|
||||||
|
int rc = syscall(__NR_fgetxattr, fd, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
*ctx = strdup(buf);
|
*ctx = strdup(buf);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __setfilecon(const char *path, const char *ctx) {
|
static int __setfilecon(const char *path, const char *ctx) {
|
||||||
return syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
|
int rc = syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
|
||||||
|
if (rc) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __lsetfilecon(const char *path, const char *ctx) {
|
static int __lsetfilecon(const char *path, const char *ctx) {
|
||||||
return syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
|
int rc = syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
|
||||||
|
if (rc) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __fsetfilecon(int fd, const char *ctx) {
|
||||||
|
int rc = syscall(__NR_fsetxattr, fd, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
|
||||||
|
if (rc) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function pointers
|
// Function pointers
|
||||||
@ -71,15 +114,32 @@ void (*freecon)(char *) = __freecon;
|
|||||||
int (*setcon)(const char *) = stub;
|
int (*setcon)(const char *) = stub;
|
||||||
int (*getfilecon)(const char *, char **) = stub;
|
int (*getfilecon)(const char *, char **) = stub;
|
||||||
int (*lgetfilecon)(const char *, char **) = stub;
|
int (*lgetfilecon)(const char *, char **) = stub;
|
||||||
|
int (*fgetfilecon)(int, char **) = stub;
|
||||||
int (*setfilecon)(const char *, const char *) = stub;
|
int (*setfilecon)(const char *, const char *) = stub;
|
||||||
int (*lsetfilecon)(const char *, const char *) = stub;
|
int (*lsetfilecon)(const char *, const char *) = stub;
|
||||||
|
int (*fsetfilecon)(int, const char *) = stub;
|
||||||
|
|
||||||
|
void getfilecon_at(int dirfd, const char *name, char **con) {
|
||||||
|
char path[4096];
|
||||||
|
fd_pathat(dirfd, name, path, sizeof(path));
|
||||||
|
if (lgetfilecon(path, con))
|
||||||
|
*con = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setfilecon_at(int dirfd, const char *name, const char *con) {
|
||||||
|
char path[4096];
|
||||||
|
fd_pathat(dirfd, name, path, sizeof(path));
|
||||||
|
lsetfilecon(path, con);
|
||||||
|
}
|
||||||
|
|
||||||
void selinux_builtin_impl() {
|
void selinux_builtin_impl() {
|
||||||
setcon = __setcon;
|
setcon = __setcon;
|
||||||
getfilecon = __getfilecon;
|
getfilecon = __getfilecon;
|
||||||
lgetfilecon = __lgetfilecon;
|
lgetfilecon = __lgetfilecon;
|
||||||
|
fgetfilecon = __fgetfilecon;
|
||||||
setfilecon = __setfilecon;
|
setfilecon = __setfilecon;
|
||||||
lsetfilecon = __lsetfilecon;
|
lsetfilecon = __lsetfilecon;
|
||||||
|
fsetfilecon = __fsetfilecon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dload_selinux() {
|
void dload_selinux() {
|
||||||
@ -95,33 +155,32 @@ void dload_selinux() {
|
|||||||
static void restore_syscon(int dirfd) {
|
static void restore_syscon(int dirfd) {
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
char *con;
|
||||||
|
|
||||||
char path[PATH_MAX], *con;
|
fgetfilecon(dirfd, &con);
|
||||||
|
|
||||||
fd_getpath(dirfd, path, sizeof(path));
|
|
||||||
size_t len = strlen(path);
|
|
||||||
getfilecon(path, &con);
|
|
||||||
if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0)
|
if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0)
|
||||||
lsetfilecon(path, SYSTEM_CON);
|
fsetfilecon(dirfd, SYSTEM_CON);
|
||||||
freecon(con);
|
freecon(con);
|
||||||
|
|
||||||
dir = xfdopendir(dirfd);
|
dir = xfdopendir(dirfd);
|
||||||
while ((entry = xreaddir(dir))) {
|
while ((entry = xreaddir(dir))) {
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
int fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
if (entry->d_type == DT_DIR) {
|
if (entry->d_type == DT_DIR) {
|
||||||
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
|
||||||
restore_syscon(fd);
|
restore_syscon(fd);
|
||||||
close(fd);
|
} else if (entry->d_type == DT_REG) {
|
||||||
} else {
|
fgetfilecon(fd, &con);
|
||||||
path[len] = '/';
|
if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0)
|
||||||
strcpy(path + len + 1, entry->d_name);
|
fsetfilecon(fd, SYSTEM_CON);
|
||||||
lgetfilecon(path, &con);
|
freecon(con);
|
||||||
if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0)
|
} else if (entry->d_type == DT_LNK) {
|
||||||
lsetfilecon(path, SYSTEM_CON);
|
getfilecon_at(dirfd, entry->d_name, &con);
|
||||||
|
if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0)
|
||||||
|
setfilecon_at(dirfd, entry->d_name, con);
|
||||||
freecon(con);
|
freecon(con);
|
||||||
path[len] = '\0';
|
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,28 +188,21 @@ static void restore_magiskcon(int dirfd) {
|
|||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
|
||||||
char path[PATH_MAX];
|
fsetfilecon(dirfd, MAGISK_CON);
|
||||||
|
fchown(dirfd, 0, 0);
|
||||||
fd_getpath(dirfd, path, sizeof(path));
|
|
||||||
size_t len = strlen(path);
|
|
||||||
lsetfilecon(path, MAGISK_CON);
|
|
||||||
lchown(path, 0, 0);
|
|
||||||
|
|
||||||
dir = xfdopendir(dirfd);
|
dir = xfdopendir(dirfd);
|
||||||
while ((entry = xreaddir(dir))) {
|
while ((entry = xreaddir(dir))) {
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
if (entry->d_type == DT_DIR) {
|
|
||||||
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (entry->d_type == DT_DIR) {
|
||||||
restore_magiskcon(fd);
|
restore_magiskcon(fd);
|
||||||
close(fd);
|
} else if (entry->d_type) {
|
||||||
} else {
|
fsetfilecon(fd, MAGISK_CON);
|
||||||
path[len] = '/';
|
fchown(fd, 0, 0);
|
||||||
strcpy(path + len + 1, entry->d_name);
|
|
||||||
lsetfilecon(path, MAGISK_CON);
|
|
||||||
lchown(path, 0, 0);
|
|
||||||
path[len] = '\0';
|
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +262,14 @@ int xlstat(const char *pathname, struct stat *buf) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xfstat(int fd, struct stat *buf) {
|
||||||
|
int ret = fstat(fd, buf);
|
||||||
|
if (ret == -1) {
|
||||||
|
PLOGE("fstat %d", fd);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int xdup2(int oldfd, int newfd) {
|
int xdup2(int oldfd, int newfd) {
|
||||||
int ret = dup2(oldfd, newfd);
|
int ret = dup2(oldfd, newfd);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user