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