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