"Fossies" - the Fresh Open Source Software Archive

Member "checkinstall-1.6.2/installwatch/installwatch.c" (16 Nov 2008, 104473 Bytes) of package /linux/privat/old/checkinstall-1.6.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "installwatch.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version
    7  * 2 of the License, or (at your option) any later version.
    8  * 
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17  *
   18  * $Id: installwatch.c,v 0.7.0.11 2008/11/09 07:47:00 izto Exp $
   19  * 
   20  * april-15-2001 - Modifications by Felipe Eduardo Sanchez Diaz Duran
   21  *                                  <izto@asic-linux.com.mx>
   22  * Added backup() and make_path() functions.
   23  *
   24  * november-25-2002 - Modifications by Olivier Fleurigeon
   25  *                                  <olivier.fleurigeon@cegedim.fr>
   26  *
   27  * march-31-2007 - Modifications by Frederick Emmott
   28  *                                  <mail@fredemmott.co.uk>
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/types.h>
   33 #include <sys/stat.h>
   34 #include <fcntl.h>
   35 #include <stdarg.h>
   36 #include <stdio.h>
   37 #include <stdlib.h>
   38 #include <dlfcn.h>
   39 #include <syslog.h>
   40 #include <errno.h>
   41 #include <unistd.h>
   42 #include <libgen.h>
   43 #include <inttypes.h>
   44 #undef basename
   45 #include <string.h>
   46 #include <time.h>
   47 #include <utime.h>
   48 #include <dlfcn.h>
   49 #include <dirent.h>
   50 
   51 /* There's no d_off on GNU/kFreeBSD */
   52 #if defined(__FreeBSD_kernel__)
   53 #define D_OFF(X) (-1)
   54 #else
   55 #define D_OFF(X) (X)
   56 #endif
   57     
   58 #include "localdecls.h"
   59 
   60 #define DEBUG 1  
   61 
   62 #define LOGLEVEL (LOG_USER | LOG_INFO | LOG_PID)
   63 #define BUFSIZE 1024
   64 
   65 #define error(X) (X < 0 ? strerror(errno) : "success")
   66 
   67 int __installwatch_refcount = 0;
   68 int __installwatch_timecount = 0;
   69 
   70 #define REFCOUNT __installwatch_refcount++
   71 #define TIMECOUNT __installwatch_timecount++
   72 
   73 static time_t (*true_time) (time_t *);
   74 static int (*true_chdir)(const char *);
   75 static int (*true_chmod)(const char *, mode_t);
   76 static int (*true_chown)(const char *, uid_t, gid_t);
   77 static int (*true_chroot)(const char *);
   78 static int (*true_creat)(const char *, mode_t);
   79 static int (*true_fchmod)(int, mode_t);
   80 static int (*true_fchown)(int, uid_t, gid_t);
   81 static FILE *(*true_fopen)(const char *,const char*);
   82 static int (*true_ftruncate)(int, TRUNCATE_T);
   83 static char *(*true_getcwd)(char*,size_t);
   84 static int (*true_lchown)(const char *, uid_t, gid_t);
   85 static int (*true_link)(const char *, const char *);
   86 static int (*true_mkdir)(const char *, mode_t);
   87 static int (*true_xmknod)(int ver,const char *, mode_t, dev_t *);
   88 static int (*true_open)(const char *, int, ...);
   89 static DIR *(*true_opendir)(const char *);
   90 static struct dirent *(*true_readdir)(DIR *dir);
   91 #if (GLIBC_MINOR <= 4)
   92 static int (*true_readlink)(const char*,char *,size_t);
   93 #else
   94 static ssize_t (*true_readlink)(const char*,char *,size_t);
   95 #endif
   96 static char *(*true_realpath)(const char *,char *);
   97 static int (*true_rename)(const char *, const char *);
   98 static int (*true_rmdir)(const char *);
   99 static int (*true_xstat)(int,const char *,struct stat *);
  100 static int (*true_lxstat)(int,const char *,struct stat *);
  101 static int (*true_scandir)( const char *,struct dirent ***,
  102                 int (*)(const struct dirent *),
  103                 int (*)(const void *,const void *));
  104 static int (*true_symlink)(const char *, const char *);
  105 static int (*true_truncate)(const char *, TRUNCATE_T);
  106 static int (*true_unlink)(const char *);
  107 static int (*true_utime)(const char *,const struct utimbuf *);
  108 static int (*true_utimes)(const char *,const struct timeval *);
  109 static int (*true_access)(const char *, int);
  110 static int (*true_setxattr)(const char *,const char *,const void *,
  111                             size_t, int);
  112 static int (*true_removexattr)(const char *,const char *);
  113 
  114 #if(GLIBC_MINOR >= 1)
  115 
  116 static int (*true_creat64)(const char *, __mode_t);
  117 static FILE *(*true_fopen64)(const char *,const char *);
  118 static int (*true_ftruncate64)(int, __off64_t);
  119 static int (*true_open64)(const char *, int, ...);
  120 static struct dirent64 *(*true_readdir64)(DIR *dir);
  121 static int (*true_scandir64)(   const char *,struct dirent64 ***,
  122                 int (*)(const struct dirent64 *),
  123                 int (*)(const void *,const void *));
  124 static int (*true_xstat64)(int,const char *, struct stat64 *);
  125 static int (*true_lxstat64)(int,const char *, struct stat64 *);
  126 static int (*true_truncate64)(const char *, __off64_t);
  127 
  128 #endif
  129 
  130 #if (GLIBC_MINOR >= 4)
  131 static int (*true_openat)(int, const char *, int, ...);
  132 static int (*true_fchmodat)(int, const char *, mode_t, int);
  133 static int (*true_fchownat)(int, const char *, uid_t, gid_t, int);
  134 static int (*true_fxstatat)(int, int, const char *, struct stat *, int);
  135 static int (*true_fxstatat64)(int, int, const char *, struct stat64 *, int);
  136 static int (*true_linkat)(int, const char *, int, const char *, int);
  137 static int (*true_mkdirat)(int, const char *, mode_t);
  138 static int (*true_readlinkat)(int, const char *, char *, size_t);
  139 static int (*true_xmknodat)(int, int, const char *, mode_t, dev_t *);
  140 static int (*true_renameat)(int, const char *, int, const char *);
  141 static int (*true_symlinkat)(const char *, int, const char *);
  142 static int (*true_unlinkat)(int, const char *, int);
  143 #endif
  144 
  145 #if defined __GNUC__ && __GNUC__>=2
  146     #define inline inline
  147 #else
  148     #define inline
  149 #endif  
  150 
  151 static inline int true_stat(const char *pathname,struct stat *info) {
  152     return true_xstat(_STAT_VER,pathname,info);
  153 }
  154 
  155 static inline int true_mknod(const char *pathname,mode_t mode,dev_t dev) {
  156     return true_xmknod(_MKNOD_VER,pathname,mode,&dev);
  157 }
  158 
  159 static inline int true_lstat(const char *pathname,struct stat *info) {
  160     return true_lxstat(_STAT_VER,pathname,info);
  161 }
  162 
  163 #if (GLIBC_MINOR >= 4)
  164 static inline int true_fstatat(int dirfd, const char *pathname, struct stat *info, int flags) {
  165     return true_fxstatat(_STAT_VER, dirfd, pathname, info, flags);
  166 }
  167 
  168 static inline int true_fstatat64(int dirfd, const char *pathname, struct stat64 *info, int flags) {
  169     return true_fxstatat64(_STAT_VER, dirfd, pathname, info, flags);
  170 }
  171 
  172 static inline int true_mknodat(int dirfd, const char *pathname,mode_t mode,dev_t dev) {
  173     return true_xmknodat(_MKNOD_VER, dirfd, pathname, mode, &dev);
  174 }
  175 
  176 #endif
  177 
  178   /* A few defines to fix things a little */
  179 #define INSTW_OK 0 
  180   /* If not set, no work with translation is allowed */
  181 #define INSTW_INITIALIZED   (1<<0)
  182   /* If not set, a wrapped function only do its "real" job */
  183 #define INSTW_OKWRAP        (1<<1)
  184 #define INSTW_OKBACKUP      (1<<2)
  185 #define INSTW_OKTRANSL      (1<<3)
  186 
  187 #define INSTW_TRANSLATED    (1<<0)
  188   /* Indicates that a translated file is identical to original */
  189 #define INSTW_IDENTITY      (1<<1)
  190 
  191   /* The file currently exists in the root filesystem */
  192 #define INSTW_ISINROOT      (1<<6)
  193   /* The file currently exists in the translated filesystem */
  194 #define INSTW_ISINTRANSL    (1<<7)
  195 
  196 #define _BACKUP "/BACKUP"
  197 #define _TRANSL "/TRANSL"
  198 
  199   /* The root that contains all the needed metas-infos */
  200 #define _META   "/META"
  201   /* We store under this subtree the translated status */
  202 #define _MTRANSL _TRANSL
  203   /* We construct under this subtree fake directory listings */
  204 #define _MDIRLS  "/DIRLS"  
  205 
  206   /* String cell used to chain excluded paths */
  207 typedef struct string_t string_t;
  208 struct string_t {
  209     char *string;
  210     string_t *next;
  211 };  
  212 
  213   /* Used to keep all infos needed to cope with backup, translated fs... */
  214 typedef struct instw_t {
  215       /*
  216        * global fields 
  217        */
  218     int gstatus;
  219     int dbglvl;
  220     pid_t pid;
  221     char *root;
  222     char *backup;
  223     char *transl;
  224     char *meta;
  225     char *mtransl;
  226     char *mdirls;
  227       /* the list of all the paths excluded from translation */
  228     string_t *exclude;
  229     
  230       /*
  231        * per instance fields
  232        */
  233     int error;
  234     int status;
  235       /* the public path, hiding translation */
  236     char path[PATH_MAX+1];
  237       /* the public resolved path, hiding translation */
  238     char reslvpath[PATH_MAX+1];  
  239       /* the real resolved path, exposing tranlsation */
  240     char truepath[PATH_MAX+1];
  241       /* the real translated path */
  242     char translpath[PATH_MAX+1];
  243       /* the list of all the equiv paths conducing to "reslvpath" */
  244     string_t *equivpaths;  
  245       /* the real path used to flag translation status */
  246     char mtranslpath[PATH_MAX+1];
  247       /* the path given to a wrapped opendir */
  248     char mdirlspath[PATH_MAX+1];
  249 } instw_t;
  250 
  251 static instw_t __instw;
  252 
  253 static int canonicalize(const char *,char *);
  254 static int reduce(char *);
  255 static int make_path(const char *);
  256 static int copy_path(const char *,const char *);
  257 static inline int path_excluded(const char *);
  258 static int unlink_recursive(const char *);
  259 
  260 int expand_path(string_t **,const char *,const char *);
  261 int parse_suffix(char *,char *,const char *);
  262 
  263   /* a lazy way to avoid sizeof */
  264 #define mallok(T,N)  (T *)malloc((N)*sizeof(T))
  265   /* single method used to minimize excessive returns */
  266 #define finalize(code) {rcod=code;goto finalize;}
  267 
  268 #if DEBUG
  269 static int __instw_printdirent(struct dirent*);
  270 #if(GLIBC_MINOR >= 1)
  271 static int __instw_printdirent64(struct dirent64*);
  272 #endif
  273 #endif
  274 
  275 #ifdef DEBUG
  276 static int instw_print(instw_t *);
  277 #endif
  278 static int instw_init(void);
  279 static int instw_fini(void);
  280 
  281 static int instw_new(instw_t *);
  282 static int instw_delete(instw_t *);
  283 
  284   /* references a translated file in /mtransl */
  285 static int instw_setmetatransl(instw_t *);
  286 
  287 static int instw_setpath(instw_t *,const char *);
  288 #if (GLIBC_MINOR >= 4)
  289 static int instw_setpathrel(instw_t *, int, const char *);
  290 #endif
  291 static int instw_getstatus(instw_t *,int *);
  292 static int instw_apply(instw_t *);
  293 static int instw_filldirls(instw_t *);
  294 static int instw_makedirls(instw_t *);
  295 
  296 static int backup(const char *);
  297 
  298 static int vlambda_log(const char *logname,const char *format,va_list ap);
  299 
  300 /*
  301 static int lambda_log(const char *logname,const char *format,...)
  302 #ifdef __GNUC__
  303     __attribute__((format(printf,2,3)))
  304 #endif 
  305 ;
  306 */
  307 
  308 static inline int logg(const char *format,...)
  309 #ifdef __GNUC__
  310     /* Tell gcc that this function behaves like printf()
  311      * for parameters 1 and 2                            */
  312     __attribute__((format(printf, 1, 2)))
  313 #endif /* defined __GNUC__ */
  314 ;
  315 
  316 static inline int debug(int dbglvl,const char *format,...)
  317 #ifdef __GNUC__
  318     __attribute__((format(printf, 2, 3)))
  319 #endif 
  320 ;
  321 
  322 #define unset_okwrap() (__instw.gstatus &= ~INSTW_OKWRAP)
  323 #define reset_okwrap() (__instw.gstatus |= INSTW_OKWRAP)
  324 
  325 /*
  326  * *****************************************************************************
  327  */
  328 
  329 static void *libc_handle=NULL;
  330 static void initialize(void) {
  331     if (libc_handle)
  332         return;
  333 
  334     #ifdef BROKEN_RTLD_NEXT
  335 //          printf ("RTLD_LAZY");
  336             libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
  337     #else
  338  //         printf ("RTLD_NEXT");
  339             libc_handle = RTLD_NEXT;
  340     #endif
  341 
  342     true_time        = dlsym(libc_handle, "time");
  343     true_chdir       = dlsym(libc_handle, "chdir");
  344     true_chmod       = dlsym(libc_handle, "chmod");
  345     true_chown       = dlsym(libc_handle, "chown");
  346     true_chroot      = dlsym(libc_handle, "chroot");
  347     true_creat       = dlsym(libc_handle, "creat");
  348     true_fchmod      = dlsym(libc_handle, "fchmod");
  349     true_fchown      = dlsym(libc_handle, "fchown");
  350     true_fopen       = dlsym(libc_handle, "fopen");
  351     true_ftruncate   = dlsym(libc_handle, "ftruncate");
  352     true_getcwd      = dlsym(libc_handle, "getcwd");
  353     true_lchown      = dlsym(libc_handle, "lchown");
  354     true_link        = dlsym(libc_handle, "link");
  355     true_mkdir       = dlsym(libc_handle, "mkdir");
  356     true_xmknod      = dlsym(libc_handle, "__xmknod");
  357     true_open        = dlsym(libc_handle, "open");
  358     true_opendir     = dlsym(libc_handle, "opendir");
  359     true_readdir     = dlsym(libc_handle, "readdir");
  360     true_readlink    = dlsym(libc_handle, "readlink");
  361     true_realpath    = dlsym(libc_handle, "realpath");
  362     true_rename      = dlsym(libc_handle, "rename");
  363     true_rmdir       = dlsym(libc_handle, "rmdir");
  364     true_scandir     = dlsym(libc_handle, "scandir");
  365     true_xstat       = dlsym(libc_handle, "__xstat");
  366     true_lxstat      = dlsym(libc_handle, "__lxstat");
  367     true_symlink     = dlsym(libc_handle, "symlink");
  368     true_truncate    = dlsym(libc_handle, "truncate");
  369     true_unlink      = dlsym(libc_handle, "unlink");
  370     true_utime       = dlsym(libc_handle, "utime");
  371     true_setxattr    = dlsym(libc_handle, "setxattr");
  372         true_utimes      = dlsym(libc_handle, "utimes");
  373         true_access      = dlsym(libc_handle, "access");
  374 
  375 
  376 
  377 #if(GLIBC_MINOR >= 1)
  378     true_creat64     = dlsym(libc_handle, "creat64");
  379     true_fopen64     = dlsym(libc_handle, "fopen64");
  380     true_ftruncate64 = dlsym(libc_handle, "ftruncate64");
  381     true_open64      = dlsym(libc_handle, "open64");
  382     true_readdir64   = dlsym(libc_handle, "readdir64");
  383     true_scandir64   = dlsym(libc_handle, "scandir64");
  384     true_xstat64     = dlsym(libc_handle, "__xstat64");
  385     true_lxstat64    = dlsym(libc_handle, "__lxstat64");
  386     true_truncate64  = dlsym(libc_handle, "truncate64");
  387         true_removexattr = dlsym(libc_handle, "removexattr");
  388 #endif
  389 
  390 #if (GLIBC_MINOR >= 4)
  391 
  392     true_openat      = dlsym(libc_handle, "openat");
  393     true_fchmodat      = dlsym(libc_handle, "fchmodat");
  394     true_fchownat      = dlsym(libc_handle, "fchownat");
  395     true_fxstatat      = dlsym(libc_handle, "__fxstatat");
  396     true_fxstatat64      = dlsym(libc_handle, "__fxstatat64");
  397     true_linkat      = dlsym(libc_handle, "linkat");
  398     true_mkdirat      = dlsym(libc_handle, "mkdirat");
  399     true_readlinkat      = dlsym(libc_handle, "readlinkat");
  400     true_xmknodat      = dlsym(libc_handle, "__xmknodat");
  401     true_renameat      = dlsym(libc_handle, "renameat");
  402     true_symlinkat     = dlsym(libc_handle, "symlinkat");
  403     true_unlinkat      = dlsym(libc_handle, "unlinkat");
  404 
  405 #endif
  406 
  407     if(instw_init()) exit(-1);
  408 }
  409 
  410 void _init(void) {
  411     initialize();
  412 }
  413 
  414 void _fini(void) {
  415     instw_fini();   
  416 }
  417 
  418 /*
  419  * *****************************************************************************
  420  */
  421 
  422 /*
  423  * procedure = / rc:=vlambda_log(logname,format,ap) /
  424  *
  425  * task      = / the va_list version of the lambda_log() procedure. /
  426  */
  427 static int vlambda_log(const char *logname,const char *format,va_list ap) {
  428     char buffer[BUFSIZE];
  429     int count;
  430     int logfd;
  431     int rcod=0;
  432         int s_errno;
  433  
  434         /* save errno */
  435         s_errno = errno;
  436 
  437         buffer[BUFSIZE-2] = '\n';
  438         buffer[BUFSIZE-1] = '\0';
  439    
  440     count=vsnprintf(buffer,BUFSIZE,format,ap);
  441     if(count == -1) {
  442           /* The buffer was not big enough */
  443         strcpy(&(buffer[BUFSIZE - 5]), "...\n");
  444         count=BUFSIZE-1;
  445     }
  446         else
  447         {
  448                 count = strlen(buffer);
  449         }
  450         
  451     if(logname!=NULL) {
  452         logfd=true_open(logname,O_WRONLY|O_CREAT|O_APPEND,0666);
  453         if(logfd>=0) {
  454             if(write(logfd,buffer,count)!=count)
  455                 syslog( LOGLEVEL,
  456                     "Count not write `%s' in `%s': %s\n",
  457                     buffer,logname,strerror(errno));
  458             if(close(logfd) < 0)
  459                 syslog( LOGLEVEL,
  460                     "Could not close `%s': %s\n",
  461                     logname,strerror(errno));
  462         } else {
  463             syslog( LOGLEVEL,
  464                 "Could not open `%s' to write `%s': %s\n",
  465                 logname,buffer,strerror(errno));
  466         }
  467     } else {
  468         syslog(LOGLEVEL, "%s", buffer);
  469     }   
  470 
  471     /* restore errno */
  472         errno = s_errno;
  473     
  474     return rcod;
  475 }
  476 
  477 /*
  478  * procedure = / rc:=lambda_log(logname,format,...) /
  479  *
  480  * task      = /   logs a message to the specified file, or via syslog
  481  *               if no file is specified. /
  482  *
  483  * returns   = /  0 ok. message logged / 
  484  *
  485  * note      = / 
  486  *  --This *general* log procedure was justified by the debug mode 
  487  *  which used either stdout or stderr, thus interfering with the 
  488  *  observed process.
  489  *      --From now, we output nothing to stdout/stderr.
  490  * /
  491  *
  492  */
  493 /*
  494 static int lambda_log(const char *logname,const char *format, ...) {
  495     va_list ap;
  496     int rcod=0;;
  497 
  498     va_start(ap,format);
  499     rcod=vlambda_log(logname,format,ap);
  500     va_end(ap);
  501 
  502     return rcod;
  503 }
  504 */
  505 
  506 static inline int logg(const char *format,...) {
  507     char *logname;
  508     va_list ap;
  509     int rcod; 
  510     
  511     logname=getenv("INSTW_LOGFILE");
  512     va_start(ap,format);
  513     rcod=vlambda_log(logname,format,ap);
  514     va_end(ap);
  515     
  516     return rcod;
  517 }
  518 
  519 static inline int debug(int dbglvl,const char *format,...) {
  520     int rcod=0; 
  521 #ifdef DEBUG
  522     char *logname;
  523     va_list ap;
  524 
  525     if( __instw.dbglvl==0 ||
  526         dbglvl>__instw.dbglvl ||
  527         dbglvl<0    ) return rcod;
  528 
  529     logname=getenv("INSTW_DBGFILE");
  530     va_start(ap,format);
  531     rcod=vlambda_log(logname,format,ap);
  532     va_end(ap);
  533 #endif  
  534 
  535     return rcod;
  536 }
  537 
  538 /*
  539  * procedure = / rc:=canonicalize(path,resolved_path) /
  540  *
  541  * note      = /
  542  *  --We use realpath here, but this function calls __lxstat().
  543  *  We want to only use "real" calls in wrapping code, hence the 
  544  *      barrier established by unset_okwrap()/reset_okwrap().
  545  *      --We try to canonicalize as much as possible, considering that 
  546  * /
  547  */
  548 static int canonicalize(const char *path, char *resolved_path) {
  549         int s_errno;
  550 
  551         /* save errno */
  552         s_errno = errno;
  553 
  554     unset_okwrap();
  555 
  556     if(!realpath(path,resolved_path)) {
  557         if((path[0] != '/')) {
  558             /* The path could not be canonicalized, append it
  559              * to the current working directory if it was not 
  560              * an absolute path                               */
  561             true_getcwd(resolved_path, PATH_MAX-2);
  562             resolved_path[MAXPATHLEN-2] = '\0';
  563             strcat(resolved_path, "/");
  564             strncat(resolved_path, path, MAXPATHLEN - 1 - strlen(resolved_path));
  565         } else {
  566             strcpy(resolved_path,path);
  567         }
  568     }
  569 
  570     reset_okwrap();
  571 
  572 #if DEBUG
  573     debug(4,"canonicalize(%s,%s)\n",path,resolved_path);
  574 #endif
  575         /* restore errno */
  576         errno = s_errno;
  577 
  578     return 0;
  579 } 
  580 
  581 /*
  582  * procedure = / rc:=reduce(path) /
  583  *
  584  * task      = /   reduces all occurences of "..", ".", and extra "/" in path.
  585  *
  586  * inputs    = / path               The modifiable string containing the path
  587  * outputs   = / path               The reduced path.
  588  *
  589  * returns   = /  0 ok. path reduced
  590  *               -1 failed. cf errno /
  591  * note      = /
  592  *      --Very similar to canonicalize()/realpath() except we don’t do link-
  593  *      expansion
  594  *      --This is purely a string manipulation function (i.e., no verification
  595  *      of a path’s validity occurs).
  596  *      --Additionally, we try to do reduction “in-place” since the ending
  597  *      path is shorter than the beginning path.
  598  *      --Also, we want only absolute paths (other paths will throw an error)
  599  * /
  600  */
  601 static int reduce(char *path) {
  602     int len;
  603     char *off;
  604 
  605     if(path == NULL || *path != '/') {
  606         errno = EINVAL;
  607         return -1;
  608     }
  609 
  610     len = strlen(path);
  611 
  612     /* First, get rid of double / */
  613     if((off = strstr(path, "//"))) {
  614         memmove(off, off+1, len - (off-path));
  615         return reduce(path);
  616     }
  617 
  618     /* Then, worry about /./  */
  619     if((off = strstr(path, "/./"))) {
  620         memmove(off, off+2, len - 1 - (off-path));
  621         return reduce(path);
  622     }
  623     
  624     /* Finally, do /../ */
  625     if((off = strstr(path, "/../"))) {
  626         char *off2 = off;
  627         if(off2++ != path)
  628             while((--off2)[-1] != '/');
  629         memmove(off2, off+4, len - 3 - (off-path));
  630         return reduce(path);
  631     }
  632 
  633     /* Beautify ending */
  634     switch(path[len - 1]) {
  635         case '.':
  636             switch(path[len - 2]) {
  637                 default:
  638                     return 0;
  639                 case '.':
  640                     if(len != 3) {
  641                         off = path+len-3;
  642                         if(*off-- != '/')
  643                             return 0;
  644                         while(*--off != '/');
  645                         off[1] = 0;
  646                         return reduce(path);
  647                     }
  648                 case '/': ;
  649             }
  650         case '/':
  651             if(len != 1) {
  652                 path[len-1] = 0;
  653                 return reduce(path);
  654             }
  655         default:
  656             return 0;
  657     }
  658 }
  659 
  660 static int make_path (const char *path) {
  661     char checkdir[BUFSIZ];
  662     struct stat inode;
  663     int s_errno;
  664     int i = 0;
  665         /* save errno */
  666         s_errno = errno;
  667 
  668 #if DEBUG
  669     debug(2,"===== make_path: %s\n", path);
  670 #endif
  671 
  672     while ( path[i] != '\0' ) {
  673         checkdir[i] = path[i];
  674         if (checkdir[i] == '/') {  /* Each time a '/' is found, check if the    */
  675             checkdir[i+1] = '\0';   /* path exists. If it doesn't, we create it. */
  676             if (true_stat (checkdir, &inode) < 0)
  677                 true_mkdir (checkdir, S_IRWXU);
  678         }
  679         i++;
  680     }
  681     
  682         /* restore errno */
  683         errno = s_errno;
  684         
  685     return 0;
  686 }
  687 
  688 
  689 /*
  690  * procedure = / rc:=copy_path(truepath,translroot) /
  691  *
  692  * task      = /   do an exact translation of 'truepath' under 'translroot', 
  693  *               the directory path to the new objet is not created / 
  694  *
  695  * returns   = /  0 ok. translation done 
  696  *               -1 failed. cf errno /
  697  *
  698  * note      = / 
  699  *  --we suppose that 'translroot' has no trailing '/' 
  700  *  --no overwrite is done is the target object already exists 
  701  *  --the copy method depends on the source object type. 
  702  *  --we don't fail if the source object doesn't exist. 
  703  *  --we don't create the directory path because that would lead in the 
  704  *      the translation case not to reference the newly created directories
  705  * /
  706  */
  707 static int copy_path(const char *truepath,const char *translroot) {
  708     int rcod;
  709     char buffer[BUFSIZ];
  710     int bytes;
  711     char translpath[PATH_MAX+1];
  712     struct stat trueinfo;
  713     struct stat translinfo;
  714     int truefd;
  715     int translfd;
  716     struct utimbuf timbuf;
  717     size_t truesz;
  718     char linkpath[PATH_MAX+1];
  719     ssize_t linksz;
  720 
  721 #if DEBUG
  722     debug(2,"copy_path(%s,%s)\n",truepath,translroot);
  723 #endif
  724 
  725     rcod=true_lstat(truepath,&trueinfo);
  726     if(rcod<0 && errno!=ENOENT) return -1;
  727     if(!rcod) {
  728         if((truesz=strlen(truepath)+strlen(translpath))>PATH_MAX) {
  729             errno=ENAMETOOLONG;
  730             return -1;
  731         }
  732         
  733         strncpy(translpath,translroot,PATH_MAX);
  734         strncat(translpath,truepath,PATH_MAX-truesz);
  735 
  736         if(!true_lstat(translpath,&translinfo)) return 0;
  737 
  738           /* symbolic links */
  739         if(S_ISLNK(trueinfo.st_mode)) {
  740             if((linksz=true_readlink(truepath,linkpath,PATH_MAX))<0) return -1;
  741             linkpath[linksz]='\0';
  742             if(true_symlink(linkpath,translpath)!=0) return -1;
  743         }
  744 
  745           /* regular file */
  746         if(S_ISREG(trueinfo.st_mode)) {
  747             if((truefd=true_open(truepath,O_RDONLY))<0) return -1;
  748             if((translfd=true_open( translpath,
  749                         O_WRONLY|O_CREAT|O_TRUNC,
  750                         trueinfo.st_mode))<0    ) {
  751                 close(truefd);
  752                 return -1;
  753             }           
  754             
  755             while((bytes=read(truefd,buffer,BUFSIZ))>0)
  756                 write(translfd,buffer,bytes);
  757     
  758             close(truefd);
  759             close(translfd);
  760         }
  761     
  762           /* directory */
  763         if(S_ISDIR(trueinfo.st_mode)) {
  764             if(true_mkdir(translpath,trueinfo.st_mode)) return -1;
  765         }
  766     
  767           /* block special file */
  768         if(S_ISBLK(trueinfo.st_mode)) {
  769             if(true_mknod(  translpath,trueinfo.st_mode|S_IFBLK,
  770                     trueinfo.st_rdev    )) return -1;
  771         }
  772     
  773           /* character special file */
  774         if(S_ISCHR(trueinfo.st_mode)) {
  775             if(true_mknod(  translpath,trueinfo.st_mode|S_IFCHR,
  776                     trueinfo.st_rdev    )) return -1;
  777         }
  778          
  779           /* fifo special file */
  780         if(S_ISFIFO(trueinfo.st_mode)) {
  781             if(true_mknod(translpath,trueinfo.st_mode|S_IFIFO,0))
  782                 return -1;
  783         }
  784         
  785         timbuf.actime=trueinfo.st_atime;
  786         timbuf.modtime=trueinfo.st_mtime;
  787         true_utime(translpath,&timbuf);
  788         
  789         if(!S_ISLNK(trueinfo.st_mode)) {
  790             true_chown(translpath,trueinfo.st_uid,trueinfo.st_gid);
  791             true_chmod(translpath,trueinfo.st_mode); 
  792         }   
  793     }
  794 
  795     return 0;
  796 }
  797 
  798 /*
  799  * procedure = / rc:=path_excluded(truepath) /
  800  *
  801  * task      = /   indicates if the given path is or is hosted under any
  802  *               of the exclusion list members. /
  803  *
  804  * returns   = /  0 is not a member
  805  *                1 is a member /
  806  *
  807  * note      = /   __instw.exclude must be initialized / 
  808  * 
  809  */
  810 static inline int path_excluded(const char *truepath) {
  811     string_t *pnext;
  812     int result;
  813 
  814     result=0;
  815     pnext=__instw.exclude;
  816 
  817     while(pnext!=NULL) {
  818         if(strstr(truepath,pnext->string)==truepath) {
  819             result=1;
  820             break;
  821         }
  822         pnext=pnext->next;  
  823     }
  824 
  825     return result;
  826 }
  827 
  828 /*
  829  * procedure = / rc:=unlink_recursive(truepath) /
  830  *
  831  * task      = /   dangerous function that unlink either a file or 
  832  *               an entire subtree. / 
  833  *
  834  * returns   = /  0 ok. recursive unlink done 
  835  *               -1 failed. cf errno /
  836  *
  837  * note      = / 
  838  *  --this procedure was needed by instw_makedirls(), in order to 
  839  *  erase a previously created temporary subtree.
  840  *      --it must be called with an absolute path, and only to delete 
  841  *      well identified trees.
  842  *      --i think it is a very weak implementation, so avoid using it
  843  *      to unlink too deep trees, or rewrite it to avoid recursivity.
  844  * /
  845  * 
  846  */
  847 static int unlink_recursive(const char *truepath) {
  848     int rcod;
  849     struct stat trueinfo;
  850     DIR *wdir;
  851     struct dirent *went;
  852     char wpath[PATH_MAX+1];
  853     struct stat winfo;
  854 
  855 #if DEBUG
  856     debug(2,"unlink_recursive(%s)\n",truepath);
  857 #endif
  858 
  859     rcod=true_lstat(truepath,&trueinfo);
  860     if(rcod<0 && errno!=ENOENT) return -1;
  861     if(rcod!=0) return 0;
  862 
  863     if(S_ISDIR(trueinfo.st_mode)) {
  864         wdir=true_opendir(truepath);
  865         if(wdir==NULL) return -1;
  866         while((went=true_readdir(wdir))!=NULL) {
  867               /* we avoid big inifinite recursion troubles */
  868             if(     went->d_name[0]=='.' && 
  869                 (   (went->d_name[1]=='\0') ||
  870                     (   went->d_name[1]=='.' &&
  871                         went->d_name[2]=='\0') ) ) 
  872                 { continue; }   
  873             
  874               /* let's get the absolute path to this entry */
  875             strcpy(wpath,truepath); 
  876             strcat(wpath,"/");
  877             strcat(wpath,went->d_name);
  878             rcod=true_lstat(wpath,&winfo);
  879             if(rcod!=0) {
  880                 closedir(wdir);
  881                 return -1;
  882             }   
  883         
  884             if(S_ISDIR(winfo.st_mode)) {
  885                 unlink_recursive(wpath);
  886                 true_rmdir(wpath);
  887             } else {
  888                 true_unlink(wpath);
  889             }
  890         }
  891         closedir(wdir);
  892         true_rmdir(truepath);
  893     } else {
  894         true_unlink(truepath);
  895     }
  896 
  897     return rcod;
  898 }
  899 
  900 /* 
  901  * procedure = / rc:=expand_path(&list,prefix,suffix) /
  902  *
  903  * task      = /   from a given path, generates all the paths that could 
  904  *               be derived from it, through symlinks expansion. /
  905  * 
  906  * note      = /
  907  *  --this procedure has been implemented to enhance the method used
  908  *  to reference files that have been translated.
  909  *  --briefly, it is necessary to reference all the paths that could
  910  *  lead to a file, not only the path and the associated real path.
  911  * /
  912  */
  913 int expand_path(string_t **list,const char *prefix,const char *suffix) {
  914     char nprefix[PATH_MAX+1];
  915     char nwork[PATH_MAX+1];
  916     char nsuffix[PATH_MAX+1];
  917     char lnkpath[PATH_MAX+1];
  918     size_t lnksz=0;
  919     string_t *pthis=NULL;
  920     string_t *list1=NULL;
  921     string_t *list2=NULL;
  922     struct stat ninfo;
  923     int rcod=0;
  924     char pnp[PATH_MAX+1];
  925     char pns[PATH_MAX+1];
  926     size_t len;
  927 
  928 #if DEBUG
  929     debug(4,"expand_path(%p,%s,%s)\n",list,prefix,suffix);
  930 #endif
  931 
  932       /* nothing more to expand, stop condition */
  933     if(suffix[0]=='\0') {
  934         (*list)=mallok(string_t,1);
  935         (*list)->string=malloc(strlen(prefix)+1);
  936         strcpy((*list)->string,prefix);
  937         (*list)->next=NULL;
  938         finalize(0);    
  939     }
  940 
  941       /* we parse the next suffix subscript */  
  942     parse_suffix(pnp,pns,suffix);   
  943     strcpy(nprefix,prefix);
  944     strcat(nprefix,pnp);
  945     strcpy(nsuffix,pns);
  946 
  947     rcod=true_lstat(nprefix,&ninfo);
  948     if( (rcod!=0) ||
  949         (rcod==0 && !S_ISLNK(ninfo.st_mode))) {
  950         expand_path(list,nprefix,nsuffix);  
  951     } else {
  952         expand_path(&list1,nprefix,nsuffix);
  953         
  954         lnksz=true_readlink(nprefix,lnkpath,PATH_MAX);
  955         lnkpath[lnksz]='\0';
  956         if(lnkpath[0]!='/') {
  957             strcpy(nprefix,prefix);
  958             len=strlen(lnkpath);
  959             if(lnkpath[len-1]=='/') {lnkpath[len-1]='\0';}
  960             strcpy(nwork,"/");
  961             strcat(nwork,lnkpath);
  962             strcat(nwork,nsuffix);
  963             strcpy(nsuffix,nwork);
  964             expand_path(&list2,nprefix,nsuffix);
  965         } else {
  966             len=strlen(lnkpath);
  967             if(lnkpath[len-1]=='/') {lnkpath[len-1]='\0';}
  968             strcpy(nprefix,"");
  969             strcpy(nwork,lnkpath);
  970             strcat(nwork,nsuffix);  
  971             strcpy(nsuffix,nwork);
  972             expand_path(&list2,nprefix,nsuffix);
  973         }
  974 
  975         *list=list1;
  976         pthis=*list;
  977         while(pthis->next!=NULL) {pthis=pthis->next;}
  978         pthis->next=list2;
  979     }   
  980 
  981     finalize:
  982 
  983     return rcod;        
  984 }
  985 
  986 int parse_suffix(char *pnp,char *pns,const char *suffix) {
  987     int rcod=0;
  988     char *p;
  989 
  990     strcpy(pnp,suffix);
  991     strcpy(pns,"");
  992 
  993     p=pnp;
  994     
  995     if(*p=='\0') {
  996         strcpy(pns,"");
  997     } else {
  998         p++;
  999         while((*p)!='\0') {
 1000             if(*p=='/') {
 1001                 strcpy(pns,p);
 1002                 *p='\0';
 1003                 break;
 1004             }
 1005             p++;    
 1006         }
 1007     }
 1008 
 1009     return rcod;
 1010 }
 1011 
 1012 /*
 1013  * *****************************************************************************
 1014  */
 1015 
 1016 static int __instw_printdirent(struct dirent *entry) {
 1017 
 1018     if(entry!=NULL) {
 1019         debug(  4,
 1020             "entry(%p) {\n"
 1021             "\td_ino     : %" PRId64 "\n"
 1022             "\td_off     : %" PRId64 "\n"
 1023             "\td_reclen  : %d\n"
 1024             "\td_type    : %d\n"
 1025             "\td_name    : \"%.*s\"\n",
 1026             entry,
 1027             (int64_t) entry->d_ino,
 1028             (int64_t) D_OFF(entry->d_off),
 1029             entry->d_reclen,
 1030             (int)entry->d_type,
 1031             (int)entry->d_reclen,(char*)(entry->d_name)
 1032             );
 1033     } else {
 1034         debug(  4,"entry(null) \n");
 1035     }
 1036 
 1037     return 0;
 1038 }
 1039 
 1040 static int __instw_printdirent64(struct dirent64 *entry) {
 1041 
 1042     if(entry!=NULL) {
 1043         debug(  4,
 1044             "entry(%p) {\n"
 1045             "\td_ino     : %" PRId64 "\n"
 1046             "\td_off     : %" PRId64 "d\n"
 1047             "\td_reclen  : %d\n"
 1048             "\td_type    : %d\n"
 1049             "\td_name    : \"%.*s\"\n",
 1050             entry,
 1051             entry->d_ino,
 1052             D_OFF(entry->d_off),
 1053             entry->d_reclen,
 1054             (int)entry->d_type,
 1055             (int)entry->d_reclen,(char*)(entry->d_name)
 1056             );
 1057     } else {
 1058         debug(  4,"entry(null) \n");
 1059     }
 1060 
 1061     return 0;
 1062 }
 1063 
 1064 /*
 1065  * *****************************************************************************
 1066  */
 1067 
 1068 #ifdef DEBUG
 1069 static int instw_print(instw_t *instw) {
 1070     string_t *pnext;
 1071     int i;
 1072     
 1073     debug(  4,
 1074         "instw(%p) {\n"
 1075         "\tgstatus     : %d\n"
 1076         "\terror       : %d\n"
 1077         "\tstatus      : %d\n"
 1078         "\tdbglvl      : %d\n"
 1079         "\tpid         : %d\n"
 1080         "\troot        : \"%.*s\"\n"
 1081         "\tbackup      : \"%.*s\"\n"
 1082         "\ttransl      : \"%.*s\"\n"
 1083         "\tmeta        : \"%.*s\"\n"
 1084         "\tmtransl     : \"%.*s\"\n"
 1085         "\tmdirls      : \"%.*s\"\n",
 1086         instw,
 1087         instw->gstatus,
 1088         instw->error,
 1089         instw->status,
 1090         instw->dbglvl,
 1091         instw->pid,
 1092         PATH_MAX,(char*)((instw->root)?:"(null)"),
 1093         PATH_MAX,(char*)((instw->backup)?:"(null)"),
 1094         PATH_MAX,(char*)((instw->transl)?:"(null)"),
 1095         PATH_MAX,(char*)((instw->meta)?:"(null)"),
 1096         PATH_MAX,(char*)((instw->mtransl)?:"(null)"),
 1097         PATH_MAX,(char*)((instw->mdirls)?:"(null)")
 1098         );
 1099 
 1100     pnext=instw->exclude;
 1101     i=0;
 1102     while(pnext!=NULL) {
 1103         debug(  4,
 1104             "\texclude     : (%02d) \"%.*s\"\n",
 1105             ++i,PATH_MAX,pnext->string  );
 1106         pnext=pnext->next;  
 1107     }
 1108 
 1109     debug(  4,
 1110         "\tpath        : \"%.*s\"\n"
 1111         "\treslvpath   : \"%.*s\"\n"
 1112         "\ttruepath    : \"%.*s\"\n"
 1113         "\ttranslpath  : \"%.*s\"\n",
 1114         PATH_MAX,(char*)(instw->path),
 1115         PATH_MAX,(char*)(instw->reslvpath),
 1116         PATH_MAX,(char*)(instw->truepath),
 1117         PATH_MAX,(char*)(instw->translpath)
 1118         );
 1119 
 1120     pnext=instw->equivpaths;
 1121     i=0;
 1122     while(pnext!=NULL) {
 1123         debug(  4,
 1124             "\tequivpaths  : (%02d) \"%.*s\"\n",
 1125             ++i,PATH_MAX,pnext->string  );
 1126         pnext=pnext->next;  
 1127     }
 1128 
 1129     debug(  4,
 1130         "\tmtranslpath : \"%.*s\"\n"
 1131         "\tmdirlspath  : \"%.*s\"\n"
 1132         "}\n",
 1133         PATH_MAX,(char*)(instw->mtranslpath),
 1134         PATH_MAX,(char*)(instw->mdirlspath)
 1135         );
 1136 
 1137     return 0;   
 1138 }
 1139 #endif
 1140 
 1141 /*
 1142  * procedure = / rc:=instw_init() /
 1143  *
 1144  * task      = /   initializes the '__transl' fields, and fills the fields 
 1145  *       provided by the environment. 
 1146  *                 this structure is a reference enabling faster 
 1147  *       local structure creations. /
 1148  *
 1149  * returns   = /  0 ok. env set 
 1150  *               -1 failed. /
 1151  */
 1152 static int instw_init(void) {
 1153     char *proot;
 1154     char *pbackup;
 1155     char *ptransl;
 1156     char *pdbglvl;
 1157     struct stat info;
 1158     char wrkpath[PATH_MAX+1];
 1159     char *pexclude;
 1160     char *exclude;
 1161     string_t **ppnext;
 1162     int okinit;
 1163     int okbackup;
 1164     int oktransl;
 1165     int okwrap;
 1166 
 1167 #if DEBUG
 1168       /*
 1169        * We set the requested dynamic debug level
 1170        */
 1171     __instw.dbglvl=0;
 1172     if((pdbglvl=getenv("INSTW_DBGLVL"))) {
 1173         __instw.dbglvl=atoi(pdbglvl);
 1174         if(__instw.dbglvl>4) { __instw.dbglvl=4; }
 1175         if(__instw.dbglvl<0) { __instw.dbglvl=0; }
 1176     }
 1177 
 1178     debug(2,"instw_init()\n");
 1179 #endif
 1180 
 1181     okinit=0;
 1182     okbackup=0;
 1183     oktransl=0;
 1184     okwrap=0;
 1185     
 1186     __instw.gstatus=0;
 1187     __instw.error=0;
 1188     __instw.status=0;
 1189     __instw.pid=getpid();
 1190     __instw.root=NULL;
 1191     __instw.backup=NULL;
 1192     __instw.transl=NULL;
 1193     __instw.meta=NULL;
 1194     __instw.mtransl=NULL;
 1195     __instw.mdirls=NULL;
 1196     __instw.exclude=NULL;
 1197 
 1198     __instw.path[0]='\0';
 1199     __instw.reslvpath[0]='\0';
 1200     __instw.truepath[0]='\0';
 1201     __instw.translpath[0]='\0';
 1202 
 1203     __instw.equivpaths=NULL;
 1204 
 1205     __instw.mtranslpath[0]='\0';
 1206     __instw.mdirlspath[0]='\0';
 1207 
 1208       /* nothing can be activated without that, anyway */
 1209     if((proot=getenv("INSTW_ROOTPATH"))) {
 1210         realpath(proot,wrkpath);
 1211         if(wrkpath[strlen(wrkpath)-1]=='/')
 1212             wrkpath[strlen(wrkpath)-1]='\0';
 1213         __instw.root=malloc(strlen(wrkpath)+1);
 1214         if(NULL==__instw.root) return -1;
 1215         strcpy(__instw.root,wrkpath);
 1216 
 1217           /* this root path must exist */
 1218         if(__instw.root[0]=='\0' || true_stat(__instw.root,&info)) {
 1219             fprintf(stderr,
 1220                 "Please check the INSTW_ROOTPATH and "
 1221                 "be sure that it does exist please !\n"
 1222                 "given value : %s\n", __instw.root);
 1223             return -1;  
 1224         }
 1225 
 1226         if((pbackup=getenv("INSTW_BACKUP"))) {
 1227             if( !strcmp(pbackup,"1") ||
 1228                 !strcmp(pbackup,"yes") ||
 1229                 !strcmp(pbackup,"true") ) {
 1230             
 1231                 if((strlen(__instw.root)+strlen(_BACKUP))>PATH_MAX) {
 1232                     fprintf(stderr,
 1233                         "Backup path would exceed PATH_MAX. Aborting.\n");
 1234                     return -1;  
 1235                 }
 1236                 __instw.backup=malloc(strlen(__instw.root)+strlen(_BACKUP)+1);
 1237                 if(NULL==__instw.backup) return -1;
 1238                 strcpy(__instw.backup,__instw.root);
 1239                 strcat(__instw.backup,_BACKUP);
 1240 
 1241                   /* we create the path that precautiously shouldn't exist */
 1242                 true_mkdir(__instw.backup,S_IRWXU);  
 1243 
 1244                 okbackup=1;
 1245             } 
 1246             else if(    strcmp(pbackup,"0") && 
 1247                     strcmp(pbackup,"no") &&
 1248                     strcmp(pbackup,"false") ) {
 1249                 fprintf(stderr,
 1250                     "Please check the INSTW_BACKUP value please !\n"
 1251                     "Recognized values are : 1/0,yes/no,true/false.\n");
 1252                 return -1;  
 1253             }       
 1254         }
 1255 
 1256         if((ptransl=getenv("INSTW_TRANSL"))) {
 1257             if( !strcmp(ptransl,"1") ||
 1258                 !strcmp(ptransl,"yes") ||
 1259                 !strcmp(ptransl,"true") ) {
 1260         
 1261                 if((strlen(__instw.root)+strlen(_TRANSL))>PATH_MAX) {
 1262                     fprintf(stderr,
 1263                         "Transl path would exceed PATH_MAX. Aborting.\n");
 1264                     return -1;  
 1265                 }
 1266                 __instw.transl=malloc(strlen(__instw.root)+strlen(_TRANSL)+1);
 1267                 if(NULL==__instw.transl) return -1;
 1268                 strcpy(__instw.transl,__instw.root);
 1269                 strcat(__instw.transl,_TRANSL);
 1270             
 1271                   /* we create the path that precautiously shouldn't exist */
 1272                 true_mkdir(__instw.transl,S_IRWXU);  
 1273             
 1274                 if((strlen(__instw.root)+strlen(_META))>PATH_MAX) {
 1275                     fprintf(stderr,
 1276                         "Meta path would exceed PATH_MAX. Aborting.\n");
 1277                     return -1;  
 1278                 }
 1279                 
 1280                 __instw.meta=malloc(strlen(__instw.root)+strlen(_META)+1);
 1281                 if(NULL==__instw.meta) return -1;
 1282                 strcpy(__instw.meta,__instw.root);
 1283                 strcat(__instw.meta,_META);
 1284             
 1285                   /* we create the path that precautiously shouldn't exist */
 1286                 true_mkdir(__instw.meta,S_IRWXU); 
 1287     
 1288                 __instw.mtransl=malloc(strlen(__instw.meta)+strlen(_MTRANSL)+1);
 1289                 if(NULL==__instw.mtransl) return -1;
 1290                 strcpy(__instw.mtransl,__instw.meta);
 1291                 strcat(__instw.mtransl,_MTRANSL);
 1292             
 1293                   /* we create the path that precautiously shouldn't exist */
 1294                 true_mkdir(__instw.mtransl,S_IRWXU); 
 1295 
 1296                 __instw.mdirls=malloc(strlen(__instw.meta)+strlen(_MDIRLS)+1);
 1297                 if(NULL==__instw.mdirls) return -1;
 1298                 strcpy(__instw.mdirls,__instw.meta);
 1299                 strcat(__instw.mdirls,_MDIRLS);
 1300             
 1301                   /* we create the path that precautiously shouldn't exist */
 1302                 true_mkdir(__instw.mdirls,S_IRWXU); 
 1303 
 1304                 oktransl=1;
 1305             } 
 1306             else if(    strcmp(ptransl,"0") && 
 1307                     strcmp(ptransl,"no") &&
 1308                     strcmp(ptransl,"false") ) {
 1309                 fprintf(stderr,
 1310                     "Please check the INSTW_TRANSL value please !\n"
 1311                     "Recognized values are : 1/0,yes/no,true/false.\n");
 1312                 return -1;  
 1313             }       
 1314         }
 1315     }
 1316 
 1317       /*
 1318        * we end up constructing the exclusion list
 1319        */
 1320 
 1321     ppnext=&__instw.exclude;
 1322 
 1323       /* we systematically add the root directory */
 1324     if(__instw.gstatus&INSTW_OKTRANSL) {
 1325         *ppnext=mallok(string_t,1);
 1326         if(*ppnext==NULL) return -1;
 1327         (*ppnext)->string=NULL;
 1328         (*ppnext)->next=NULL;
 1329         realpath(__instw.root,wrkpath);
 1330         (*ppnext)->string=malloc(strlen(wrkpath)+1);
 1331         strcpy((*ppnext)->string,wrkpath);
 1332         ppnext=&(*ppnext)->next;
 1333     }   
 1334        
 1335     if((pexclude=getenv("INSTW_EXCLUDE"))) {
 1336         exclude=malloc(strlen(pexclude)+1);
 1337         strcpy(exclude,pexclude);
 1338         pexclude=strtok(exclude,",");
 1339 
 1340         while(pexclude!=NULL) {
 1341             *ppnext=malloc(sizeof(string_t));
 1342             if(*ppnext==NULL) return -1;
 1343             (*ppnext)->string=NULL;
 1344             (*ppnext)->next=NULL;
 1345               /* let's store the next excluded path */
 1346             if(strlen(pexclude)>PATH_MAX) return -1;
 1347             realpath(pexclude,wrkpath);
 1348             (*ppnext)->string=malloc(strlen(wrkpath)+1);
 1349             strcpy((*ppnext)->string,wrkpath);
 1350             ppnext=&(*ppnext)->next;
 1351             pexclude=strtok(NULL,",");
 1352         }
 1353     
 1354     }
 1355 
 1356 
 1357     okinit=1;
 1358     okwrap=1;
 1359 
 1360     if(okinit) __instw.gstatus |= INSTW_INITIALIZED;
 1361     if(okwrap) __instw.gstatus |= INSTW_OKWRAP;
 1362     if(okbackup) __instw.gstatus |= INSTW_OKBACKUP;
 1363     if(oktransl) __instw.gstatus |= INSTW_OKTRANSL; 
 1364     
 1365 #if DEBUG
 1366     debug(4,"__instw(%p)\n",&__instw);
 1367     instw_print(&__instw);
 1368 #endif
 1369 
 1370     return 0;
 1371 }
 1372 
 1373 /*
 1374  * procedure = / rc:=instw_fini() /
 1375  *
 1376  * task      = /   properly finalizes the instw job /  
 1377  *
 1378  * returns   = /  0 ok. env set 
 1379  *               -1 failed. /
 1380  */
 1381 static int instw_fini(void) {
 1382     int rcod=0;
 1383     string_t *pnext;
 1384     string_t *pthis;
 1385 
 1386 #if DEBUG
 1387     debug(2,"instw_fini()\n");
 1388 #endif
 1389 
 1390     if( !(__instw.gstatus & INSTW_INITIALIZED) ) finalize(0);
 1391 
 1392     __instw.gstatus &= ~INSTW_INITIALIZED;
 1393 
 1394     if(__instw.root != NULL) {free(__instw.root);__instw.root=NULL;}    
 1395     if(__instw.backup != NULL) {free(__instw.backup);__instw.backup=NULL;}  
 1396     if(__instw.transl != NULL) {free(__instw.transl);__instw.transl=NULL;}  
 1397     if(__instw.meta != NULL) {free(__instw.meta);__instw.meta=NULL;}    
 1398     if(__instw.mtransl != NULL) {free(__instw.mtransl);__instw.mtransl=NULL;}   
 1399     if(__instw.mdirls != NULL) {free(__instw.mdirls);__instw.mdirls=NULL;}  
 1400 
 1401     pthis=__instw.exclude;
 1402     while(pthis != NULL) {
 1403         free(pthis->string);
 1404         pnext=pthis->next;
 1405         free(pthis);
 1406         pthis=pnext;
 1407     }
 1408     __instw.exclude=NULL;
 1409 
 1410     finalize:
 1411 
 1412     return rcod;
 1413 }
 1414 
 1415 /*
 1416  * procedure = / rc:=instw_new(instw) /
 1417  *
 1418  * task      = / Initializes a new instw_t structure before any work on it /
 1419  *
 1420  * returns   = /  0 ok. ready to be used
 1421  *               -1 failed. /
 1422  */
 1423 static int instw_new(instw_t *instw) {
 1424     int rcod=0;
 1425 
 1426     *instw=__instw;
 1427 
 1428     instw->error=0;
 1429     instw->status=0;
 1430     instw->path[0]='\0';
 1431     instw->reslvpath[0]='\0';
 1432     instw->truepath[0]='\0';
 1433     instw->translpath[0]='\0';
 1434     instw->equivpaths=NULL;
 1435     instw->mtranslpath[0]='\0';
 1436     instw->mdirlspath[0]='\0';
 1437 
 1438     return rcod;
 1439 }
 1440 
 1441 /*
 1442  * procedure = / rc:=instw_delete(instw) /
 1443  *
 1444  * task      = / properly finalizes an instw structure /
 1445  *
 1446  * returns   = /  0 ok. ready to be used
 1447  *               -1 failed. /
 1448  */
 1449 static int instw_delete(instw_t *instw) {
 1450     int rcod=0;
 1451     string_t *pnext;
 1452     string_t *pthis;
 1453 
 1454     pthis=instw->equivpaths;
 1455     while(pthis != NULL) {
 1456         free(pthis->string);
 1457         pnext=pthis->next;
 1458         free(pthis);
 1459         pthis=pnext;
 1460     }
 1461 
 1462     instw->status=0;
 1463 
 1464     return rcod;
 1465 }
 1466 
 1467 /* 
 1468  * procedure = / rc:=instw_setmetatransl(instw) /
 1469  *
 1470  * task      = / Refreshes as mush as possible the translation 
 1471  *               status of a translated file /
 1472  *
 1473  * note      = /
 1474  *  --this procedure is meant to be called after the various
 1475  *   translation status flags have been setted.
 1476  *        the only thing it does is referencing a file that has been
 1477  *   flagged as "translated".
 1478  *        if it is, we musn't try to use the eventual real version 
 1479  *   of the file anymore, hence the full referencement under /mtransl.
 1480  *
 1481  *      --in some cases, for example when you create manually a subtree 
 1482  *  and a file in this subtree directly directly in the translated fs 
 1483  *  (yes, it is possible) the meta infos won't exist.
 1484  *        so, to be able to cope with this case, we firstly try to
 1485  *  create the full reference to the file, and if this fails, we try
 1486  *  to reference all the traversed directories.
 1487  * /
 1488  */
 1489 static int instw_setmetatransl(instw_t *instw) {
 1490     int rcod=0;
 1491     struct stat info;
 1492     char mtransldir[PATH_MAX+1];
 1493     char mtranslpath[PATH_MAX+1];
 1494     char reslvpath[PATH_MAX+1];
 1495     size_t mesz=0;
 1496     int i=0;
 1497     string_t *pthis;
 1498 
 1499 #if DEBUG
 1500     debug(3,"instw_setmetatransl(%p)\n",instw);
 1501     instw_print(instw);
 1502 #endif
 1503 
 1504     if( !(instw->gstatus & INSTW_INITIALIZED) ||
 1505         !(instw->gstatus & INSTW_OKTRANSL) ) finalize(0); 
 1506 
 1507     if(!(instw->status & INSTW_TRANSLATED) ) finalize(0);
 1508 
 1509     if(instw->equivpaths==NULL) {   
 1510         expand_path(&(instw->equivpaths),"",instw->reslvpath);
 1511     }   
 1512 
 1513 #if DEBUG
 1514     instw_print(instw);
 1515 #endif
 1516 
 1517     pthis=instw->equivpaths;    
 1518     while(pthis!=NULL) {
 1519         strcpy(mtranslpath,instw->mtransl);
 1520         strcat(mtranslpath,pthis->string);
 1521         strcpy(reslvpath,pthis->string);
 1522 
 1523         if( (true_stat(mtranslpath,&info)) && 
 1524             (true_mkdir(mtranslpath,S_IRWXU)) ) {
 1525             strcpy(mtransldir,mtranslpath);
 1526             mesz=strlen(instw->mtransl);
 1527     
 1528             for(i=0;reslvpath[i]!='\0';i++) {
 1529                 mtransldir[mesz+i]=reslvpath[i];
 1530                 if(reslvpath[i]=='/') {
 1531                     mtransldir[mesz+i+1]='\0';
 1532                     true_mkdir(mtransldir,S_IRWXU);
 1533                 }
 1534             }
 1535     
 1536             true_mkdir(mtranslpath,S_IRWXU);
 1537         }
 1538 
 1539         pthis=pthis->next;
 1540     }
 1541 
 1542     finalize: 
 1543 
 1544     return rcod;
 1545 }
 1546 
 1547 /*
 1548  * procedure = / rc:=instw_setpath(instw,path) /
 1549  *
 1550  * task      = /   sets the 'instw->path' field and updates all the fields that 
 1551  *               can be deduced from 'path', such as 'instw->translpath'. /
 1552  *
 1553  * inputs    = / path               The given path, as is 
 1554  * outputs   = / instw->path        A stored copy of 'path'
 1555  *               instw->truepath    The given path, canonicalized
 1556  *               instw->translpath  The real translated path 
 1557  *               instw->mtranslpath The translation status path  /
 1558  *
 1559  * returns   = /  0 ok. path set
 1560  *               -1 failed. cf errno /
 1561  */
 1562 static int instw_setpath(instw_t *instw,const char *path) {
 1563     size_t relen;
 1564     size_t trlen = 0;
 1565     size_t melen;
 1566 
 1567 #if DEBUG
 1568     debug(2,"instw_setpath(%p,%s)\n",instw,path);
 1569 #endif
 1570 
 1571     instw->status=0;
 1572 
 1573     strncpy(instw->path,path,PATH_MAX);
 1574     instw->truepath[0]='\0';
 1575 
 1576     if(instw->path[0]!='/') {
 1577         true_getcwd(instw->truepath,PATH_MAX+1);
 1578         if(instw->truepath[strlen(instw->truepath)-1]!='/'){
 1579             strcat(instw->truepath,"/");
 1580         }
 1581         strcat(instw->truepath,instw->path);
 1582     } else {
 1583         reduce(instw->path);
 1584         strcpy(instw->truepath,instw->path);
 1585     }
 1586     relen=strlen(instw->truepath);
 1587     
 1588     /* remove relative elements from the truepath */
 1589     reduce(instw->truepath);
 1590     
 1591       /* 
 1592        *   if library is not completely initialized, or if translation 
 1593        * is not active, we make things so it is equivalent to the
 1594        * to the identity, this avoid needs to cope with special cases.
 1595        */
 1596     if( !(instw->gstatus&INSTW_INITIALIZED) || 
 1597         !(instw->gstatus&INSTW_OKTRANSL)) {
 1598         strncpy(instw->reslvpath,instw->truepath,PATH_MAX);
 1599         strncpy(instw->translpath,instw->truepath,PATH_MAX);
 1600         return 0;
 1601     }
 1602     
 1603       /*
 1604        *   we fill instw->reslvpath , applying the inversed translation
 1605        * if truepath is inside /transl.
 1606        */
 1607     if(strstr(instw->truepath,instw->transl)==instw->truepath) {
 1608         strcpy(instw->reslvpath,instw->truepath+strlen(instw->transl));
 1609     } else {
 1610         strcpy(instw->reslvpath,instw->truepath);
 1611     }
 1612 
 1613       /*
 1614        *   if instw->path is relative, no troubles.
 1615        *   but if it is absolute and located under /transl, we have 
 1616        * to untranslate it.
 1617        */
 1618     if( (instw->path[0]=='/') &&
 1619         (strstr(instw->path,instw->transl)==instw->path)) {
 1620         strcpy(instw->path,instw->reslvpath);
 1621     } 
 1622 
 1623       /*
 1624        * We must detect early 'path' matching with already translated files  
 1625        */
 1626     if(path_excluded(instw->truepath)) {
 1627         strncpy(instw->translpath,instw->truepath,PATH_MAX);
 1628         instw->status |= ( INSTW_TRANSLATED | INSTW_IDENTITY);
 1629     } else {
 1630           /* Building the real translated path */
 1631         strncpy(instw->translpath,instw->transl,PATH_MAX);
 1632         trlen=strlen(instw->translpath);
 1633         if((trlen+relen)>PATH_MAX) {
 1634             instw->error=errno=ENAMETOOLONG;
 1635             return -1;
 1636         }
 1637         strncat(instw->translpath,instw->reslvpath,PATH_MAX-trlen);
 1638         instw->translpath[PATH_MAX]='\0';
 1639     }   
 1640 
 1641       /* Building the translation status path */
 1642     strncpy(instw->mtranslpath,instw->mtransl,PATH_MAX);
 1643     instw->mtranslpath[PATH_MAX]='\0';
 1644     melen=strlen(instw->mtranslpath);
 1645     if((melen+relen)>PATH_MAX) {
 1646         instw->error=errno=ENAMETOOLONG;
 1647         return -1;
 1648     }
 1649     strncat(instw->mtranslpath,instw->reslvpath,PATH_MAX-trlen);
 1650     instw->mtranslpath[PATH_MAX]='\0';
 1651 
 1652     return 0;
 1653 }
 1654 
 1655 /*
 1656  * procedure = / rc:=instw_setpathrel(instw,dirfd,relpath) /
 1657  *
 1658  * task      = /   sets the 'instw->path' field and updates all the fields that
 1659  *               can be deduced from 'path', such as 'instw->translpath'. Much
 1660  *               like instw_setpath, except for paths relative to a dirfd. /
 1661  *
 1662  * inputs    = / dirfd              An open file descriptor to a directory
 1663  *               relpath            The given path relative to dirfd, as is
 1664  * outputs   = / instw->path        The full absolute (non-relative) path
 1665  *               instw->truepath    The given path, canonicalized
 1666  *               instw->translpath  The real translated path 
 1667  *               instw->mtranslpath The translation status path  /
 1668  *
 1669  * returns   = /  0 ok. path set
 1670  *               -1 failed. cf errno /
 1671  */
 1672 #if (GLIBC_MINOR >= 4)
 1673 static int instw_setpathrel(instw_t *instw, int dirfd, const char *relpath) {
 1674 
 1675 /* This constant should be large enough to make a string that holds
 1676  * /proc/self/fd/xxxxx  if you have an open fd with more than five digits,
 1677  * something is seriously messed up.
 1678  */
 1679 #define PROC_PATH_LEN 20
 1680     
 1681     debug(2,"instw_setpathrel(%p,%d,%s)\n",instw,dirfd,relpath);
 1682     int retval = -1, l;
 1683     char *newpath;
 1684     char proc_path[PROC_PATH_LEN];
 1685     struct stat s;
 1686 
 1687 
 1688     /* If dirfd is AT_FDCWD then we got nothing to do, return the */
 1689     /* path as-is                                                 */
 1690 
 1691     if ( dirfd == AT_FDCWD ) return instw_setpath(instw, relpath);
 1692 
 1693     snprintf(proc_path, PROC_PATH_LEN, "/proc/self/fd/%d", dirfd);
 1694     if(true_stat(proc_path, &s) == -1)
 1695         goto out;
 1696     if(!(newpath = malloc(s.st_size+strlen(relpath)+2)))
 1697         goto out;
 1698     if((l = true_readlink(proc_path, newpath, s.st_size)) == -1)
 1699         goto free_out;
 1700     newpath[l] = '/';
 1701     strcpy(newpath + l + 1, relpath);
 1702     
 1703     retval = instw_setpath(instw, newpath);
 1704 
 1705 free_out:
 1706     free(newpath);
 1707 out:
 1708     return retval;
 1709 
 1710 #undef PROC_PATH_LEN
 1711 }
 1712 #endif
 1713 
 1714 /*
 1715  * procedure = / rc:=instw_getstatus(instw,status) /
 1716  *
 1717  * outputs   = / status  instw->path flags field status in the translated fs
 1718  *                 INSTW_ISINROOT   file exists in the real fs 
 1719  *                 INSTW_ISINTRANSL file exists in the translated fs
 1720  *                 INSTW_TRANSLATED file has been translated /
 1721  *
 1722  * returns   = /  0 ok. stated 
 1723  *               -1 failed. cf errno /
 1724  */
 1725 static int instw_getstatus(instw_t *instw,int *status) {
 1726     struct stat inode;
 1727     struct stat rinode;
 1728     struct stat tinode;
 1729 
 1730 #if DEBUG
 1731     debug(2,"instw_getstatus(%p,%p)\n",instw,status);
 1732 #endif
 1733 
 1734       /* 
 1735        * is the file referenced as being translated ?
 1736        */
 1737     if( (instw->gstatus&INSTW_INITIALIZED) &&
 1738         (instw->gstatus&INSTW_OKTRANSL) &&
 1739        !(instw->status&INSTW_TRANSLATED) &&  
 1740        !true_stat(instw->mtranslpath,&inode) ) {
 1741         instw->status |= INSTW_TRANSLATED;
 1742     }
 1743 
 1744       /*
 1745        * do the file currently exist in the translated fs ?
 1746        */
 1747     if( (instw->gstatus&INSTW_INITIALIZED) &&
 1748          (instw->gstatus&INSTW_OKTRANSL) && 
 1749          !true_stat(instw->translpath,&tinode) ) {
 1750         instw->status |= INSTW_ISINTRANSL;
 1751     }   
 1752 
 1753       /*
 1754        * is it a newly created file, or a modified one ?
 1755        */
 1756     if( instw->gstatus&INSTW_INITIALIZED &&
 1757         !true_stat(instw->reslvpath,&rinode) ) {
 1758         instw->status |= INSTW_ISINROOT;
 1759     }
 1760     
 1761       /*
 1762        *   if the file exists, why is it not referenced as 
 1763        * being translated ?
 1764        *   we have to reference it and all the traversed 
 1765        * directories leading to it.
 1766        */
 1767     if( (instw->gstatus&INSTW_INITIALIZED) &&
 1768         (instw->gstatus&INSTW_OKTRANSL) &&
 1769         (instw->status&INSTW_ISINTRANSL) &&
 1770         !(instw->status&INSTW_TRANSLATED) ) {
 1771         instw->status |= INSTW_TRANSLATED;
 1772         instw_setmetatransl(instw);
 1773     }    
 1774       
 1775       /*
 1776        *   are the public resolved path and its translated counterpart 
 1777        * identical ? if so, we flag it
 1778        */
 1779     if( (instw->gstatus & INSTW_INITIALIZED) &&
 1780         (instw->gstatus & INSTW_OKTRANSL) && 
 1781         (instw->status & INSTW_TRANSLATED) && 
 1782         (0==(strcmp(instw->truepath,instw->translpath))) ) {
 1783         instw->status |= INSTW_IDENTITY;  
 1784     }    
 1785 
 1786     *status=instw->status;
 1787 
 1788     return 0;
 1789 }
 1790 
 1791 /*
 1792  * procedure = / rc:=instw_apply(instw) /
 1793  *
 1794  * task      = /   actually do the translation prepared in 'transl' /
 1795  *
 1796  * note      = /   --after a call to instw_apply(), the translation related 
 1797  *                 status flags are updated. 
 1798  *                 --if a translation is requested and if the original file 
 1799  *                 exists, all parent directories are created and referenced
 1800  *                 if necessary.
 1801  *                   if the original file does not exist, we translate at
 1802  *                 least the existing path. /
 1803  *
 1804  * returns   = /  0 ok. translation done 
 1805  *               -1 failed. cf errno     /
 1806  */
 1807 static int instw_apply(instw_t *instw) {
 1808     int rcod=0;
 1809     int status=0;
 1810     
 1811     char dirpart[PATH_MAX+1];
 1812     char basepart[PATH_MAX+1];
 1813     char *pdir;
 1814     char *pbase;
 1815     struct stat reslvinfo;
 1816     instw_t iw;
 1817     char wpath[PATH_MAX+1];
 1818     size_t wsz=0;
 1819     char linkpath[PATH_MAX+1];
 1820 
 1821 
 1822 #if DEBUG
 1823     debug(2,"instw_apply(%p)\n",instw);
 1824     instw_print(instw);
 1825 #endif
 1826 
 1827       /* 
 1828        * if library incompletely initialized or if translation 
 1829        * is inactive, nothing to apply 
 1830        */
 1831     if( !(instw->gstatus&INSTW_INITIALIZED) ||
 1832         !(instw->gstatus&INSTW_OKTRANSL) )  finalize(0); 
 1833      
 1834       /* let's get the file translation status */
 1835     if(instw_getstatus(instw,&status)) finalize(-1);
 1836 
 1837       /* we ignore files already translated */
 1838     if(status & INSTW_TRANSLATED) return 0;
 1839 
 1840     strcpy(basepart,instw->reslvpath);
 1841     strcpy(dirpart,instw->reslvpath);
 1842     
 1843     pbase=basename(basepart);
 1844     pdir=dirname(dirpart);
 1845 
 1846       /* recursivity termination test, */
 1847     if(pdir[0]=='/' && pdir[1]=='\0' && pbase[0]=='\0') {
 1848         instw->status|=INSTW_TRANSLATED;
 1849         finalize(0);
 1850     }   
 1851     
 1852     instw_new(&iw); 
 1853     instw_setpath(&iw,pdir);
 1854     instw_apply(&iw);
 1855     instw_delete(&iw);
 1856 
 1857       /* will we have to copy the original file ? */
 1858     if(!true_lstat(instw->reslvpath,&reslvinfo)) {
 1859         copy_path(instw->reslvpath,instw->transl);
 1860 
 1861           /* a symlink ! we have to translate the target */
 1862         if(S_ISLNK(reslvinfo.st_mode)) {
 1863             wsz=true_readlink(instw->reslvpath,wpath,PATH_MAX);
 1864             wpath[wsz]='\0';
 1865 
 1866             instw_new(&iw);
 1867             if(wpath[0]!='/') { 
 1868                 strcpy(linkpath,pdir);
 1869                 strcat(linkpath,"/");
 1870                 strcat(linkpath,wpath);
 1871             } else {
 1872                 strcpy(linkpath,wpath);
 1873             }
 1874 
 1875             instw_setpath(&iw,linkpath);
 1876             instw_apply(&iw);
 1877             instw_delete(&iw);
 1878         }
 1879     }
 1880 
 1881     
 1882     instw->status|=INSTW_TRANSLATED;
 1883     instw_setmetatransl(instw);
 1884 
 1885     finalize:
 1886 
 1887     return rcod;
 1888 }
 1889 
 1890 /*
 1891  * procedure = / rc:=instw_filldirls(instw) /
 1892  *
 1893  * task      = /   used to create dummy entries in the mdirlspath reflecting 
 1894  *               the content that would have been accessible with no
 1895  *               active translation. /
 1896  *
 1897  * note      = / 
 1898  *  --This procedure must be called after instw_makedirls() has been 
 1899  *  called itself.
 1900  *  --It implies that the translated directory and the real one are
 1901  *      distincts, but it does not matter if one of them, or both is empty
 1902  * /
 1903  */
 1904 static int instw_filldirls(instw_t *instw) {
 1905     int rcod=0;
 1906     DIR *wdir;
 1907     struct dirent *went;
 1908     char spath[PATH_MAX+1];
 1909     char dpath[PATH_MAX+1];
 1910     char lpath[PATH_MAX+1];
 1911     struct stat sinfo;
 1912     struct stat dinfo;
 1913     int wfd;
 1914     size_t wsz;
 1915     instw_t iw_entry;
 1916     int status=0;
 1917 
 1918 #if DEBUG
 1919     debug(2,"instw_filldirls(%p)\n",instw);
 1920 #endif
 1921 
 1922     if((wdir=true_opendir(instw->translpath))==NULL) { return -1; } 
 1923     while((went=true_readdir(wdir))!=NULL) {
 1924         if(     went->d_name[0]=='.' && 
 1925             (   (went->d_name[1]=='\0') ||
 1926                 (   went->d_name[1]=='.' &&
 1927                     went->d_name[2]=='\0') ) ) 
 1928             { continue; }   
 1929 
 1930         strcpy(spath,instw->translpath);
 1931         strcat(spath,"/");
 1932         strcat(spath,went->d_name);
 1933         
 1934         if(true_lstat(spath,&sinfo)) { continue; }
 1935 
 1936         strcpy(dpath,instw->mdirlspath);
 1937         strcat(dpath,"/");
 1938         strcat(dpath,went->d_name);
 1939 
 1940           /* symbolic links */
 1941         if(S_ISLNK(sinfo.st_mode)) {
 1942             if((wsz=true_readlink(spath,lpath,PATH_MAX))>=0) { 
 1943                 lpath[wsz]='\0';
 1944                 true_symlink(lpath,dpath); 
 1945 #if DEBUG
 1946                 debug(4,"\tfilled symlink       : %s\n",dpath);
 1947 #endif
 1948             }
 1949                 
 1950         }
 1951 
 1952           /* regular file */
 1953         if(S_ISREG(sinfo.st_mode)) {
 1954             if((wfd=true_creat(dpath,sinfo.st_mode))>=0) {
 1955                 close(wfd); 
 1956 #if DEBUG
 1957                 debug(4,"\tfilled regular file  : %s\n",dpath);
 1958 #endif
 1959             }
 1960         }
 1961     
 1962           /* directory */
 1963         if(S_ISDIR(sinfo.st_mode)) {
 1964             true_mkdir(dpath,sinfo.st_mode);
 1965 #if DEBUG
 1966             debug(4,"\tfilled directory     : %s\n",dpath);
 1967 #endif
 1968 
 1969         }
 1970     
 1971           /* block special file */
 1972         if(S_ISBLK(sinfo.st_mode)) {
 1973             true_mknod(dpath,sinfo.st_mode|S_IFBLK,sinfo.st_rdev);
 1974 #if DEBUG
 1975             debug(4,"\tfilled special block : %s\n",dpath);
 1976 #endif
 1977 
 1978         }
 1979     
 1980           /* character special file */
 1981         if(S_ISCHR(sinfo.st_mode)) {
 1982             true_mknod(dpath,sinfo.st_mode|S_IFCHR,sinfo.st_rdev);
 1983 #if DEBUG
 1984             debug(4,"\tfilled special char  : %s\n",dpath);
 1985 #endif
 1986         }
 1987          
 1988           /* fifo special file */
 1989         if(S_ISFIFO(sinfo.st_mode)) {
 1990             true_mknod(dpath,sinfo.st_mode|S_IFIFO,0);
 1991 #if DEBUG
 1992             debug(4,"\tfilled special fifo  : %s\n",dpath);
 1993 #endif
 1994         }
 1995             
 1996     }
 1997     closedir(wdir);
 1998 
 1999     if((wdir=true_opendir(instw->reslvpath))==NULL) return -1;
 2000     while((went=true_readdir(wdir))!=NULL) {
 2001         if(     went->d_name[0]=='.' && 
 2002             (   (went->d_name[1]=='\0') ||
 2003                 (   went->d_name[1]=='.' &&
 2004                     went->d_name[2]=='\0') ) ) 
 2005             { continue; }   
 2006 
 2007         strcpy(spath,instw->reslvpath);
 2008         strcat(spath,"/");
 2009         strcat(spath,went->d_name);
 2010         if(true_lstat(spath,&sinfo)) { continue; }
 2011 
 2012         instw_new(&iw_entry);
 2013         instw_setpath(&iw_entry,spath);
 2014         instw_getstatus(&iw_entry,&status);
 2015 
 2016           /*
 2017            *   This entry exists in the real fs, but has been 
 2018            * translated and destroyed in the translated fs.
 2019            *   So, we mustn't present it !!!
 2020            */
 2021         if( (status & INSTW_TRANSLATED) &&
 2022             !(status & INSTW_ISINTRANSL) ) { continue; }
 2023 
 2024         strcpy(dpath,instw->mdirlspath);
 2025         strcat(dpath,"/");
 2026         strcat(dpath,went->d_name);
 2027     
 2028           /* already exists in the translated fs, we iterate */
 2029         if(!true_lstat(dpath,&dinfo)) { continue; }
 2030 
 2031           /* symbolic links */
 2032         if(S_ISLNK(sinfo.st_mode)) {
 2033             if((wsz=true_readlink(spath,lpath,PATH_MAX))>=0) {
 2034                 lpath[wsz]='\0';
 2035                 true_symlink(lpath,dpath);
 2036 #if DEBUG
 2037                 debug(4,"\tfilled symlink       : %s\n",dpath);
 2038 #endif
 2039             }
 2040         }
 2041 
 2042           /* regular file */
 2043         if(S_ISREG(sinfo.st_mode)) {
 2044             if((wfd=true_creat(dpath,sinfo.st_mode))>=0) {
 2045                 close(wfd); 
 2046 #if DEBUG
 2047                 debug(4,"\tfilled regular file  : %s\n",dpath);
 2048 #endif
 2049             }   
 2050         }
 2051     
 2052           /* directory */
 2053         if(S_ISDIR(sinfo.st_mode)) {
 2054             true_mkdir(dpath,sinfo.st_mode);
 2055 #if DEBUG
 2056             debug(4,"\tfilled directory     : %s\n",dpath);
 2057 #endif
 2058         }
 2059     
 2060           /* block special file */
 2061         if(S_ISBLK(sinfo.st_mode)) {
 2062             true_mknod(dpath,sinfo.st_mode|S_IFBLK,sinfo.st_rdev);
 2063 #if DEBUG
 2064             debug(4,"\tfilled special block : %s\n",dpath);
 2065 #endif
 2066         }
 2067     
 2068           /* character special file */
 2069         if(S_ISCHR(sinfo.st_mode)) {
 2070             true_mknod(dpath,sinfo.st_mode|S_IFCHR,sinfo.st_rdev);
 2071 #if DEBUG
 2072             debug(4,"\tfilled special char  : %s\n",dpath);
 2073 #endif
 2074         }
 2075          
 2076           /* fifo special file */
 2077         if(S_ISFIFO(sinfo.st_mode)) {
 2078             true_mknod(dpath,sinfo.st_mode|S_IFIFO,0);
 2079 #if DEBUG
 2080             debug(4,"\tfilled special fifo  : %s\n",dpath);
 2081 #endif
 2082         }
 2083         
 2084         instw_delete(&iw_entry);
 2085     }
 2086     closedir(wdir);
 2087 
 2088     return rcod;
 2089 }
 2090 
 2091 /*
 2092  * procedure = / rc:=instw_makedirls(instw) /
 2093  *
 2094  * task      = /   eventually prepares a fake temporary directory used to 
 2095  *               present 'overlaid' content to opendir(),readdir()... /
 2096  *
 2097  * note      = /
 2098  *      --This procedure must be called after instw_setpath(). 
 2099  *
 2100  *  --The "fake" temporary directories are created and...forgotten.
 2101  *      If we need to reuse later the same directory, it is previously 
 2102  *      erased, which ensures that it is correclty refreshed.
 2103  * /
 2104  *
 2105  * returns   = /  0 ok. makedirls done 
 2106  *               -1 failed. cf errno     /
 2107  */
 2108 static int instw_makedirls(instw_t *instw) {
 2109     int rcod=0;
 2110     int status=0;
 2111     struct stat translinfo;
 2112     struct stat dirlsinfo;
 2113     char wdirname[NAME_MAX+1];
 2114 
 2115 #if DEBUG
 2116     debug(2,"instw_makedirls(%p)\n",instw);
 2117 #endif
 2118 
 2119       /* 
 2120        * if library incompletely initialized or if translation 
 2121        * is inactive, nothing to do 
 2122        */
 2123     if( !(instw->gstatus&INSTW_INITIALIZED) ||
 2124         !(instw->gstatus&INSTW_OKTRANSL)) {
 2125         strcpy(instw->mdirlspath,instw->path);
 2126         return 0; 
 2127     } 
 2128      
 2129       /* let's get the file translation status */
 2130     if(instw_getstatus(instw,&status)) return -1;
 2131 
 2132     if( !(status&INSTW_TRANSLATED) ||
 2133         ((status&INSTW_TRANSLATED) && (status&INSTW_IDENTITY)) ) {
 2134         strcpy(instw->mdirlspath,instw->path);
 2135     } else {
 2136           /*   if it's a new directory, we open it in 
 2137            * the translated fs .
 2138            *   otherwise, it means that we will have to construct a
 2139            * merged directory.
 2140            */
 2141         if(!(status & INSTW_ISINROOT)) {
 2142             strcpy(instw->mdirlspath,instw->translpath);
 2143         } else {
 2144             rcod=true_stat(instw->translpath,&translinfo);
 2145 
 2146             sprintf(wdirname,"/%d_%lld_%lld",
 2147                     instw->pid,
 2148                     (long long int) translinfo.st_dev,
 2149                     (long long int) translinfo.st_ino);
 2150         
 2151             strcpy(instw->mdirlspath,instw->mdirls);
 2152             strcat(instw->mdirlspath,wdirname);
 2153 
 2154               /* we erase a previous identical dirls */
 2155             if(!true_stat(instw->mdirlspath,&dirlsinfo)) {
 2156                 unlink_recursive(instw->mdirlspath);
 2157             }
 2158             true_mkdir(instw->mdirlspath,S_IRWXU);
 2159     
 2160               /* we construct the merged directory here */
 2161             instw_filldirls(instw);
 2162         }
 2163     }
 2164 
 2165 #if DEBUG
 2166     instw_print(instw);
 2167 #endif
 2168 
 2169     return rcod;
 2170 }
 2171 
 2172 /* 
 2173  *
 2174  */
 2175 static int backup(const char *path) {
 2176     char checkdir[BUFSIZ];
 2177     char backup_path[BUFSIZ];
 2178     int placeholder,
 2179         i,
 2180         blen;
 2181     struct stat inode,backup_inode;
 2182     struct utimbuf timbuf;
 2183 
 2184 #if DEBUG
 2185     debug(2,"========= backup () =========  path: %s\n", path); 
 2186 #endif
 2187 
 2188       /* INSTW_OKBACKUP not set, we won't do any backups */
 2189     if (!(__instw.gstatus&INSTW_OKBACKUP)) {
 2190         #ifdef DEBUG
 2191         debug(3,"Backup not enabled, path: %s\n", path);
 2192         #endif
 2193         return 0;
 2194     }
 2195 
 2196     /* Check if this is inside /dev */
 2197     if (strstr (path, "/dev") == path) {
 2198         #if DEBUG
 2199         debug(3,"%s is inside /dev. Ignoring.\n", path);
 2200         #endif
 2201         return 0; 
 2202     }
 2203 
 2204     /* Now check for /tmp */
 2205     if (strstr (path, "/tmp") == path) {
 2206         #if DEBUG
 2207         debug(3,"%s is inside /tmp. Ignoring.\n", path);
 2208         #endif
 2209         return 0; 
 2210     }
 2211 
 2212     /* Finally, the backup path itself */
 2213     if (strstr (path,__instw.backup ) == path) {
 2214         #if DEBUG
 2215         debug(3,"%s is inside the backup path. Ignoring.\n", path);
 2216         #endif
 2217         return 0; 
 2218     }
 2219 
 2220     /* Does it exist already? */
 2221     #if DEBUG
 2222     debug(3,"Exists %s?\n", path);
 2223     #endif
 2224     if (true_stat(path, &inode) < 0) {
 2225 
 2226         /* It doesn't exist, we'll tag it so we won't back it up  */
 2227         /* if we run into it later                                */
 2228 
 2229         strcpy(backup_path,__instw.backup );
 2230         strncat(backup_path, "/no-backup", 11);
 2231         strcat(backup_path, path);
 2232         make_path(backup_path);
 2233 
 2234         /* This one's just a placeholder */
 2235         placeholder = true_creat(backup_path, S_IREAD);  
 2236         if (!(placeholder < 0)) close (placeholder);
 2237 
 2238         #if DEBUG
 2239         debug(3,"does not exist\n");
 2240         #endif
 2241         return 0;
 2242     }
 2243 
 2244 
 2245     /* Is this one tagged for no backup (i.e. it didn't previously exist)? */
 2246     strcpy (backup_path,__instw.backup);
 2247     strncat (backup_path, "/no-backup", 11);
 2248     strcat (backup_path, path);
 2249 
 2250     if (true_stat (backup_path, &backup_inode) >= 0) {
 2251         #if DEBUG
 2252         debug(3,"%s should not be backed up\n", backup_path);
 2253         #endif
 2254         return 0;
 2255     }
 2256 
 2257 
 2258     #if DEBUG
 2259     debug(3,"Exists in real path. Lets see what it is.\n");
 2260     #endif
 2261 
 2262     /* Append the path to the backup_path */
 2263     strcpy (backup_path,__instw.backup);
 2264     strcat (backup_path, path);
 2265 
 2266     /* Create the directory tree for this file in the backup dir */
 2267     make_path (backup_path);
 2268 
 2269       /* let's backup the source file */
 2270     if(copy_path(path,__instw.backup))
 2271         return -1;
 2272 
 2273       /* Check the owner and permission of the created directories */
 2274     i=0;
 2275     blen = strlen (__instw.backup);
 2276     while ( path[i] != '\0' ) {
 2277         checkdir[i] = backup_path[blen+i] = path[i];
 2278         if (checkdir[i] == '/') {  /* Each time a '/' is found, check if the    */
 2279             checkdir[i+1] = '\0';   /* path exists. If it does, set it's perms.  */
 2280             if (!true_stat (checkdir, &inode)) {
 2281             backup_path[blen+i+1]='\0';
 2282             timbuf.actime=inode.st_atime;
 2283             timbuf.modtime=inode.st_mtime;
 2284             true_utime(backup_path, &timbuf);
 2285             true_chmod(backup_path, inode.st_mode);
 2286             true_chown(backup_path, inode.st_uid, inode.st_gid);
 2287             }
 2288         }
 2289         i++;
 2290     }
 2291     
 2292     return 0;
 2293 }
 2294 
 2295 time_t time (time_t *timer) {
 2296     TIMECOUNT;
 2297 
 2298     if (!libc_handle)
 2299         initialize();
 2300 
 2301 #if DEBUG
 2302     debug(2,"time\n");
 2303 #endif
 2304 
 2305 return true_time(timer);
 2306 }
 2307 
 2308 /* 
 2309  * *****************************************************************************
 2310  */
 2311 
 2312 int chdir(const char *pathname) {
 2313     int result;
 2314     instw_t instw;
 2315     int status;
 2316 
 2317     if (!libc_handle)
 2318         initialize();
 2319 
 2320 #if DEBUG
 2321     debug(2,"chdir(%s)\n",pathname);
 2322 #endif
 2323 
 2324       /* We were asked to work in "real" mode */
 2325     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2326         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2327         result=true_chdir(pathname);
 2328         return result;
 2329     }    
 2330 
 2331     instw_new(&instw);
 2332     instw_setpath(&instw,pathname);
 2333     instw_getstatus(&instw,&status);
 2334 
 2335     if(status&INSTW_TRANSLATED && !(status&INSTW_ISINROOT)) {
 2336         result=true_chdir(instw.translpath);
 2337         debug(3,"\teffective chdir(%s)\n",instw.translpath);
 2338     } else {
 2339         result=true_chdir(pathname);
 2340         debug(3,"\teffective chdir(%s)\n",pathname);
 2341     }
 2342 
 2343     instw_delete(&instw);
 2344 
 2345     return result;
 2346 }
 2347 
 2348 int chmod(const char *path, mode_t mode) {
 2349     int result;
 2350     instw_t instw;
 2351 
 2352     REFCOUNT;
 2353     
 2354     if (!libc_handle)
 2355         initialize();
 2356 
 2357 #if DEBUG
 2358     debug(2,"chmod(%s,mode)\n",path);
 2359 #endif
 2360 
 2361       /* We were asked to work in "real" mode */
 2362     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2363         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2364         result=true_chmod(path,mode);
 2365         return result;
 2366     }
 2367 
 2368     instw_new(&instw);
 2369     instw_setpath(&instw,path);
 2370 
 2371 #if DEBUG
 2372     instw_print(&instw);
 2373 #endif
 2374 
 2375     backup (instw.truepath);
 2376     instw_apply(&instw);
 2377 
 2378     result = true_chmod(instw.translpath, mode);
 2379     logg("%d\tchmod\t%s\t0%04o\t#%s\n",result,
 2380         instw.reslvpath,mode,error(result));
 2381 
 2382     instw_delete(&instw);
 2383 
 2384     return result;
 2385 }
 2386 
 2387 int chown(const char *path, uid_t owner, gid_t group) {
 2388     int result;
 2389     instw_t instw;
 2390 
 2391     REFCOUNT;
 2392 
 2393     if (!libc_handle)
 2394         initialize();
 2395 
 2396 #if DEBUG
 2397     debug(2,"chown(%s,owner,group)\n",path);
 2398 #endif
 2399 
 2400       /* We were asked to work in "real" mode */
 2401     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2402         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2403         result=true_chown(path,owner,group);
 2404         return result;
 2405     }
 2406 
 2407     instw_new(&instw);
 2408     instw_setpath(&instw,path);
 2409 
 2410 #if DEBUG
 2411     instw_print(&instw);
 2412 #endif
 2413 
 2414     backup(instw.truepath);
 2415     instw_apply(&instw);
 2416 
 2417     result=true_chown(instw.translpath,owner,group);
 2418     logg("%d\tchown\t%s\t%d\t%d\t#%s\n",result,
 2419         instw.reslvpath,owner,group,error(result));
 2420 
 2421     instw_delete(&instw);
 2422 
 2423     return result;
 2424 }
 2425 
 2426 
 2427 int chown32(const char *path, uid_t owner, gid_t group) {
 2428 
 2429    return chown(path, owner, group);
 2430 
 2431 }
 2432 
 2433 int chroot(const char *path) {
 2434     int result;
 2435     char canonic[MAXPATHLEN];
 2436 
 2437     REFCOUNT;
 2438 
 2439     if (!libc_handle)
 2440         initialize();
 2441 
 2442 #if DEBUG
 2443     debug(2,"chroot(%s)\n",path);
 2444 #endif
 2445 
 2446     canonicalize(path, canonic);
 2447     result = true_chroot(path);
 2448       /*
 2449        * From now on, another log file will be written if 
 2450        * INSTW_LOGFILE is set                          
 2451        */
 2452     logg("%d\tchroot\t%s\t#%s\n", result, canonic, error(result));
 2453     return result;
 2454 }
 2455 
 2456 int creat(const char *pathname, mode_t mode) {
 2457 /* Is it a system call? */
 2458     int result;
 2459     instw_t instw;
 2460     
 2461     REFCOUNT;
 2462 
 2463     if (!libc_handle)
 2464         initialize();
 2465 
 2466 #if DEBUG
 2467     debug(2,"creat(%s,mode)\n",pathname);
 2468 #endif
 2469     
 2470       /* We were asked to work in "real" mode */
 2471     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2472         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2473         result=true_creat(pathname,mode);
 2474         return result;
 2475     }
 2476 
 2477     instw_new(&instw);
 2478     instw_setpath(&instw,pathname);
 2479 
 2480 #if DEBUG
 2481     instw_print(&instw);
 2482 #endif
 2483 
 2484     backup(instw.truepath);
 2485     instw_apply(&instw);
 2486 
 2487     result = true_open(instw.translpath,O_CREAT|O_WRONLY|O_TRUNC,mode);
 2488     logg("%d\tcreat\t%s\t#%s\n",result,instw.reslvpath,error(result));
 2489 
 2490     instw_delete(&instw);
 2491 
 2492     return result;
 2493 }
 2494 
 2495 int fchmod(int filedes, mode_t mode) {
 2496     int result;
 2497 
 2498     REFCOUNT;
 2499 
 2500     if (!libc_handle)
 2501         initialize();
 2502 
 2503 #if DEBUG
 2504     debug(2,"fchmod\n");
 2505 #endif
 2506 
 2507     result = true_fchmod(filedes, mode);
 2508     logg("%d\tfchmod\t%d\t0%04o\t#%s\n",result,filedes,mode,error(result));
 2509     return result;
 2510 }
 2511 
 2512 int fchown(int fd, uid_t owner, gid_t group) {
 2513     int result;
 2514 
 2515     REFCOUNT;
 2516 
 2517     if (!libc_handle)
 2518         initialize();
 2519 
 2520 #if DEBUG
 2521     debug(2,"fchown\n");
 2522 #endif
 2523 
 2524     result = true_fchown(fd, owner, group);
 2525     logg("%d\tfchown\t%d\t%d\t%d\t#%s\n",result,fd,owner,group,error(result));
 2526     return result;
 2527 }
 2528 
 2529 FILE *fopen(const char *pathname, const char *mode) {
 2530     FILE *result;
 2531     instw_t instw;
 2532     int status=0;
 2533 
 2534     REFCOUNT;
 2535 
 2536     if (!libc_handle)
 2537         initialize();
 2538 
 2539 #if DEBUG
 2540     debug(2,"fopen(%s,%s)\n",pathname,mode);
 2541 #endif
 2542 
 2543       /* We were asked to work in "real" mode */
 2544     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2545         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2546         result=true_fopen(pathname,mode);
 2547         return result;
 2548     }
 2549 
 2550     instw_new(&instw);
 2551     instw_setpath(&instw,pathname);
 2552     
 2553 #if DEBUG
 2554     instw_print(&instw);
 2555 #endif
 2556 
 2557     if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+') {
 2558         backup(instw.truepath);
 2559         instw_apply(&instw);
 2560         logg("%" PRIdPTR "\tfopen\t%s\t#%s\n",(intptr_t)result,
 2561             instw.reslvpath,error(result));
 2562     }
 2563 
 2564     instw_getstatus(&instw,&status);
 2565     
 2566     if(status&INSTW_TRANSLATED) {
 2567         debug(4,"\teffective fopen(%s)\n",instw.translpath);
 2568         result=true_fopen(instw.translpath,mode); 
 2569     } else {
 2570         debug(4,"\teffective fopen(%s)\n",instw.path);
 2571         result=true_fopen(instw.path,mode);
 2572     }
 2573     
 2574     if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+') 
 2575         logg("%" PRIdPTR "\tfopen\t%s\t#%s\n",(intptr_t)result,
 2576             instw.reslvpath,error(result));
 2577 
 2578     instw_delete(&instw);
 2579 
 2580     return result;
 2581 }
 2582 
 2583 int ftruncate(int fd, TRUNCATE_T length) {
 2584     int result;
 2585 
 2586     REFCOUNT;
 2587 
 2588     if (!libc_handle)
 2589         initialize();
 2590 
 2591 #if DEBUG
 2592     debug(2,"ftruncate\n");
 2593 #endif
 2594 
 2595     result = true_ftruncate(fd, length);
 2596     logg("%d\tftruncate\t%d\t%d\t#%s\n",result,fd,(int)length,error(result));
 2597     return result;
 2598 }
 2599 
 2600 char *getcwd(char *buffer,size_t size) {
 2601     char wpath[PATH_MAX+1];
 2602     char *result;
 2603     char *wptr;
 2604     size_t wsize;
 2605 
 2606     if (!libc_handle)
 2607         initialize();
 2608 
 2609 #if DEBUG
 2610     debug(2,"getcwd(%p,%ld)\n",buffer,(long int)size);
 2611 #endif
 2612 
 2613       /* We were asked to work in "real" mode */
 2614     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2615         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2616         result=true_getcwd(buffer,size);
 2617         return result;
 2618     }
 2619 
 2620     if( __instw.gstatus&INSTW_INITIALIZED &&
 2621         __instw.gstatus&INSTW_OKTRANSL && 
 2622         (NULL!=(result=true_getcwd(wpath,sizeof(wpath)))) ) {
 2623           /* we untranslate any translated path */
 2624         if(strstr(wpath,__instw.transl)==wpath) {
 2625             wptr=wpath+strlen(__instw.transl);
 2626             wsize=strlen(wptr)+1;
 2627         } else {
 2628             wptr=wpath;
 2629             wsize=strlen(wptr)+1;
 2630         }
 2631 
 2632         if (buffer == NULL) {
 2633             if (size !=0 && size < wsize) {
 2634                 result=NULL;
 2635                 errno=(size<=0?EINVAL:ERANGE);
 2636             } else {
 2637                 result=malloc(wsize);
 2638                 if(result == NULL) {
 2639                     errno=ENOMEM;
 2640                 } else {
 2641                     strcpy(result,wptr);
 2642                 }
 2643             }
 2644         } else {
 2645             if(size>=wsize) {
 2646                 strcpy(buffer,wptr);
 2647             } else {
 2648                 result=NULL;
 2649                 errno=(size<=0?EINVAL:ERANGE);
 2650             }
 2651         }
 2652     } else  {
 2653         result=true_getcwd(buffer,size);
 2654     }
 2655 
 2656 #if DEBUG
 2657     debug(3,"\teffective getcwd(%s,%ld)\n",
 2658           (result?buffer:"(null)"),(long int)size);
 2659 #endif  
 2660 
 2661     return result;
 2662 }
 2663 
 2664 int lchown(const char *path, uid_t owner, gid_t group) {
 2665 /* Linux specific? */
 2666     int result;
 2667     instw_t instw;
 2668 
 2669     REFCOUNT;
 2670 
 2671     if (!libc_handle)
 2672         initialize();
 2673 
 2674 #if DEBUG
 2675     debug(2,"lchown(%s,owner,group)\n",path);
 2676 #endif
 2677 
 2678       /* We were asked to work in "real" mode */
 2679     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2680         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2681         result=true_lchown(path,owner,group);
 2682         return result;
 2683     }
 2684 
 2685     instw_new(&instw);
 2686     instw_setpath(&instw,path);
 2687     
 2688 #if DEBUG
 2689     instw_print(&instw);
 2690 #endif
 2691 
 2692     backup(instw.truepath);
 2693     instw_apply(&instw);
 2694 
 2695     result=true_lchown(instw.translpath,owner,group);
 2696     logg("%d\tlchown\t%s\t%d\t%d\t#%s\n",result,
 2697         instw.reslvpath,owner,group,error(result));
 2698         
 2699     instw_delete(&instw);
 2700 
 2701     return result;
 2702 }
 2703 
 2704 int link(const char *oldpath, const char *newpath) {
 2705     int result;
 2706     instw_t instw_o;
 2707     instw_t instw_n;
 2708 
 2709     REFCOUNT;
 2710 
 2711     if (!libc_handle)
 2712         initialize();
 2713 
 2714 #if DEBUG
 2715     debug(2,"link(%s,%s)\n",oldpath,newpath);
 2716 #endif
 2717 
 2718       /* We were asked to work in "real" mode */
 2719     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2720         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2721         result=true_link(oldpath,newpath);
 2722         return result;
 2723     }
 2724 
 2725     instw_new(&instw_o);
 2726     instw_new(&instw_n);
 2727     instw_setpath(&instw_o,oldpath);
 2728     instw_setpath(&instw_n,newpath);
 2729 
 2730 #if DEBUG
 2731     instw_print(&instw_o);
 2732     instw_print(&instw_n);
 2733 #endif
 2734 
 2735     backup(instw_o.truepath);
 2736     instw_apply(&instw_o);
 2737     instw_apply(&instw_n);
 2738     
 2739     result=true_link(instw_o.translpath,instw_n.translpath);
 2740     logg("%d\tlink\t%s\t%s\t#%s\n",result,
 2741         instw_o.reslvpath,instw_n.reslvpath,error(result));
 2742         
 2743     instw_delete(&instw_o);
 2744     instw_delete(&instw_n);
 2745 
 2746     return result;
 2747 }
 2748 
 2749 int mkdir(const char *pathname, mode_t mode) {
 2750     int result;
 2751     instw_t instw;
 2752 
 2753     REFCOUNT;
 2754 
 2755     if (!libc_handle)
 2756         initialize();
 2757 
 2758 #if DEBUG
 2759     debug(2,"mkdir(%s,mode)\n",pathname);
 2760 #endif
 2761 
 2762       /* We were asked to work in "real" mode */
 2763     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2764         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2765         result=true_mkdir(pathname,mode);
 2766         return result;
 2767     }
 2768 
 2769     instw_new(&instw);
 2770     instw_setpath(&instw,pathname);
 2771 
 2772 #if DEBUG
 2773     instw_print(&instw);
 2774 #endif
 2775 
 2776     instw_apply(&instw);
 2777 
 2778     result=true_mkdir(instw.translpath,mode);
 2779     logg("%d\tmkdir\t%s\t#%s\n",result,instw.reslvpath,error(result));
 2780 
 2781     instw_delete(&instw);
 2782 
 2783     return result;
 2784 }
 2785 
 2786 int __xmknod(int version,const char *pathname, mode_t mode,dev_t *dev) {
 2787     int result;
 2788     instw_t instw;
 2789     
 2790     REFCOUNT;
 2791 
 2792     if (!libc_handle)
 2793         initialize();
 2794 
 2795 #if DEBUG
 2796     debug(2,"mknod(%s,mode,dev)\n",pathname);
 2797 #endif
 2798 
 2799       /* We were asked to work in "real" mode */
 2800     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2801         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2802         result=true_xmknod(version,pathname,mode,dev);
 2803         return result;
 2804     }
 2805 
 2806     instw_new(&instw);
 2807     instw_setpath(&instw,pathname);
 2808 
 2809 #if DEBUG
 2810     instw_print(&instw);
 2811 #endif
 2812 
 2813     instw_apply(&instw);
 2814     backup(instw.truepath);
 2815 
 2816     result=true_xmknod(version,instw.translpath,mode,dev);
 2817     logg("%d\tmknod\t%s\t#%s\n",result,instw.reslvpath,error(result));
 2818 
 2819     instw_delete(&instw);
 2820     
 2821     return result;
 2822 }
 2823 
 2824 int open(const char *pathname, int flags, ...) {
 2825 /* Eventually, there is a third parameter: it's mode_t mode */
 2826     va_list ap;
 2827     mode_t mode;
 2828     int result;
 2829     instw_t instw;
 2830     int status;
 2831 
 2832     REFCOUNT;
 2833 
 2834     if (!libc_handle)
 2835         initialize();
 2836 
 2837 #if DEBUG
 2838     debug(2,"open(%s,%d,mode)\n",pathname,flags);
 2839 #endif
 2840 
 2841     va_start(ap, flags);
 2842     mode = va_arg(ap, mode_t);
 2843     va_end(ap);
 2844 
 2845       /* We were asked to work in "real" mode */
 2846     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2847         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2848         result=true_open(pathname,flags,mode);
 2849         return result;
 2850     }
 2851 
 2852     instw_new(&instw);
 2853     instw_setpath(&instw,pathname);
 2854     
 2855 #if DEBUG
 2856     instw_print(&instw);
 2857 #endif
 2858 
 2859     if(flags & (O_WRONLY | O_RDWR)) {
 2860         backup(instw.truepath);
 2861         instw_apply(&instw);
 2862     }
 2863 
 2864     instw_getstatus(&instw,&status);
 2865 
 2866     if(status&INSTW_TRANSLATED) 
 2867         result=true_open(instw.translpath,flags,mode);
 2868     else
 2869         result=true_open(instw.path,flags,mode);
 2870     
 2871     if(flags & (O_WRONLY | O_RDWR)) 
 2872         logg("%d\topen\t%s\t#%s\n",result,instw.reslvpath,error(result));
 2873 
 2874     instw_delete(&instw);
 2875 
 2876     return result;
 2877 }
 2878 
 2879 /*
 2880  *
 2881  */
 2882 DIR *opendir(const char *dirname) {
 2883     DIR *result;
 2884     instw_t instw;
 2885 
 2886     if (!libc_handle)
 2887         initialize();
 2888 
 2889 #if DEBUG
 2890     debug(2,"opendir(%s)\n",dirname);
 2891 #endif
 2892     
 2893       /* We were asked to work in "real" mode */
 2894     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2895         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2896         result=true_opendir(dirname);
 2897         return result;
 2898     }
 2899 
 2900     instw_new(&instw);
 2901     instw_setpath(&instw,dirname);
 2902     instw_makedirls(&instw);
 2903 
 2904 #if DEBUG
 2905     instw_print(&instw);
 2906 #endif
 2907 
 2908     result=true_opendir(instw.mdirlspath);
 2909 
 2910     instw_delete(&instw);
 2911 
 2912     return result;
 2913 }
 2914 
 2915 struct dirent *readdir(DIR *dir) {
 2916     struct dirent *result;
 2917 
 2918     if (!libc_handle)
 2919         initialize();
 2920 
 2921 #if DEBUG
 2922     debug(3,"readdir(%p)\n",dir);
 2923 #endif
 2924 
 2925       /* We were asked to work in "real" mode */
 2926     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2927         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2928         result=true_readdir(dir);
 2929         return result;
 2930     }
 2931 
 2932     result=true_readdir(dir);
 2933 
 2934 #if DEBUG
 2935     __instw_printdirent(result);
 2936 #endif
 2937 
 2938     return result;
 2939 }
 2940 
 2941 #if (GLIBC_MINOR <= 4)
 2942 int readlink(const char *path,char *buf,size_t bufsiz) {
 2943     int result;
 2944 #else
 2945 ssize_t readlink(const char *path,char *buf,size_t bufsiz) {
 2946     ssize_t result;
 2947 #endif
 2948     instw_t instw;
 2949     int status;
 2950 
 2951     if (!libc_handle)
 2952         initialize();
 2953 
 2954 #if DEBUG
 2955     debug(2,"readlink(\"%s\",%p,%ld)\n",path,buf,(long int)bufsiz);
 2956 #endif
 2957 
 2958       /* We were asked to work in "real" mode */
 2959     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2960         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2961         result=true_readlink(path,buf,bufsiz);
 2962         return result;
 2963     }
 2964 
 2965     instw_new(&instw);
 2966     instw_setpath(&instw,path);
 2967     instw_getstatus(&instw,&status);
 2968     
 2969 #if DEBUG
 2970     instw_print(&instw);
 2971 #endif
 2972 
 2973     if(status&INSTW_TRANSLATED)
 2974         result=true_readlink(instw.translpath,buf,bufsiz);
 2975     else
 2976         result=true_readlink(instw.path,buf,bufsiz);
 2977 
 2978     instw_delete(&instw);
 2979 
 2980     return result;  
 2981 }
 2982 
 2983 char *realpath(const char *file_name,char *resolved_name) {
 2984     char *result;
 2985 
 2986     if (!libc_handle)
 2987         initialize();
 2988 
 2989       /* We were asked to work in "real" mode */
 2990     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 2991         !(__instw.gstatus & INSTW_OKWRAP) ) {
 2992         result=true_realpath(file_name,resolved_name);
 2993         return result;
 2994     }
 2995 
 2996     result=true_realpath(file_name,resolved_name);
 2997 
 2998     return result;
 2999 }
 3000 
 3001 int rename(const char *oldpath, const char *newpath) {
 3002     int result;
 3003     instw_t oldinstw;
 3004     instw_t newinstw;
 3005 
 3006     REFCOUNT;
 3007     
 3008     if (!libc_handle)
 3009         initialize();
 3010 
 3011 #if DEBUG
 3012     debug(2,"rename(\"%s\",\"%s\")\n",oldpath,newpath); 
 3013 #endif
 3014 
 3015       /* We were asked to work in "real" mode */
 3016     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3017         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3018         result=true_rename(oldpath,newpath);
 3019         return result;
 3020     }
 3021 
 3022     instw_new(&oldinstw);
 3023     instw_new(&newinstw);
 3024     instw_setpath(&oldinstw,oldpath);
 3025     instw_setpath(&newinstw,newpath);
 3026 
 3027 #if DEBUG
 3028     instw_print(&oldinstw);
 3029     instw_print(&newinstw);
 3030 #endif
 3031 
 3032     backup(oldinstw.truepath);
 3033     instw_apply(&oldinstw);
 3034     instw_apply(&newinstw);
 3035 
 3036     result=true_rename(oldinstw.translpath,newinstw.translpath);
 3037     logg("%d\trename\t%s\t%s\t#%s\n",result,
 3038         oldinstw.reslvpath,newinstw.reslvpath,error(result));
 3039 
 3040     instw_delete(&oldinstw);
 3041     instw_delete(&newinstw);
 3042 
 3043     return result;
 3044 }
 3045 
 3046 int rmdir(const char *pathname) {
 3047     int result;
 3048     instw_t instw;
 3049 
 3050     REFCOUNT;
 3051 
 3052     if (!libc_handle)
 3053         initialize();
 3054 
 3055 #if DEBUG
 3056     debug(2,"rmdir(%s)\n",pathname);
 3057 #endif
 3058 
 3059       /* We were asked to work in "real" mode */
 3060     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3061         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3062         result=true_rmdir(pathname);
 3063         return result;
 3064     }
 3065 
 3066     instw_new(&instw);
 3067     instw_setpath(&instw,pathname);
 3068 
 3069     backup(instw.truepath);
 3070     instw_apply(&instw);
 3071 
 3072     result=true_rmdir(instw.translpath);
 3073     logg("%d\trmdir\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3074     
 3075     instw_delete(&instw);
 3076     
 3077     return result;
 3078 }
 3079 
 3080 int scandir(    const char *dir,struct dirent ***namelist,
 3081         int (*select)(const struct dirent *),
 3082         int (*compar)(const void *,const void *)    ) {
 3083     int result;
 3084 
 3085     if (!libc_handle)
 3086         initialize();
 3087 
 3088 #if DEBUG
 3089     debug(2,"scandir(%s,%p,%p,%p)\n",dir,namelist,select,compar);
 3090 #endif
 3091 
 3092       /* We were asked to work in "real" mode */
 3093     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3094         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3095         result=true_scandir(dir,namelist,select,compar);
 3096         return result;
 3097     }
 3098 
 3099     result=true_scandir(dir,namelist,select,compar);
 3100 
 3101     return result;
 3102 }       
 3103 
 3104 int __xstat(int version,const char *pathname,struct stat *info) {
 3105     int result;
 3106     instw_t instw;
 3107     int status;
 3108 
 3109     if (!libc_handle)
 3110         initialize();
 3111 
 3112 #if DEBUG
 3113     debug(2,"stat(%s,%p)\n",pathname,info);
 3114 #endif
 3115 
 3116       /* We were asked to work in "real" mode */
 3117     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3118         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3119         result=true_xstat(version,pathname,info);
 3120         return result;
 3121     }
 3122 
 3123     instw_new(&instw);
 3124     instw_setpath(&instw,pathname);
 3125     instw_getstatus(&instw,&status);
 3126 
 3127 #if DEBUG
 3128     instw_print(&instw);
 3129 #endif
 3130 
 3131     if(status&INSTW_TRANSLATED) {
 3132         debug(4,"\teffective stat(%s,%p)\n",
 3133               instw.translpath,info);
 3134         result=true_xstat(version,instw.translpath,info);
 3135     } else {
 3136         debug(4,"\teffective stat(%s,%p)\n",
 3137               instw.path,info);
 3138         result=true_xstat(version,instw.path,info);
 3139     }
 3140 
 3141     instw_delete(&instw);
 3142 
 3143     return result;  
 3144 }
 3145 
 3146 int __lxstat(int version,const char *pathname,struct stat *info) {
 3147     int result;
 3148     instw_t instw;
 3149     int status;
 3150 
 3151     if (!libc_handle)
 3152         initialize();
 3153 
 3154 #if DEBUG
 3155     debug(2,"lstat(%s,%p)\n",pathname,info);
 3156 #endif
 3157 
 3158       /* We were asked to work in "real" mode */
 3159     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3160         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3161         result=true_lxstat(version,pathname,info);
 3162         return result;
 3163     }
 3164 
 3165     instw_new(&instw);
 3166     instw_setpath(&instw,pathname);
 3167     instw_getstatus(&instw,&status);
 3168 
 3169 #if DEBUG
 3170     instw_print(&instw);
 3171 #endif
 3172 
 3173     if(status&INSTW_TRANSLATED) {
 3174         debug(4,"\teffective lstat(%s,%p)\n",
 3175             instw.translpath,info);
 3176         result=true_lxstat(version,instw.translpath,info);
 3177     } else {
 3178         debug(4,"\teffective lstat(%s,%p)\n",
 3179             instw.path,info);
 3180         result=true_lxstat(version,instw.path,info);
 3181     }
 3182 
 3183     instw_delete(&instw);
 3184 
 3185     return result;  
 3186 }
 3187 
 3188 int symlink(const char *pathname, const char *slink) {
 3189     int result;
 3190     instw_t instw;
 3191     instw_t instw_slink;
 3192 
 3193     REFCOUNT;
 3194 
 3195     if (!libc_handle)
 3196         initialize();
 3197 
 3198 #if DEBUG
 3199     debug(2,"symlink(%s,%s)\n",pathname,slink);
 3200 #endif
 3201 
 3202       /* We were asked to work in "real" mode */
 3203     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3204         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3205         result=true_symlink(pathname,slink);
 3206         return result;
 3207     }
 3208 
 3209     instw_new(&instw);
 3210     instw_new(&instw_slink);
 3211     instw_setpath(&instw,pathname);
 3212     instw_setpath(&instw_slink,slink);
 3213 
 3214 #if DEBUG
 3215     instw_print(&instw_slink);
 3216 #endif
 3217 
 3218     backup(instw_slink.truepath);
 3219     instw_apply(&instw_slink);
 3220     
 3221     result=true_symlink(pathname,instw_slink.translpath);
 3222     logg("%d\tsymlink\t%s\t%s\t#%s\n",
 3223            result,instw.path,instw_slink.reslvpath,error(result));
 3224 
 3225         
 3226     instw_delete(&instw);
 3227     instw_delete(&instw_slink);
 3228 
 3229     return result;
 3230 }
 3231 
 3232 int truncate(const char *path, TRUNCATE_T length) {
 3233     int result;
 3234     instw_t instw;
 3235 
 3236     REFCOUNT;
 3237 
 3238     if (!libc_handle)
 3239         initialize();
 3240 
 3241 #if DEBUG
 3242     debug(2,"truncate(%s,length)\n",path);
 3243 #endif
 3244 
 3245       /* We were asked to work in "real" mode */
 3246     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3247         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3248         result=true_truncate(path,length);
 3249         return result;
 3250     }
 3251 
 3252     instw_new(&instw);
 3253     instw_setpath(&instw,path);
 3254 
 3255 #if DEBUG
 3256     instw_print(&instw);
 3257 #endif
 3258 
 3259     backup(instw.truepath);
 3260     instw_apply(&instw);
 3261 
 3262     result=true_truncate(instw.translpath,length);
 3263     logg("%d\ttruncate\t%s\t%d\t#%s\n",result,
 3264         instw.reslvpath,(int)length,error(result));
 3265 
 3266     instw_delete(&instw);
 3267 
 3268     return result;
 3269 }
 3270 
 3271 int unlink(const char *pathname) {
 3272     int result;
 3273     instw_t instw;
 3274 
 3275     REFCOUNT;
 3276 
 3277     if (!libc_handle)
 3278         initialize();
 3279 
 3280 #if DEBUG
 3281     debug(2,"unlink(%s)\n",pathname);
 3282 #endif
 3283 
 3284       /* We were asked to work in "real" mode */
 3285     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3286         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3287         result=true_unlink(pathname);
 3288         return result;
 3289     }
 3290 
 3291     instw_new(&instw);
 3292     instw_setpath(&instw,pathname);
 3293 
 3294 #if DEBUG
 3295     instw_print(&instw);
 3296 #endif
 3297 
 3298     backup(instw.truepath);
 3299     instw_apply(&instw);
 3300 
 3301     result=true_unlink(instw.translpath);
 3302     logg("%d\tunlink\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3303 
 3304     instw_delete(&instw);
 3305 
 3306     return result;
 3307 }
 3308 
 3309 int utime (const char *pathname, const struct utimbuf *newtimes) {
 3310     int result;
 3311     instw_t instw;
 3312 
 3313     if (!libc_handle)
 3314         initialize();
 3315 
 3316 #if DEBUG
 3317     debug(2,"utime(%s,newtimes)\n",pathname);
 3318 #endif
 3319 
 3320       /* We were asked to work in "real" mode */
 3321     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3322         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3323         result=true_utime(pathname,newtimes);
 3324         return result;
 3325     }
 3326 
 3327     instw_new(&instw);
 3328     instw_setpath(&instw,pathname);
 3329 
 3330 #if DEBUG
 3331     instw_print(&instw);
 3332 #endif
 3333 
 3334     backup(instw.truepath);
 3335     instw_apply(&instw);
 3336 
 3337     result=true_utime(instw.translpath,newtimes);
 3338     logg("%d\tutime\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3339 
 3340     instw_delete(&instw);
 3341 
 3342     return result;
 3343 }
 3344 
 3345 int utimes (const char *pathname, const struct timeval *newtimes) {
 3346        int result;
 3347        instw_t instw;
 3348 
 3349        if (!libc_handle)
 3350                initialize();
 3351 
 3352 #if DEBUG
 3353        debug(2,"utimes(%s,newtimes)\n",pathname);
 3354 #endif
 3355 
 3356          /* We were asked to work in "real" mode */
 3357        if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3358            !(__instw.gstatus & INSTW_OKWRAP) ) {
 3359                result=true_utimes(pathname,newtimes);
 3360                return result;
 3361        }
 3362 
 3363        instw_new(&instw);
 3364        instw_setpath(&instw,pathname);
 3365 
 3366 #if DEBUG
 3367        instw_print(&instw);
 3368 #endif
 3369 
 3370        backup(instw.truepath);
 3371        instw_apply(&instw);
 3372 
 3373        result=true_utimes(instw.translpath,newtimes);
 3374        logg("%d\tutimes\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3375 
 3376        instw_delete(&instw);
 3377 
 3378        return result;
 3379 }
 3380 
 3381 int access (const char *pathname, int type) {
 3382        int result;
 3383        instw_t instw;
 3384 
 3385        if (!libc_handle)
 3386                initialize();
 3387 
 3388 #if DEBUG
 3389        debug(2,"access(%s,%d)\n",pathname,type);
 3390 #endif
 3391 
 3392          /* We were asked to work in "real" mode */
 3393        if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3394            !(__instw.gstatus & INSTW_OKWRAP) ) {
 3395                result=true_access(pathname,type);
 3396                return result;
 3397        }
 3398 
 3399        instw_new(&instw);
 3400        instw_setpath(&instw,pathname);
 3401 
 3402 #if DEBUG
 3403        instw_print(&instw);
 3404 #endif
 3405 
 3406        backup(instw.truepath);
 3407        instw_apply(&instw);
 3408 
 3409        result=true_access(instw.translpath,type);
 3410        logg("%d\taccess\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3411 
 3412        instw_delete(&instw);
 3413 
 3414        return result;
 3415 }
 3416 
 3417 int setxattr (const char *pathname, const char *name,
 3418               const void *value, size_t size, int flags)
 3419 {
 3420         int result;
 3421         instw_t instw;
 3422 
 3423         REFCOUNT;
 3424 
 3425         if (!libc_handle)
 3426                initialize();
 3427 
 3428 #if DEBUG
 3429         debug(2,"setxattr(%s,%s)\n",pathname,name);
 3430 #endif
 3431 
 3432          /* We were asked to work in "real" mode */
 3433         if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3434            !(__instw.gstatus & INSTW_OKWRAP) ) {
 3435                result=true_setxattr(pathname,name,
 3436                        value,size,flags);
 3437                return result;
 3438         }
 3439 
 3440         instw_new(&instw);
 3441         instw_setpath(&instw,pathname);
 3442 
 3443 #if DEBUG
 3444         instw_print(&instw);
 3445 #endif
 3446 
 3447         backup(instw.truepath);
 3448         instw_apply(&instw);
 3449 
 3450         result=true_setxattr(instw.translpath,name,value,size,flags);
 3451         logg("%d\tsetxattr\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3452 
 3453         instw_delete(&instw);
 3454 
 3455         return result;
 3456 }
 3457 
 3458 int removexattr (const char *pathname, const char *name)
 3459 {
 3460         int result;
 3461         instw_t instw;
 3462 
 3463         REFCOUNT;
 3464 
 3465         if (!libc_handle)
 3466                initialize();
 3467 
 3468 #if DEBUG
 3469         debug(2,"removexattr(%s,%s)\n",pathname,name);
 3470 #endif
 3471 
 3472          /* We were asked to work in "real" mode */
 3473         if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3474             !(__instw.gstatus & INSTW_OKWRAP) ) {
 3475                 result=true_removexattr(pathname,name);
 3476                 return result;
 3477         }
 3478 
 3479         instw_new(&instw);
 3480         instw_setpath(&instw,pathname);
 3481 
 3482 #if DEBUG
 3483         instw_print(&instw);
 3484 #endif
 3485 
 3486         backup(instw.truepath);
 3487         instw_apply(&instw);
 3488 
 3489         result=true_removexattr(instw.translpath,name);
 3490         logg("%d\tremovexattr\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3491 
 3492         instw_delete(&instw);
 3493 
 3494         return result;
 3495 }
 3496 
 3497 #if(GLIBC_MINOR >= 1)
 3498 
 3499 int creat64(const char *pathname, __mode_t mode) {
 3500 /* Is it a system call? */
 3501     int result;
 3502     instw_t instw;
 3503 
 3504     REFCOUNT;
 3505 
 3506     if (!libc_handle)
 3507         initialize();
 3508 
 3509 #if DEBUG
 3510     debug(2,"creat64(%s,mode)\n",pathname);
 3511 #endif
 3512 
 3513       /* We were asked to work in "real" mode */
 3514     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3515         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3516         result=true_creat64(pathname,mode);
 3517         return result;
 3518     }
 3519 
 3520     instw_new(&instw);
 3521     instw_setpath(&instw,pathname);
 3522 
 3523 #if DEBUG
 3524     instw_print(&instw);
 3525 #endif
 3526 
 3527     backup(instw.truepath);
 3528     instw_apply(&instw);
 3529 
 3530     result=true_open64(instw.translpath,O_CREAT | O_WRONLY | O_TRUNC, mode);
 3531     logg("%d\tcreat\t%s\t#%s\n",result,instw.reslvpath,error(result));
 3532 
 3533     instw_delete(&instw);
 3534 
 3535     return result;
 3536 }
 3537 
 3538 int ftruncate64(int fd, __off64_t length) {
 3539     int result;
 3540 
 3541     REFCOUNT;
 3542 
 3543     if (!libc_handle)
 3544         initialize();
 3545 
 3546 #if DEBUG
 3547     debug(2,"ftruncate64\n");
 3548 #endif
 3549 
 3550     result = true_ftruncate64(fd, length);
 3551     logg("%d\tftruncate\t%d\t%d\t#%s\n",result,fd,(int)length,error(result));
 3552     return result;
 3553 }
 3554 
 3555 FILE *fopen64(const char *pathname, const char *mode) {
 3556     FILE *result;
 3557     instw_t instw;
 3558     int status;
 3559 
 3560     REFCOUNT;
 3561 
 3562     if (!libc_handle)
 3563         initialize();
 3564 
 3565 #if DEBUG
 3566     debug(2,"fopen64(%s,%s)\n",pathname,mode);
 3567 #endif
 3568     
 3569       /* We were asked to work in "real" mode */
 3570     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3571         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3572         result=true_fopen64(pathname,mode);
 3573         return result;
 3574     }
 3575 
 3576     instw_new(&instw);
 3577     instw_setpath(&instw,pathname);
 3578     
 3579 #if DEBUG
 3580     instw_print(&instw);
 3581 #endif
 3582 
 3583     if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+') {
 3584         backup(instw.truepath);
 3585         instw_apply(&instw);
 3586     }
 3587 
 3588     instw_getstatus(&instw,&status);
 3589     
 3590     if(status&INSTW_TRANSLATED) {
 3591         debug(4,"\teffective fopen64(%s)\n",instw.translpath);
 3592         result=true_fopen64(instw.translpath,mode); 
 3593     } else {
 3594         debug(4,"\teffective fopen64(%s)\n",instw.path);
 3595         result=true_fopen64(instw.path,mode);
 3596     }
 3597 
 3598     if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+') 
 3599         logg("%" PRIdPTR "\tfopen64\t%s\t#%s\n",(intptr_t)result,
 3600             instw.reslvpath,error(result));
 3601 
 3602     instw_delete(&instw);
 3603 
 3604     return result;
 3605 }
 3606 
 3607 int open64(const char *pathname, int flags, ...) {
 3608 /* Eventually, there is a third parameter: it's mode_t mode */
 3609     va_list ap;
 3610     mode_t mode;
 3611     int result;
 3612     instw_t instw;
 3613     int status;
 3614 
 3615     REFCOUNT;
 3616 
 3617     if (!libc_handle)
 3618         initialize();
 3619 
 3620 #if DEBUG
 3621     debug(2,"open64(%s,%d,mode)\n",pathname,flags);
 3622 #endif
 3623 
 3624     va_start(ap, flags);
 3625     mode = va_arg(ap, mode_t);
 3626     va_end(ap);
 3627 
 3628       /* We were asked to work in "real" mode */
 3629     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3630         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3631         result=true_open64(pathname,flags,mode);
 3632         return result;
 3633     }
 3634 
 3635     instw_new(&instw);
 3636     instw_setpath(&instw,pathname);
 3637 
 3638 #if DEBUG
 3639     instw_print(&instw);
 3640 #endif
 3641 
 3642     if(flags & (O_WRONLY | O_RDWR)) {
 3643         backup(instw.truepath);
 3644         instw_apply(&instw);
 3645     }
 3646 
 3647     instw_getstatus(&instw,&status);
 3648 
 3649     if(status&INSTW_TRANSLATED) {
 3650         debug(4,"\teffective open64(%s)\n",instw.translpath);
 3651         result=true_open64(instw.translpath,flags,mode);
 3652     } else {
 3653         debug(4,"\teffective open64(%s)\n",instw.path);
 3654         result=true_open64(instw.path,flags,mode);
 3655     }
 3656     
 3657     if(flags & (O_WRONLY | O_RDWR)) 
 3658         logg("%d\topen\t%s\t#%s\n",result,
 3659             instw.reslvpath,error(result));
 3660 
 3661     instw_delete(&instw);
 3662 
 3663     return result;
 3664 }
 3665 
 3666 struct dirent64 *readdir64(DIR *dir) {
 3667     struct dirent64 *result;
 3668 
 3669     if (!libc_handle)
 3670         initialize();
 3671 
 3672 #if DEBUG
 3673     debug(3,"readdir64(%p)\n",dir);
 3674 #endif
 3675 
 3676       /* We were asked to work in "real" mode */
 3677     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3678         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3679         result=true_readdir64(dir);
 3680         return result;
 3681     }
 3682 
 3683     result=true_readdir64(dir);
 3684 
 3685 #if DEBUG
 3686     __instw_printdirent64(result);
 3687 #endif
 3688 
 3689     return result;
 3690 }
 3691 
 3692 int scandir64(  const char *dir,struct dirent64 ***namelist,
 3693         int (*select)(const struct dirent64 *),
 3694         int (*compar)(const void *,const void *)    ) {
 3695     int result;
 3696 
 3697     if (!libc_handle)
 3698         initialize();
 3699 
 3700 #if DEBUG
 3701     debug(2,"scandir64(%s,%p,%p,%p)\n",dir,namelist,select,compar);
 3702 #endif
 3703 
 3704       /* We were asked to work in "real" mode */
 3705     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3706         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3707         result=true_scandir64(dir,namelist,select,compar);
 3708         return result;
 3709     }
 3710 
 3711     result=true_scandir64(dir,namelist,select,compar);
 3712 
 3713     return result;
 3714 }       
 3715 
 3716 int __xstat64(int version,const char *pathname,struct stat64 *info) {
 3717     int result;
 3718     instw_t instw;
 3719     int status;
 3720 
 3721 #if DEBUG
 3722     debug(2,"stat64(%s,%p)\n",pathname,info);
 3723 #endif
 3724 
 3725       /* We were asked to work in "real" mode */
 3726     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3727         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3728         result=true_xstat64(version,pathname,info);
 3729         return result;
 3730     }
 3731 
 3732     instw_new(&instw);
 3733     instw_setpath(&instw,pathname);
 3734     instw_getstatus(&instw,&status);
 3735 
 3736 #if DEBUG
 3737     instw_print(&instw);
 3738 #endif
 3739 
 3740     if(status&INSTW_TRANSLATED) {
 3741         debug(4,"\teffective stat64(%s,%p)\n",
 3742               instw.translpath,info);
 3743         result=true_xstat64(version,instw.translpath,info);
 3744     } else {
 3745         debug(4,"\teffective stat64(%s,%p)\n",
 3746               instw.path,info);
 3747         result=true_xstat64(version,instw.path,info);
 3748     }   
 3749 
 3750     instw_delete(&instw);
 3751 
 3752     return result;  
 3753 }
 3754 
 3755 int __lxstat64(int version,const char *pathname,struct stat64 *info) {
 3756     int result;
 3757     instw_t instw;
 3758     int status;
 3759 
 3760 #if DEBUG
 3761     debug(2,"lstat64(%s,%p)\n",pathname,info);
 3762 #endif
 3763 
 3764       /* We were asked to work in "real" mode */
 3765     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3766         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3767         result=true_lxstat64(version,pathname,info);
 3768         return result;
 3769     }
 3770 
 3771     instw_new(&instw);
 3772     instw_setpath(&instw,pathname);
 3773     instw_getstatus(&instw,&status);
 3774 
 3775 #if DEBUG
 3776     instw_print(&instw);
 3777 #endif
 3778 
 3779     if(status&INSTW_TRANSLATED) {
 3780         debug(4,"\teffective lstat64(%s,%p)\n",
 3781             instw.translpath,info);
 3782         result=true_lxstat64(version,instw.translpath,info);
 3783     } else {
 3784         debug(4,"\teffective lstat64(%s,%p)\n",
 3785             instw.path,info);
 3786         result=true_lxstat64(version,instw.path,info);
 3787     }
 3788 
 3789     instw_delete(&instw);
 3790 
 3791     return result;  
 3792 }
 3793 
 3794 int truncate64(const char *path, __off64_t length) {
 3795     int result;
 3796     instw_t instw;
 3797 
 3798     if (!libc_handle)
 3799         initialize();
 3800 
 3801     REFCOUNT;
 3802 
 3803     if (!libc_handle)
 3804         initialize();
 3805 
 3806 #if DEBUG
 3807     debug(2,"truncate64(%s,length)\n",path);
 3808 #endif
 3809 
 3810       /* We were asked to work in "real" mode */
 3811     if( !(__instw.gstatus & INSTW_INITIALIZED) ||
 3812         !(__instw.gstatus & INSTW_OKWRAP) ) {
 3813         result=true_truncate64(path,length);
 3814         return result;
 3815     }
 3816 
 3817     instw_new(&instw);
 3818     instw_setpath(&instw,path);
 3819 
 3820 #if DEBUG
 3821     instw_print(&instw);
 3822 #endif
 3823 
 3824     backup(instw.truepath);
 3825     instw_apply(&instw);
 3826 
 3827     result=true_truncate64(instw.translpath,length);
 3828     
 3829     logg("%d\ttruncate\t%s\t%d\t#%s\n",result,
 3830         instw.reslvpath,(int)length,error(result));
 3831 
 3832     instw_delete(&instw);
 3833 
 3834     return result;
 3835 }
 3836 
 3837 #endif /* GLIBC_MINOR >= 1 */
 3838 
 3839 
 3840 /***********************************************
 3841  * openat() and its relatives are defined here
 3842  *
 3843  * They are mostly wrappers for the already
 3844  * defined "non-at" functions defined above.
 3845  *
 3846  * They transform the path relative to the
 3847  * fd into an absolute path and then call
 3848  * the normal functions. The transformation
 3849  * is done by calling instw_setpathrel().
 3850  *
 3851  * Maybe we could wrap all of these into a
 3852  * single generic wrap-any function?
 3853  *
 3854  * Thanks to Gilbert Ashley for his work on this!
 3855  */
 3856 
 3857 #if (GLIBC_MINOR >= 4)
 3858  
 3859 int openat (int dirfd, const char *path, int flags, ...) {
 3860     mode_t mode = 0;
 3861     va_list arg;
 3862     if(flags & O_CREAT) {
 3863         va_start(arg, flags);
 3864         mode = va_arg(arg, mode_t);
 3865         va_end (arg);
 3866     }
 3867     
 3868     int result;
 3869     instw_t instw;
 3870  
 3871     /* If all we are doing is normal open, forgo refcounting, etc. */
 3872          if(dirfd == AT_FDCWD || *path == '/')
 3873                  return open(path, flags, mode);
 3874  
 3875     REFCOUNT;
 3876  
 3877     if (!libc_handle)
 3878         initialize();
 3879  
 3880 #if DEBUG
 3881     debug(2, "openat(%d, %s, 0x%x, 0%o)\n", dirfd, path, flags, mode);
 3882 #endif
 3883     
 3884     /* We were asked to work in "real" mode */
 3885     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 3886        !(__instw.gstatus & INSTW_OKWRAP))
 3887         return true_open(path,flags,mode);
 3888     
 3889     instw_new(&instw);
 3890     instw_setpathrel(&instw,dirfd,path);
 3891     
 3892 #if DEBUG
 3893     instw_print(&instw);
 3894 #endif
 3895     
 3896     result=open(instw.path,flags,mode);
 3897     
 3898     instw_delete(&instw);
 3899  
 3900     return result;
 3901 }
 3902 
 3903 int fchmodat (int dirfd, const char *path, mode_t mode, int flag) {
 3904     
 3905     int result;
 3906     instw_t instw;
 3907  
 3908     /* If all we are doing is normal open, forgo refcounting, etc. */
 3909          if(dirfd == AT_FDCWD || *path == '/')
 3910         {
 3911          #if DEBUG
 3912             debug(2, "fchmodat(%d,%s,0%o)\n", dirfd, path, mode);
 3913          #endif
 3914          return chmod(path, mode);
 3915         }
 3916  
 3917     REFCOUNT;
 3918  
 3919     if (!libc_handle)
 3920         initialize();
 3921  
 3922 #if DEBUG
 3923     debug(2, "fchmodat(%d,%s,0%o)\n", dirfd, path, mode);
 3924 #endif
 3925     
 3926     /* We were asked to work in "real" mode */
 3927     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 3928        !(__instw.gstatus & INSTW_OKWRAP))
 3929         return true_chmod(path,mode);
 3930     
 3931     instw_new(&instw);
 3932     instw_setpathrel(&instw,dirfd,path);
 3933     
 3934 #if DEBUG
 3935     instw_print(&instw);
 3936 #endif
 3937     
 3938     result=chmod(instw.path,mode);
 3939     
 3940     instw_delete(&instw);
 3941  
 3942     return result;
 3943 }
 3944 
 3945 int fchownat (int dirfd, const char *path,uid_t owner,gid_t group,int flags) {
 3946     
 3947     int result;
 3948     instw_t instw;
 3949  
 3950     /* If all we are doing is normal open, forgo refcounting, etc. */
 3951          if(dirfd == AT_FDCWD || *path == '/')
 3952         {
 3953          #if DEBUG
 3954             debug(2, "fchownat(%d,%s,%d,%d,0%o)\n", dirfd, path, owner, group, flags);
 3955          #endif
 3956 
 3957          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 3958          /* lchwon() behaviour, according to fchownat(2) */
 3959 
 3960          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 3961             return lchown(path, owner, group); 
 3962          }
 3963          else {
 3964             return chown(path, owner, group);
 3965          }
 3966 
 3967         }
 3968  
 3969     REFCOUNT;
 3970  
 3971     if (!libc_handle)
 3972         initialize();
 3973  
 3974 #if DEBUG
 3975     debug(2,"fchownat(%d,%s,%d,%d,0%o)\n", dirfd, path, owner, group, flags);
 3976 #endif
 3977     
 3978     /* We were asked to work in "real" mode */
 3979     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 3980        !(__instw.gstatus & INSTW_OKWRAP)) {
 3981 
 3982          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 3983          /* lchwon() behaviour, according to fchownat(2) */
 3984 
 3985          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 3986             return true_lchown(path, owner, group); 
 3987          }
 3988          else {
 3989             return true_chown(path, owner, group);
 3990          }
 3991     }
 3992     
 3993     instw_new(&instw);
 3994     instw_setpathrel(&instw,dirfd,path);
 3995     
 3996 #if DEBUG
 3997     instw_print(&instw);
 3998 #endif
 3999      /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4000      /* lchwon() behaviour, according to fchownat(2) */
 4001 
 4002      if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4003         result=lchown(instw.path, owner, group); 
 4004      }
 4005      else {
 4006         result=chown(instw.path, owner, group);
 4007      }
 4008 
 4009 
 4010     
 4011     instw_delete(&instw);
 4012  
 4013     return result;
 4014 }
 4015 
 4016 
 4017 int __fxstatat (int version, int dirfd, const char *path, struct stat *s, int flags) {
 4018     
 4019     int result;
 4020     instw_t instw;
 4021  
 4022     /* If all we are doing is normal open, forgo refcounting, etc. */
 4023          if(dirfd == AT_FDCWD || *path == '/')
 4024         {
 4025          #if DEBUG
 4026             debug(2, "__fxstatat(%d,%s,%p,0%o)\n", dirfd, path, s, flags);
 4027          #endif
 4028 
 4029          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4030          /* lstat() behaviour, according to fstatat(2) */
 4031 
 4032          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4033             return __lxstat(version, path, s); 
 4034          }
 4035          else {
 4036             return __xstat(version, path, s);
 4037          }
 4038 
 4039         }
 4040  
 4041     REFCOUNT;
 4042  
 4043     if (!libc_handle)
 4044         initialize();
 4045  
 4046 #if DEBUG
 4047     debug(2, "__fxstatat(%d,%s,%p,0%o)\n", dirfd, path, s, flags);
 4048 #endif
 4049     
 4050     /* We were asked to work in "real" mode */
 4051     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4052        !(__instw.gstatus & INSTW_OKWRAP)) {
 4053 
 4054 
 4055          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4056          /* lstat() behaviour, according to fstatat(2) */
 4057 
 4058          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4059             return true_lxstat(version, path, s); 
 4060          }
 4061          else {
 4062             return true_xstat(version, path, s);
 4063          }
 4064     }
 4065 
 4066     
 4067     instw_new(&instw);
 4068     instw_setpathrel(&instw,dirfd,path);
 4069     
 4070 #if DEBUG
 4071     instw_print(&instw);
 4072 #endif
 4073  
 4074          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4075          /* lstat() behaviour, according to fstatat(2) */
 4076 
 4077          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4078             result=__lxstat(version, instw.path, s);
 4079          }
 4080          else {
 4081             result=__xstat(version, instw.path, s);
 4082             
 4083          }  
 4084     
 4085     instw_delete(&instw);
 4086  
 4087     return result;
 4088 }
 4089 
 4090 int __fxstatat64 (int version, int dirfd, const char *path, struct stat64 *s, int flags) {
 4091     
 4092     int result;
 4093     instw_t instw;
 4094  
 4095     /* If all we are doing is normal open, forgo refcounting, etc. */
 4096          if(dirfd == AT_FDCWD || *path == '/')
 4097         {
 4098          #if DEBUG
 4099             debug(2, "__fxstatat(%d,%s,%p,0%o)\n", dirfd, path, s, flags);
 4100          #endif
 4101 
 4102          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4103          /* lstat() behaviour, according to fstatat(2) */
 4104 
 4105          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4106             return __lxstat64(version, path, s); 
 4107          }
 4108          else {
 4109             return __xstat64(version, path, s);
 4110          }
 4111 
 4112         }
 4113  
 4114     REFCOUNT;
 4115  
 4116     if (!libc_handle)
 4117         initialize();
 4118  
 4119 #if DEBUG
 4120     debug(2, "__fxstatat(%d,%s,%p,0%o)\n", dirfd, path, s, flags);
 4121 #endif
 4122     
 4123     /* We were asked to work in "real" mode */
 4124     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4125        !(__instw.gstatus & INSTW_OKWRAP)) {
 4126 
 4127          /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4128          /* lstat() behaviour, according to fstatat(2) */
 4129 
 4130          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4131             return true_lxstat64(version, path, s); 
 4132          }
 4133          else {
 4134             return true_xstat64(version, path, s);
 4135          }
 4136     }
 4137 
 4138     
 4139     instw_new(&instw);
 4140     instw_setpathrel(&instw,dirfd,path);
 4141     
 4142 #if DEBUG
 4143     instw_print(&instw);
 4144 #endif
 4145 
 4146     /* If we have AT_SYMLINK_NOFOLLOW then we need  */
 4147     /* lstat() behaviour, according to fstatat(2) */
 4148 
 4149     if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4150        result=__lxstat64(version, instw.path, s);
 4151     }
 4152     else {
 4153        result=__xstat64(version, instw.path, s);
 4154     }
 4155     
 4156     instw_delete(&instw);
 4157  
 4158     return result;
 4159 
 4160 }
 4161 
 4162 
 4163 int linkat (int olddirfd, const char *oldpath,
 4164                   int newdirfd, const char *newpath, int flags) {
 4165     
 4166     int result;
 4167     instw_t instwold;
 4168     instw_t instwnew;
 4169  
 4170     /* If all we are doing is normal open, forgo refcounting, etc. */
 4171          if( (olddirfd == AT_FDCWD || *oldpath == '/') &&
 4172              (newdirfd == AT_FDCWD || *newpath == '/') )
 4173         {
 4174          #if DEBUG
 4175             debug(2, "linkat(%d, %s, %d, %s, 0%o)\n", olddirfd, oldpath, newdirfd, newpath, flags );
 4176          #endif
 4177 
 4178          return link(oldpath, newpath); 
 4179 
 4180 /*** FIXME: If we have AT_SYMLINK_NOFOLLOW we need to dereference the links 
 4181 
 4182          if ( flags & AT_SYMLINK_NOFOLLOW ) {
 4183             return link(oldpath, newpath); 
 4184          }
 4185          else {
 4186             return link(oldpath, newpath);
 4187          }
 4188 ***************************************************************** FIXME */
 4189 
 4190         }
 4191  
 4192     REFCOUNT;
 4193  
 4194     if (!libc_handle)
 4195         initialize();
 4196  
 4197 #if DEBUG
 4198     debug(2, "linkat(%d, %s, %d, %s, 0%o)\n", olddirfd, oldpath, newdirfd, newpath, flags );
 4199 #endif
 4200     
 4201     /* We were asked to work in "real" mode */
 4202     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4203        !(__instw.gstatus & INSTW_OKWRAP))
 4204         return true_link(oldpath, newpath);
 4205     
 4206     instw_new(&instwold);
 4207     instw_new(&instwnew);
 4208     instw_setpathrel(&instwold,olddirfd,oldpath);
 4209     instw_setpathrel(&instwnew,newdirfd,newpath);
 4210     
 4211 #if DEBUG
 4212     instw_print(&instwold);
 4213     instw_print(&instwnew);
 4214 #endif
 4215     
 4216     result=link(instwold.path, instwnew.path);
 4217     
 4218     instw_delete(&instwold);
 4219     instw_delete(&instwnew);
 4220  
 4221     return result;
 4222 }
 4223 
 4224 
 4225 int mkdirat (int dirfd, const char *path, mode_t mode) {
 4226     
 4227     int result;
 4228     instw_t instw;
 4229  
 4230     /* If all we are doing is normal open, forgo refcounting, etc. */
 4231          if(dirfd == AT_FDCWD || *path == '/')
 4232         {
 4233          #if DEBUG
 4234             debug(2, "mkdirat(%d,%s,0%o)\n", dirfd, path, mode);
 4235          #endif
 4236          return mkdir(path, mode);
 4237         }
 4238  
 4239     REFCOUNT;
 4240  
 4241     if (!libc_handle)
 4242         initialize();
 4243  
 4244 #if DEBUG
 4245     debug(2, "mkdirat(%d,%s,0%o)\n", dirfd, path, mode);
 4246 #endif
 4247     
 4248     /* We were asked to work in "real" mode */
 4249     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4250        !(__instw.gstatus & INSTW_OKWRAP))
 4251         return true_mkdir(path,mode);
 4252     
 4253     instw_new(&instw);
 4254     instw_setpathrel(&instw,dirfd,path);
 4255     
 4256 #if DEBUG
 4257     instw_print(&instw);
 4258 #endif
 4259     
 4260     result=mkdir(instw.path,mode);
 4261     
 4262     instw_delete(&instw);
 4263  
 4264     return result;
 4265 }
 4266 
 4267 
 4268 READLINKAT_T readlinkat (int dirfd, const char *path,
 4269                       char *buf, size_t bufsiz) {
 4270     
 4271     int result;
 4272     instw_t instw;
 4273  
 4274     /* If all we are doing is normal open, forgo refcounting, etc. */
 4275          if(dirfd == AT_FDCWD || *path == '/')
 4276         {
 4277          #if DEBUG
 4278                     debug(2, "readlinkat(%d,%s, %s, %ld)\n", dirfd, path, buf, (long)bufsiz);
 4279          #endif
 4280          return readlink(path, buf, bufsiz);
 4281         }
 4282  
 4283     REFCOUNT;
 4284  
 4285     if (!libc_handle)
 4286         initialize();
 4287  
 4288 #if DEBUG
 4289     debug(2, "readlinkat(%d,%s, %s, %ld)\n", dirfd, path, buf, (long)bufsiz);
 4290 #endif
 4291     
 4292     /* We were asked to work in "real" mode */
 4293     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4294        !(__instw.gstatus & INSTW_OKWRAP))
 4295         return true_readlink(path, buf, bufsiz);
 4296     
 4297     instw_new(&instw);
 4298     instw_setpathrel(&instw,dirfd,path);
 4299     
 4300 #if DEBUG
 4301     instw_print(&instw);
 4302 #endif
 4303     
 4304     result=readlink(instw.path, buf, bufsiz);
 4305     
 4306     instw_delete(&instw);
 4307  
 4308     return result;
 4309 }
 4310 
 4311 
 4312 int __xmknodat (int version, int dirfd,const char *path,mode_t mode,dev_t *dev) {
 4313     
 4314     int result;
 4315     instw_t instw;
 4316  
 4317     /* If all we are doing is normal open, forgo refcounting, etc. */
 4318          if(dirfd == AT_FDCWD || *path == '/')
 4319         {
 4320          #if DEBUG
 4321             debug(2, "__xmknod(%d, %s, 0%o, %p)\n", version, path, mode, dev);
 4322          #endif
 4323          return __xmknod(version, path, mode, dev);
 4324         }
 4325  
 4326     REFCOUNT;
 4327  
 4328     if (!libc_handle)
 4329         initialize();
 4330  
 4331 #if DEBUG
 4332     debug(2, "__xmknod(%d, %s, 0%o, %p)\n", version, path, mode, dev);
 4333 #endif
 4334     
 4335     /* We were asked to work in "real" mode */
 4336     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4337        !(__instw.gstatus & INSTW_OKWRAP))
 4338         return true_xmknod(version, path, mode, dev);
 4339     
 4340     instw_new(&instw);
 4341     instw_setpathrel(&instw,dirfd,path);
 4342     
 4343 #if DEBUG
 4344     instw_print(&instw);
 4345 #endif
 4346     
 4347     result=__xmknod(version, instw.path, mode, dev);
 4348     
 4349     instw_delete(&instw);
 4350  
 4351     return result;
 4352 }
 4353 
 4354 
 4355 int renameat (int olddirfd, const char *oldpath,
 4356                   int newdirfd, const char *newpath) {
 4357     
 4358     int result;
 4359     instw_t instwold;
 4360     instw_t instwnew;
 4361  
 4362     /* If all we are doing is normal open, forgo refcounting, etc. */
 4363          if( (olddirfd == AT_FDCWD || *oldpath == '/') &&
 4364              (newdirfd == AT_FDCWD || *newpath == '/') )
 4365         {
 4366          #if DEBUG
 4367             debug(2, "renameat(%d, %s, %d, %s)\n", olddirfd, oldpath, newdirfd, newpath);
 4368          #endif
 4369 
 4370          return rename(oldpath, newpath); 
 4371 
 4372 
 4373         }
 4374  
 4375     REFCOUNT;
 4376  
 4377     if (!libc_handle)
 4378         initialize();
 4379  
 4380 #if DEBUG
 4381     debug(2, "renameat(%d, %s, %d, %s)\n", olddirfd, oldpath, newdirfd, newpath);
 4382 #endif
 4383     
 4384     /* We were asked to work in "real" mode */
 4385     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4386        !(__instw.gstatus & INSTW_OKWRAP))
 4387         return true_rename(oldpath, newpath);
 4388     
 4389     instw_new(&instwold);
 4390     instw_new(&instwnew);
 4391     instw_setpathrel(&instwold,olddirfd,oldpath);
 4392     instw_setpathrel(&instwnew,newdirfd,newpath);
 4393     
 4394 #if DEBUG
 4395     instw_print(&instwold);
 4396     instw_print(&instwnew);
 4397 #endif
 4398     
 4399     result=rename(instwold.path, instwnew.path);
 4400     
 4401     instw_delete(&instwold);
 4402     instw_delete(&instwnew);
 4403  
 4404     return result;
 4405 }
 4406 
 4407 
 4408 int symlinkat (const char *oldpath, int dirfd, const char *newpath) {
 4409     
 4410     int result;
 4411     instw_t instw;
 4412  
 4413     /* If all we are doing is normal open, forgo refcounting, etc. */
 4414          if(dirfd == AT_FDCWD || *newpath == '/')
 4415         {
 4416          #if DEBUG
 4417             debug(2, "symlinkat(%s, %d, %s)\n", oldpath, dirfd, newpath);
 4418          #endif
 4419          return symlink(oldpath, newpath);
 4420         }
 4421  
 4422     REFCOUNT;
 4423  
 4424     if (!libc_handle)
 4425         initialize();
 4426  
 4427 #if DEBUG
 4428     debug(2, "symlinkat(%s, %d, %s)\n", oldpath, dirfd, newpath);
 4429 #endif
 4430     
 4431     /* We were asked to work in "real" mode */
 4432     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4433        !(__instw.gstatus & INSTW_OKWRAP))
 4434         return true_symlink(oldpath, newpath);
 4435     
 4436     instw_new(&instw);
 4437     instw_setpathrel(&instw,dirfd,newpath);
 4438     
 4439 #if DEBUG
 4440     instw_print(&instw);
 4441 #endif
 4442     
 4443     result=symlink(oldpath, instw.path);
 4444     
 4445     instw_delete(&instw);
 4446  
 4447     return result;
 4448 }
 4449 
 4450 
 4451 int unlinkat (int dirfd, const char *path, int flags) {
 4452     
 4453     int result;
 4454     instw_t instw;
 4455  
 4456     /* If all we are doing is normal open, forgo refcounting, etc. */
 4457          if(dirfd == AT_FDCWD || *path == '/')
 4458         {
 4459          #if DEBUG
 4460             debug(2, "unlinkat(%d,%s,0%o)\n", dirfd, path, flags);
 4461          #endif
 4462 
 4463          /* If we have AT_REMOVEDIR then we need        */
 4464          /* rmdir() behaviour, according to unlinkat(2) */
 4465 
 4466          if ( flags & AT_REMOVEDIR ) {
 4467             return rmdir(path); 
 4468          }
 4469          else {
 4470             return unlink(path);
 4471          }
 4472 
 4473         }
 4474  
 4475     REFCOUNT;
 4476  
 4477     if (!libc_handle)
 4478         initialize();
 4479  
 4480 #if DEBUG
 4481     debug(2, "unlinkat(%d,%s,0%o)\n", dirfd, path, flags);
 4482 #endif
 4483     
 4484     /* We were asked to work in "real" mode */
 4485     if(!(__instw.gstatus & INSTW_INITIALIZED) ||
 4486        !(__instw.gstatus & INSTW_OKWRAP)) {
 4487         /* If we have AT_REMOVEDIR then we need        */
 4488          /* rmdir() behaviour, according to unlinkat(2) */
 4489 
 4490          if ( flags & AT_REMOVEDIR ) {
 4491             result=true_rmdir(path); 
 4492          }
 4493          else {
 4494             result=true_unlink(path);
 4495          }
 4496     }
 4497     
 4498     
 4499     instw_new(&instw);
 4500     instw_setpathrel(&instw,dirfd,path);
 4501     
 4502 #if DEBUG
 4503     instw_print(&instw);
 4504 #endif
 4505     
 4506      /* If we have AT_REMOVEDIR then we need        */
 4507      /* rmdir() behaviour, according to unlinkat(2) */
 4508 
 4509      if ( flags & AT_REMOVEDIR ) {
 4510         result=rmdir(instw.path); 
 4511      }
 4512      else {
 4513         result=unlink(instw.path);
 4514      }
 4515     
 4516     instw_delete(&instw);
 4517  
 4518     return result;
 4519 
 4520 }
 4521 
 4522 
 4523 #endif /* GLIBC_MINOR >= 4 */