1 Star 0 Fork 2

公子文彬 / fakeroot

forked from openKylin / fakeroot 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
libfakeroot.c 59.70 KB
一键复制 编辑 原始数据 按行查看 历史
邓好 提交于 2022-11-10 15:44 . merge upstream 1.30.1
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681
/*
Copyright © 1997, 1998, 1999, 2000, 2001 joost witteveen
Copyright © 2002-2020 Clint Adams
Copyright © 2012 Mikhail Gusarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
/* #define _POSIX_C_SOURCE 199309L whatever that may mean...*/
/* #define _BSD_SOURCE I use strdup, S_IFDIR, etc */
/* Roderich Schupp writes (bug #79100):
/usr/include/dlfcn.h from libc6 2.2-5 defines RTLD_NEXT only
when compiled with _GNU_SOURCE defined. Hence libfakeroot.c doesn't pick
it
up and does a dlopen("/lib/libc.so.6",...) in get_libc().
This works most of the time, but explodes if you have an arch-optimized
libc installed: the program now has two versions of libc.so
(/lib/libc.so.6 and, say, /lib/i586/libc.so.6) mapped. Again for
some programs you might get away with this, but running bash under
fakeroot
always bombs. Simple fix:
*/
#define _GNU_SOURCE
#define FAKEROOT_LIBFAKEROOT
#ifdef __APPLE__
/*
In this file, we want 'struct stat' to have a 32-bit 'ino_t'.
We use 'struct stat64' when we need a 64-bit 'ino_t'.
*/
# include <sys/types.h>
# if __DARWIN_ONLY_64_BIT_INO_T
# define _DARWIN_USE_64_BIT_INODE
# else
# define _DARWIN_NO_64_BIT_INODE
# endif
/* The helper _unix2003 version of this file calls a few functions in this file
that are marked with static_nonapple so that needs to become private instead
*/
#define static_nonapple __attribute__((visibility("hidden")))
#ifndef __LP64__
/*
This file is for 32-bit symbols which do not have the "$UNIX2003" version.
*/
#define _NONSTD_SOURCE
#endif
#else /* !__APPLE__ */
/* static_nonapple needs to become static in this case */
#define static_nonapple static
#endif /* !__APPLE__ */
#include "config.h"
#include "communicate.h"
#ifdef __APPLE__
/* The *xattr functions are currently disabled on __APPLE__ since the prototypes
are all different from the Linux versions and there is, as of yet, no
STUPID_APPLE_HACK (or similar) to deal with the differences.
Note that __APPLE__ does not have the l*xattr variants or capset so those
will already be undefined.
*/
#undef HAVE_LISTXATTR
#undef HAVE_FLISTXATTR
#undef HAVE_GETXATTR
#undef HAVE_FGETXATTR
#undef HAVE_SETXATTR
#undef HAVE_FSETXATTR
#undef HAVE_REMOVEXATTR
#undef HAVE_FREMOVEXATTR
#endif /* __APPLE__ */
#ifdef STUPID_ALPHA_HACK
#define SEND_STAT(a,b,c) send_stat(a,b,c)
#define SEND_STAT64(a,b,c) send_stat64(a,b,c)
#define SEND_GET_STAT(a,b) send_get_stat(a,b)
#define SEND_GET_STAT64(a,b) send_get_stat64(a,b)
#define SEND_GET_XATTR64(a,b,c) send_get_xattr64(a,b,c)
#else
#define SEND_STAT(a,b,c) send_stat(a,b)
#define SEND_STAT64(a,b,c) send_stat64(a,b)
#define SEND_GET_STAT(a,b) send_get_stat(a)
#define SEND_GET_STAT64(a,b) send_get_stat64(a)
#define SEND_GET_XATTR64(a,b,c) send_get_xattr64(a,b)
#endif
#ifndef _STAT_VER
#if defined __linux__
#if defined (__aarch64__)
#define _STAT_VER 0
#elif defined (__ia64__)
#define _STAT_VER 1
#elif defined (__powerpc__) && __WORDSIZE == 64
#define _STAT_VER 1
#elif defined (__riscv) && __riscv_xlen==64
#define _STAT_VER 0
#elif defined (__s390x__)
#define _STAT_VER 1
#elif defined (__x86_64__)
#define _STAT_VER 1
#else
#define _STAT_VER 3
#endif
#elif defined __GNU__
#define _STAT_VER 0
#endif
#endif
/*
These INT_* (which stands for internal) macros should always be used when
the fakeroot library owns the storage of the stat variable.
*/
#ifdef STAT64_SUPPORT
#define INT_STRUCT_STAT struct stat64
#define INT_NEXT_STAT(a,b) NEXT_STAT64(_STAT_VER,a,b)
#define INT_NEXT_LSTAT(a,b) NEXT_LSTAT64(_STAT_VER,a,b)
#define INT_NEXT_FSTAT(a,b) NEXT_FSTAT64(_STAT_VER,a,b)
#define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT64(_STAT_VER,a,b,c,d)
#define INT_SEND_STAT(a,b) SEND_STAT64(a,b,_STAT_VER)
#define INT_SEND_GET_XATTR(a,b) SEND_GET_XATTR64(a,b,_STAT_VER)
#define INT_SEND_GET_STAT(a,b) SEND_GET_STAT64(a,b)
#else
#define INT_STRUCT_STAT struct stat
#define INT_NEXT_STAT(a,b) NEXT_STAT(_STAT_VER,a,b)
#define INT_NEXT_LSTAT(a,b) NEXT_LSTAT(_STAT_VER,a,b)
#define INT_NEXT_FSTAT(a,b) NEXT_FSTAT(_STAT_VER,a,b)
#define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT(_STAT_VER,a,b,c,d)
#define INT_SEND_STAT(a,b) SEND_STAT(a,b,_STAT_VER)
#define INT_SEND_GET_XATTR(a,b) SEND_GET_XATTR(a,b,_STAT_VER)
#define INT_SEND_GET_STAT(a,b) SEND_GET_STAT(a,b)
/* 10.10 uses id_t in getpriority/setpriority calls, so pretend
id_t is used everywhere, just happens to be int on some OSes */
#ifndef _ID_T
#define _ID_T
typedef int id_t;
#endif
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif /* HAVE_SYS_ACL_H */
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
#if HAVE_FTS_H
#include <fts.h>
#endif /* HAVE_FTS_H */
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h>
#endif
#ifdef __sun
#include <sys/systeminfo.h>
#endif
#ifdef __APPLE__
#include <paths.h>
#include <sys/stat.h>
#include <crt_externs.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
#include <spawn.h>
#endif
#ifndef va_copy
#define va_copy(dest,src) ((dest)=(src))
#endif
#endif /* __APPLE__ */
#if !HAVE_DECL_SETENV
extern int setenv (const char *name, const char *value, int replace);
#endif
#if !HAVE_DECL_UNSETENV
extern int unsetenv (const char *name);
#endif
/*
Where are those shared libraries?
If I knew of a configure/libtool way to find that out, I'd use it. Or
any other way other than the method I'm using below. Does anybody know
how I can get that location? (BTW, symply linking a programme, and running
`ldd' on it isn't the option, as Digital Unix doesn't have ldd)
*/
/*
Note that LIBCPATH isn't actually used on Linux or Solaris, as RTLD_NEXT
is defined and we use that to get the `next_*' functions
Linux:
*/
/* OSF1 :*/
/*#define LIBCPATH "/usr/shlib/libc.so"*/
#undef __xstat
#undef __fxstat
#undef __lxstat
#undef __xstat64
#undef __fxstat64
#undef __lxstat64
#undef _FILE_OFFSET_BITS
#ifndef AT_EMPTY_PATH
#define AT_EMPTY_PATH 0
#endif
#ifndef AT_NO_AUTOMOUNT
#define AT_NO_AUTOMOUNT 0
#endif
/*
// next_wrap_st:
// this structure is used in next_wrap, which is defined in
// wrapstruct.h, included below
*/
struct next_wrap_st{
void **doit;
char *name;
};
void *get_libc(){
#ifndef RTLD_NEXT
void *lib=0;
if(!lib){
lib= dlopen(LIBCPATH,RTLD_LAZY);
}
if (NULL==lib) {
fprintf(stderr, "Couldn't find libc at: %s\n", LIBCPATH);
abort();
}
return lib;
#else
return RTLD_NEXT;
#endif
}
void load_library_symbols(void);
int fakeroot_disabled = 0;
#ifdef LIBFAKEROOT_DEBUGGING
int fakeroot_debug = 0;
#endif /* LIBFAKEROOT_DEBUGGING */
#ifdef __APPLE__
#include "patchattr.h"
#endif
#include "wrapped.h"
#include "wraptmpf.h"
#include "wrapdef.h"
#include "wrapstruct.h"
void load_library_symbols(void){
/* this function loads all original functions from the C library.
This function is only called once.
I ran into problems when each function individually
loaded it's original counterpart, as RTLD_NEXT seems to have
a different meaning in files with different names than libtricks.c
(I.E, dlsym(RTLD_NEXT, ...) called in vsearch.c returned funtions
defined in libtricks */
/* The calling of this function itself is somewhat tricky:
the awk script wrapawk generates several .h files. In wraptmpf.h
there are temporary definitions for tmp_*, that do the call
to this function. The other generated .h files do even more tricky
things :) */
int i;
const char *msg;
#ifdef LIBFAKEROOT_DEBUGGING
if (getenv("FAKEROOT_DEBUG")) {
fakeroot_debug=1;
}
if (fakeroot_debug) {
fprintf(stderr, "load_library_symbols\n");
}
#endif /* LIBFAKEROOT_DEBUGGING */
for(i=0; next_wrap[i].doit; i++){
/* clear dlerror() just in case dlsym() legitimately returns NULL */
msg = dlerror();
*(next_wrap[i].doit)=dlsym(get_libc(), next_wrap[i].name);
#ifdef LIBFAKEROOT_DEBUGGING
/* illumos libc creates noise if symbols is not found (e. g. acl_get())*/
if ( (msg = dlerror()) != NULL){
fprintf (stderr, "dlsym(%s): %s\n", next_wrap[i].name, msg);
}
#endif /* LIBFAKEROOT_DEBUGGING */
}
}
/*
* Fake implementations for the setuid family of functions.
* The fake IDs are inherited by child processes via environment variables.
*
* Issues:
* o Privileges are not checked, which results in incorrect behaviour.
* Example: process changes its (real, effective and saved) uid to 1000
* and then tries to regain root privileges. This should normally result
* in an EPERM, but our implementation doesn't care...
* o If one of the setenv calls fails, the state may get corrupted.
* o Not thread-safe.
*/
/* Generic set/get ID functions */
static int env_get_id(const char *key) {
char *str = getenv(key);
if (str)
return atoi(str);
return 0;
}
static int env_set_id(const char *key, int id) {
if (id == 0) {
unsetenv(key);
return 0;
} else {
char str[12];
snprintf(str, sizeof (str), "%d", id);
return setenv(key, str, 1);
}
}
static void read_id(unsigned int *id, const char *key) {
if (*id == (unsigned int)-1)
*id = env_get_id(key);
}
static int write_id(const char *key, int id) {
if (env_get_id(key) != id)
return env_set_id(key, id);
return 0;
}
/* Fake ID storage */
static uid_t faked_real_uid = (uid_t)-1;
static gid_t faked_real_gid = (gid_t)-1;
static uid_t faked_effective_uid = (uid_t)-1;
static gid_t faked_effective_gid = (gid_t)-1;
static uid_t faked_saved_uid = (uid_t)-1;
static gid_t faked_saved_gid = (gid_t)-1;
static uid_t faked_fs_uid = (uid_t)-1;
static gid_t faked_fs_gid = (gid_t)-1;
/* Read user ID */
static void read_real_uid() {
read_id(&faked_real_uid, FAKEROOTUID_ENV);
}
static void read_effective_uid() {
read_id(&faked_effective_uid, FAKEROOTEUID_ENV);
}
static void read_saved_uid() {
read_id(&faked_saved_uid, FAKEROOTSUID_ENV);
}
static void read_fs_uid() {
read_id(&faked_fs_uid, FAKEROOTFUID_ENV);
}
static void read_uids() {
read_real_uid();
read_effective_uid();
read_saved_uid();
read_fs_uid();
}
/* Read group ID */
static void read_real_gid() {
read_id(&faked_real_gid, FAKEROOTGID_ENV);
}
static void read_effective_gid() {
read_id(&faked_effective_gid, FAKEROOTEGID_ENV);
}
static void read_saved_gid() {
read_id(&faked_saved_gid, FAKEROOTSGID_ENV);
}
static void read_fs_gid() {
read_id(&faked_fs_gid, FAKEROOTFGID_ENV);
}
static void read_gids() {
read_real_gid();
read_effective_gid();
read_saved_gid();
read_fs_gid();
}
/* Write user ID */
static int write_real_uid() {
return write_id(FAKEROOTUID_ENV, faked_real_uid);
}
static int write_effective_uid() {
return write_id(FAKEROOTEUID_ENV, faked_effective_uid);
}
static int write_saved_uid() {
return write_id(FAKEROOTSUID_ENV, faked_saved_uid);
}
static int write_fs_uid() {
return write_id(FAKEROOTFUID_ENV, faked_fs_uid);
}
static int write_uids() {
if (write_real_uid() < 0)
return -1;
if (write_effective_uid() < 0)
return -1;
if (write_saved_uid() < 0)
return -1;
if (write_fs_uid() < 0)
return -1;
return 0;
}
/* Write group ID */
static int write_real_gid() {
return write_id(FAKEROOTGID_ENV, faked_real_gid);
}
static int write_effective_gid() {
return write_id(FAKEROOTEGID_ENV, faked_effective_gid);
}
static int write_saved_gid() {
return write_id(FAKEROOTSGID_ENV, faked_saved_gid);
}
static int write_fs_gid() {
return write_id(FAKEROOTFGID_ENV, faked_fs_gid);
}
static int write_gids() {
if (write_real_gid() < 0)
return -1;
if (write_effective_gid() < 0)
return -1;
if (write_saved_gid() < 0)
return -1;
if (write_fs_gid() < 0)
return -1;
return 0;
}
/* Faked get functions */
static uid_t get_faked_uid() {
read_real_uid();
return faked_real_uid;
}
static gid_t get_faked_gid() {
read_real_gid();
return faked_real_gid;
}
static uid_t get_faked_euid() {
read_effective_uid();
return faked_effective_uid;
}
static gid_t get_faked_egid() {
read_effective_gid();
return faked_effective_gid;
}
static uid_t get_faked_suid() {
read_saved_uid();
return faked_saved_uid;
}
static gid_t get_faked_sgid() {
read_saved_gid();
return faked_saved_gid;
}
static uid_t get_faked_fsuid() {
read_fs_uid();
return faked_fs_uid;
}
static gid_t get_faked_fsgid() {
read_fs_gid();
return faked_fs_gid;
}
/* Faked set functions */
static int set_faked_uid(uid_t uid) {
read_uids();
if (faked_effective_uid == 0) {
faked_real_uid = uid;
faked_effective_uid = uid;
faked_saved_uid = uid;
} else {
faked_effective_uid = uid;
}
faked_fs_uid = uid;
return write_uids();
}
static int set_faked_gid(gid_t gid) {
read_gids();
if (faked_effective_gid == 0) {
faked_real_gid = gid;
faked_effective_gid = gid;
faked_saved_gid = gid;
} else {
faked_effective_gid = gid;
}
faked_fs_gid = gid;
return write_gids();
}
static int set_faked_euid(uid_t euid) {
read_effective_uid();
faked_effective_uid = euid;
read_fs_uid();
faked_fs_uid = euid;
if (write_effective_uid() < 0)
return -1;
if (write_fs_uid() < 0)
return -1;
return 0;
}
static int set_faked_egid(gid_t egid) {
read_effective_gid();
faked_effective_gid = egid;
read_fs_gid();
faked_fs_gid = egid;
if (write_effective_gid() < 0)
return -1;
if (write_fs_gid() < 0)
return -1;
return 0;
}
static_nonapple int set_faked_reuid(uid_t ruid, uid_t euid) {
read_uids();
if (ruid != (uid_t)-1 || euid != (uid_t)-1)
faked_saved_uid = faked_effective_uid;
if (ruid != (uid_t)-1)
faked_real_uid = ruid;
if (euid != (uid_t)-1)
faked_effective_uid = euid;
faked_fs_uid = faked_effective_uid;
return write_uids();
}
static_nonapple int set_faked_regid(gid_t rgid, gid_t egid) {
read_gids();
if (rgid != (gid_t)-1 || egid != (gid_t)-1)
faked_saved_gid = faked_effective_gid;
if (rgid != (gid_t)-1)
faked_real_gid = rgid;
if (egid != (gid_t)-1)
faked_effective_gid = egid;
faked_fs_gid = faked_effective_gid;
return write_gids();
}
#ifdef HAVE_SETRESUID
static int set_faked_resuid(uid_t ruid, uid_t euid, uid_t suid) {
read_uids();
if (ruid != (uid_t)-1)
faked_real_uid = ruid;
if (euid != (uid_t)-1)
faked_effective_uid = euid;
if (suid != (uid_t)-1)
faked_saved_uid = suid;
faked_fs_uid = faked_effective_uid;
return write_uids();
}
#endif
#ifdef HAVE_SETRESGID
static int set_faked_resgid(gid_t rgid, gid_t egid, gid_t sgid) {
read_gids();
if (rgid != (gid_t)-1)
faked_real_gid = rgid;
if (egid != (gid_t)-1)
faked_effective_gid = egid;
if (sgid != (gid_t)-1)
faked_saved_gid = sgid;
faked_fs_gid = faked_effective_gid;
return write_gids();
}
#endif
#ifdef HAVE_SETFSUID
static uid_t set_faked_fsuid(uid_t fsuid) {
uid_t prev_fsuid = get_faked_fsuid();
faked_fs_uid = fsuid;
return prev_fsuid;
}
#endif
#ifdef HAVE_SETFSGID
static gid_t set_faked_fsgid(gid_t fsgid) {
gid_t prev_fsgid = get_faked_fsgid();
faked_fs_gid = fsgid;
return prev_fsgid;
}
#endif
static_nonapple int dont_try_chown(){
static int inited=0;
static int donttry;
if(!inited){
donttry=(env_var_set(FAKEROOTDONTTRYCHOWN_ENV)!=NULL);
inited=1;
}
return donttry;
}
/* The wrapped functions */
int WRAP_LSTAT LSTAT_ARG(int ver,
const char *file_name,
struct stat *statbuf){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lstat file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_LSTAT(ver, file_name, statbuf);
if(r)
return -1;
SEND_GET_STAT(statbuf, ver);
return 0;
}
int WRAP_STAT STAT_ARG(int ver,
const char *file_name,
struct stat *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "stat file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_STAT(ver, file_name, st);
if(r)
return -1;
SEND_GET_STAT(st,ver);
return 0;
}
int WRAP_FSTAT FSTAT_ARG(int ver,
int fd,
struct stat *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fstat fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_FSTAT(ver, fd, st);
if(r)
return -1;
SEND_GET_STAT(st,ver);
return 0;
}
#ifdef HAVE_FSTATAT
int WRAP_FSTATAT FSTATAT_ARG(int ver,
int dir_fd,
const char *path,
struct stat *st,
int flags){
int r;
r=NEXT_FSTATAT(ver, dir_fd, path, st, flags);
if(r)
return -1;
SEND_GET_STAT(st,ver);
return 0;
}
#endif /* HAVE_FSTATAT */
#ifdef STAT64_SUPPORT
int WRAP_LSTAT64 LSTAT64_ARG (int ver,
const char *file_name,
struct stat64 *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lstat64 file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_LSTAT64(ver, file_name, st);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
int WRAP_STAT64 STAT64_ARG(int ver,
const char *file_name,
struct stat64 *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "stat64 file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_STAT64(ver,file_name,st);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
int WRAP_FSTAT64 FSTAT64_ARG(int ver,
int fd,
struct stat64 *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fstat64 fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_FSTAT64(ver, fd, st);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
#ifdef HAVE_FSTATAT
int WRAP_FSTATAT64 FSTATAT64_ARG(int ver,
int dir_fd,
const char *path,
struct stat64 *st,
int flags){
int r;
r=NEXT_FSTATAT64(ver, dir_fd, path, st, flags);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
#endif /* HAVE_FSTATAT */
#endif /* STAT64_SUPPORT */
/*************************************************************/
/*
Wrapped functions general info:
In general, the structure is as follows:
- Then, if the function does things that (possibly) fail by
other users than root, allow for `fake' root privileges.
Do this by obtaining the inode the function works on, and then
informing faked (the deamon that remembers all `fake' file
permissions e.d.) about the intentions of the user.
Faked maintains a list of inodes and their respective
`fake' ownerships/filemodes.
- Or, if the function requests information that we should
fake, again get the inode of the file, and ask faked about the
ownership/filemode data it maintains for that inode.
*/
/*************************************************************/
/* chown, lchown, fchown, chmod, fchmod, mknod functions
quite general. See the `Wrapped functions general info:' above
for more info.
*/
int chown(const char *path, uid_t owner, gid_t group){
INT_STRUCT_STAT st;
int r=0;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "chown path %s owner %d group %d\n", path, owner, group);
}
#endif /* LIBFAKEROOT_DEBUGGING */
#ifdef LCHOWN_SUPPORT
/*chown(sym-link) works on the target of the symlink if lchown is
present and enabled.*/
r=INT_NEXT_STAT(path, &st);
#else
/*chown(sym-link) works on the symlink itself, use lstat: */
r=INT_NEXT_LSTAT(path, &st);
#endif
if(r)
return r;
st.st_uid=owner;
st.st_gid=group;
INT_SEND_STAT(&st,chown_func);
if(!dont_try_chown())
r=next_lchown(path,owner,group);
else
r=0;
if(r&&(errno==EPERM))
r=0;
return r;
}
#ifdef LCHOWN_SUPPORT
int lchown(const char *path, uid_t owner, gid_t group){
INT_STRUCT_STAT st;
int r=0;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lchown path %s owner %d group %d\n", path, owner, group);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
st.st_uid=owner;
st.st_gid=group;
INT_SEND_STAT(&st,chown_func);
if(!dont_try_chown())
r=next_lchown(path,owner,group);
else
r=0;
if(r&&(errno==EPERM))
r=0;
return r;
}
#endif
int fchown(int fd, uid_t owner, gid_t group){
INT_STRUCT_STAT st;
int r;
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return r;
st.st_uid=owner;
st.st_gid=group;
INT_SEND_STAT(&st, chown_func);
if(!dont_try_chown())
r=next_fchown(fd,owner,group);
else
r=0;
if(r&&(errno==EPERM))
r=0;
return r;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_FCHOWNAT
int fchownat(int dir_fd, const char *path, uid_t owner, gid_t group, int flags) {
int r;
/* If AT_SYMLINK_NOFOLLOW is set in the fchownat call it should
be when we stat it. */
INT_STRUCT_STAT st;
r=INT_NEXT_FSTATAT(dir_fd, path, &st, (flags & (AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH | AT_NO_AUTOMOUNT)));
if(r)
return(r);
st.st_uid=owner;
st.st_gid=group;
INT_SEND_STAT(&st,chown_func);
if(!dont_try_chown())
r=next_fchownat(dir_fd,path,owner,group,flags);
else
r=0;
if(r&&(errno==EPERM))
r=0;
return r;
}
#endif /* HAVE_FCHOWNAT */
#endif /* HAVE_FSTATAT */
int chmod(const char *path, mode_t mode){
INT_STRUCT_STAT st;
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "chmod path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_STAT(path, &st);
if(r)
return r;
st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
INT_SEND_STAT(&st, chmod_func);
/* if a file is unwritable, then root can still write to it
(no matter who owns the file). If we are fakeroot, the only
way to fake this is to always make the file writable, readable
etc for the real user (who started fakeroot). Also holds for
the exec bit of directories.
Yes, packages requering that are broken. But we have lintian
to get rid of broken packages, not fakeroot.
*/
mode |= 0600;
if(S_ISDIR(st.st_mode))
mode |= 0100;
r=next_chmod(path, mode);
if(r&&(errno==EPERM))
r=0;
#ifdef EFTYPE /* available under FreeBSD kernel */
if(r&&(errno==EFTYPE))
r=0;
#endif
return r;
}
#ifdef HAVE_LCHMOD
int lchmod(const char *path, mode_t mode){
INT_STRUCT_STAT st;
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lchmod path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
INT_SEND_STAT(&st, chmod_func);
/* see chmod() for comment */
mode |= 0600;
if(S_ISDIR(st.st_mode))
mode |= 0100;
r=next_lchmod(path, mode);
if(r&&(errno==EPERM))
r=0;
#ifdef EFTYPE /* available under FreeBSD kernel */
if(r&&(errno==EFTYPE))
r=0;
#endif
return r;
}
#endif
int fchmod(int fd, mode_t mode){
int r;
INT_STRUCT_STAT st;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fchmod fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return(r);
st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
INT_SEND_STAT(&st,chmod_func);
/* see chmod() for comment */
mode |= 0600;
if(S_ISDIR(st.st_mode))
mode |= 0100;
r=next_fchmod(fd, mode);
if(r&&(errno==EPERM))
r=0;
#ifdef EFTYPE /* available under FreeBSD kernel */
if(r&&(errno==EFTYPE))
r=0;
#endif
return r;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_FCHMODAT
int fchmodat(int dir_fd, const char *path, mode_t mode, int flags) {
/* (int fd, mode_t mode){*/
int r;
INT_STRUCT_STAT st;
/* If AT_SYMLINK_NOFOLLOW is set in the fchownat call it should
be when we stat it. */
r=INT_NEXT_FSTATAT(dir_fd, path, &st, flags & (AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH | AT_NO_AUTOMOUNT));
if(r)
return(r);
st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS);
INT_SEND_STAT(&st,chmod_func);
/* see chmod() for comment */
mode |= 0600;
if(S_ISDIR(st.st_mode))
mode |= 0100;
r=next_fchmodat(dir_fd, path, mode, flags);
if(r&&(errno==EPERM))
r=0;
#ifdef EFTYPE /* available under FreeBSD kernel */
if(r&&(errno==EFTYPE))
r=0;
#endif
return r;
}
#endif /* HAVE_FCHMODAT */
#endif /* HAVE_FSTATAT */
int WRAP_MKNOD MKNOD_ARG(int ver UNUSED,
const char *pathname,
mode_t mode, dev_t XMKNOD_FRTH_ARG dev)
{
INT_STRUCT_STAT st;
mode_t old_mask=umask(022);
int fd,r;
umask(old_mask);
/*Don't bother to mknod the file, that probably doesn't work.
just create it as normal file, and leave the premissions
to the fakemode.*/
fd=open(pathname, O_WRONLY|O_CREAT|O_TRUNC, 00644);
if(fd==-1)
return -1;
close(fd);
/* get the inode, to communicate with faked */
r=INT_NEXT_LSTAT(pathname, &st);
if(r)
return -1;
st.st_mode= mode & ~old_mask;
st.st_rdev= XMKNOD_FRTH_ARG dev;
INT_SEND_STAT(&st,mknod_func);
return 0;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_MKNODAT
int WRAP_MKNODAT MKNODAT_ARG(int ver UNUSED,
int dir_fd,
const char *pathname,
mode_t mode, dev_t XMKNODAT_FIFTH_ARG dev)
{
INT_STRUCT_STAT st;
mode_t old_mask=umask(022);
int fd,r;
umask(old_mask);
/*Don't bother to mknod the file, that probably doesn't work.
just create it as normal file, and leave the permissions
to the fakemode.*/
fd=openat(dir_fd, pathname, O_WRONLY|O_CREAT|O_TRUNC, 00644);
if(fd==-1)
return -1;
close(fd);
/* get the inode, to communicate with faked */
/* The only known flag is AT_SYMLINK_NOFOLLOW and
we don't want that here. */
r=INT_NEXT_FSTATAT(dir_fd, pathname, &st, 0);
if(r)
return -1;
st.st_mode= mode & ~old_mask;
st.st_rdev= XMKNODAT_FIFTH_ARG dev;
INT_SEND_STAT(&st,mknod_func);
return 0;
}
#endif /* HAVE_MKNODAT */
#endif /* HAVE_FSTATAT */
int mkdir(const char *path, mode_t mode){
INT_STRUCT_STAT st;
int r;
mode_t old_mask=umask(022);
umask(old_mask);
/* we need to tell the fake deamon the real mode. In order
to communicate with faked we need a struct stat, so we now
do a stat of the new directory (just for the inode/dev) */
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "mkdir path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=next_mkdir(path, mode|0700);
/* mode|0700: see comment in the chown() function above */
if(r)
return -1;
r=INT_NEXT_STAT(path, &st);
if(r)
return -1;
st.st_mode=(mode&~old_mask&ALLPERMS)|(st.st_mode&~ALLPERMS)|S_IFDIR;
INT_SEND_STAT(&st, chmod_func);
return 0;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_MKDIRAT
int mkdirat(int dir_fd, const char *path, mode_t mode){
INT_STRUCT_STAT st;
int r;
mode_t old_mask=umask(022);
umask(old_mask);
/* we need to tell the fake deamon the real mode. In order
to communicate with faked we need a struct stat, so we now
do a stat of the new directory (just for the inode/dev) */
r=next_mkdirat(dir_fd, path, mode|0700);
/* mode|0700: see comment in the chown() function above */
if(r)
return -1;
r=INT_NEXT_FSTATAT(dir_fd, path, &st, 0);
if(r)
return -1;
st.st_mode=(mode&~old_mask&ALLPERMS)|(st.st_mode&~ALLPERMS)|S_IFDIR;
INT_SEND_STAT(&st, chmod_func);
return 0;
}
#endif /* HAVE_MKDIRAT */
#endif /* HAVE_FSTATAT */
/*
The remove funtions: unlink, rmdir, rename.
These functions can all remove inodes from the system.
I need to inform faked about the removal of these inodes because
of the following:
# rm -f file
# touch file
# chown admin file
# rm file
# touch file
In the above example, assuming that for both touch-es, the same
inode is generated, faked will still report the owner of `file'
as `admin', unless it's informed about the removal of the inode.
*/
int unlink(const char *pathname){
int r;
INT_STRUCT_STAT st;
r=INT_NEXT_LSTAT(pathname, &st);
if(r)
return -1;
r=next_unlink(pathname);
if(r)
return -1;
INT_SEND_STAT(&st, unlink_func);
return 0;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_UNLINKAT
int unlinkat(int dir_fd, const char *pathname, int flags){
int r;
INT_STRUCT_STAT st;
r=INT_NEXT_FSTATAT(dir_fd, pathname, &st, (flags&~AT_REMOVEDIR) | AT_SYMLINK_NOFOLLOW);
if(r)
return -1;
r=next_unlinkat(dir_fd, pathname, flags);
if(r)
return -1;
INT_SEND_STAT(&st, unlink_func);
return 0;
}
#endif /* HAVE_UNLINKAT */
#endif /* HAVE_FSTATAT */
/*
See the `remove funtions:' comments above for more info on
these remove function wrappers.
*/
int rmdir(const char *pathname){
int r;
INT_STRUCT_STAT st;
r=INT_NEXT_LSTAT(pathname, &st);
if(r)
return -1;
r=next_rmdir(pathname);
if(r)
return -1;
INT_SEND_STAT(&st,unlink_func);
return 0;
}
/*
See the `remove funtions:' comments above for more info on
these remove function wrappers.
*/
int remove(const char *pathname){
int r;
INT_STRUCT_STAT st;
r=INT_NEXT_LSTAT(pathname, &st);
if(r)
return -1;
r=next_remove(pathname);
if(r)
return -1;
INT_SEND_STAT(&st,unlink_func);
return r;
}
/*
if the second argument to the rename() call points to an
existing file, then that file will be removed. So, we have
to treat this function as one of the `remove functions'.
See the `remove funtions:' comments above for more info on
these remove function wrappers.
*/
int rename(const char *oldpath, const char *newpath){
int r,s;
INT_STRUCT_STAT st;
/* If newpath points to an existing file, that file will be
unlinked. Make sure we tell the faked daemon about this! */
/* we need the st_new struct in order to inform faked about the
(possible) unlink of the file */
r=INT_NEXT_LSTAT(newpath, &st);
s=next_rename(oldpath, newpath);
if(s)
return -1;
if(!r)
INT_SEND_STAT(&st,unlink_func);
return 0;
}
#ifdef HAVE_FSTATAT
#ifdef HAVE_RENAMEAT
int renameat(int olddir_fd, const char *oldpath,
int newdir_fd, const char *newpath){
int r,s;
INT_STRUCT_STAT st;
/* If newpath points to an existing file, that file will be
unlinked. Make sure we tell the faked daemon about this! */
/* we need the st_new struct in order to inform faked about the
(possible) unlink of the file */
r=INT_NEXT_FSTATAT(newdir_fd, newpath, &st, AT_SYMLINK_NOFOLLOW);
s=next_renameat(olddir_fd, oldpath, newdir_fd, newpath);
if(s)
return -1;
if(!r)
INT_SEND_STAT(&st,unlink_func);
return 0;
}
#endif /* HAVE_RENAMEAT */
#endif /* HAVE_FSTATAT */
#if defined(__GLIBC__)
#if __GLIBC_PREREQ(2,33)
/* Glibc 2.33 exports symbols for these functions in the shared lib */
int lstat(const char *file_name, struct stat *statbuf) {
return WRAP_LSTAT LSTAT_ARG(_STAT_VER, file_name, statbuf);
}
int stat(const char *file_name, struct stat *st) {
return WRAP_STAT STAT_ARG(_STAT_VER, file_name, st);
}
int fstat(int fd, struct stat *st) {
return WRAP_FSTAT FSTAT_ARG(_STAT_VER, fd, st);
}
#ifdef HAVE_FSTATAT
int fstatat(int dir_fd, const char *path, struct stat *st, int flags) {
return WRAP_FSTATAT FSTATAT_ARG(_STAT_VER, dir_fd, path, st, flags);
}
#endif
#ifdef STAT64_SUPPORT
int lstat64(const char *file_name, struct stat64 *st) {
return WRAP_LSTAT64 LSTAT64_ARG(_STAT_VER, file_name, st);
}
int stat64(const char *file_name, struct stat64 *st) {
return WRAP_STAT64 STAT64_ARG(_STAT_VER, file_name, st);
}
int fstat64(int fd, struct stat64 *st) {
return WRAP_FSTAT64 FSTAT64_ARG(_STAT_VER, fd, st);
}
#ifdef HAVE_FSTATAT
int fstatat64(int dir_fd, const char *path, struct stat64 *st, int flags) {
return WRAP_FSTATAT64 FSTATAT64_ARG(_STAT_VER, dir_fd, path, st, flags);
}
#endif
#endif
int mknod(const char *pathname, mode_t mode, dev_t dev) {
return WRAP_MKNOD MKNOD_ARG(_STAT_VER, pathname, mode, &dev);
}
#if defined(HAVE_FSTATAT) && defined(HAVE_MKNODAT)
int mknodat(int dir_fd, const char *pathname, mode_t mode, dev_t dev) {
return WRAP_MKNODAT MKNODAT_ARG(_STAT_VER, dir_fd, pathname, mode, &dev);
}
#endif
#endif /* __GLIBC__ */
#endif /* GLIBC_PREREQ */
#ifdef FAKEROOT_FAKENET
pid_t fork(void)
{
pid_t pid;
pid = next_fork();
if (pid == 0) {
/* No need to lock in the child process. */
if (comm_sd >= 0) {
next_close(comm_sd);
comm_sd = -1;
}
}
return pid;
}
pid_t vfork(void)
{
/* We can't wrap vfork(2) without breaking everything... */
return fork();
}
/* Return an error when trying to close the comm_sd file descriptor
(pretend that it's closed). */
int close(int fd)
{
int retval, reterr;
lock_comm_sd();
if (comm_sd >= 0 && comm_sd == fd) {
retval = -1;
reterr = EBADF;
} else {
retval = next_close(fd);
reterr = errno;
}
unlock_comm_sd();
errno = reterr;
return retval;
}
int dup2(int oldfd, int newfd)
{
int retval, reterr;
lock_comm_sd();
if (comm_sd >= 0 && comm_sd == newfd) {
/* If dup fails, comm_sd gets set to -1, which is fine. */
comm_sd = dup(newfd);
next_close(newfd);
}
retval = next_dup2(oldfd, newfd);
reterr = errno;
unlock_comm_sd();
errno = reterr;
return retval;
}
#endif /* FAKEROOT_FAKENET */
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
static int check_fakeroot_disabled(void *retaddr){
Dl_info info;
const char *suffix;
if (fakeroot_disabled || !dladdr(retaddr, &info))
return fakeroot_disabled;
suffix = strrchr(info.dli_fname, '/');
if (suffix && (strcmp(suffix, "/CarbonCore") == 0 ||
strcmp(suffix, "/CoreServicesInternal") == 0))
return 1;
return fakeroot_disabled;
}
#define fakeroot_disabled check_fakeroot_disabled(__builtin_return_address(0))
#endif
#endif /* __APPLE__ */
uid_t getuid(void){
if (fakeroot_disabled)
return next_getuid();
return get_faked_uid();
}
uid_t geteuid(void){
if (fakeroot_disabled)
return next_geteuid();
return get_faked_euid();
}
#ifdef HAVE_GETRESUID
int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid){
if (fakeroot_disabled)
return next_getresuid(ruid, euid, suid);
*ruid = get_faked_uid();
*euid = get_faked_euid();
*suid = get_faked_suid();
return 0;
}
#endif /* HAVE_GETRESUID */
uid_t getgid(void){
if (fakeroot_disabled)
return next_getgid();
return get_faked_gid();
}
uid_t getegid(void){
if (fakeroot_disabled)
return next_getegid();
return get_faked_egid();
}
#ifdef HAVE_GETRESGID
int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid){
if (fakeroot_disabled)
return next_getresgid(rgid, egid, sgid);
*rgid = get_faked_gid();
*egid = get_faked_egid();
*sgid = get_faked_sgid();
return 0;
}
#endif /* HAVE_GETRESGID */
int setuid(uid_t id){
if (fakeroot_disabled)
return next_setuid(id);
return set_faked_uid(id);
}
int setgid(uid_t id){
if (fakeroot_disabled)
return next_setgid(id);
return set_faked_gid(id);
}
int seteuid(uid_t id){
if (fakeroot_disabled)
return next_seteuid(id);
return set_faked_euid(id);
}
int setegid(uid_t id){
if (fakeroot_disabled)
return next_setegid(id);
return set_faked_egid(id);
}
int setreuid(SETREUID_ARG ruid, SETREUID_ARG euid){
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "setreuid\n");
}
#endif /* LIBFAKEROOT_DEBUGGING */
if (fakeroot_disabled)
return next_setreuid(ruid, euid);
return set_faked_reuid(ruid, euid);
}
int setregid(SETREGID_ARG rgid, SETREGID_ARG egid){
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "setregid\n");
}
#endif /* LIBFAKEROOT_DEBUGGING */
if (fakeroot_disabled)
return next_setregid(rgid, egid);
return set_faked_regid(rgid, egid);
}
#ifdef HAVE_SETRESUID
int setresuid(uid_t ruid, uid_t euid, uid_t suid){
if (fakeroot_disabled)
return next_setresuid(ruid, euid, suid);
return set_faked_resuid(ruid, euid, suid);
}
#endif /* HAVE_SETRESUID */
#ifdef HAVE_SETRESGID
int setresgid(gid_t rgid, gid_t egid, gid_t sgid){
if (fakeroot_disabled)
return next_setresgid(rgid, egid, sgid);
return set_faked_resgid(rgid, egid, sgid);
}
#endif /* HAVE_SETRESGID */
#ifdef HAVE_SETFSUID
uid_t setfsuid(uid_t fsuid){
if (fakeroot_disabled)
return next_setfsuid(fsuid);
return set_faked_fsuid(fsuid);
}
#endif /* HAVE_SETFSUID */
#ifdef HAVE_SETFSGID
gid_t setfsgid(gid_t fsgid){
if (fakeroot_disabled)
return next_setfsgid(fsgid);
return set_faked_fsgid(fsgid);
}
#endif /* HAVE_SETFSGID */
int initgroups(const char* user, INITGROUPS_SECOND_ARG group){
if (fakeroot_disabled)
return next_initgroups(user, group);
else
return 0;
}
int getgroups(int size, gid_t list[]){
if (fakeroot_disabled)
return next_setgroups(size, list);
else {
if (size > 0)
list[0] = get_faked_gid();
return 1;
}
}
int setgroups(SETGROUPS_SIZE_TYPE size, const gid_t *list){
if (fakeroot_disabled)
return next_setgroups(size, list);
else
return 0;
}
#ifdef HAVE_CAPSET
int capset(cap_user_header_t hdrp, const cap_user_data_t datap)
{
int rc = next_capset(hdrp, datap);
return (fakeroot_disabled) ? (rc) : 0;
}
#endif /* HAVE_CAPSET */
#if defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR)
static size_t common_setxattr(INT_STRUCT_STAT *st, const char *name, void * value, size_t size, int flags)
{
xattr_args xattr;
xattr.name = name;
xattr.value = value;
xattr.size = size;
xattr.flags = flags;
xattr.func = setxattr_func;
INT_SEND_GET_XATTR(st, &xattr);
if (xattr.rc)
{
errno = xattr.rc;
return -1;
}
return 0;
}
#endif /* defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || defined(HAVE_FSETXATTR) */
#if defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR)
static size_t common_getxattr(INT_STRUCT_STAT *st, const char *name, void * value, size_t size)
{
xattr_args xattr;
xattr.name = name;
xattr.value = value;
xattr.size = size;
xattr.func = getxattr_func;
INT_SEND_GET_XATTR(st, &xattr);
if (xattr.rc)
{
errno = xattr.rc;
return -1;
}
return xattr.size;
}
#endif /* defined(HAVE_GETXATTR) || defined(HAVE_LGETXATTR) || defined(HAVE_FGETXATTR) */
#if defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR)
static size_t common_listxattr(INT_STRUCT_STAT *st, char *list, size_t size)
{
xattr_args xattr;
xattr.name = NULL;
xattr.value = list;
xattr.size = size;
xattr.func = listxattr_func;
INT_SEND_GET_XATTR(st, &xattr);
if (xattr.rc)
{
errno = xattr.rc;
return -1;
}
return xattr.size;
}
#endif /* defined(HAVE_LISTXATTR) || defined(HAVE_LLISTXATTR) || defined(HAVE_FLISTXATTR) */
#if defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR)
static size_t common_removexattr(INT_STRUCT_STAT *st, const char *name)
{
xattr_args xattr;
xattr.name = name;
xattr.value = NULL;
xattr.size = 0;
xattr.func = removexattr_func;
INT_SEND_GET_XATTR(st, &xattr);
if (xattr.rc)
{
errno = xattr.rc;
return -1;
}
return 0;
}
#endif /* defined(HAVE_REMOVEXATTR) || defined(HAVE_LREMOVEXATTR) || defined(HAVE_FREMOVEXATTR) */
#ifdef HAVE_SETXATTR
ssize_t setxattr(const char *path, const char *name, void *value, size_t size, int flags)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_setxattr(path, name, value, size, flags);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "setxattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_STAT(path, &st);
if(r)
return r;
return common_setxattr(&st, name, value, size, flags);
}
#endif /* HAVE_SETXATTR */
#ifdef HAVE_LSETXATTR
ssize_t lsetxattr(const char *path, const char *name, void *value, size_t size, int flags)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_lsetxattr(path, name, value, size, flags);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lsetxattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
return common_setxattr(&st, name, value, size, flags);
}
#endif /* HAVE_LSETXATTR */
#ifdef HAVE_FSETXATTR
ssize_t fsetxattr(int fd, const char *name, void *value, size_t size, int flags)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_fsetxattr(fd, name, value, size, flags);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fsetxattr fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return r;
return common_setxattr(&st, name, value, size, flags);
}
#endif /* HAVE_FSETXATTR */
#ifdef HAVE_GETXATTR
ssize_t getxattr(const char *path, const char *name, void *value, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_getxattr(path, name, value, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "getxattr path %s name %s size %d\n", path, name, size);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_STAT(path, &st);
if(r)
return r;
return common_getxattr(&st, name, value, size);
}
#endif /* HAVE_GETXATTR */
#ifdef HAVE_LGETXATTR
ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_lgetxattr(path, name, value, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lgetxattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
return common_getxattr(&st, name, value, size);
}
#endif /* HAVE_LGETXATTR */
#ifdef HAVE_FGETXATTR
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_fgetxattr(fd, name, value, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fgetxattr fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return r;
return common_getxattr(&st, name, value, size);
}
#endif /* HAVE_FGETXATTR */
#ifdef HAVE_LISTXATTR
ssize_t listxattr(const char *path, char *list, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_listxattr(path, list, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "listxattr path %s size %d\n", path, size);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_STAT(path, &st);
if(r)
return r;
return common_listxattr(&st, list, size);
}
#endif /* HAVE_LISTXATTR */
#ifdef HAVE_LLISTXATTR
ssize_t llistxattr(const char *path, char *list, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_llistxattr(path, list, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "llistxattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
return common_listxattr(&st, list, size);
}
#endif /* HAVE_LLISTXATTR */
#ifdef HAVE_FLISTXATTR
ssize_t flistxattr(int fd, char *list, size_t size)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_flistxattr(fd, list, size);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "flistxattr fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return r;
return common_listxattr(&st, list, size);
}
#endif /* HAVE_FLISTXATTR */
#ifdef HAVE_REMOVEXATTR
ssize_t removexattr(const char *path, const char *name)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_removexattr(path, name);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "removexattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_STAT(path, &st);
if(r)
return r;
return common_removexattr(&st, name);
}
#endif /* HAVE_REMOVEXATTR */
#ifdef HAVE_LREMOVEXATTR
ssize_t lremovexattr(const char *path, const char *name)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_lremovexattr(path, name);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lremovexattr path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_LSTAT(path, &st);
if(r)
return r;
return common_removexattr(&st, name);
}
#endif /* HAVE_LREMOVEXATTR */
#ifdef HAVE_FREMOVEXATTR
ssize_t fremovexattr(int fd, const char *name)
{
INT_STRUCT_STAT st;
int r;
if (fakeroot_disabled)
return next_fremovexattr(fd, name);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fremovexattr fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTAT(fd, &st);
if(r)
return r;
return common_removexattr(&st, name);
}
#endif /* HAVE_FREMOVEXATTR */
int setpriority(int which, id_t who, int prio){
if (fakeroot_disabled)
return next_setpriority(which, who, prio);
next_setpriority(which, who, prio);
return 0;
}
#undef fakeroot_disabled
int fakeroot_disable(int new)
{
int old = fakeroot_disabled;
fakeroot_disabled = new ? 1 : 0;
return old;
}
int fakeroot_isdisabled(void)
{
return fakeroot_disabled;
}
#ifdef HAVE_ACL_T
/* linux: */
#ifdef HAVE_ACL_GET_FD
acl_t acl_get_fd(int fd) {
errno = ENOTSUP;
return (acl_t)NULL;
}
acl_t acl_get_file(const char *path_p, acl_type_t type) {
errno = ENOTSUP;
return (acl_t)NULL;
}
int acl_set_fd(int fd, acl_t acl) {
errno = ENOTSUP;
return -1;
}
int acl_set_file(const char *path_p, acl_type_t type, acl_t acl) {
errno = ENOTSUP;
return -1;
}
#endif /* HAVE_ACL_GET_FD */
/* illumos: */
#ifdef HAVE_ACL_TRIVIAL
int acl_get(const char *path, int flags, acl_t **aclp)
{
errno = ENOSYS;
return -1;
}
int facl_get(int fd, int flags, acl_t **aclp)
{
errno = ENOSYS;
return -1;
}
int acl_set(const char *path, acl_t *aclp)
{
errno = ENOSYS;
return -1;
}
int facl_set(int fd, acl_t *aclp)
{
errno = ENOSYS;
return -1;
}
int acl_trivial(const char *path)
{
return 0;
}
int acl(const char *path, int cmd, int cnt, void *buf)
{
errno = ENOSYS;
return -1;
}
int facl(int fd, int cmd, int cnt, void *buf)
{
errno = ENOSYS;
return -1;
}
#endif /* HAVE_ACL_TRIVIAL */
#endif /* HAVE_ACL_T */
#ifdef HAVE_FTS_READ
FTSENT *fts_read(FTS *ftsp) {
FTSENT *r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fts_read\n");
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=next_fts_read(ftsp);
if (r && ((ftsp->fts_options & FTS_NOSTAT)
|| r->fts_info == FTS_NS || r->fts_info == FTS_NSOK))
r->fts_statp = NULL; /* Otherwise fts_statp may be a random pointer */
if(r && r->fts_statp) { /* Should we bother checking fts_info here? */
SEND_GET_STAT(r->fts_statp, _STAT_VER);
}
return r;
}
#endif /* HAVE_FTS_READ */
#ifdef HAVE_FTS_CHILDREN
FTSENT *fts_children(FTS *ftsp, int options) {
FTSENT *first, *r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fts_children\n");
}
#endif /* LIBFAKEROOT_DEBUGGING */
first=next_fts_children(ftsp, options);
for(r = first; r; r = r->fts_link) {
if(r && r->fts_statp) { /* Should we bother checking fts_info here? */
SEND_GET_STAT(r->fts_statp, _STAT_VER);
}
}
return first;
}
#endif /* HAVE_FTS_CHILDREN */
#ifdef __APPLE__
#ifdef __LP64__
int
getattrlist(const char *path, void *attrList, void *attrBuf,
size_t attrBufSize, unsigned int options)
#else
int
getattrlist(const char *path, void *attrList, void *attrBuf,
size_t attrBufSize, unsigned long options)
#endif
{
int r;
struct stat st;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "getattrlist path %s\n", path);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=next_getattrlist(path, attrList, attrBuf, attrBufSize, options);
if (r) {
return r;
}
if (options & FSOPT_NOFOLLOW) {
r=WRAP_LSTAT(path, &st);
} else {
r=WRAP_STAT(path, &st);
}
if (r) {
return r;
}
patchattr(attrList, attrBuf, st.st_uid, st.st_gid, st.st_mode);
return 0;
}
#if HAVE_FGETATTRLIST
#ifdef __LP64__
int
fgetattrlist(int fd, void *attrList, void *attrBuf,
size_t attrBufSize, unsigned int options)
#else
int
fgetattrlist(int fd, void *attrList, void *attrBuf,
size_t attrBufSize, unsigned long options)
#endif
{
int r;
struct stat st;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fgetattrlist fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=next_fgetattrlist(fd, attrList, attrBuf, attrBufSize, options);
if (r) {
return r;
}
r=WRAP_FSTAT(fd, &st);
if (r) {
return r;
}
patchattr(attrList, attrBuf, st.st_uid, st.st_gid, st.st_mode);
return 0;
}
#endif /* if HAVE_FGETATTRLIST */
/*
* Prevent loss of DYLD_INSERT_LIBRARIES, FAKEROOTKEY and FAKED_MODE
* environment variables during packaging (packagemaker otherwise clears them).
*/
static char *dylib_insert;
static char *fakeroot_key;
static char *faked_mode;
static int spawnexec_in_progress;
static pid_t spawnexec_pid;
static int is_spawnexec_active()
{
if (getpid() != spawnexec_pid) {
spawnexec_in_progress = 0;
}
return spawnexec_in_progress;
}
static void enter_spawnexec()
{
(void)is_spawnexec_active();
if (++spawnexec_in_progress == 1)
spawnexec_pid = getpid();
}
static void exit_spawnexec()
{
(void)is_spawnexec_active();
if (spawnexec_in_progress)
--spawnexec_in_progress;
}
__attribute__((__constructor__,__used__)) static void retrieve_dylib();
static void retrieve_dylib()
{
const char *dil = getenv("DYLD_INSERT_LIBRARIES");
const char *frk = fakeroot_key = getenv("FAKEROOTKEY");
const char *fdm = faked_mode = getenv("FAKED_MODE");
if (frk) {
char *savekey = (char *)malloc(12 + strlen(frk) + 1);
if (savekey) {
sprintf(savekey, "FAKEROOTKEY=%s", frk);
fakeroot_key = savekey;
}
}
if (fdm) {
char *savemode = (char *)malloc(11 + strlen(fdm) + 1);
if (savemode) {
sprintf(savemode, "FAKED_MODE=%s", fdm);
faked_mode = savemode;
}
}
if (dil) {
char *dupe = strdup(dil);
if (dupe) {
char *ptr = dupe;
do {
char *next = strchr(ptr, ':');
if (next)
*next++ = '\0';
if (strstr(ptr, "libfakeroot") && strstr(ptr, ".dylib")) {
dylib_insert = ptr;
return;
}
ptr = next;
} while (ptr);
free(dupe);
}
}
}
static char **get_exec_envp(char *const envp[], char **insenvp)
{
int i, envcount = 0;
char **altenv = NULL;
*insenvp = NULL;
if (!envp || !dylib_insert || !fakeroot_key ||
getenv("FAKEROOT_TEST_PRELOAD"))
return (char **)envp;
while (envp[envcount]) {
++envcount;
}
altenv = (char **)malloc((envcount + 4) * sizeof(char *));
if (!altenv)
return (char **)envp;
memcpy(altenv, envp, (envcount + 1) * sizeof(char *));
for (i=0; i<envcount; ++i) {
if (strncmp(altenv[i], "FAKEROOTKEY=", 12) == 0)
break;
}
if (i >= envcount) {
altenv[envcount] = fakeroot_key;
altenv[++envcount] = NULL;
}
for (i=0; i<envcount; ++i) {
if (strncmp(altenv[i], "FAKED_MODE=", 11) == 0)
break;
}
if (i >= envcount && faked_mode) {
altenv[envcount] = faked_mode;
altenv[++envcount] = NULL;
}
for (i=0; i<envcount; ++i) {
if (strncmp(altenv[i], "DYLD_INSERT_LIBRARIES=", 22) == 0) {
if (strstr(altenv[i], dylib_insert))
return altenv;
else {
*insenvp = (char *)malloc(strlen(altenv[i]) + strlen(dylib_insert) + 2);
if (!*insenvp) {
free(altenv);
return (char **)envp;
}
sprintf(*insenvp, "DYLD_INSERT_LIBRARIES=%s:%s", dylib_insert,
altenv[i]+22);
altenv[i] = *insenvp;
return altenv;
}
}
}
*insenvp = (char *)malloc(22 + strlen(dylib_insert) + 1);
if (!*insenvp) {
free(altenv);
return (char **)envp;
}
sprintf(*insenvp, "DYLD_INSERT_LIBRARIES=%s", dylib_insert);
altenv[envcount] = *insenvp;
altenv[envcount+1] = NULL;
return altenv;
}
int execve(const char *path, char *const argv[], char *const envp[])
{
int result;
char **altenv;
char *insenv;
if (!path || !argv || !envp || is_spawnexec_active()) {
enter_spawnexec();
result = next_execve(path, argv, envp);
exit_spawnexec();
return result;
}
altenv = get_exec_envp(envp, &insenv);
enter_spawnexec();
result = next_execve(path, argv, altenv);
exit_spawnexec();
if (altenv != envp)
free(altenv);
if (insenv)
free(insenv);
return result;
}
/* funnel execl, execle, execlp, execv, execvp and execvP into execve */
int execv(const char *path, char *const argv[])
{
return execve(path, argv, *_NSGetEnviron());
}
static char *find_exec_path(const char *file, const char *search_path)
{
char *path = (char *)file;
if (file && *file && !strchr(file, '/') && search_path && *search_path) {
size_t splen = strlen(search_path);
const char *search_end = search_path + splen;
const char *next;
char *buff = malloc(strlen(file) + splen + 2);
if (!buff)
return NULL;
for (; search_path < search_end; search_path = next) {
struct stat info;
size_t plen;
if ((next = strchr(search_path, ':')))
plen = next++ - search_path;
else
plen = (next = search_end) - search_path;
memcpy(buff, search_path, plen);
sprintf(buff + plen, "%s%s", plen ? "/" : "", file);
if (stat(buff, &info) || !S_ISREG(info.st_mode) || access(buff, X_OK))
continue;
path = buff;
break;
}
if (path == file) {
free(buff);
errno = ENOENT;
return NULL;
}
}
return path;
}
int execvP(const char *file, const char *search_path, char *const argv[])
{
int result;
char *path = find_exec_path(file, search_path);
if (!path)
return -1;
result = execve(path, argv, *_NSGetEnviron());
if (path != file)
free(path);
return result;
}
int execvp(const char *file, char *const argv[])
{
const char *path = getenv("PATH");
return execvP(file, path ? path : _PATH_DEFPATH, argv);
}
static char **collect_args(const char *arg0, va_list args, char ***envp)
{
char **arglist;
size_t count = 0;
char **outp;
va_list args_copy;
va_copy(args_copy, args);
for (;;) {
char *ap = va_arg(args_copy, char *);
if (!ap)
break;
++count;
}
va_end(args_copy);
arglist = (char **)malloc((count + 2) * sizeof(char *));
if (!arglist)
return NULL;
outp = arglist;
*outp++ = (char *)arg0;
for (;;) {
char *ap = va_arg(args, char *);
*outp++ = ap;
if (!ap)
break;
}
if (envp)
*envp = va_arg(args, char **);
return arglist;
}
int execl(const char *path, const char *arg0, ...)
{
int result;
char **arglist;
va_list args;
va_start(args, arg0);
arglist = collect_args(arg0, args, NULL);
va_end(args);
if (!arglist)
return -1;
result = execve(path, arglist, *_NSGetEnviron());
free(arglist);
return result;
}
int execle(const char *path, const char *arg0, ...)
{
int result;
char **arglist;
char **envp;
va_list args;
va_start(args, arg0);
arglist = collect_args(arg0, args, &envp);
va_end(args);
if (!arglist)
return -1;
result = execve(path, arglist, envp);
free(arglist);
return result;
}
int execlp(const char *file, const char *arg0, ...)
{
int result;
char **arglist;
va_list args;
va_start(args, arg0);
arglist = collect_args(arg0, args, NULL);
va_end(args);
if (!arglist)
return -1;
result = execvp(file, arglist);
free(arglist);
return result;
}
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
/* handle posix_spawn and posix_spawnp separately */
int 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])
{
int result;
char **altenv;
char *insenv;
if (!path || !argv || !envp || is_spawnexec_active()) {
enter_spawnexec();
result = next_posix_spawn(pid, path, file_actions, attrp, argv, envp);
exit_spawnexec();
return result;
}
altenv = get_exec_envp(envp, &insenv);
enter_spawnexec();
result = next_posix_spawn(pid, path, file_actions, attrp, argv, altenv);
exit_spawnexec();
if (altenv != envp)
free(altenv);
if (insenv)
free(insenv);
return result;
}
int 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])
{
int result;
const char *search_path = getenv("PATH");
char *path = find_exec_path(file, search_path ? search_path : _PATH_DEFPATH);
if (!path)
return errno;
result = posix_spawn(pid, path, file_actions, attrp, argv, envp);
if (path != file)
free(path);
return result;
}
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 */
#endif /* ifdef __APPLE__ */
#ifdef HAVE_STATX
int statx (int dirfd, const char *path, int flags, unsigned int mask, struct statx *buf)
{
int r;
INT_STRUCT_STAT st;
if (fakeroot_disabled)
return next_statx(dirfd, path, flags, mask, buf);
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "statx fd %d\n", dirfd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=INT_NEXT_FSTATAT(dirfd, path, &st, flags);
if(r)
return -1;
INT_SEND_GET_STAT(&st,ver);
r=next_statx(dirfd, path, flags, mask, buf);
if(r)
return -1;
buf->stx_uid = st.st_uid;
buf->stx_gid = st.st_gid;
buf->stx_mode = st.st_mode;
buf->stx_rdev_major = major(st.st_rdev);
buf->stx_rdev_minor = minor(st.st_rdev);
return 0;
}
#endif /* HAVE_STATX */
#ifdef __sun
/*
* Disable the runtime selection of binaries on Solaris: libfakeroot is (yet?)
* unable to cope with several bitnesses of binaries being run.
*/
int sysinfo(int command, char *buf, long count)
{
if (command == SI_ISALIST)
{
/* do the evil trick */
#ifdef sparc
#ifdef __arch64__
strncpy(buf, "sparcv9 sparc", count - 1);
return sizeof("sparcv9 sparc");
#else
strncpy(buf, "sparcv7 sparc", count - 1);
return sizeof("sparcv7 sparc");
#endif
#else
strncpy(buf, "i386 i86", count - 1);
return sizeof("i386 i86");
#endif
}
else
{
return next_sysinfo(command, buf, count);
}
}
#endif
#ifdef TIME64_HACK
int WRAP_LSTAT64_TIME64 LSTAT64_TIME64_ARG(int ver,
const char *file_name,
struct stat64 *statbuf){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "lstat[time64] file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_LSTAT64_TIME64(ver, file_name, statbuf);
if(r)
return -1;
SEND_GET_STAT64(statbuf, ver);
return 0;
}
int WRAP_STAT64_TIME64 STAT64_TIME64_ARG(int ver,
const char *file_name,
struct stat64 *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "stat64[time64] file_name %s\n", file_name);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_STAT64_TIME64(ver, file_name, st);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
int WRAP_FSTAT64_TIME64 FSTAT64_TIME64_ARG(int ver,
int fd,
struct stat64 *st){
int r;
#ifdef LIBFAKEROOT_DEBUGGING
if (fakeroot_debug) {
fprintf(stderr, "fstat64[time64] fd %d\n", fd);
}
#endif /* LIBFAKEROOT_DEBUGGING */
r=NEXT_FSTAT64_TIME64(ver, fd, st);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
int WRAP_FSTATAT64_TIME64 FSTATAT64_TIME64_ARG(int ver,
int dir_fd,
const char *path,
struct stat64 *st,
int flags){
int r;
r=NEXT_FSTATAT64_TIME64(ver, dir_fd, path, st, flags);
if(r)
return -1;
SEND_GET_STAT64(st,ver);
return 0;
}
#endif /* TIME64_HACK */
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xiewei/fakeroot.git
git@gitee.com:xiewei/fakeroot.git
xiewei
fakeroot
fakeroot
openkylin/yangtze

搜索帮助

344bd9b3 5694891 D2dac590 5694891