1 /*
2 Copyright Ⓒ 2009 Regis Duchesne
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 */
15
16 #if defined __APPLE__ && !defined __LP64__
17 /*
18 In this file, we want 'struct stat' to have a 32-bit 'ino_t'.
19 We use 'struct stat64' when we need a 64-bit 'ino_t'.
20 */
21 #define _DARWIN_NO_64_BIT_INODE
22
23 /*
24 This file is for 32-bit symbols which have the "$UNIX2003" version, i.e.
25 32-bit symbols whose semantics adhere to the SUSv3 standard.
26 */
27 #define _DARWIN_C_SOURCE
28
29 #include "config.h"
30 #include "communicate.h"
31
32 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
33
34 #ifdef STUPID_ALPHA_HACK
35 #define SEND_STAT(a,b,c) send_stat(a,b,c)
36 #define SEND_STAT64(a,b,c) send_stat64(a,b,c)
37 #define SEND_GET_STAT(a,b) send_get_stat(a,b)
38 #define SEND_GET_STAT64(a,b) send_get_stat64(a,b)
39 #else
40 #define SEND_STAT(a,b,c) send_stat(a,b)
41 #define SEND_STAT64(a,b,c) send_stat64(a,b)
42 #define SEND_GET_STAT(a,b) send_get_stat(a)
43 #define SEND_GET_STAT64(a,b) send_get_stat64(a)
44 #endif
45
46 /*
47 These INT_* (which stands for internal) macros should always be used when
48 the fakeroot library owns the storage of the stat variable.
49 */
50 #ifdef STAT64_SUPPORT
51 #define INT_STRUCT_STAT struct stat64
52 #define INT_NEXT_STAT(a,b) NEXT_STAT64(_STAT_VER,a,b)
53 #define INT_NEXT_LSTAT(a,b) NEXT_LSTAT64(_STAT_VER,a,b)
54 #define INT_NEXT_FSTAT(a,b) NEXT_FSTAT64(_STAT_VER,a,b)
55 #define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT64(_STAT_VER,a,b,c,d)
56 #define INT_SEND_STAT(a,b) SEND_STAT64(a,b,_STAT_VER)
57 #else
58 #define INT_STRUCT_STAT struct stat
59 #define INT_NEXT_STAT(a,b) NEXT_STAT(_STAT_VER,a,b)
60 #define INT_NEXT_LSTAT(a,b) NEXT_LSTAT(_STAT_VER,a,b)
61 #define INT_NEXT_FSTAT(a,b) NEXT_FSTAT(_STAT_VER,a,b)
62 #define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT(_STAT_VER,a,b,c,d)
63 #define INT_SEND_STAT(a,b) SEND_STAT(a,b,_STAT_VER)
64 #endif
65
66 #include <stdio.h>
67 #include <unistd.h>
68 #include <errno.h>
69 #include <spawn.h>
70 #ifdef HAVE_SYS_ACL_H
71 #include <sys/acl.h>
72 #endif /* HAVE_SYS_ACL_H */
73 #if HAVE_FTS_H
74 #include <fts.h>
75 #endif /* HAVE_FTS_H */
76
77 #include "patchattr.h"
78 #include "wrapped.h"
79 #include "wraptmpf.h"
80 #include "wrapdef.h"
81
82 extern int fakeroot_disabled;
83
84 #ifdef LCHOWN_SUPPORT
85 extern int dont_try_chown() __attribute__((visibility("hidden")));
86
lchown$UNIX2003(const char * path,uid_t owner,gid_t group)87 int lchown$UNIX2003(const char *path, uid_t owner, gid_t group){
88 INT_STRUCT_STAT st;
89 int r=0;
90
91 #ifdef LIBFAKEROOT_DEBUGGING
92 if (fakeroot_debug) {
93 fprintf(stderr, "lchown$UNIX2003 path %s owner %d group %d\n", path, owner, group);
94 }
95 #endif /* LIBFAKEROOT_DEBUGGING */
96 r=INT_NEXT_LSTAT(path, &st);
97 if(r)
98 return r;
99 st.st_uid=owner;
100 st.st_gid=group;
101 INT_SEND_STAT(&st,chown_func);
102 if(!dont_try_chown())
103 r=next_lchown$UNIX2003(path,owner,group);
104 else
105 r=0;
106 if(r&&(errno==EPERM))
107 r=0;
108
109 return r;
110 }
111 #endif
112
chmod$UNIX2003(const char * path,mode_t mode)113 int chmod$UNIX2003(const char *path, mode_t mode){
114 INT_STRUCT_STAT st;
115 int r;
116
117 #ifdef LIBFAKEROOT_DEBUGGING
118 if (fakeroot_debug) {
119 fprintf(stderr, "chmod$UNIX2003 path %s\n", path);
120 }
121 #endif /* LIBFAKEROOT_DEBUGGING */
122 r=INT_NEXT_STAT(path, &st);
123 if(r)
124 return r;
125
126 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
127
128 INT_SEND_STAT(&st, chmod_func);
129
130 /* if a file is unwritable, then root can still write to it
131 (no matter who owns the file). If we are fakeroot, the only
132 way to fake this is to always make the file writable, readable
133 etc for the real user (who started fakeroot). Also holds for
134 the exec bit of directories.
135 Yes, packages requering that are broken. But we have lintian
136 to get rid of broken packages, not fakeroot.
137 */
138 mode |= 0600;
139 if(S_ISDIR(st.st_mode))
140 mode |= 0100;
141
142 r=next_chmod$UNIX2003(path, mode);
143 if(r&&(errno==EPERM))
144 r=0;
145 #ifdef EFTYPE /* available under FreeBSD kernel */
146 if(r&&(errno==EFTYPE))
147 r=0;
148 #endif
149 return r;
150 }
151
fchmod$UNIX2003(int fd,mode_t mode)152 int fchmod$UNIX2003(int fd, mode_t mode){
153 int r;
154 INT_STRUCT_STAT st;
155
156
157 #ifdef LIBFAKEROOT_DEBUGGING
158 if (fakeroot_debug) {
159 fprintf(stderr, "fchmod$UNIX2003 fd %d\n", fd);
160 }
161 #endif /* LIBFAKEROOT_DEBUGGING */
162 r=INT_NEXT_FSTAT(fd, &st);
163
164 if(r)
165 return(r);
166
167 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
168 INT_SEND_STAT(&st,chmod_func);
169
170 /* see chmod() for comment */
171 mode |= 0600;
172 if(S_ISDIR(st.st_mode))
173 mode |= 0100;
174
175 r=next_fchmod$UNIX2003(fd, mode);
176 if(r&&(errno==EPERM))
177 r=0;
178 #ifdef EFTYPE /* available under FreeBSD kernel */
179 if(r&&(errno==EFTYPE))
180 r=0;
181 #endif
182 return r;
183 }
184
185 extern int set_faked_reuid(uid_t ruid, uid_t euid) __attribute__((visibility("hidden")));
186
setreuid$UNIX2003(SETREUID_ARG ruid,SETREUID_ARG euid)187 int setreuid$UNIX2003(SETREUID_ARG ruid, SETREUID_ARG euid){
188 #ifdef LIBFAKEROOT_DEBUGGING
189 if (fakeroot_debug) {
190 fprintf(stderr, "setreuid$UNIX2003\n");
191 }
192 #endif /* LIBFAKEROOT_DEBUGGING */
193 if (fakeroot_disabled)
194 return next_setreuid$UNIX2003(ruid, euid);
195 return set_faked_reuid(ruid, euid);
196 }
197
198 extern int set_faked_regid(gid_t rgid, gid_t egid) __attribute__((visibility("hidden")));
199
setregid$UNIX2003(SETREGID_ARG rgid,SETREGID_ARG egid)200 int setregid$UNIX2003(SETREGID_ARG rgid, SETREGID_ARG egid){
201 #ifdef LIBFAKEROOT_DEBUGGING
202 if (fakeroot_debug) {
203 fprintf(stderr, "setregid$UNIX2003\n");
204 }
205 #endif /* LIBFAKEROOT_DEBUGGING */
206 if (fakeroot_disabled)
207 return next_setregid$UNIX2003(rgid, egid);
208 return set_faked_regid(rgid, egid);
209 }
210
211 int
getattrlist$UNIX2003(const char * path,void * attrList,void * attrBuf,size_t attrBufSize,unsigned long options)212 getattrlist$UNIX2003(const char *path, void *attrList, void *attrBuf,
213 size_t attrBufSize, unsigned long options)
214 {
215 int r;
216 struct stat st;
217
218 #ifdef LIBFAKEROOT_DEBUGGING
219 if (fakeroot_debug) {
220 fprintf(stderr, "getattrlist$UNIX2003 path %s\n", path);
221 }
222 #endif /* LIBFAKEROOT_DEBUGGING */
223 r=next_getattrlist$UNIX2003(path, attrList, attrBuf, attrBufSize, options);
224 if (r) {
225 return r;
226 }
227 if (options & FSOPT_NOFOLLOW) {
228 r=WRAP_LSTAT(path, &st);
229 } else {
230 r=WRAP_STAT(path, &st);
231 }
232 if (r) {
233 return r;
234 }
235 patchattr(attrList, attrBuf, st.st_uid, st.st_gid, st.st_mode);
236
237 return 0;
238 }
239 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 */
240 #endif /* if defined __APPLE__ && !defined __LP64__ */
241