1 /*
2 Copyright Ⓒ 1997, 1998, 1999, 2000, 2001 joost witteveen
3 Copyright Ⓒ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Clint Adams
4 Copyright Ⓒ 2012 Mikhail Gusarov
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program 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 */
17 /* #define _POSIX_C_SOURCE 199309L whatever that may mean...*/
18 /* #define _BSD_SOURCE I use strdup, S_IFDIR, etc */
19
20 /* Roderich Schupp writes (bug #79100):
21 /usr/include/dlfcn.h from libc6 2.2-5 defines RTLD_NEXT only
22 when compiled with _GNU_SOURCE defined. Hence libfakeroot.c doesn't pick
23 it
24 up and does a dlopen("/lib/libc.so.6",...) in get_libc().
25 This works most of the time, but explodes if you have an arch-optimized
26 libc installed: the program now has two versions of libc.so
27 (/lib/libc.so.6 and, say, /lib/i586/libc.so.6) mapped. Again for
28 some programs you might get away with this, but running bash under
29 fakeroot
30 always bombs. Simple fix:
31 */
32 #define _GNU_SOURCE
33
34 #define FAKEROOT_LIBFAKEROOT
35
36 #ifdef __APPLE__
37 /*
38 In this file, we want 'struct stat' to have a 32-bit 'ino_t'.
39 We use 'struct stat64' when we need a 64-bit 'ino_t'.
40 */
41 #define _DARWIN_NO_64_BIT_INODE
42
43 /* The helper _unix2003 version of this file calls a few functions in this file
44 that are marked with static_nonapple so that needs to become private instead
45 */
46 #define static_nonapple __attribute__((visibility("hidden")))
47
48 #ifndef __LP64__
49 /*
50 This file is for 32-bit symbols which do not have the "$UNIX2003" version.
51 */
52 #define _NONSTD_SOURCE
53 #endif
54 #else /* !__APPLE__ */
55 /* static_nonapple needs to become static in this case */
56 #define static_nonapple static
57 #endif /* !__APPLE__ */
58
59 #include "config.h"
60 #include "communicate.h"
61
62 #ifdef __APPLE__
63 /* The *xattr functions are currently disabled on __APPLE__ since the prototypes
64 are all different from the Linux versions and there is, as of yet, no
65 STUPID_APPLE_HACK (or similar) to deal with the differences.
66 Note that __APPLE__ does not have the l*xattr variants or capset so those
67 will already be undefined.
68 */
69 #undef HAVE_LISTXATTR
70 #undef HAVE_FLISTXATTR
71 #undef HAVE_GETXATTR
72 #undef HAVE_FGETXATTR
73 #undef HAVE_SETXATTR
74 #undef HAVE_FSETXATTR
75 #undef HAVE_REMOVEXATTR
76 #undef HAVE_FREMOVEXATTR
77 #endif /* __APPLE__ */
78
79 #ifdef STUPID_ALPHA_HACK
80 #define SEND_STAT(a,b,c) send_stat(a,b,c)
81 #define SEND_STAT64(a,b,c) send_stat64(a,b,c)
82 #define SEND_GET_STAT(a,b) send_get_stat(a,b)
83 #define SEND_GET_STAT64(a,b) send_get_stat64(a,b)
84 #define SEND_GET_XATTR64(a,b,c) send_get_xattr64(a,b,c)
85 #else
86 #define SEND_STAT(a,b,c) send_stat(a,b)
87 #define SEND_STAT64(a,b,c) send_stat64(a,b)
88 #define SEND_GET_STAT(a,b) send_get_stat(a)
89 #define SEND_GET_STAT64(a,b) send_get_stat64(a)
90 #define SEND_GET_XATTR64(a,b,c) send_get_xattr64(a,b)
91 #endif
92
93 /*
94 These INT_* (which stands for internal) macros should always be used when
95 the fakeroot library owns the storage of the stat variable.
96 */
97 #ifdef STAT64_SUPPORT
98 #define INT_STRUCT_STAT struct stat64
99 #define INT_NEXT_STAT(a,b) NEXT_STAT64(_STAT_VER,a,b)
100 #define INT_NEXT_LSTAT(a,b) NEXT_LSTAT64(_STAT_VER,a,b)
101 #define INT_NEXT_FSTAT(a,b) NEXT_FSTAT64(_STAT_VER,a,b)
102 #define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT64(_STAT_VER,a,b,c,d)
103 #define INT_SEND_STAT(a,b) SEND_STAT64(a,b,_STAT_VER)
104 #define INT_SEND_GET_XATTR(a,b) SEND_GET_XATTR64(a,b,_STAT_VER)
105 #else
106 #define INT_STRUCT_STAT struct stat
107 #define INT_NEXT_STAT(a,b) NEXT_STAT(_STAT_VER,a,b)
108 #define INT_NEXT_LSTAT(a,b) NEXT_LSTAT(_STAT_VER,a,b)
109 #define INT_NEXT_FSTAT(a,b) NEXT_FSTAT(_STAT_VER,a,b)
110 #define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT(_STAT_VER,a,b,c,d)
111 #define INT_SEND_STAT(a,b) SEND_STAT(a,b,_STAT_VER)
112 #define INT_SEND_GET_XATTR(a,b) SEND_GET_XATTR(a,b,_STAT_VER)
113 #endif
114
115 #include <stdlib.h>
116 #include <sys/ipc.h>
117 #include <sys/msg.h>
118 #include <fcntl.h>
119 #include <string.h>
120 #include <stdio.h>
121 #include <stdarg.h>
122 #include <dlfcn.h>
123 #include <unistd.h>
124 #include <dirent.h>
125 #include <errno.h>
126 #include <sys/types.h>
127 #ifdef HAVE_SYS_ACL_H
128 #include <sys/acl.h>
129 #endif /* HAVE_SYS_ACL_H */
130 #ifdef HAVE_SYS_CAPABILITY_H
131 #include <sys/capability.h>
132 #endif
133 #if HAVE_FTS_H
134 #include <fts.h>
135 #endif /* HAVE_FTS_H */
136 #ifdef __sun
137 #include <sys/systeminfo.h>
138 #endif
139 #ifdef __APPLE__
140 #include <paths.h>
141 #include <sys/stat.h>
142 #include <crt_externs.h>
143 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
144 #include <spawn.h>
145 #endif
146 #ifndef va_copy
147 #define va_copy(dest,src) ((dest)=(src))
148 #endif
149 #endif /* __APPLE__ */
150
151 #if !HAVE_DECL_SETENV
152 extern int setenv (const char *name, const char *value, int replace);
153 #endif
154 #if !HAVE_DECL_UNSETENV
155 extern int unsetenv (const char *name);
156 #endif
157
158
159 /*
160 Where are those shared libraries?
161 If I knew of a configure/libtool way to find that out, I'd use it. Or
162 any other way other than the method I'm using below. Does anybody know
163 how I can get that location? (BTW, symply linking a programme, and running
164 `ldd' on it isn't the option, as Digital Unix doesn't have ldd)
165 */
166
167
168 /*
169 Note that LIBCPATH isn't actually used on Linux or Solaris, as RTLD_NEXT
170 is defined and we use that to get the `next_*' functions
171
172 Linux:
173 */
174
175 /* OSF1 :*/
176 /*#define LIBCPATH "/usr/shlib/libc.so"*/
177
178 #undef __xstat
179 #undef __fxstat
180 #undef __lxstat
181 #undef __xstat64
182 #undef __fxstat64
183 #undef __lxstat64
184 #undef _FILE_OFFSET_BITS
185
186 /*
187 // next_wrap_st:
188 // this structure is used in next_wrap, which is defined in
189 // wrapstruct.h, included below
190 */
191
192 struct next_wrap_st{
193 void **doit;
194 char *name;
195 };
196
get_libc()197 void *get_libc(){
198
199 #ifndef RTLD_NEXT
200 void *lib=0;
201 if(!lib){
202 lib= dlopen(LIBCPATH,RTLD_LAZY);
203 }
204 if (NULL==lib) {
205 fprintf(stderr, "Couldn't find libc at: %s\n", LIBCPATH);
206 abort();
207 }
208 return lib;
209 #else
210 return RTLD_NEXT;
211 #endif
212 }
213 void load_library_symbols(void);
214
215 int fakeroot_disabled = 0;
216 #ifdef LIBFAKEROOT_DEBUGGING
217 int fakeroot_debug = 0;
218 #endif /* LIBFAKEROOT_DEBUGGING */
219
220 #ifdef __APPLE__
221 #include "patchattr.h"
222 #endif
223 #include "wrapped.h"
224 #include "wraptmpf.h"
225 #include "wrapdef.h"
226 #include "wrapstruct.h"
227
228
load_library_symbols(void)229 void load_library_symbols(void){
230 /* this function loads all original functions from the C library.
231 This function is only called once.
232 I ran into problems when each function individually
233 loaded it's original counterpart, as RTLD_NEXT seems to have
234 a different meaning in files with different names than libtricks.c
235 (I.E, dlsym(RTLD_NEXT, ...) called in vsearch.c returned funtions
236 defined in libtricks */
237 /* The calling of this function itself is somewhat tricky:
238 the awk script wrapawk generates several .h files. In wraptmpf.h
239 there are temporary definitions for tmp_*, that do the call
240 to this function. The other generated .h files do even more tricky
241 things :) */
242
243 int i;
244 const char *msg;
245
246 #ifdef LIBFAKEROOT_DEBUGGING
247 if (getenv("FAKEROOT_DEBUG")) {
248 fakeroot_debug=1;
249 }
250 if (fakeroot_debug) {
251 fprintf(stderr, "load_library_symbols\n");
252 }
253
254 #endif /* LIBFAKEROOT_DEBUGGING */
255 for(i=0; next_wrap[i].doit; i++){
256 /* clear dlerror() just in case dlsym() legitimately returns NULL */
257 msg = dlerror();
258 *(next_wrap[i].doit)=dlsym(get_libc(), next_wrap[i].name);
259 if ( (msg = dlerror()) != NULL){
260 fprintf (stderr, "dlsym(%s): %s\n", next_wrap[i].name, msg);
261 /* abort ();*/
262 }
263 }
264 }
265
266
267 /*
268 * Fake implementations for the setuid family of functions.
269 * The fake IDs are inherited by child processes via environment variables.
270 *
271 * Issues:
272 * o Privileges are not checked, which results in incorrect behaviour.
273 * Example: process changes its (real, effective and saved) uid to 1000
274 * and then tries to regain root privileges. This should normally result
275 * in an EPERM, but our implementation doesn't care...
276 * o If one of the setenv calls fails, the state may get corrupted.
277 * o Not thread-safe.
278 */
279
280
281 /* Generic set/get ID functions */
282
env_get_id(const char * key)283 static int env_get_id(const char *key) {
284 char *str = getenv(key);
285 if (str)
286 return atoi(str);
287 return 0;
288 }
289
env_set_id(const char * key,int id)290 static int env_set_id(const char *key, int id) {
291 if (id == 0) {
292 unsetenv(key);
293 return 0;
294 } else {
295 char str[12];
296 snprintf(str, sizeof (str), "%d", id);
297 return setenv(key, str, 1);
298 }
299 }
300
read_id(unsigned int * id,const char * key)301 static void read_id(unsigned int *id, const char *key) {
302 if (*id == (unsigned int)-1)
303 *id = env_get_id(key);
304 }
305
write_id(const char * key,int id)306 static int write_id(const char *key, int id) {
307 if (env_get_id(key) != id)
308 return env_set_id(key, id);
309 return 0;
310 }
311
312 /* Fake ID storage */
313
314 static uid_t faked_real_uid = (uid_t)-1;
315 static gid_t faked_real_gid = (gid_t)-1;
316 static uid_t faked_effective_uid = (uid_t)-1;
317 static gid_t faked_effective_gid = (gid_t)-1;
318 static uid_t faked_saved_uid = (uid_t)-1;
319 static gid_t faked_saved_gid = (gid_t)-1;
320 static uid_t faked_fs_uid = (uid_t)-1;
321 static gid_t faked_fs_gid = (gid_t)-1;
322
323 /* Read user ID */
324
read_real_uid()325 static void read_real_uid() {
326 read_id(&faked_real_uid, FAKEROOTUID_ENV);
327 }
328
read_effective_uid()329 static void read_effective_uid() {
330 read_id(&faked_effective_uid, FAKEROOTEUID_ENV);
331 }
332
read_saved_uid()333 static void read_saved_uid() {
334 read_id(&faked_saved_uid, FAKEROOTSUID_ENV);
335 }
336
read_fs_uid()337 static void read_fs_uid() {
338 read_id(&faked_fs_uid, FAKEROOTFUID_ENV);
339 }
340
read_uids()341 static void read_uids() {
342 read_real_uid();
343 read_effective_uid();
344 read_saved_uid();
345 read_fs_uid();
346 }
347
348 /* Read group ID */
349
read_real_gid()350 static void read_real_gid() {
351 read_id(&faked_real_gid, FAKEROOTGID_ENV);
352 }
353
read_effective_gid()354 static void read_effective_gid() {
355 read_id(&faked_effective_gid, FAKEROOTEGID_ENV);
356 }
357
read_saved_gid()358 static void read_saved_gid() {
359 read_id(&faked_saved_gid, FAKEROOTSGID_ENV);
360 }
361
read_fs_gid()362 static void read_fs_gid() {
363 read_id(&faked_fs_gid, FAKEROOTFGID_ENV);
364 }
365
read_gids()366 static void read_gids() {
367 read_real_gid();
368 read_effective_gid();
369 read_saved_gid();
370 read_fs_gid();
371 }
372
373 /* Write user ID */
374
write_real_uid()375 static int write_real_uid() {
376 return write_id(FAKEROOTUID_ENV, faked_real_uid);
377 }
378
write_effective_uid()379 static int write_effective_uid() {
380 return write_id(FAKEROOTEUID_ENV, faked_effective_uid);
381 }
382
write_saved_uid()383 static int write_saved_uid() {
384 return write_id(FAKEROOTSUID_ENV, faked_saved_uid);
385 }
386
write_fs_uid()387 static int write_fs_uid() {
388 return write_id(FAKEROOTFUID_ENV, faked_fs_uid);
389 }
390
write_uids()391 static int write_uids() {
392 if (write_real_uid() < 0)
393 return -1;
394 if (write_effective_uid() < 0)
395 return -1;
396 if (write_saved_uid() < 0)
397 return -1;
398 if (write_fs_uid() < 0)
399 return -1;
400 return 0;
401 }
402
403 /* Write group ID */
404
write_real_gid()405 static int write_real_gid() {
406 return write_id(FAKEROOTGID_ENV, faked_real_gid);
407 }
408
write_effective_gid()409 static int write_effective_gid() {
410 return write_id(FAKEROOTEGID_ENV, faked_effective_gid);
411 }
412
write_saved_gid()413 static int write_saved_gid() {
414 return write_id(FAKEROOTSGID_ENV, faked_saved_gid);
415 }
416
write_fs_gid()417 static int write_fs_gid() {
418 return write_id(FAKEROOTFGID_ENV, faked_fs_gid);
419 }
420
write_gids()421 static int write_gids() {
422 if (write_real_gid() < 0)
423 return -1;
424 if (write_effective_gid() < 0)
425 return -1;
426 if (write_saved_gid() < 0)
427 return -1;
428 if (write_fs_gid() < 0)
429 return -1;
430 return 0;
431 }
432
433 /* Faked get functions */
434
get_faked_uid()435 static uid_t get_faked_uid() {
436 read_real_uid();
437 return faked_real_uid;
438 }
439
get_faked_gid()440 static gid_t get_faked_gid() {
441 read_real_gid();
442 return faked_real_gid;
443 }
444
get_faked_euid()445 static uid_t get_faked_euid() {
446 read_effective_uid();
447 return faked_effective_uid;
448 }
449
get_faked_egid()450 static gid_t get_faked_egid() {
451 read_effective_gid();
452 return faked_effective_gid;
453 }
454
get_faked_suid()455 static uid_t get_faked_suid() {
456 read_saved_uid();
457 return faked_saved_uid;
458 }
459
get_faked_sgid()460 static gid_t get_faked_sgid() {
461 read_saved_gid();
462 return faked_saved_gid;
463 }
464
get_faked_fsuid()465 static uid_t get_faked_fsuid() {
466 read_fs_uid();
467 return faked_fs_uid;
468 }
469
get_faked_fsgid()470 static gid_t get_faked_fsgid() {
471 read_fs_gid();
472 return faked_fs_gid;
473 }
474
475 /* Faked set functions */
476
set_faked_uid(uid_t uid)477 static int set_faked_uid(uid_t uid) {
478 read_uids();
479 if (faked_effective_uid == 0) {
480 faked_real_uid = uid;
481 faked_effective_uid = uid;
482 faked_saved_uid = uid;
483 } else {
484 faked_effective_uid = uid;
485 }
486 faked_fs_uid = uid;
487 return write_uids();
488 }
489
set_faked_gid(gid_t gid)490 static int set_faked_gid(gid_t gid) {
491 read_gids();
492 if (faked_effective_gid == 0) {
493 faked_real_gid = gid;
494 faked_effective_gid = gid;
495 faked_saved_gid = gid;
496 } else {
497 faked_effective_gid = gid;
498 }
499 faked_fs_gid = gid;
500 return write_gids();
501 }
502
set_faked_euid(uid_t euid)503 static int set_faked_euid(uid_t euid) {
504 read_effective_uid();
505 faked_effective_uid = euid;
506 read_fs_uid();
507 faked_fs_uid = euid;
508 if (write_effective_uid() < 0)
509 return -1;
510 if (write_fs_uid() < 0)
511 return -1;
512 return 0;
513 }
514
set_faked_egid(gid_t egid)515 static int set_faked_egid(gid_t egid) {
516 read_effective_gid();
517 faked_effective_gid = egid;
518 read_fs_gid();
519 faked_fs_gid = egid;
520 if (write_effective_gid() < 0)
521 return -1;
522 if (write_fs_gid() < 0)
523 return -1;
524 return 0;
525 }
526
set_faked_reuid(uid_t ruid,uid_t euid)527 static_nonapple int set_faked_reuid(uid_t ruid, uid_t euid) {
528 read_uids();
529 if (ruid != (uid_t)-1 || euid != (uid_t)-1)
530 faked_saved_uid = faked_effective_uid;
531 if (ruid != (uid_t)-1)
532 faked_real_uid = ruid;
533 if (euid != (uid_t)-1)
534 faked_effective_uid = euid;
535 faked_fs_uid = faked_effective_uid;
536 return write_uids();
537 }
538
set_faked_regid(gid_t rgid,gid_t egid)539 static_nonapple int set_faked_regid(gid_t rgid, gid_t egid) {
540 read_gids();
541 if (rgid != (gid_t)-1 || egid != (gid_t)-1)
542 faked_saved_gid = faked_effective_gid;
543 if (rgid != (gid_t)-1)
544 faked_real_gid = rgid;
545 if (egid != (gid_t)-1)
546 faked_effective_gid = egid;
547 faked_fs_gid = faked_effective_gid;
548 return write_gids();
549 }
550
551 #ifdef HAVE_SETRESUID
set_faked_resuid(uid_t ruid,uid_t euid,uid_t suid)552 static int set_faked_resuid(uid_t ruid, uid_t euid, uid_t suid) {
553 read_uids();
554 if (ruid != (uid_t)-1)
555 faked_real_uid = ruid;
556 if (euid != (uid_t)-1)
557 faked_effective_uid = euid;
558 if (suid != (uid_t)-1)
559 faked_saved_uid = suid;
560 faked_fs_uid = faked_effective_uid;
561 return write_uids();
562 }
563 #endif
564
565 #ifdef HAVE_SETRESGID
set_faked_resgid(gid_t rgid,gid_t egid,gid_t sgid)566 static int set_faked_resgid(gid_t rgid, gid_t egid, gid_t sgid) {
567 read_gids();
568 if (rgid != (gid_t)-1)
569 faked_real_gid = rgid;
570 if (egid != (gid_t)-1)
571 faked_effective_gid = egid;
572 if (sgid != (gid_t)-1)
573 faked_saved_gid = sgid;
574 faked_fs_gid = faked_effective_gid;
575 return write_gids();
576 }
577 #endif
578
579 #ifdef HAVE_SETFSUID
set_faked_fsuid(uid_t fsuid)580 static uid_t set_faked_fsuid(uid_t fsuid) {
581 uid_t prev_fsuid = get_faked_fsuid();
582 faked_fs_uid = fsuid;
583 return prev_fsuid;
584 }
585 #endif
586
587 #ifdef HAVE_SETFSGID
set_faked_fsgid(gid_t fsgid)588 static gid_t set_faked_fsgid(gid_t fsgid) {
589 gid_t prev_fsgid = get_faked_fsgid();
590 faked_fs_gid = fsgid;
591 return prev_fsgid;
592 }
593 #endif
594
595
dont_try_chown()596 static_nonapple int dont_try_chown(){
597 static int inited=0;
598 static int donttry;
599
600 if(!inited){
601 donttry=(env_var_set(FAKEROOTDONTTRYCHOWN_ENV)!=NULL);
602 inited=1;
603 }
604 return donttry;
605 }
606
607
608 /* The wrapped functions */
609
610
LSTAT_ARG(int ver,const char * file_name,struct stat * statbuf)611 int WRAP_LSTAT LSTAT_ARG(int ver,
612 const char *file_name,
613 struct stat *statbuf){
614
615 int r;
616
617 #ifdef LIBFAKEROOT_DEBUGGING
618 if (fakeroot_debug) {
619 fprintf(stderr, "lstat file_name %s\n", file_name);
620 }
621 #endif /* LIBFAKEROOT_DEBUGGING */
622 r=NEXT_LSTAT(ver, file_name, statbuf);
623 if(r)
624 return -1;
625 SEND_GET_STAT(statbuf, ver);
626 return 0;
627 }
628
629
STAT_ARG(int ver,const char * file_name,struct stat * st)630 int WRAP_STAT STAT_ARG(int ver,
631 const char *file_name,
632 struct stat *st){
633 int r;
634
635 #ifdef LIBFAKEROOT_DEBUGGING
636 if (fakeroot_debug) {
637 fprintf(stderr, "stat file_name %s\n", file_name);
638 }
639 #endif /* LIBFAKEROOT_DEBUGGING */
640 r=NEXT_STAT(ver, file_name, st);
641 if(r)
642 return -1;
643 SEND_GET_STAT(st,ver);
644 return 0;
645 }
646
647
FSTAT_ARG(int ver,int fd,struct stat * st)648 int WRAP_FSTAT FSTAT_ARG(int ver,
649 int fd,
650 struct stat *st){
651
652
653 int r;
654
655 #ifdef LIBFAKEROOT_DEBUGGING
656 if (fakeroot_debug) {
657 fprintf(stderr, "fstat fd %d\n", fd);
658 }
659 #endif /* LIBFAKEROOT_DEBUGGING */
660 r=NEXT_FSTAT(ver, fd, st);
661 if(r)
662 return -1;
663 SEND_GET_STAT(st,ver);
664 return 0;
665 }
666
667 #ifdef HAVE_FSTATAT
FSTATAT_ARG(int ver,int dir_fd,const char * path,struct stat * st,int flags)668 int WRAP_FSTATAT FSTATAT_ARG(int ver,
669 int dir_fd,
670 const char *path,
671 struct stat *st,
672 int flags){
673
674
675 int r;
676
677 r=NEXT_FSTATAT(ver, dir_fd, path, st, flags);
678 if(r)
679 return -1;
680 SEND_GET_STAT(st,ver);
681 return 0;
682 }
683 #endif /* HAVE_FSTATAT */
684
685 #ifdef STAT64_SUPPORT
686
LSTAT64_ARG(int ver,const char * file_name,struct stat64 * st)687 int WRAP_LSTAT64 LSTAT64_ARG (int ver,
688 const char *file_name,
689 struct stat64 *st){
690
691 int r;
692
693 #ifdef LIBFAKEROOT_DEBUGGING
694 if (fakeroot_debug) {
695 fprintf(stderr, "lstat64 file_name %s\n", file_name);
696 }
697 #endif /* LIBFAKEROOT_DEBUGGING */
698 r=NEXT_LSTAT64(ver, file_name, st);
699
700 if(r)
701 return -1;
702
703 SEND_GET_STAT64(st,ver);
704 return 0;
705 }
706
707
STAT64_ARG(int ver,const char * file_name,struct stat64 * st)708 int WRAP_STAT64 STAT64_ARG(int ver,
709 const char *file_name,
710 struct stat64 *st){
711 int r;
712
713 #ifdef LIBFAKEROOT_DEBUGGING
714 if (fakeroot_debug) {
715 fprintf(stderr, "stat64 file_name %s\n", file_name);
716 }
717 #endif /* LIBFAKEROOT_DEBUGGING */
718 r=NEXT_STAT64(ver,file_name,st);
719 if(r)
720 return -1;
721 SEND_GET_STAT64(st,ver);
722 return 0;
723 }
724
725
FSTAT64_ARG(int ver,int fd,struct stat64 * st)726 int WRAP_FSTAT64 FSTAT64_ARG(int ver,
727 int fd,
728 struct stat64 *st){
729 int r;
730
731 #ifdef LIBFAKEROOT_DEBUGGING
732 if (fakeroot_debug) {
733 fprintf(stderr, "fstat64 fd %d\n", fd);
734 }
735 #endif /* LIBFAKEROOT_DEBUGGING */
736 r=NEXT_FSTAT64(ver, fd, st);
737 if(r)
738 return -1;
739 SEND_GET_STAT64(st,ver);
740
741 return 0;
742 }
743
744 #ifdef HAVE_FSTATAT
FSTATAT64_ARG(int ver,int dir_fd,const char * path,struct stat64 * st,int flags)745 int WRAP_FSTATAT64 FSTATAT64_ARG(int ver,
746 int dir_fd,
747 const char *path,
748 struct stat64 *st,
749 int flags){
750
751
752 int r;
753
754 r=NEXT_FSTATAT64(ver, dir_fd, path, st, flags);
755 if(r)
756 return -1;
757 SEND_GET_STAT64(st,ver);
758 return 0;
759 }
760 #endif /* HAVE_FSTATAT */
761
762 #endif /* STAT64_SUPPORT */
763
764 /*************************************************************/
765 /*
766 Wrapped functions general info:
767
768 In general, the structure is as follows:
769 - Then, if the function does things that (possibly) fail by
770 other users than root, allow for `fake' root privileges.
771 Do this by obtaining the inode the function works on, and then
772 informing faked (the deamon that remembers all `fake' file
773 permissions e.d.) about the intentions of the user.
774 Faked maintains a list of inodes and their respective
775 `fake' ownerships/filemodes.
776 - Or, if the function requests information that we should
777 fake, again get the inode of the file, and ask faked about the
778 ownership/filemode data it maintains for that inode.
779
780 */
781 /*************************************************************/
782
783
784
785 /* chown, lchown, fchown, chmod, fchmod, mknod functions
786
787 quite general. See the `Wrapped functions general info:' above
788 for more info.
789 */
790
chown(const char * path,uid_t owner,gid_t group)791 int chown(const char *path, uid_t owner, gid_t group){
792 INT_STRUCT_STAT st;
793 int r=0;
794
795
796 #ifdef LIBFAKEROOT_DEBUGGING
797 if (fakeroot_debug) {
798 fprintf(stderr, "chown path %s owner %d group %d\n", path, owner, group);
799 }
800 #endif /* LIBFAKEROOT_DEBUGGING */
801 #ifdef LCHOWN_SUPPORT
802 /*chown(sym-link) works on the target of the symlink if lchown is
803 present and enabled.*/
804 r=INT_NEXT_STAT(path, &st);
805 #else
806 /*chown(sym-link) works on the symlink itself, use lstat: */
807 r=INT_NEXT_LSTAT(path, &st);
808 #endif
809
810 if(r)
811 return r;
812 st.st_uid=owner;
813 st.st_gid=group;
814 INT_SEND_STAT(&st,chown_func);
815 if(!dont_try_chown())
816 r=next_lchown(path,owner,group);
817 else
818 r=0;
819 if(r&&(errno==EPERM))
820 r=0;
821
822 return r;
823 }
824
825
826 #ifdef LCHOWN_SUPPORT
lchown(const char * path,uid_t owner,gid_t group)827 int lchown(const char *path, uid_t owner, gid_t group){
828 INT_STRUCT_STAT st;
829 int r=0;
830
831 #ifdef LIBFAKEROOT_DEBUGGING
832 if (fakeroot_debug) {
833 fprintf(stderr, "lchown path %s owner %d group %d\n", path, owner, group);
834 }
835 #endif /* LIBFAKEROOT_DEBUGGING */
836 r=INT_NEXT_LSTAT(path, &st);
837 if(r)
838 return r;
839 st.st_uid=owner;
840 st.st_gid=group;
841 INT_SEND_STAT(&st,chown_func);
842 if(!dont_try_chown())
843 r=next_lchown(path,owner,group);
844 else
845 r=0;
846 if(r&&(errno==EPERM))
847 r=0;
848
849 return r;
850 }
851 #endif
852
fchown(int fd,uid_t owner,gid_t group)853 int fchown(int fd, uid_t owner, gid_t group){
854 INT_STRUCT_STAT st;
855 int r;
856
857 r=INT_NEXT_FSTAT(fd, &st);
858 if(r)
859 return r;
860
861 st.st_uid=owner;
862 st.st_gid=group;
863 INT_SEND_STAT(&st, chown_func);
864
865 if(!dont_try_chown())
866 r=next_fchown(fd,owner,group);
867 else
868 r=0;
869
870 if(r&&(errno==EPERM))
871 r=0;
872
873 return r;
874 }
875
876 #ifdef HAVE_FSTATAT
877 #ifdef HAVE_FCHOWNAT
fchownat(int dir_fd,const char * path,uid_t owner,gid_t group,int flags)878 int fchownat(int dir_fd, const char *path, uid_t owner, gid_t group, int flags) {
879 int r;
880 /* If AT_SYMLINK_NOFOLLOW is set in the fchownat call it should
881 be when we stat it. */
882 INT_STRUCT_STAT st;
883 r=INT_NEXT_FSTATAT(dir_fd, path, &st, (flags & AT_SYMLINK_NOFOLLOW));
884
885 if(r)
886 return(r);
887
888 st.st_uid=owner;
889 st.st_gid=group;
890 INT_SEND_STAT(&st,chown_func);
891
892 if(!dont_try_chown())
893 r=next_fchownat(dir_fd,path,owner,group,flags);
894 else
895 r=0;
896
897 if(r&&(errno==EPERM))
898 r=0;
899
900 return r;
901 }
902 #endif /* HAVE_FCHOWNAT */
903 #endif /* HAVE_FSTATAT */
904
chmod(const char * path,mode_t mode)905 int chmod(const char *path, mode_t mode){
906 INT_STRUCT_STAT st;
907 int r;
908
909 #ifdef LIBFAKEROOT_DEBUGGING
910 if (fakeroot_debug) {
911 fprintf(stderr, "chmod path %s\n", path);
912 }
913 #endif /* LIBFAKEROOT_DEBUGGING */
914 r=INT_NEXT_STAT(path, &st);
915 if(r)
916 return r;
917
918 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
919
920 INT_SEND_STAT(&st, chmod_func);
921
922 /* if a file is unwritable, then root can still write to it
923 (no matter who owns the file). If we are fakeroot, the only
924 way to fake this is to always make the file writable, readable
925 etc for the real user (who started fakeroot). Also holds for
926 the exec bit of directories.
927 Yes, packages requering that are broken. But we have lintian
928 to get rid of broken packages, not fakeroot.
929 */
930 mode |= 0600;
931 if(S_ISDIR(st.st_mode))
932 mode |= 0100;
933
934 r=next_chmod(path, mode);
935 if(r&&(errno==EPERM))
936 r=0;
937 #ifdef EFTYPE /* available under FreeBSD kernel */
938 if(r&&(errno==EFTYPE))
939 r=0;
940 #endif
941 return r;
942 }
943
944 #ifdef HAVE_LCHMOD
lchmod(const char * path,mode_t mode)945 int lchmod(const char *path, mode_t mode){
946 INT_STRUCT_STAT st;
947 int r;
948
949 #ifdef LIBFAKEROOT_DEBUGGING
950 if (fakeroot_debug) {
951 fprintf(stderr, "lchmod path %s\n", path);
952 }
953 #endif /* LIBFAKEROOT_DEBUGGING */
954 r=INT_NEXT_LSTAT(path, &st);
955 if(r)
956 return r;
957
958 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
959
960 INT_SEND_STAT(&st, chmod_func);
961
962 /* see chmod() for comment */
963 mode |= 0600;
964 if(S_ISDIR(st.st_mode))
965 mode |= 0100;
966
967 r=next_lchmod(path, mode);
968 if(r&&(errno==EPERM))
969 r=0;
970 #ifdef EFTYPE /* available under FreeBSD kernel */
971 if(r&&(errno==EFTYPE))
972 r=0;
973 #endif
974 return r;
975 }
976 #endif
977
fchmod(int fd,mode_t mode)978 int fchmod(int fd, mode_t mode){
979 int r;
980 INT_STRUCT_STAT st;
981
982
983 #ifdef LIBFAKEROOT_DEBUGGING
984 if (fakeroot_debug) {
985 fprintf(stderr, "fchmod fd %d\n", fd);
986 }
987 #endif /* LIBFAKEROOT_DEBUGGING */
988 r=INT_NEXT_FSTAT(fd, &st);
989
990 if(r)
991 return(r);
992
993 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
994 INT_SEND_STAT(&st,chmod_func);
995
996 /* see chmod() for comment */
997 mode |= 0600;
998 if(S_ISDIR(st.st_mode))
999 mode |= 0100;
1000
1001 r=next_fchmod(fd, mode);
1002 if(r&&(errno==EPERM))
1003 r=0;
1004 #ifdef EFTYPE /* available under FreeBSD kernel */
1005 if(r&&(errno==EFTYPE))
1006 r=0;
1007 #endif
1008 return r;
1009 }
1010
1011 #ifdef HAVE_FSTATAT
1012 #ifdef HAVE_FCHMODAT
fchmodat(int dir_fd,const char * path,mode_t mode,int flags)1013 int fchmodat(int dir_fd, const char *path, mode_t mode, int flags) {
1014 /* (int fd, mode_t mode){*/
1015 int r;
1016 INT_STRUCT_STAT st;
1017
1018 /* If AT_SYMLINK_NOFOLLOW is set in the fchownat call it should
1019 be when we stat it. */
1020 r=INT_NEXT_FSTATAT(dir_fd, path, &st, flags & AT_SYMLINK_NOFOLLOW);
1021
1022 if(r)
1023 return(r);
1024
1025 st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
1026 INT_SEND_STAT(&st,chmod_func);
1027
1028 /* see chmod() for comment */
1029 mode |= 0600;
1030 if(S_ISDIR(st.st_mode))
1031 mode |= 0100;
1032
1033 r=next_fchmodat(dir_fd, path, mode, flags);
1034 if(r&&(errno==EPERM))
1035 r=0;
1036 #ifdef EFTYPE /* available under FreeBSD kernel */
1037 if(r&&(errno==EFTYPE))
1038 r=0;
1039 #endif
1040 return r;
1041 }
1042 #endif /* HAVE_FCHMODAT */
1043 #endif /* HAVE_FSTATAT */
1044
MKNOD_ARG(int ver UNUSED,const char * pathname,mode_t mode,dev_t XMKNOD_FRTH_ARG dev)1045 int WRAP_MKNOD MKNOD_ARG(int ver UNUSED,
1046 const char *pathname,
1047 mode_t mode, dev_t XMKNOD_FRTH_ARG dev)
1048 {
1049 INT_STRUCT_STAT st;
1050 mode_t old_mask=umask(022);
1051 int fd,r;
1052
1053 umask(old_mask);
1054
1055 /*Don't bother to mknod the file, that probably doesn't work.
1056 just create it as normal file, and leave the premissions
1057 to the fakemode.*/
1058
1059 fd=open(pathname, O_WRONLY|O_CREAT|O_TRUNC, 00644);
1060
1061 if(fd==-1)
1062 return -1;
1063
1064 close(fd);
1065 /* get the inode, to communicate with faked */
1066
1067 r=INT_NEXT_LSTAT(pathname, &st);
1068
1069 if(r)
1070 return -1;
1071
1072 st.st_mode= mode & ~old_mask;
1073 st.st_rdev= XMKNOD_FRTH_ARG dev;
1074
1075 INT_SEND_STAT(&st,mknod_func);
1076
1077 return 0;
1078 }
1079
1080 #ifdef HAVE_FSTATAT
1081 #ifdef HAVE_MKNODAT
MKNODAT_ARG(int ver UNUSED,int dir_fd,const char * pathname,mode_t mode,dev_t XMKNODAT_FIFTH_ARG dev)1082 int WRAP_MKNODAT MKNODAT_ARG(int ver UNUSED,
1083 int dir_fd,
1084 const char *pathname,
1085 mode_t mode, dev_t XMKNODAT_FIFTH_ARG dev)
1086 {
1087 INT_STRUCT_STAT st;
1088 mode_t old_mask=umask(022);
1089 int fd,r;
1090
1091 umask(old_mask);
1092
1093 /*Don't bother to mknod the file, that probably doesn't work.
1094 just create it as normal file, and leave the permissions
1095 to the fakemode.*/
1096
1097 fd=openat(dir_fd, pathname, O_WRONLY|O_CREAT|O_TRUNC, 00644);
1098
1099 if(fd==-1)
1100 return -1;
1101
1102 close(fd);
1103 /* get the inode, to communicate with faked */
1104
1105 /* The only known flag is AT_SYMLINK_NOFOLLOW and
1106 we don't want that here. */
1107 r=INT_NEXT_FSTATAT(dir_fd, pathname, &st, 0);
1108
1109 if(r)
1110 return -1;
1111
1112 st.st_mode= mode & ~old_mask;
1113 st.st_rdev= XMKNODAT_FIFTH_ARG dev;
1114
1115 INT_SEND_STAT(&st,mknod_func);
1116
1117 return 0;
1118 }
1119 #endif /* HAVE_MKNODAT */
1120 #endif /* HAVE_FSTATAT */
1121
mkdir(const char * path,mode_t mode)1122 int mkdir(const char *path, mode_t mode){
1123 INT_STRUCT_STAT st;
1124 int r;
1125 mode_t old_mask=umask(022);
1126
1127 umask(old_mask);
1128
1129
1130 /* we need to tell the fake deamon the real mode. In order
1131 to communicate with faked we need a struct stat, so we now
1132 do a stat of the new directory (just for the inode/dev) */
1133
1134 #ifdef LIBFAKEROOT_DEBUGGING
1135 if (fakeroot_debug) {
1136 fprintf(stderr, "mkdir path %s\n", path);
1137 }
1138 #endif /* LIBFAKEROOT_DEBUGGING */
1139 r=next_mkdir(path, mode|0700);
1140 /* mode|0700: see comment in the chown() function above */
1141 if(r)
1142 return -1;
1143 r=INT_NEXT_STAT(path, &st);
1144
1145 if(r)
1146 return -1;
1147
1148 st.st_mode=(mode&~old_mask&ALLPERMS)|(st.st_mode&~ALLPERMS)|S_IFDIR;
1149
1150 INT_SEND_STAT(&st, chmod_func);
1151
1152 return 0;
1153 }
1154
1155 #ifdef HAVE_FSTATAT
1156 #ifdef HAVE_MKDIRAT
mkdirat(int dir_fd,const char * path,mode_t mode)1157 int mkdirat(int dir_fd, const char *path, mode_t mode){
1158 INT_STRUCT_STAT st;
1159 int r;
1160 mode_t old_mask=umask(022);
1161
1162 umask(old_mask);
1163
1164
1165 /* we need to tell the fake deamon the real mode. In order
1166 to communicate with faked we need a struct stat, so we now
1167 do a stat of the new directory (just for the inode/dev) */
1168
1169 r=next_mkdirat(dir_fd, path, mode|0700);
1170 /* mode|0700: see comment in the chown() function above */
1171 if(r)
1172 return -1;
1173 r=INT_NEXT_FSTATAT(dir_fd, path, &st, 0);
1174
1175 if(r)
1176 return -1;
1177
1178 st.st_mode=(mode&~old_mask&ALLPERMS)|(st.st_mode&~ALLPERMS)|S_IFDIR;
1179
1180 INT_SEND_STAT(&st, chmod_func);
1181
1182 return 0;
1183 }
1184 #endif /* HAVE_MKDIRAT */
1185 #endif /* HAVE_FSTATAT */
1186
1187 /*
1188 The remove funtions: unlink, rmdir, rename.
1189 These functions can all remove inodes from the system.
1190 I need to inform faked about the removal of these inodes because
1191 of the following:
1192 # rm -f file
1193 # touch file
1194 # chown admin file
1195 # rm file
1196 # touch file
1197 In the above example, assuming that for both touch-es, the same
1198 inode is generated, faked will still report the owner of `file'
1199 as `admin', unless it's informed about the removal of the inode.
1200 */
1201
unlink(const char * pathname)1202 int unlink(const char *pathname){
1203 int r;
1204 INT_STRUCT_STAT st;
1205
1206
1207 r=INT_NEXT_LSTAT(pathname, &st);
1208 if(r)
1209 return -1;
1210
1211 r=next_unlink(pathname);
1212
1213 if(r)
1214 return -1;
1215
1216 INT_SEND_STAT(&st, unlink_func);
1217
1218 return 0;
1219 }
1220
1221 #ifdef HAVE_FSTATAT
1222 #ifdef HAVE_UNLINKAT
unlinkat(int dir_fd,const char * pathname,int flags)1223 int unlinkat(int dir_fd, const char *pathname, int flags){
1224 int r;
1225 INT_STRUCT_STAT st;
1226 r=INT_NEXT_FSTATAT(dir_fd, pathname, &st, (flags&~AT_REMOVEDIR) | AT_SYMLINK_NOFOLLOW);
1227 if(r)
1228 return -1;
1229
1230 r=next_unlinkat(dir_fd, pathname, flags);
1231
1232 if(r)
1233 return -1;
1234
1235 INT_SEND_STAT(&st, unlink_func);
1236
1237 return 0;
1238 }
1239 #endif /* HAVE_UNLINKAT */
1240 #endif /* HAVE_FSTATAT */
1241
1242 /*
1243 See the `remove funtions:' comments above for more info on
1244 these remove function wrappers.
1245 */
rmdir(const char * pathname)1246 int rmdir(const char *pathname){
1247 int r;
1248 INT_STRUCT_STAT st;
1249
1250 r=INT_NEXT_LSTAT(pathname, &st);
1251 if(r)
1252 return -1;
1253 r=next_rmdir(pathname);
1254 if(r)
1255 return -1;
1256
1257 INT_SEND_STAT(&st,unlink_func);
1258
1259 return 0;
1260 }
1261
1262 /*
1263 See the `remove funtions:' comments above for more info on
1264 these remove function wrappers.
1265 */
remove(const char * pathname)1266 int remove(const char *pathname){
1267 int r;
1268 INT_STRUCT_STAT st;
1269
1270 r=INT_NEXT_LSTAT(pathname, &st);
1271 if(r)
1272 return -1;
1273 r=next_remove(pathname);
1274 if(r)
1275 return -1;
1276 INT_SEND_STAT(&st,unlink_func);
1277
1278 return r;
1279 }
1280
1281 /*
1282 if the second argument to the rename() call points to an
1283 existing file, then that file will be removed. So, we have
1284 to treat this function as one of the `remove functions'.
1285
1286 See the `remove funtions:' comments above for more info on
1287 these remove function wrappers.
1288 */
1289
rename(const char * oldpath,const char * newpath)1290 int rename(const char *oldpath, const char *newpath){
1291 int r,s;
1292 INT_STRUCT_STAT st;
1293
1294 /* If newpath points to an existing file, that file will be
1295 unlinked. Make sure we tell the faked daemon about this! */
1296
1297 /* we need the st_new struct in order to inform faked about the
1298 (possible) unlink of the file */
1299
1300 r=INT_NEXT_LSTAT(newpath, &st);
1301
1302 s=next_rename(oldpath, newpath);
1303 if(s)
1304 return -1;
1305 if(!r)
1306 INT_SEND_STAT(&st,unlink_func);
1307
1308 return 0;
1309 }
1310
1311 #ifdef HAVE_FSTATAT
1312 #ifdef HAVE_RENAMEAT
renameat(int olddir_fd,const char * oldpath,int newdir_fd,const char * newpath)1313 int renameat(int olddir_fd, const char *oldpath,
1314 int newdir_fd, const char *newpath){
1315 int r,s;
1316 INT_STRUCT_STAT st;
1317
1318 /* If newpath points to an existing file, that file will be
1319 unlinked. Make sure we tell the faked daemon about this! */
1320
1321 /* we need the st_new struct in order to inform faked about the
1322 (possible) unlink of the file */
1323
1324 r=INT_NEXT_FSTATAT(newdir_fd, newpath, &st, AT_SYMLINK_NOFOLLOW);
1325
1326 s=next_renameat(olddir_fd, oldpath, newdir_fd, newpath);
1327 if(s)
1328 return -1;
1329 if(!r)
1330 INT_SEND_STAT(&st,unlink_func);
1331
1332 return 0;
1333 }
1334 #endif /* HAVE_RENAMEAT */
1335 #endif /* HAVE_FSTATAT */
1336
1337
1338 #ifdef FAKEROOT_FAKENET
fork(void)1339 pid_t fork(void)
1340 {
1341 pid_t pid;
1342
1343 pid = next_fork();
1344
1345 if (pid == 0) {
1346 /* No need to lock in the child process. */
1347 if (comm_sd >= 0) {
1348 next_close(comm_sd);
1349 comm_sd = -1;
1350 }
1351 }
1352
1353 return pid;
1354 }
1355
vfork(void)1356 pid_t vfork(void)
1357 {
1358 /* We can't wrap vfork(2) without breaking everything... */
1359 return fork();
1360 }
1361
1362 /* Return an error when trying to close the comm_sd file descriptor
1363 (pretend that it's closed). */
close(int fd)1364 int close(int fd)
1365 {
1366 int retval, reterr;
1367
1368 lock_comm_sd();
1369
1370 if (comm_sd >= 0 && comm_sd == fd) {
1371 retval = -1;
1372 reterr = EBADF;
1373 } else {
1374 retval = next_close(fd);
1375 reterr = errno;
1376 }
1377
1378 unlock_comm_sd();
1379
1380 errno = reterr;
1381 return retval;
1382 }
1383
dup2(int oldfd,int newfd)1384 int dup2(int oldfd, int newfd)
1385 {
1386 int retval, reterr;
1387
1388 lock_comm_sd();
1389
1390 if (comm_sd >= 0 && comm_sd == newfd) {
1391 /* If dup fails, comm_sd gets set to -1, which is fine. */
1392 comm_sd = dup(newfd);
1393 next_close(newfd);
1394 }
1395
1396 retval = next_dup2(oldfd, newfd);
1397 reterr = errno;
1398
1399 unlock_comm_sd();
1400
1401 errno = reterr;
1402 return retval;
1403 }
1404 #endif /* FAKEROOT_FAKENET */
1405
1406 #ifdef __APPLE__
1407 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1408
check_fakeroot_disabled(void * retaddr)1409 static int check_fakeroot_disabled(void *retaddr){
1410 Dl_info info;
1411 const char *suffix;
1412 if (fakeroot_disabled || !dladdr(retaddr, &info))
1413 return fakeroot_disabled;
1414 suffix = strrchr(info.dli_fname, '/');
1415 if (suffix && (strcmp(suffix, "/CarbonCore") == 0 ||
1416 strcmp(suffix, "/CoreServicesInternal") == 0))
1417 return 1;
1418 return fakeroot_disabled;
1419 }
1420
1421 #define fakeroot_disabled check_fakeroot_disabled(__builtin_return_address(0))
1422
1423 #endif
1424 #endif /* __APPLE__ */
1425
getuid(void)1426 uid_t getuid(void){
1427 if (fakeroot_disabled)
1428 return next_getuid();
1429 return get_faked_uid();
1430 }
1431
geteuid(void)1432 uid_t geteuid(void){
1433 if (fakeroot_disabled)
1434 return next_geteuid();
1435 return get_faked_euid();
1436 }
1437
1438 #ifdef HAVE_GETRESUID
getresuid(uid_t * ruid,uid_t * euid,uid_t * suid)1439 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid){
1440 if (fakeroot_disabled)
1441 return next_getresuid(ruid, euid, suid);
1442 *ruid = get_faked_uid();
1443 *euid = get_faked_euid();
1444 *suid = get_faked_suid();
1445 return 0;
1446 }
1447 #endif /* HAVE_GETRESUID */
1448
getgid(void)1449 uid_t getgid(void){
1450 if (fakeroot_disabled)
1451 return next_getgid();
1452 return get_faked_gid();
1453 }
1454
getegid(void)1455 uid_t getegid(void){
1456 if (fakeroot_disabled)
1457 return next_getegid();
1458 return get_faked_egid();
1459 }
1460
1461 #ifdef HAVE_GETRESGID
getresgid(gid_t * rgid,gid_t * egid,gid_t * sgid)1462 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid){
1463 if (fakeroot_disabled)
1464 return next_getresgid(rgid, egid, sgid);
1465 *rgid = get_faked_gid();
1466 *egid = get_faked_egid();
1467 *sgid = get_faked_sgid();
1468 return 0;
1469 }
1470 #endif /* HAVE_GETRESGID */
1471
setuid(uid_t id)1472 int setuid(uid_t id){
1473 if (fakeroot_disabled)
1474 return next_setuid(id);
1475 return set_faked_uid(id);
1476 }
1477
setgid(uid_t id)1478 int setgid(uid_t id){
1479 if (fakeroot_disabled)
1480 return next_setgid(id);
1481 return set_faked_gid(id);
1482 }
1483
seteuid(uid_t id)1484 int seteuid(uid_t id){
1485 if (fakeroot_disabled)
1486 return next_seteuid(id);
1487 return set_faked_euid(id);
1488 }
1489
setegid(uid_t id)1490 int setegid(uid_t id){
1491 if (fakeroot_disabled)
1492 return next_setegid(id);
1493 return set_faked_egid(id);
1494 }
1495
setreuid(SETREUID_ARG ruid,SETREUID_ARG euid)1496 int setreuid(SETREUID_ARG ruid, SETREUID_ARG euid){
1497 #ifdef LIBFAKEROOT_DEBUGGING
1498 if (fakeroot_debug) {
1499 fprintf(stderr, "setreuid\n");
1500 }
1501 #endif /* LIBFAKEROOT_DEBUGGING */
1502 if (fakeroot_disabled)
1503 return next_setreuid(ruid, euid);
1504 return set_faked_reuid(ruid, euid);
1505 }
1506
setregid(SETREGID_ARG rgid,SETREGID_ARG egid)1507 int setregid(SETREGID_ARG rgid, SETREGID_ARG egid){
1508 #ifdef LIBFAKEROOT_DEBUGGING
1509 if (fakeroot_debug) {
1510 fprintf(stderr, "setregid\n");
1511 }
1512 #endif /* LIBFAKEROOT_DEBUGGING */
1513 if (fakeroot_disabled)
1514 return next_setregid(rgid, egid);
1515 return set_faked_regid(rgid, egid);
1516 }
1517
1518 #ifdef HAVE_SETRESUID
setresuid(uid_t ruid,uid_t euid,uid_t suid)1519 int setresuid(uid_t ruid, uid_t euid, uid_t suid){
1520 if (fakeroot_disabled)
1521 return next_setresuid(ruid, euid, suid);
1522 return set_faked_resuid(ruid, euid, suid);
1523 }
1524 #endif /* HAVE_SETRESUID */
1525
1526 #ifdef HAVE_SETRESGID
setresgid(gid_t rgid,gid_t egid,gid_t sgid)1527 int setresgid(gid_t rgid, gid_t egid, gid_t sgid){
1528 if (fakeroot_disabled)
1529 return next_setresgid(rgid, egid, sgid);
1530 return set_faked_resgid(rgid, egid, sgid);
1531 }
1532 #endif /* HAVE_SETRESGID */
1533
1534 #ifdef HAVE_SETFSUID
setfsuid(uid_t fsuid)1535 uid_t setfsuid(uid_t fsuid){
1536 if (fakeroot_disabled)
1537 return next_setfsuid(fsuid);
1538 return set_faked_fsuid(fsuid);
1539 }
1540 #endif /* HAVE_SETFSUID */
1541
1542 #ifdef HAVE_SETFSGID
setfsgid(gid_t fsgid)1543 gid_t setfsgid(gid_t fsgid){
1544 if (fakeroot_disabled)
1545 return next_setfsgid(fsgid);
1546 return set_faked_fsgid(fsgid);
1547 }
1548 #endif /* HAVE_SETFSGID */
1549
initgroups(const char * user,INITGROUPS_SECOND_ARG group)1550 int initgroups(const char* user, INITGROUPS_SECOND_ARG group){
1551 if (fakeroot_disabled)
1552 return next_initgroups(user, group);
1553 else
1554 return 0;
1555 }
1556
setgroups(SETGROUPS_SIZE_TYPE size,const gid_t * list)1557 int setgroups(SETGROUPS_SIZE_TYPE size, const gid_t *list){
1558 if (fakeroot_disabled)
1559 return next_setgroups(size, list);
1560 else
1561 return 0;
1562 }
1563
1564 #ifdef HAVE_CAPSET
capset(cap_user_header_t hdrp,const cap_user_data_t datap)1565 int capset(cap_user_header_t hdrp, const cap_user_data_t datap)
1566 {
1567 int rc = next_capset(hdrp, datap);
1568 return (fakeroot_disabled) ? (rc) : 0;
1569 }
1570 #endif /* HAVE_CAPSET */
1571
1572 #if defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR)
common_setxattr(INT_STRUCT_STAT * st,const char * name,void * value,size_t size,int flags)1573 static size_t common_setxattr(INT_STRUCT_STAT *st, const char *name, void * value, size_t size, int flags)
1574 {
1575 xattr_args xattr;
1576 xattr.name = name;
1577 xattr.value = value;
1578 xattr.size = size;
1579 xattr.flags = flags;
1580 xattr.func = setxattr_func;
1581 INT_SEND_GET_XATTR(st, &xattr);
1582 if (xattr.rc)
1583 {
1584 errno = xattr.rc;
1585 return -1;
1586 }
1587 return 0;
1588 }
1589 #endif /* defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR) */
1590
1591 #if defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR)
common_getxattr(INT_STRUCT_STAT * st,const char * name,void * value,size_t size)1592 static size_t common_getxattr(INT_STRUCT_STAT *st, const char *name, void * value, size_t size)
1593 {
1594 xattr_args xattr;
1595 xattr.name = name;
1596 xattr.value = value;
1597 xattr.size = size;
1598 xattr.func = getxattr_func;
1599 INT_SEND_GET_XATTR(st, &xattr);
1600 if (xattr.rc)
1601 {
1602 errno = xattr.rc;
1603 return -1;
1604 }
1605 return xattr.size;
1606 }
1607 #endif /* defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR) */
1608
1609 #if defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR)
common_listxattr(INT_STRUCT_STAT * st,char * list,size_t size)1610 static size_t common_listxattr(INT_STRUCT_STAT *st, char *list, size_t size)
1611 {
1612 xattr_args xattr;
1613 xattr.name = NULL;
1614 xattr.value = list;
1615 xattr.size = size;
1616 xattr.func = listxattr_func;
1617 INT_SEND_GET_XATTR(st, &xattr);
1618 if (xattr.rc)
1619 {
1620 errno = xattr.rc;
1621 return -1;
1622 }
1623 return xattr.size;
1624 }
1625 #endif /* defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR) */
1626
1627 #if defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR)
common_removexattr(INT_STRUCT_STAT * st,const char * name)1628 static size_t common_removexattr(INT_STRUCT_STAT *st, const char *name)
1629 {
1630 xattr_args xattr;
1631 xattr.name = name;
1632 xattr.value = NULL;
1633 xattr.size = 0;
1634 xattr.func = removexattr_func;
1635 INT_SEND_GET_XATTR(st, &xattr);
1636 if (xattr.rc)
1637 {
1638 errno = xattr.rc;
1639 return -1;
1640 }
1641 return 0;
1642 }
1643 #endif /* defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR) */
1644
1645 #ifdef HAVE_SETXATTR
setxattr(const char * path,const char * name,void * value,size_t size,int flags)1646 ssize_t setxattr(const char *path, const char *name, void *value, size_t size, int flags)
1647 {
1648 INT_STRUCT_STAT st;
1649 int r;
1650 if (fakeroot_disabled)
1651 return next_setxattr(path, name, value, size, flags);
1652
1653 #ifdef LIBFAKEROOT_DEBUGGING
1654 if (fakeroot_debug) {
1655 fprintf(stderr, "setxattr path %s\n", path);
1656 }
1657 #endif /* LIBFAKEROOT_DEBUGGING */
1658 r=INT_NEXT_STAT(path, &st);
1659 if(r)
1660 return r;
1661
1662 return common_setxattr(&st, name, value, size, flags);
1663 }
1664 #endif /* HAVE_SETXATTR */
1665
1666 #ifdef HAVE_LSETXATTR
lsetxattr(const char * path,const char * name,void * value,size_t size,int flags)1667 ssize_t lsetxattr(const char *path, const char *name, void *value, size_t size, int flags)
1668 {
1669 INT_STRUCT_STAT st;
1670 int r;
1671 if (fakeroot_disabled)
1672 return next_lsetxattr(path, name, value, size, flags);
1673
1674 #ifdef LIBFAKEROOT_DEBUGGING
1675 if (fakeroot_debug) {
1676 fprintf(stderr, "lsetxattr path %s\n", path);
1677 }
1678 #endif /* LIBFAKEROOT_DEBUGGING */
1679 r=INT_NEXT_LSTAT(path, &st);
1680 if(r)
1681 return r;
1682
1683 return common_setxattr(&st, name, value, size, flags);
1684 }
1685 #endif /* HAVE_LSETXATTR */
1686
1687 #ifdef HAVE_FSETXATTR
fsetxattr(int fd,const char * name,void * value,size_t size,int flags)1688 ssize_t fsetxattr(int fd, const char *name, void *value, size_t size, int flags)
1689 {
1690 INT_STRUCT_STAT st;
1691 int r;
1692 if (fakeroot_disabled)
1693 return next_fsetxattr(fd, name, value, size, flags);
1694
1695 #ifdef LIBFAKEROOT_DEBUGGING
1696 if (fakeroot_debug) {
1697 fprintf(stderr, "fsetxattr fd %d\n", fd);
1698 }
1699 #endif /* LIBFAKEROOT_DEBUGGING */
1700 r=INT_NEXT_FSTAT(fd, &st);
1701 if(r)
1702 return r;
1703
1704 return common_setxattr(&st, name, value, size, flags);
1705 }
1706 #endif /* HAVE_FSETXATTR */
1707
1708 #ifdef HAVE_GETXATTR
getxattr(const char * path,const char * name,void * value,size_t size)1709 ssize_t getxattr(const char *path, const char *name, void *value, size_t size)
1710 {
1711 INT_STRUCT_STAT st;
1712 int r;
1713 if (fakeroot_disabled)
1714 return next_getxattr(path, name, value, size);
1715
1716 #ifdef LIBFAKEROOT_DEBUGGING
1717 if (fakeroot_debug) {
1718 fprintf(stderr, "getxattr path %s name %s size %d\n", path, name, size);
1719 }
1720 #endif /* LIBFAKEROOT_DEBUGGING */
1721 r=INT_NEXT_STAT(path, &st);
1722 if(r)
1723 return r;
1724
1725 return common_getxattr(&st, name, value, size);
1726 }
1727 #endif /* HAVE_GETXATTR */
1728
1729 #ifdef HAVE_LGETXATTR
lgetxattr(const char * path,const char * name,void * value,size_t size)1730 ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size)
1731 {
1732 INT_STRUCT_STAT st;
1733 int r;
1734 if (fakeroot_disabled)
1735 return next_lgetxattr(path, name, value, size);
1736
1737 #ifdef LIBFAKEROOT_DEBUGGING
1738 if (fakeroot_debug) {
1739 fprintf(stderr, "lgetxattr path %s\n", path);
1740 }
1741 #endif /* LIBFAKEROOT_DEBUGGING */
1742 r=INT_NEXT_LSTAT(path, &st);
1743 if(r)
1744 return r;
1745
1746 return common_getxattr(&st, name, value, size);
1747 }
1748 #endif /* HAVE_LGETXATTR */
1749
1750 #ifdef HAVE_FGETXATTR
fgetxattr(int fd,const char * name,void * value,size_t size)1751 ssize_t fgetxattr(int fd, const char *name, void *value, size_t size)
1752 {
1753 INT_STRUCT_STAT st;
1754 int r;
1755 if (fakeroot_disabled)
1756 return next_fgetxattr(fd, name, value, size);
1757
1758 #ifdef LIBFAKEROOT_DEBUGGING
1759 if (fakeroot_debug) {
1760 fprintf(stderr, "fgetxattr fd %d\n", fd);
1761 }
1762 #endif /* LIBFAKEROOT_DEBUGGING */
1763 r=INT_NEXT_FSTAT(fd, &st);
1764 if(r)
1765 return r;
1766
1767 return common_getxattr(&st, name, value, size);
1768 }
1769 #endif /* HAVE_FGETXATTR */
1770
1771 #ifdef HAVE_LISTXATTR
listxattr(const char * path,char * list,size_t size)1772 ssize_t listxattr(const char *path, char *list, size_t size)
1773 {
1774 INT_STRUCT_STAT st;
1775 int r;
1776 if (fakeroot_disabled)
1777 return next_listxattr(path, list, size);
1778
1779 #ifdef LIBFAKEROOT_DEBUGGING
1780 if (fakeroot_debug) {
1781 fprintf(stderr, "listxattr path %s size %d\n", path, size);
1782 }
1783 #endif /* LIBFAKEROOT_DEBUGGING */
1784 r=INT_NEXT_STAT(path, &st);
1785 if(r)
1786 return r;
1787
1788 return common_listxattr(&st, list, size);
1789 }
1790 #endif /* HAVE_LISTXATTR */
1791
1792 #ifdef HAVE_LLISTXATTR
llistxattr(const char * path,char * list,size_t size)1793 ssize_t llistxattr(const char *path, char *list, size_t size)
1794 {
1795 INT_STRUCT_STAT st;
1796 int r;
1797 if (fakeroot_disabled)
1798 return next_llistxattr(path, list, size);
1799
1800 #ifdef LIBFAKEROOT_DEBUGGING
1801 if (fakeroot_debug) {
1802 fprintf(stderr, "llistxattr path %s\n", path);
1803 }
1804 #endif /* LIBFAKEROOT_DEBUGGING */
1805 r=INT_NEXT_LSTAT(path, &st);
1806 if(r)
1807 return r;
1808
1809 return common_listxattr(&st, list, size);
1810 }
1811 #endif /* HAVE_LLISTXATTR */
1812
1813 #ifdef HAVE_FLISTXATTR
flistxattr(int fd,char * list,size_t size)1814 ssize_t flistxattr(int fd, char *list, size_t size)
1815 {
1816 INT_STRUCT_STAT st;
1817 int r;
1818 if (fakeroot_disabled)
1819 return next_flistxattr(fd, list, size);
1820
1821 #ifdef LIBFAKEROOT_DEBUGGING
1822 if (fakeroot_debug) {
1823 fprintf(stderr, "flistxattr fd %d\n", fd);
1824 }
1825 #endif /* LIBFAKEROOT_DEBUGGING */
1826 r=INT_NEXT_FSTAT(fd, &st);
1827 if(r)
1828 return r;
1829
1830 return common_listxattr(&st, list, size);
1831 }
1832 #endif /* HAVE_FLISTXATTR */
1833
1834 #ifdef HAVE_REMOVEXATTR
removexattr(const char * path,const char * name)1835 ssize_t removexattr(const char *path, const char *name)
1836 {
1837 INT_STRUCT_STAT st;
1838 int r;
1839 if (fakeroot_disabled)
1840 return next_removexattr(path, name);
1841
1842 #ifdef LIBFAKEROOT_DEBUGGING
1843 if (fakeroot_debug) {
1844 fprintf(stderr, "removexattr path %s\n", path);
1845 }
1846 #endif /* LIBFAKEROOT_DEBUGGING */
1847 r=INT_NEXT_STAT(path, &st);
1848 if(r)
1849 return r;
1850
1851 return common_removexattr(&st, name);
1852 }
1853 #endif /* HAVE_REMOVEXATTR */
1854
1855 #ifdef HAVE_LREMOVEXATTR
lremovexattr(const char * path,const char * name)1856 ssize_t lremovexattr(const char *path, const char *name)
1857 {
1858 INT_STRUCT_STAT st;
1859 int r;
1860 if (fakeroot_disabled)
1861 return next_lremovexattr(path, name);
1862
1863 #ifdef LIBFAKEROOT_DEBUGGING
1864 if (fakeroot_debug) {
1865 fprintf(stderr, "lremovexattr path %s\n", path);
1866 }
1867 #endif /* LIBFAKEROOT_DEBUGGING */
1868 r=INT_NEXT_LSTAT(path, &st);
1869 if(r)
1870 return r;
1871
1872 return common_removexattr(&st, name);
1873 }
1874 #endif /* HAVE_LREMOVEXATTR */
1875
1876 #ifdef HAVE_FREMOVEXATTR
fremovexattr(int fd,const char * name)1877 ssize_t fremovexattr(int fd, const char *name)
1878 {
1879 INT_STRUCT_STAT st;
1880 int r;
1881 if (fakeroot_disabled)
1882 return next_fremovexattr(fd, name);
1883
1884 #ifdef LIBFAKEROOT_DEBUGGING
1885 if (fakeroot_debug) {
1886 fprintf(stderr, "fremovexattr fd %d\n", fd);
1887 }
1888 #endif /* LIBFAKEROOT_DEBUGGING */
1889 r=INT_NEXT_FSTAT(fd, &st);
1890 if(r)
1891 return r;
1892
1893 return common_removexattr(&st, name);
1894 }
1895 #endif /* HAVE_FREMOVEXATTR */
1896
setpriority(int which,int who,int prio)1897 int setpriority(int which, int who, int prio){
1898 if (fakeroot_disabled)
1899 return next_setpriority(which, who, prio);
1900 next_setpriority(which, who, prio);
1901 return 0;
1902 }
1903
1904 #undef fakeroot_disabled
1905
fakeroot_disable(int new)1906 int fakeroot_disable(int new)
1907 {
1908 int old = fakeroot_disabled;
1909 fakeroot_disabled = new ? 1 : 0;
1910 return old;
1911 }
1912
fakeroot_isdisabled(void)1913 int fakeroot_isdisabled(void)
1914 {
1915 return fakeroot_disabled;
1916 }
1917
1918 #ifdef HAVE_ACL_T
acl_get_fd(int fd)1919 acl_t acl_get_fd(int fd) {
1920 errno = ENOTSUP;
1921 return (acl_t)NULL;
1922 }
acl_get_file(const char * path_p,acl_type_t type)1923 acl_t acl_get_file(const char *path_p, acl_type_t type) {
1924 errno = ENOTSUP;
1925 return (acl_t)NULL;
1926 }
acl_set_fd(int fd,acl_t acl)1927 int acl_set_fd(int fd, acl_t acl) {
1928 errno = ENOTSUP;
1929 return -1;
1930 }
1931
acl_set_file(const char * path_p,acl_type_t type,acl_t acl)1932 int acl_set_file(const char *path_p, acl_type_t type, acl_t acl) {
1933 errno = ENOTSUP;
1934 return -1;
1935 }
1936 #endif /* HAVE_SYS_ACL_H */
1937
1938 #ifdef HAVE_FTS_READ
fts_read(FTS * ftsp)1939 FTSENT *fts_read(FTS *ftsp) {
1940 FTSENT *r;
1941
1942 #ifdef LIBFAKEROOT_DEBUGGING
1943 if (fakeroot_debug) {
1944 fprintf(stderr, "fts_read\n");
1945 }
1946 #endif /* LIBFAKEROOT_DEBUGGING */
1947 r=next_fts_read(ftsp);
1948 if (r && ((ftsp->fts_options & FTS_NOSTAT)
1949 || r->fts_info == FTS_NS || r->fts_info == FTS_NSOK))
1950 r->fts_statp = NULL; /* Otherwise fts_statp may be a random pointer */
1951 if(r && r->fts_statp) { /* Should we bother checking fts_info here? */
1952 # if defined(STAT64_SUPPORT) && !defined(__APPLE__)
1953 SEND_GET_STAT64(r->fts_statp, _STAT_VER);
1954 # else
1955 SEND_GET_STAT(r->fts_statp, _STAT_VER);
1956 # endif
1957 }
1958
1959 return r;
1960 }
1961 #endif /* HAVE_FTS_READ */
1962
1963 #ifdef HAVE_FTS_CHILDREN
fts_children(FTS * ftsp,int options)1964 FTSENT *fts_children(FTS *ftsp, int options) {
1965 FTSENT *first, *r;
1966
1967 #ifdef LIBFAKEROOT_DEBUGGING
1968 if (fakeroot_debug) {
1969 fprintf(stderr, "fts_children\n");
1970 }
1971 #endif /* LIBFAKEROOT_DEBUGGING */
1972 first=next_fts_children(ftsp, options);
1973 for(r = first; r; r = r->fts_link) {
1974 if(r && r->fts_statp) { /* Should we bother checking fts_info here? */
1975 # if defined(STAT64_SUPPORT) && !defined(__APPLE__)
1976 SEND_GET_STAT64(r->fts_statp, _STAT_VER);
1977 # else
1978 SEND_GET_STAT(r->fts_statp, _STAT_VER);
1979 # endif
1980 }
1981 }
1982
1983 return first;
1984 }
1985 #endif /* HAVE_FTS_CHILDREN */
1986
1987 #ifdef __APPLE__
1988 #ifdef __LP64__
1989 int
getattrlist(const char * path,void * attrList,void * attrBuf,size_t attrBufSize,unsigned int options)1990 getattrlist(const char *path, void *attrList, void *attrBuf,
1991 size_t attrBufSize, unsigned int options)
1992 #else
1993 int
1994 getattrlist(const char *path, void *attrList, void *attrBuf,
1995 size_t attrBufSize, unsigned long options)
1996 #endif
1997 {
1998 int r;
1999 struct stat st;
2000
2001 #ifdef LIBFAKEROOT_DEBUGGING
2002 if (fakeroot_debug) {
2003 fprintf(stderr, "getattrlist path %s\n", path);
2004 }
2005 #endif /* LIBFAKEROOT_DEBUGGING */
2006 r=next_getattrlist(path, attrList, attrBuf, attrBufSize, options);
2007 if (r) {
2008 return r;
2009 }
2010 if (options & FSOPT_NOFOLLOW) {
2011 r=WRAP_LSTAT(path, &st);
2012 } else {
2013 r=WRAP_STAT(path, &st);
2014 }
2015 if (r) {
2016 return r;
2017 }
2018 patchattr(attrList, attrBuf, st.st_uid, st.st_gid, st.st_mode);
2019
2020 return 0;
2021 }
2022
2023 #if HAVE_FGETATTRLIST
2024 #ifdef __LP64__
2025 int
fgetattrlist(int fd,void * attrList,void * attrBuf,size_t attrBufSize,unsigned int options)2026 fgetattrlist(int fd, void *attrList, void *attrBuf,
2027 size_t attrBufSize, unsigned int options)
2028 #else
2029 int
2030 fgetattrlist(int fd, void *attrList, void *attrBuf,
2031 size_t attrBufSize, unsigned long options)
2032 #endif
2033 {
2034 int r;
2035 struct stat st;
2036
2037 #ifdef LIBFAKEROOT_DEBUGGING
2038 if (fakeroot_debug) {
2039 fprintf(stderr, "fgetattrlist fd %d\n", fd);
2040 }
2041 #endif /* LIBFAKEROOT_DEBUGGING */
2042 r=next_fgetattrlist(fd, attrList, attrBuf, attrBufSize, options);
2043 if (r) {
2044 return r;
2045 }
2046 r=WRAP_FSTAT(fd, &st);
2047 if (r) {
2048 return r;
2049 }
2050 patchattr(attrList, attrBuf, st.st_uid, st.st_gid, st.st_mode);
2051
2052 return 0;
2053 }
2054 #endif /* if HAVE_FGETATTRLIST */
2055
2056 /*
2057 * Prevent loss of DYLD_INSERT_LIBRARIES, FAKEROOTKEY and FAKED_MODE
2058 * environment variables during packaging (packagemaker otherwise clears them).
2059 */
2060
2061 static char *dylib_insert;
2062 static char *fakeroot_key;
2063 static char *faked_mode;
2064 static int spawnexec_in_progress;
2065 static pid_t spawnexec_pid;
2066
is_spawnexec_active()2067 static int is_spawnexec_active()
2068 {
2069 if (getpid() != spawnexec_pid) {
2070 spawnexec_in_progress = 0;
2071 }
2072 return spawnexec_in_progress;
2073 }
2074
enter_spawnexec()2075 static void enter_spawnexec()
2076 {
2077 (void)is_spawnexec_active();
2078 if (++spawnexec_in_progress == 1)
2079 spawnexec_pid = getpid();
2080 }
2081
exit_spawnexec()2082 static void exit_spawnexec()
2083 {
2084 (void)is_spawnexec_active();
2085 if (spawnexec_in_progress)
2086 --spawnexec_in_progress;
2087 }
2088
2089 __attribute__((__constructor__,__used__)) static void retrieve_dylib();
retrieve_dylib()2090 static void retrieve_dylib()
2091 {
2092 const char *dil = getenv("DYLD_INSERT_LIBRARIES");
2093 const char *frk = fakeroot_key = getenv("FAKEROOTKEY");
2094 const char *fdm = faked_mode = getenv("FAKED_MODE");
2095 if (frk) {
2096 char *savekey = (char *)malloc(12 + strlen(frk) + 1);
2097 if (savekey) {
2098 sprintf(savekey, "FAKEROOTKEY=%s", frk);
2099 fakeroot_key = savekey;
2100 }
2101 }
2102 if (fdm) {
2103 char *savemode = (char *)malloc(11 + strlen(fdm) + 1);
2104 if (savemode) {
2105 sprintf(savemode, "FAKED_MODE=%s", fdm);
2106 faked_mode = savemode;
2107 }
2108 }
2109 if (dil) {
2110 char *dupe = strdup(dil);
2111 if (dupe) {
2112 char *ptr = dupe;
2113 do {
2114 char *next = strchr(ptr, ':');
2115 if (next)
2116 *next++ = '\0';
2117 if (strstr(ptr, "libfakeroot") && strstr(ptr, ".dylib")) {
2118 dylib_insert = ptr;
2119 return;
2120 }
2121 ptr = next;
2122 } while (ptr);
2123 free(dupe);
2124 }
2125 }
2126 }
2127
get_exec_envp(char * const envp[],char ** insenvp)2128 static char **get_exec_envp(char *const envp[], char **insenvp)
2129 {
2130 int i, envcount = 0;
2131 char **altenv = NULL;
2132
2133 *insenvp = NULL;
2134 if (!envp || !dylib_insert || !fakeroot_key ||
2135 getenv("FAKEROOT_TEST_PRELOAD"))
2136 return (char **)envp;
2137
2138 while (envp[envcount]) {
2139 ++envcount;
2140 }
2141 altenv = (char **)malloc((envcount + 4) * sizeof(char *));
2142 if (!altenv)
2143 return (char **)envp;
2144 memcpy(altenv, envp, (envcount + 1) * sizeof(char *));
2145
2146 for (i=0; i<envcount; ++i) {
2147 if (strncmp(altenv[i], "FAKEROOTKEY=", 12) == 0)
2148 break;
2149 }
2150 if (i >= envcount) {
2151 altenv[envcount] = fakeroot_key;
2152 altenv[++envcount] = NULL;
2153 }
2154
2155 for (i=0; i<envcount; ++i) {
2156 if (strncmp(altenv[i], "FAKED_MODE=", 11) == 0)
2157 break;
2158 }
2159 if (i >= envcount && faked_mode) {
2160 altenv[envcount] = faked_mode;
2161 altenv[++envcount] = NULL;
2162 }
2163
2164 for (i=0; i<envcount; ++i) {
2165 if (strncmp(altenv[i], "DYLD_INSERT_LIBRARIES=", 22) == 0) {
2166 if (strstr(altenv[i], dylib_insert))
2167 return altenv;
2168 else {
2169 *insenvp = (char *)malloc(strlen(altenv[i]) + strlen(dylib_insert) + 2);
2170 if (!*insenvp) {
2171 free(altenv);
2172 return (char **)envp;
2173 }
2174 sprintf(*insenvp, "DYLD_INSERT_LIBRARIES=%s:%s", dylib_insert,
2175 altenv[i]+22);
2176 altenv[i] = *insenvp;
2177 return altenv;
2178 }
2179 }
2180 }
2181 *insenvp = (char *)malloc(22 + strlen(dylib_insert) + 1);
2182 if (!*insenvp) {
2183 free(altenv);
2184 return (char **)envp;
2185 }
2186 sprintf(*insenvp, "DYLD_INSERT_LIBRARIES=%s", dylib_insert);
2187 altenv[envcount] = *insenvp;
2188 altenv[envcount+1] = NULL;
2189 return altenv;
2190 }
2191
execve(const char * path,char * const argv[],char * const envp[])2192 int execve(const char *path, char *const argv[], char *const envp[])
2193 {
2194 int result;
2195 char **altenv;
2196 char *insenv;
2197
2198 if (!path || !argv || !envp || is_spawnexec_active()) {
2199 enter_spawnexec();
2200 result = next_execve(path, argv, envp);
2201 exit_spawnexec();
2202 return result;
2203 }
2204
2205 altenv = get_exec_envp(envp, &insenv);
2206 enter_spawnexec();
2207 result = next_execve(path, argv, altenv);
2208 exit_spawnexec();
2209 if (altenv != envp)
2210 free(altenv);
2211 if (insenv)
2212 free(insenv);
2213 return result;
2214 }
2215
2216 /* funnel execl, execle, execlp, execv, execvp and execvP into execve */
2217
execv(const char * path,char * const argv[])2218 int execv(const char *path, char *const argv[])
2219 {
2220 return execve(path, argv, *_NSGetEnviron());
2221 }
2222
find_exec_path(const char * file,const char * search_path)2223 static char *find_exec_path(const char *file, const char *search_path)
2224 {
2225 char *path = (char *)file;
2226 if (file && *file && !strchr(file, '/') && search_path && *search_path) {
2227 size_t splen = strlen(search_path);
2228 const char *search_end = search_path + splen;
2229 const char *next;
2230 char *buff = malloc(strlen(file) + splen + 2);
2231 if (!buff)
2232 return NULL;
2233 for (; search_path < search_end; search_path = next) {
2234 struct stat info;
2235 size_t plen;
2236 if ((next = strchr(search_path, ':')))
2237 plen = next++ - search_path;
2238 else
2239 plen = (next = search_end) - search_path;
2240 memcpy(buff, search_path, plen);
2241 sprintf(buff + plen, "%s%s", plen ? "/" : "", file);
2242 if (stat(buff, &info) || !S_ISREG(info.st_mode) || access(buff, X_OK))
2243 continue;
2244 path = buff;
2245 break;
2246 }
2247 if (path == file) {
2248 free(buff);
2249 errno = ENOENT;
2250 return NULL;
2251 }
2252 }
2253 return path;
2254 }
2255
execvP(const char * file,const char * search_path,char * const argv[])2256 int execvP(const char *file, const char *search_path, char *const argv[])
2257 {
2258 int result;
2259 char *path = find_exec_path(file, search_path);
2260 if (!path)
2261 return -1;
2262 result = execve(path, argv, *_NSGetEnviron());
2263 if (path != file)
2264 free(path);
2265 return result;
2266 }
2267
execvp(const char * file,char * const argv[])2268 int execvp(const char *file, char *const argv[])
2269 {
2270 const char *path = getenv("PATH");
2271 return execvP(file, path ? path : _PATH_DEFPATH, argv);
2272 }
2273
collect_args(const char * arg0,va_list args,char *** envp)2274 static char **collect_args(const char *arg0, va_list args, char ***envp)
2275 {
2276 char **arglist;
2277 size_t count = 0;
2278 char **outp;
2279
2280 va_list args_copy;
2281 va_copy(args_copy, args);
2282 for (;;) {
2283 char *ap = va_arg(args_copy, char *);
2284 if (!ap)
2285 break;
2286 ++count;
2287 }
2288 va_end(args_copy);
2289 arglist = (char **)malloc((count + 2) * sizeof(char *));
2290 if (!arglist)
2291 return NULL;
2292 outp = arglist;
2293 *outp++ = (char *)arg0;
2294 for (;;) {
2295 char *ap = va_arg(args, char *);
2296 *outp++ = ap;
2297 if (!ap)
2298 break;
2299 }
2300 if (envp)
2301 *envp = va_arg(args, char **);
2302 return arglist;
2303 }
2304
execl(const char * path,const char * arg0,...)2305 int execl(const char *path, const char *arg0, ...)
2306 {
2307 int result;
2308 char **arglist;
2309 va_list args;
2310 va_start(args, arg0);
2311 arglist = collect_args(arg0, args, NULL);
2312 va_end(args);
2313 if (!arglist)
2314 return -1;
2315 result = execve(path, arglist, *_NSGetEnviron());
2316 free(arglist);
2317 return result;
2318 }
2319
execle(const char * path,const char * arg0,...)2320 int execle(const char *path, const char *arg0, ...)
2321 {
2322 int result;
2323 char **arglist;
2324 char **envp;
2325 va_list args;
2326 va_start(args, arg0);
2327 arglist = collect_args(arg0, args, &envp);
2328 va_end(args);
2329 if (!arglist)
2330 return -1;
2331 result = execve(path, arglist, envp);
2332 free(arglist);
2333 return result;
2334 }
2335
execlp(const char * file,const char * arg0,...)2336 int execlp(const char *file, const char *arg0, ...)
2337 {
2338 int result;
2339 char **arglist;
2340 va_list args;
2341 va_start(args, arg0);
2342 arglist = collect_args(arg0, args, NULL);
2343 va_end(args);
2344 if (!arglist)
2345 return -1;
2346 result = execvp(file, arglist);
2347 free(arglist);
2348 return result;
2349 }
2350
2351 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
2352
2353 /* handle posix_spawn and posix_spawnp separately */
2354
posix_spawn(pid_t * __restrict pid,const char * __restrict path,const posix_spawn_file_actions_t * file_actions,const posix_spawnattr_t * __restrict attrp,char * const argv[__restrict],char * const envp[__restrict])2355 int posix_spawn(pid_t * __restrict pid, const char * __restrict path,
2356 const posix_spawn_file_actions_t *file_actions,
2357 const posix_spawnattr_t * __restrict attrp,
2358 char *const argv[ __restrict], char *const envp[ __restrict])
2359 {
2360 int result;
2361 char **altenv;
2362 char *insenv;
2363
2364 if (!path || !argv || !envp || is_spawnexec_active()) {
2365 enter_spawnexec();
2366 result = next_posix_spawn(pid, path, file_actions, attrp, argv, envp);
2367 exit_spawnexec();
2368 return result;
2369 }
2370
2371 altenv = get_exec_envp(envp, &insenv);
2372 enter_spawnexec();
2373 result = next_posix_spawn(pid, path, file_actions, attrp, argv, altenv);
2374 exit_spawnexec();
2375 if (altenv != envp)
2376 free(altenv);
2377 if (insenv)
2378 free(insenv);
2379 return result;
2380 }
2381
posix_spawnp(pid_t * __restrict pid,const char * __restrict file,const posix_spawn_file_actions_t * file_actions,const posix_spawnattr_t * __restrict attrp,char * const argv[__restrict],char * const envp[__restrict])2382 int posix_spawnp(pid_t * __restrict pid, const char * __restrict file,
2383 const posix_spawn_file_actions_t *file_actions,
2384 const posix_spawnattr_t * __restrict attrp,
2385 char *const argv[ __restrict], char *const envp[ __restrict])
2386 {
2387 int result;
2388 const char *search_path = getenv("PATH");
2389 char *path = find_exec_path(file, search_path ? search_path : _PATH_DEFPATH);
2390 if (!path)
2391 return errno;
2392 result = posix_spawn(pid, path, file_actions, attrp, argv, envp);
2393 if (path != file)
2394 free(path);
2395 return result;
2396 }
2397 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 */
2398 #endif /* ifdef __APPLE__ */
2399
2400 #ifdef __sun
2401 /*
2402 * Disable the runtime selection of binaries on Solaris: libfakeroot is (yet?)
2403 * unable to cope with several bitnesses of binaries being run.
2404 */
sysinfo(int command,char * buf,long count)2405 int sysinfo(int command, char *buf, long count)
2406 {
2407 if (command == SI_ISALIST)
2408 {
2409 /* do the evil trick */
2410 #ifdef sparc
2411 #ifdef __arch64__
2412 strncpy(buf, "sparcv9 sparc", count - 1);
2413 return sizeof("sparcv9 sparc");
2414 #else
2415 strncpy(buf, "sparcv7 sparc", count - 1);
2416 return sizeof("sparcv7 sparc");
2417 #endif
2418 #else
2419 strncpy(buf, "i386 i86", count - 1);
2420 return sizeof("i386 i86");
2421 #endif
2422 }
2423 else
2424 {
2425 return next_sysinfo(command, buf, count);
2426 }
2427 }
2428 #endif
2429