sfakeroot

manipulate files faking root privileges
git clone git://git.vx21.xyz/sfakeroot
Log | Files | Refs | README | LICENSE

libsfakeroot.c (5119B)


      1 /* sfakeroot
      2  *
      3  * Copyright © 2020 - 2025 Richard Ipsum
      4  *
      5  * This file is part of sfakeroot.
      6  *
      7  * sfakeroot is free software: you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation, version 3 of the License.
     10  *
     11  * sfakeroot is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with sfakeroot.  If not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <stdbool.h>
     23 #include <fcntl.h>
     24 #include <unistd.h>
     25 #include <string.h>
     26 #include <errno.h>
     27 #include <sys/stat.h>
     28 #include <sys/types.h>
     29 #include <sys/socket.h>
     30 #include <sys/wait.h>
     31 #include <sys/un.h>
     32 
     33 #include "sfakeroot.h"
     34 #include "sfakeroot_inline.h"
     35 
     36 static int sfakeroot__call(struct sfakeroot_msg *m)
     37 {
     38     int sockfd;
     39     int sendfds[1];
     40     char *wd;
     41 
     42     sockfd = sfakeroot_session_open();
     43     if (sockfd == -1) {
     44         return -1;
     45     }
     46     if ((wd = getcwd(NULL, 0)) == NULL) {
     47         return -1;
     48     }
     49 
     50     strlcpy(m->working_dir, wd, sizeof (m->working_dir));
     51     free(wd);
     52     if (m->fd >= 0) {
     53         sendfds[0] = m->fd;
     54     }
     55     if (sfakeroot_sendmsg(sockfd, m, m->fd >= 0 ? sendfds : NULL, m->fd >= 0 ? 1 : 0) == -1) {
     56         return -1;
     57     }
     58     if (sfakeroot_recvmsg(sockfd, m) == -1) {
     59         return -1;
     60     }
     61     close(sockfd);
     62     errno = m->reterrno;
     63     return m->retcode;
     64 }
     65 
     66 int chmod(const char *path, mode_t mode)
     67 {
     68     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_CHMOD, .mode = mode, .fd = -1};
     69     debug("chmod %s %o\n", path, mode);
     70     strlcpy(m.path, path, sizeof (m.path));
     71     return sfakeroot__call(&m);
     72 }
     73 
     74 int chown(const char *path, uid_t uid, gid_t gid)
     75 {
     76     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_CHOWN, .uid = uid, .gid = gid, .fd = -1};
     77     strlcpy(m.path, path, sizeof (m.path));
     78     debug("chown: path: %s, uid: %d, gid: %d\n", path, (int) uid, (int) gid);
     79     return sfakeroot__call(&m);
     80 }
     81 
     82 int lchown(const char *path, uid_t uid, gid_t gid)
     83 {
     84     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_LCHOWN, .uid = uid, .gid = gid, .fd = -1};
     85     strlcpy(m.path, path, sizeof (m.path));
     86     debug("lchown: path: %s, uid: %d, gid: %d\n", path, (int) uid, (int) gid);
     87     return sfakeroot__call(&m);
     88 }
     89 
     90 int fchown(int fd, uid_t uid, gid_t gid)
     91 {
     92     struct sfakeroot_msg m = {
     93         .type = SFAKEROOT_MSG_FCHOWN,
     94         .fd = fd,
     95         .uid = uid,
     96         .gid = gid
     97     };
     98     return sfakeroot__call(&m);
     99 }
    100 
    101 int fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag)
    102 {
    103     struct sfakeroot_msg m = {
    104         .type = SFAKEROOT_MSG_FCHOWNAT,
    105         .fd = fd,
    106         .flag = flag,
    107         .uid = uid,
    108         .gid = gid
    109     };
    110     debug("fchownat %d %s %u %u %u\n", fd, path, uid, gid, flag);
    111     strlcpy(m.path, path, sizeof (m.path));
    112     return sfakeroot__call(&m);
    113 }
    114 
    115 static int sfakeroot__stat(struct sfakeroot_msg *m, struct stat *s)
    116 {
    117     int ret;
    118     if ((ret = sfakeroot__call(m)) == -1) {
    119         return -1;
    120     }
    121     *s = m->st;
    122     return ret;
    123 }
    124 
    125 int stat(const char *path, struct stat *s)
    126 {
    127     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_STAT, .fd = -1};
    128     debug("stat\n");
    129     strlcpy(m.path, path, sizeof (m.path));
    130     return sfakeroot__stat(&m, s);
    131 }
    132 
    133 int __xstat(int ver, const char *path, struct stat *s)
    134 {
    135     (void) ver;
    136     return stat(path, s);
    137 }
    138 
    139 int lstat(const char *path, struct stat *s)
    140 {
    141     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_LSTAT, .fd = -1};
    142     debug("lstat\n");
    143     strlcpy(m.path, path, sizeof (m.path));
    144     return sfakeroot__stat(&m, s);
    145 }
    146 
    147 int __lxstat(int ver, const char *path, struct stat *s)
    148 {
    149     (void) ver;
    150     return lstat(path, s);
    151 }
    152 
    153 int fstat(int fd, struct stat *s)
    154 {
    155     struct sfakeroot_msg m = {.type = SFAKEROOT_MSG_FSTAT, .fd = fd};
    156     return sfakeroot__stat(&m, s);
    157 }
    158 
    159 int __fxstat(int ver, int fd, struct stat *sb)
    160 {
    161     (void) ver;
    162     return fstat(fd, sb);
    163 }
    164 
    165 int fstatat(int fd, const char *path, struct stat *s, int flag)
    166 {
    167     struct sfakeroot_msg m = {
    168         .type = SFAKEROOT_MSG_FSTATAT,
    169         .fd = fd,
    170         .flag = flag,
    171     };
    172     strlcpy(m.path, path, sizeof (m.path));
    173     return sfakeroot__stat(&m, s);
    174 }
    175 
    176 #if USE_STATX
    177 int statx(int dirfd, const char *path, int flags, unsigned int mask,
    178           struct statx *statxbuf)
    179 {
    180     struct sfakeroot_msg m = {
    181         .type = SFAKEROOT_MSG_STATX,
    182         .fd = dirfd,
    183         .flag = flags,
    184         .mask = mask
    185     };
    186     int ret;
    187     strlcpy(m.path, path, sizeof (m.path));
    188     if ((ret = sfakeroot__call(&m)) == -1) {
    189         return -1;
    190     }
    191     *statxbuf = m.statxbuf;
    192     return ret;
    193 }
    194 #endif
    195 
    196 #undef __xstat
    197 #undef __fxstat
    198 #undef __lxstat
    199 #undef __xstat64
    200 #undef __fxstat64
    201 #undef __lxstat64
    202 #undef _FILE_OFFSET_BITS
    203 
    204 // TODO:
    205 // int
    206 // utimes(const char *path, const struct timeval *times);
    207 //
    208 // int
    209 // futimes(int fd, const struct timeval *times);