Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=402688 diff -Nru fakeroot-1.6.5.orig/config.h.in fakeroot-1.6.5/config.h.in --- fakeroot-1.6.5.orig/config.h.in 2007-03-23 15:16:09.357845554 +0100 +++ fakeroot-1.6.5/config.h.in 2007-03-23 15:31:20.711930341 +0100 @@ -19,12 +19,21 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H +/* Define to 1 if you have the `fchmodat' function. */ +#undef HAVE_FCHMODAT + +/* Define to 1 if you have the `fchownat' function. */ +#undef HAVE_FCHOWNAT + /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_FEATURES_H +/* Define to 1 if you have the `fstatat' function. */ +#undef HAVE_FSTATAT + /* Define to 1 if you have the `getresgid' function. */ #undef HAVE_GETRESGID @@ -49,12 +58,24 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `mkdirat' function. */ +#undef HAVE_MKDIRAT + +/* Define to 1 if you have the `mknodat' function. */ +#undef HAVE_MKNODAT + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H +/* Define to 1 if you have the `openat' function. */ +#undef HAVE_OPENAT + /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H +/* Define to 1 if you have the `renameat' function. */ +#undef HAVE_RENAMEAT + /* have the semun union */ #undef HAVE_SEMUN_DEF @@ -114,6 +135,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `unlinkat' function. */ +#undef HAVE_UNLINKAT + /* second argument of initgroups */ #undef INITGROUPS_SECOND_ARG @@ -185,6 +209,11 @@ #define TMP_FSTAT __astat #define NEXT_FSTAT_NOARG next___astat +#define WRAP_FSTATAT_QUOTE __astatat +#define WRAP_FSTATAT __astatat +#define TMP_FSTATAT __astatat +#define NEXT_FSTATAT_NOARG next___astatat + #define WRAP_STAT64_QUOTE __astat64 #define WRAP_STAT64 __astat64 #define TMP_STAT64 __astat64 @@ -200,11 +229,24 @@ #define TMP_FSTAT64 __astat64 #define NEXT_FSTAT64_NOARG next___astat64 +#define WRAP_FSTATAT64_QUOTE __astatat64 +#define WRAP_FSTATAT64 __astatat64 +#define TMP_FSTATAT64 __astatat64 +#define NEXT_FSTATAT64_NOARG next___astatat64 + #define WRAP_MKNOD_QUOTE __amknod #define WRAP_MKNOD __amknod #define TMP_MKNOD __amknod #define NEXT_MKNOD_NOARG next___amknod +#define WRAP_MKNODAT_QUOTE __amknodat +#define WRAP_MKNODAT __amknodat +#define TMP_MKNODAT __amknodat +#define NEXT_MKNODAT_NOARG next___amknodat + + +/* fifth argument of __xmknodat */ +#undef XMKNODAT_FIFTH_ARG /* fourth argument of __xmknod */ #undef XMKNOD_FRTH_ARG diff -Nru fakeroot-1.6.5.orig/configure.ac fakeroot-1.6.5/configure.ac --- fakeroot-1.6.5.orig/configure.ac 2007-03-23 15:16:09.357845554 +0100 +++ fakeroot-1.6.5/configure.ac 2007-03-23 15:31:20.711930341 +0100 @@ -144,6 +144,33 @@ ]) +dnl Possibly this should only be done if we actually have mknodat +dnl on the system. Nothing breaks by running the test itself though. +AH_TEMPLATE([XMKNODAT_FIFTH_ARG], [fifth argument of __xmknodat]) +dnl glibc uses `* dev' as fifth argument of __xmknodat. +dnl Although the test below should probably be more general +dnl (not just __xmknodat, but also mknod etc), at the moment this +dnl seems enough, as probably glibc is the only that does this. +AC_MSG_CHECKING([for type of arg of __xmknodat]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + #include + #include + ]], [[ + int __xmknodat ( int ver, + inf dirfd, + const char *pathname , + mode_t mode , dev_t dev); + ]])],[ + AC_DEFINE(XMKNODAT_FIFTH_ARG,) + AC_MSG_RESULT([no extra *]) + ],[ + AC_DEFINE(XMKNODAT_FIFTH_ARG,[*]) + AC_MSG_RESULT([needs *]) + + ]) + AH_TEMPLATE([INITGROUPS_SECOND_ARG], [second argument of initgroups]) dnl FreeBSD 4.7 uses int instead of gid_t AC_MSG_CHECKING([for type of arg of initgroups]) @@ -234,6 +261,8 @@ ]) done +AC_CHECK_FUNCS(fchmodat fchownat fstatat mkdirat mknodat openat renameat unlinkat) + dnl find out how stat() etc are called. On linux systems, we really dnl need to wrap (IIRC): dnl Linux : __xstat @@ -243,7 +272,7 @@ :>fakerootconfig.h.tmp -for SEARCH in %stat f%stat l%stat %stat64 f%stat64 l%stat64 %mknod; do +for SEARCH in %stat f%stat l%stat f%statat %stat64 f%stat64 l%stat64 f%statat64 %mknod %mknodat; do FUNC=`echo $SEARCH|sed -e 's/.*%//'` PRE=`echo $SEARCH|sed -e 's/%.*//'` FOUND= @@ -271,6 +300,12 @@ fi if test "${FUNC}" = "mknod"; then DEF_END=",d" + elif test "${FUNC}" = "mknodat"; then + DEF_END=",d,e" + elif test "${FUNC}" = "statat"; then + DEF_END=",d,e" + elif test "${FUNC}" = "statat64"; then + DEF_END=",d,e" else DEF_END="" fi @@ -389,6 +424,11 @@ #define TMP_FSTAT __astat #define NEXT_FSTAT_NOARG next___astat +#define WRAP_FSTATAT_QUOTE __astatat +#define WRAP_FSTATAT __astatat +#define TMP_FSTATAT __astatat +#define NEXT_FSTATAT_NOARG next___astatat + #define WRAP_STAT64_QUOTE __astat64 #define WRAP_STAT64 __astat64 #define TMP_STAT64 __astat64 @@ -404,10 +444,20 @@ #define TMP_FSTAT64 __astat64 #define NEXT_FSTAT64_NOARG next___astat64 +#define WRAP_FSTATAT64_QUOTE __astatat64 +#define WRAP_FSTATAT64 __astatat64 +#define TMP_FSTATAT64 __astatat64 +#define NEXT_FSTATAT64_NOARG next___astatat64 + #define WRAP_MKNOD_QUOTE __amknod #define WRAP_MKNOD __amknod #define TMP_MKNOD __amknod #define NEXT_MKNOD_NOARG next___amknod + +#define WRAP_MKNODAT_QUOTE __amknodat +#define WRAP_MKNODAT __amknodat +#define TMP_MKNODAT __amknodat +#define NEXT_MKNODAT_NOARG next___amknodat ]) dnl kludge end diff -Nru fakeroot-1.6.5.orig/libfakeroot.c fakeroot-1.6.5/libfakeroot.c --- fakeroot-1.6.5.orig/libfakeroot.c 2007-03-23 15:16:09.357845554 +0100 +++ fakeroot-1.6.5/libfakeroot.c 2007-03-23 15:31:20.721930057 +0100 @@ -548,6 +548,27 @@ 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; +#ifndef STUPID_ALPHA_HACK + send_get_stat(st); +#else + send_get_stat(st,ver); +#endif + return 0; +} +#endif /* HAVE_FSTATAT */ #ifdef STAT64_SUPPORT @@ -605,7 +626,29 @@ 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; +#ifndef STUPID_ALPHA_HACK + send_get_stat64(st); +#else + send_get_stat64(st,ver); #endif + return 0; +} +#endif /* HAVE_FSTATAT */ + +#endif /* STAT64_SUPPORT */ @@ -724,6 +767,54 @@ 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. */ +#ifdef STAT64_SUPPORT + struct stat64 st; + r=NEXT_FSTATAT64(_STAT_VER, dir_fd, path, &st, (flags & AT_SYMLINK_NOFOLLOW)); +#else + struct stat st; + r=NEXT_FSTATAT(_STAT_VER, dir_fd, path, &st, (flags & AT_SYMLINK_NOFOLLOW)); +#endif + + if(r) + return(r); + + st.st_uid=owner; + st.st_gid=group; +#ifdef STAT64_SUPPORT +#ifndef STUPID_ALPHA_HACK + send_stat64(&st,chown_func); +#else + send_stat64(&st,chown_func, _STAT_VER); +#endif +#else +#ifndef STUPID_ALPHA_HACK + send_stat(&st,chown_func); +#else + send_stat(&st,chown_func, _STAT_VER); +#endif +#endif /* STAT64_SUPPORT */ + + 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; @@ -786,6 +877,40 @@ 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; + struct stat st; + + /* If AT_SYMLINK_NOFOLLOW is set in the fchownat call it should + be when we stat it. */ + r=NEXT_FSTATAT(_STAT_VER, dir_fd, path, &st, flags & AT_SYMLINK_NOFOLLOW); + + if(r) + return(r); + + st.st_mode=(mode&ALLPERMS)|(st.st_mode&~ALLPERMS); +#ifndef STUPID_ALPHA_HACK + send_stat(&st,chmod_func); +#else + send_stat(&st,chmod_func, _STAT_VER); +#endif + + /* 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; + 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) @@ -825,6 +950,54 @@ 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) +{ + 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=NEXT_FSTATAT(_STAT_VER, dir_fd, pathname, &st, 0); + + if(r) + return -1; + + st.st_mode= mode & ~old_mask; + st.st_rdev= XMKNODAT_FIFTH_ARG dev; + +#ifndef STUPID_ALPHA_HACK + send_stat(&st,mknod_func); +#else + send_stat(&st,mknod_func, _STAT_VER); +#endif + + return 0; +} +#endif /* HAVE_MKNODAT */ +#endif /* HAVE_FSTATAT */ + + int mkdir(const char *path, mode_t mode){ INT_STRUCT_STAT st; int r; @@ -857,6 +1030,42 @@ return 0; } +#ifdef HAVE_FSTATAT +#ifdef HAVE_MKDIRAT +int mkdirat(int dir_fd, const char *path, mode_t mode){ + 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=NEXT_FSTATAT(_STAT_VER, dir_fd, path, &st, 0); + + if(r) + return -1; + + st.st_mode=(mode&~old_mask&ALLPERMS)|(st.st_mode&~ALLPERMS)|S_IFDIR; + +#ifndef STUPID_ALPHA_HACK + send_stat(&st, chmod_func); +#else + send_stat(&st, chmod_func, _STAT_VER); +#endif + + return 0; +} +#endif /* HAVE_MKDIRAT */ +#endif /* HAVE_FSTATAT */ + /* The remove funtions: unlink, rmdir, rename. These functions can all remove inodes from the system. @@ -895,6 +1104,40 @@ return 0; } +#ifdef HAVE_FSTATAT +#ifdef HAVE_UNLINKAT +int unlinkat(int dir_fd, const char *pathname, int flags){ + int r; +#ifdef STAT64_SUPPORT + struct stat64 st; + r=NEXT_FSTATAT64(_STAT_VER, dir_fd, pathname, &st, (flags&~AT_REMOVEDIR) | AT_SYMLINK_NOFOLLOW); +#else + struct stat st; + r=NEXT_FSTATAT(_STAT_VER, dir_fd, pathname, &st, (flags&~AT_REMOVEDIR) | AT_SYMLINK_NOFOLLOW); +#endif + if(r) + return -1; + + r=next_unlinkat(dir_fd, pathname, flags); + + if(r) + return -1; + +#ifdef STAT64_SUPPORT +#ifndef STUPID_ALPHA_HACK + send_stat64(&st, unlink_func); +#else + send_stat64(&st, unlink_func, _STAT_VER); +#endif +#else + send_stat(&st, unlink_func); +#endif + + return 0; +} +#endif /* HAVE_UNLINKAT */ +#endif /* HAVE_FSTATAT */ + /* See the `remove funtions:' comments above for more info on these remove function wrappers. @@ -976,6 +1219,37 @@ 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; + 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=NEXT_FSTATAT(_STAT_VER, newdir_fd, newpath, &st, AT_SYMLINK_NOFOLLOW); + + s=next_renameat(olddir_fd, oldpath, newdir_fd, newpath); + if(s) + return -1; + if(!r) +#ifndef STUPID_ALPHA_HACK + send_stat(&st,unlink_func); +#else + send_stat(&st,unlink_func, _STAT_VER); +#endif + + return 0; +} +#endif /* HAVE_RENAMEAT */ +#endif /* HAVE_FSTATAT */ + + #ifdef FAKEROOT_FAKENET pid_t fork(void) { diff -Nru fakeroot-1.6.5.orig/wrapfunc.inp fakeroot-1.6.5/wrapfunc.inp --- fakeroot-1.6.5.orig/wrapfunc.inp 2007-03-23 15:16:09.357845554 +0100 +++ fakeroot-1.6.5/wrapfunc.inp 2007-03-23 15:31:20.721930057 +0100 @@ -22,15 +22,27 @@ WRAP_LSTAT;int;LSTAT_ARG(int ver, const char *file_name, struct stat *buf);LSTAT_ARG(ver, file_name, buf);LSTAT WRAP_STAT;int;STAT_ARG(int ver, const char *file_name, struct stat *buf);STAT_ARG(ver, file_name, buf);STAT WRAP_FSTAT;int;FSTAT_ARG(int ver, int fd, struct stat *buf);FSTAT_ARG(ver, fd, buf);FSTAT +#ifdef HAVE_FSTATAT +WRAP_FSTATAT;int;FSTATAT_ARG(int ver, int dir_fd, const char *path, struct stat *buf, int flags);FSTATAT_ARG(ver, dir_fd, path, buf, flags);FSTATAT +#endif /* HAVE_FSTATAT */ #ifdef STAT64_SUPPORT WRAP_LSTAT64;int;LSTAT64_ARG(int ver, const char *file_name, struct stat64 *buf);LSTAT64_ARG(ver, file_name, buf);LSTAT64 WRAP_STAT64;int;STAT64_ARG(int ver, const char *file_name, struct stat64 *buf);STAT64_ARG(ver, file_name, buf);STAT64 WRAP_FSTAT64;int;FSTAT64_ARG(int ver, int fd, struct stat64 *buf);FSTAT64_ARG(ver, fd, buf);FSTAT64 -#endif +#ifdef HAVE_FSTATAT +WRAP_FSTATAT64;int;FSTATAT64_ARG(int ver, int dir_fd, const char *path, struct stat64 *buf, int flags);FSTATAT64_ARG(ver, dir_fd, path, buf, flags);FSTATAT64 +#endif /* HAVE_FSTATAT */ +#endif /* STAT64_SUPPORT */ WRAP_MKNOD;int;MKNOD_ARG(int ver, const char *pathname, mode_t mode, dev_t XMKNOD_FRTH_ARG dev);MKNOD_ARG(ver, pathname, mode, dev);MKNOD +#ifdef HAVE_FSTATAT +#ifdef HAVE_MKNODAT +WRAP_MKNODAT;int;MKNODAT_ARG(int ver, int dir_fd, const char *pathname, mode_t mode, dev_t dev);MKNODAT_ARG(ver, dir_fd, pathname, mode, dev);MKNODAT +#endif /* HAVE_MKNODAT */ +#endif /* HAVE_FSTATAT */ + /*opendir;DIR *;(const char *name);(name)*/ /*closedir;int;(DIR *dir);(dir)*/ /*readdir;struct dirent *;(DIR *dir);(dir)*/ @@ -89,3 +101,26 @@ #endif /* HAVE_SETFSGID */ initgroups;int;(const char *user, INITGROUPS_SECOND_ARG group);(user, group) setgroups;int;(SETGROUPS_SIZE_TYPE size, const gid_t *list);(size, list) + +#ifdef HAVE_FSTATAT +#ifdef HAVE_FCHMODAT +fchmodat;int;(int dir_fd, const char *path, mode_t mode, int flags);(dir_fd, path, mode, flags) +#endif /* HAVE_FCHMODAT */ +#ifdef HAVE_FCHOWNAT +fchownat;int;(int dir_fd, const char *path, uid_t owner, gid_t group, int flags);(dir_fd, path, owner, group, flags) +#endif /* HAVE_FCHOWNAT */ +#ifdef HAVE_MKDIRAT +mkdirat;int;(int dir_fd, const char *pathname, mode_t mode);(dir_fd, pathname, mode) +#endif /* HAVE_MKDIRAT */ +#ifdef HAVE_OPENAT +openat;int;(int dir_fd, const char *pathname, int flags);(dir_fd, pathname, flags) +#endif /* HAVE_OPENAT */ +#ifdef HAVE_RENAMEAT +renameat;int;(int olddir_fd, const char *oldpath, int newdir_fd, const char *newpath);(olddir_fd, oldpath, newdir_fd, newpath) +#endif /* HAVE_RENAMEAT */ +#ifdef HAVE_UNLINKAT +unlinkat;int;(int dir_fd, const char *pathname, int flags);(dir_fd, pathname, flags) +#endif /* HAVE_UNLINKAT */ +#endif /* HAVE_FSTATAT */ + +