"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 */