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.6.3.2 2001/12/22 23:01:20 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 
25 #include <sys/param.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <dlfcn.h>
33 #include <syslog.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <time.h>
38 #include <dlfcn.h>
39 
40 #include "localdecls.h"
41 
42 /* #define DEBUG 1  */
43 
44 #define LOGLEVEL (LOG_USER | LOG_INFO | LOG_PID)
45 #define BUFSIZE 1024
46 
47 #define error(X) (X < 0 ? strerror(errno) : "success")
48 
49 int __installwatch_refcount = 0;
50 int __installwatch_timecount = 0;
51 
52 #define REFCOUNT __installwatch_refcount++
53 #define TIMECOUNT __installwatch_timecount++
54 
55 static time_t (*true_time) (time_t *);
56 static int(*true_chmod)(const char *, mode_t);
57 static int(*true_chown)(const char *, uid_t, gid_t);
58 static int(*true_chroot)(const char *);
59 static int(*true_creat)(const char *, mode_t);
60 static int(*true_fchmod)(int, mode_t);
61 static int(*true_fchown)(int, uid_t, gid_t);
62 static FILE *(*true_fopen)(const char *,const char*);
63 static int(*true_ftruncate)(int, TRUNCATE_T);
64 static int(*true_lchown)(const char *, uid_t, gid_t);
65 static int(*true_link)(const char *, const char *);
66 static int(*true_mkdir)(const char *, mode_t);
67 static int(*true_open)(const char *, int, ...);
68 static int(*true_rename)(const char *, const char *);
69 static int(*true_rmdir)(const char *);
70 static int(*true_symlink)(const char *, const char *);
71 static int(*true_truncate)(const char *, TRUNCATE_T);
72 static int(*true_unlink)(const char *);
73 
74 #if(GLIBC_MINOR >= 1)
75 
76 static int(*true_creat64)(const char *, __mode_t);
77 static FILE *(*true_fopen64)(const char *,const char *);
78 static int(*true_ftruncate64)(int, __off64_t);
79 static int(*true_open64)(const char *, int, ...);
80 static int(*true_truncate64)(const char *, __off64_t);
81 
82 #endif
83 
84 static void log(const char *format, ...)
85 #ifdef __GNUC__
86 	/* Tell gcc that this function behaves like printf()
87 	 * for parameters 1 and 2                            */
88 	__attribute__((format(printf, 1, 2)))
89 #endif /* defined __GNUC__ */
90 ;
91 
_init(void)92 void _init(void) {
93 
94 	void *libc_handle;
95 
96 	#ifdef BROKEN_RTLD_NEXT
97 //        	printf ("RTLD_LAZY");
98         	libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
99 	#else
100  //       	printf ("RTLD_NEXT");
101         	libc_handle = RTLD_NEXT;
102 	#endif
103 
104 
105 	true_time = dlsym(libc_handle, "time");
106 	true_chmod = dlsym(libc_handle, "chmod");
107 	true_chown = dlsym(libc_handle, "chown");
108 	true_chroot = dlsym(libc_handle, "chroot");
109 	true_creat = dlsym(libc_handle, "creat");
110 	true_fchmod = dlsym(libc_handle, "fchmod");
111 	true_fchown = dlsym(libc_handle, "fchown");
112 	true_fopen = dlsym(libc_handle, "fopen");
113 	true_ftruncate = dlsym(libc_handle, "ftruncate");
114 	true_lchown = dlsym(libc_handle, "lchown");
115 	true_link = dlsym(libc_handle, "link");
116 	true_mkdir = dlsym(libc_handle, "mkdir");
117 	true_open = dlsym(libc_handle, "open");
118 	true_rename = dlsym(libc_handle, "rename");
119 	true_rmdir = dlsym(libc_handle, "rmdir");
120 	true_symlink = dlsym(libc_handle, "symlink");
121 	true_truncate = dlsym(libc_handle, "truncate");
122 	true_unlink = dlsym(libc_handle, "unlink");
123 
124 #if(GLIBC_MINOR >= 1)
125 	true_creat64 = dlsym(libc_handle, "creat64");
126 	true_fopen64 = dlsym(libc_handle, "fopen64");
127 	true_ftruncate64 = dlsym(libc_handle, "ftruncate64");
128 	true_open64 = dlsym(libc_handle, "open64");
129 	true_truncate64 = dlsym(libc_handle, "truncate64");
130 #endif
131 
132 }
133 
log(const char * format,...)134 static void log(const char *format, ...) {
135 	char buffer[BUFSIZE], *logname;
136 	va_list ap;
137 	int count, logfd;
138 
139 	va_start(ap, format);
140 	count = vsnprintf(buffer, BUFSIZE, format, ap);
141 	va_end(ap);
142 	if(count == -1) {
143 		/* The buffer was not big enough */
144 		strcpy(&(buffer[BUFSIZE - 5]), "...\n");
145 		count = BUFSIZE - 1;
146 	}
147 	if((logname = getenv("INSTALLWATCHFILE"))) {
148 		logfd = true_open(logname, O_WRONLY | O_CREAT | O_APPEND, 0666);
149 		if(logfd >= 0) {
150 			if(write(logfd, buffer, count) != count)
151 				syslog(LOGLEVEL, "Count not write `%s' in `%s': %s\n", buffer, logname, strerror(errno));
152 			if(close(logfd) < 0)
153 				syslog(LOGLEVEL, "Could not close `%s': %s\n", logname, strerror(errno));
154 		} else
155 			syslog(LOGLEVEL, "Could not open `%s' to write `%s': %s\n", logname, buffer, strerror(errno));
156 
157 	} else
158 		syslog(LOGLEVEL, buffer);
159 }
160 
canonicalize(const char * path,char * resolved_path)161 static void canonicalize(const char *path, char *resolved_path) {
162 	if(!realpath(path, resolved_path) && (path[0] != '/')) {
163 		/* The path could not be canonicalized, append it
164 		 * to the current working directory if it was not
165 		 * an absolute path                               */
166 		getcwd(resolved_path, MAXPATHLEN - 2);
167 		strcat(resolved_path, "/");
168 		strncat(resolved_path, path, MAXPATHLEN - 1);
169 	}
170 }
171 
make_path(char * path)172 static void make_path (char *path) {
173  char checkdir[BUFSIZ];
174  struct stat inode;
175  int i = 0;
176 
177 #if DEBUG
178 printf ("===== make_path: %s\n", path);
179 #endif
180 
181  while ( path[i] != '\0' ) {
182     checkdir[i] = path[i];
183     if (checkdir[i] == '/') {  /* Each time a '/' is found, check if the    */
184        checkdir[i+1] = '\0';   /* path exists. If it doesn't, we create it. */
185        if (stat (checkdir, &inode) < 0)
186           true_mkdir (checkdir, S_IRWXU);
187     }
188     i++;
189  }
190 
191 }
192 
193 
194 
backup(char * path)195 static void backup(char *path) {
196 
197    char buffer[BUFSIZ];
198    char checkdir[BUFSIZ];
199    char backup_path[BUFSIZ];
200    int orig,
201        dest,
202        placeholder,
203        bytes,
204        i,
205        blen;
206 
207 
208    struct stat inode, newinode, backup_inode;
209 
210 #if DEBUG
211 printf ("========= backup () =========\npath: %s\n", path);
212 #endif
213 
214 /* If INSTALLWATCH_BACKUP_PATH is not defined then we won't do the backup */
215  if (!getenv("INSTALLWATCH_BACKUP_PATH")) {
216     #ifdef DEBUG
217     printf ("Backup not enabled, path: %s\n", path);
218     #endif
219     return;
220  }
221 
222 
223  /* Check if this is inside /dev */
224    if (strstr (path, "/dev") == path) {
225      #if DEBUG
226       printf ("%s is inside /dev. Ignoring.\n", path);
227      #endif
228       return;
229    }
230 
231  /* Now check for /tmp */
232    if (strstr (path, "/tmp") == path) {
233      #if DEBUG
234       printf ("%s is inside /tmp. Ignoring.\n", path);
235      #endif
236       return;
237    }
238 
239  /* Finally, the backup path itself */
240    if (strstr (path, getenv("INSTALLWATCH_BACKUP_PATH")) == path) {
241      #if DEBUG
242       printf ("%s is inside the backup path. Ignoring.\n", path);
243      #endif
244       return;
245    }
246 
247 
248  /* Does it exist already? */
249 #if DEBUG
250 printf ("Existe %s?\n", path);
251 #endif
252    if (stat(path, &inode) < 0) {
253 
254       /* It doesn't exist, we'll tag it so we won't back it up  */
255       /* if we run into it later                                */
256 
257       strcpy (backup_path, getenv ("INSTALLWATCH_BACKUP_PATH"));
258       strncat (backup_path, "/no-backup/", 11);
259       strcat (backup_path, path);
260       make_path(backup_path);
261 
262      /* This one's just a placeholder */
263       placeholder = true_creat(backup_path, S_IREAD);
264       if (!(placeholder < 0)) close (placeholder);
265 
266 #if DEBUG
267 printf ("NO EXISTE\n");
268 #endif
269       return;
270    }
271 
272 
273 /* Is this one tagged for no backup (i.e. it didn't previously exist)? */
274 
275 
276 strcpy (backup_path, getenv ("INSTALLWATCH_BACKUP_PATH"));
277 strncat (backup_path, "/no-backup/", 11);
278 strcat (backup_path, path);
279 
280 if (stat (backup_path, &backup_inode) >= 0) {
281 #if DEBUG
282 printf ("%s no debe ser respaldado", backup_path);
283 #endif
284 return;
285 }
286 
287 
288 #if DEBUG
289 printf ("Si existe, veamos de que tipo es.\n");
290 #endif
291 
292  /* Append the path to the backup_path */
293 
294       strcpy (backup_path, getenv ("INSTALLWATCH_BACKUP_PATH"));
295       strcat (backup_path, path);
296 
297 
298 /* Create the directory tree for this file in the backup dir */
299    make_path (backup_path);
300 
301 /* What kind of file is this? */
302 
303 /* Regular file */
304  if (S_ISREG(inode.st_mode)) {
305     #if DEBUG
306     printf ("%s es un archivo regular\n", path);
307     #endif
308     if ( (orig = true_open (path, O_RDONLY)) < 0) return;
309 
310     /* Write the backup */
311    if ( (dest = true_open (backup_path, O_WRONLY|O_CREAT|O_TRUNC, inode.st_mode)) < 0) {
312       close (orig);
313       return ;
314    }
315 
316     while ( (bytes = read (orig, buffer, BUFSIZ)) > 0)
317       write (dest, buffer, bytes);
318     close( dest );
319     close( orig );
320  }
321 
322 
323 /* Directory */
324  if (S_ISDIR(inode.st_mode)) {
325     #if DEBUG
326     printf ("%s es un directorio\n", path);
327     #endif
328     true_mkdir (backup_path, inode.st_mode);
329  }
330 
331 
332 /* Block special */
333 
334 /* Since we're ignoring everything under /dev,
335  * this one will be hard to find. */
336 
337  if (S_ISBLK(inode.st_mode)) {
338     #if DEBUG
339     printf ("%s es un blkspecial\n", path);
340     #endif
341     mknod (backup_path, inode.st_mode | S_IFBLK, inode.st_rdev);
342  }
343 
344 
345 /* Character special */
346  if (S_ISCHR(inode.st_mode)) {
347     #if DEBUG
348     printf ("%s es un charspecial\n", path);
349     #endif
350     mknod (backup_path, inode.st_mode | S_IFCHR, inode.st_rdev);
351  }
352 
353 
354 /* FIFO */
355  if (S_ISFIFO(inode.st_mode)) {
356     #if DEBUG
357     printf ("%s es un fifo\n", path);
358     #endif
359     mknod (backup_path, inode.st_mode | S_IFIFO, 0);
360  }
361 
362 /* If we have a new file, set it to the right owner and group */
363  if (!stat (path, &newinode)) true_chown (backup_path, inode.st_uid, inode.st_gid);
364 
365 
366 /* Check the owner and permission of the created directories */
367  i=0;
368  blen = strlen (getenv ("INSTALLWATCH_BACKUP_PATH"));
369  while ( path[i] != '\0' ) {
370     checkdir[i] = backup_path[blen+i] = path[i];
371     if (checkdir[i] == '/') {  /* Each time a '/' is found, check if the    */
372        checkdir[i+1] = '\0';   /* path exists. If it does, set it's perms.  */
373        if (!stat (checkdir, &inode)) {
374           backup_path[blen+i+1]='\0';
375           true_chmod (backup_path, inode.st_mode);
376           true_chown (backup_path, inode.st_uid, inode.st_gid);
377        }
378     }
379     i++;
380  }
381 
382 }
383 
time(time_t * timer)384 time_t time (time_t *timer) {
385 	TIMECOUNT;
386 
387 #if DEBUG
388 	puts("time\n");
389 #endif
390 
391 return true_time(timer);
392 }
393 
chmod(const char * path,mode_t mode)394 int chmod(const char *path, mode_t mode) {
395 	int result;
396 	char canonic[MAXPATHLEN];
397 
398 	REFCOUNT;
399 	canonicalize(path, canonic);
400 
401      #if DEBUG
402 	puts ("in installwatch chmod\n");
403      #endif
404 	backup (canonic);
405 
406 	result = true_chmod(path, mode);
407 	log("%d\tchmod\t%s\t0%04o\t#%s\n", result, canonic, mode, error(result));
408 	return result;
409 }
410 
chown(const char * path,uid_t owner,gid_t group)411 int chown(const char *path, uid_t owner, gid_t group) {
412 	int result;
413 	char canonic[MAXPATHLEN];
414 
415 	REFCOUNT;
416 	canonicalize(path, canonic);
417 
418 #if DEBUG
419 	puts("chown\n");
420 #endif
421 	backup (canonic);
422 
423 	result = true_chown(path, owner, group);
424 	log("%d\tchown\t%s\t%d\t%d\t#%s\n", result, canonic, owner, group, error(result));
425 	return result;
426 }
427 
chroot(const char * path)428 int chroot(const char *path) {
429 	int result;
430 	char canonic[MAXPATHLEN];
431 
432 	REFCOUNT;
433 	canonicalize(path, canonic);
434 	result = true_chroot(path);
435 	/* From now on, another log file will be written if *
436 	 * INSTALLWATCHFILE is set                          */
437 	log("%d\tchroot\t%s\t#%s\n", result, canonic, error(result));
438 	return result;
439 }
440 
creat(const char * pathname,mode_t mode)441 int creat(const char *pathname, mode_t mode) {
442 /* Is it a system call? */
443 	int result;
444 	char canonic[MAXPATHLEN];
445 
446 	REFCOUNT;
447 	canonicalize(pathname, canonic);
448 
449 #if DEBUG
450 	printf("creat\n");
451 #endif
452 	backup(canonic);
453 
454 
455 	result = true_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
456 	log("%d\tcreat\t%s\t#%s\n", result, canonic, error(result));
457 	return result;
458 }
459 
fchmod(int filedes,mode_t mode)460 int fchmod(int filedes, mode_t mode) {
461 	int result;
462 
463 	REFCOUNT;
464 
465 #if DEBUG
466 	puts("fchmod\n");
467 #endif
468 
469 	result = true_fchmod(filedes, mode);
470 	log("%d\tfchmod\t%d\t0%04o\t#%s\n", result, filedes, mode, error(result));
471 	return result;
472 }
473 
fchown(int fd,uid_t owner,gid_t group)474 int fchown(int fd, uid_t owner, gid_t group) {
475 	int result;
476 
477 	REFCOUNT;
478 
479 #if DEBUG
480 	puts("fchown\n");
481 #endif
482 
483 	result = true_fchown(fd, owner, group);
484 	log("%d\tfchown\t%d\t%d\t%d\t#%s\n", result, fd, owner, group, error(result));
485 	return result;
486 }
487 
fopen(const char * pathname,const char * mode)488 FILE *fopen(const char *pathname, const char *mode) {
489 	FILE *result;
490 	char canonic[MAXPATHLEN];
491 
492 	REFCOUNT;
493 	canonicalize(pathname, canonic);
494 
495 #if DEBUG
496 	puts("fopen\n");
497 #endif
498 	if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+')
499 	backup (canonic);
500 
501 	result = true_fopen(pathname,mode);
502 	if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+')
503 		log("%d\tfopen\t%s\t#%s\n", (int)result, canonic, error(result));
504 	return result;
505 }
506 
ftruncate(int fd,TRUNCATE_T length)507 int ftruncate(int fd, TRUNCATE_T length) {
508 	int result;
509 
510 	REFCOUNT;
511 
512 #if DEBUG
513 	puts ("ftruncate\n");
514 #endif
515 
516 	result = true_ftruncate(fd, length);
517 	log("%d\tftruncate\t%d\t%d\t#%s\n", result, fd, (int)length, error(result));
518 	return result;
519 }
520 
lchown(const char * path,uid_t owner,gid_t group)521 int lchown(const char *path, uid_t owner, gid_t group) {
522 /* Linux specific? */
523 	int result;
524 	char canonic[MAXPATHLEN];
525 
526 	REFCOUNT;
527 
528 #if DEBUG
529 	puts ("lchown\n");
530 #endif
531 	canonicalize(path, canonic);
532 
533 	backup (canonic);
534 
535 	result = true_chown(path, owner, group);
536 	log("%d\tlchown\t%s\t%d\t%d\t#%s\n", result, canonic, owner, group, error(result));
537 	return result;
538 }
539 
link(const char * oldpath,const char * newpath)540 int link(const char *oldpath, const char *newpath) {
541 	int result;
542 	char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
543 
544 	REFCOUNT;
545 
546 #if DEBUG
547 	puts ("link\n");
548 #endif
549 
550 	canonicalize(oldpath, old_canonic);
551 	canonicalize(newpath, new_canonic);
552 	result = true_link(oldpath, newpath);
553 	log("%d\tlink\t%s\t%s\t#%s\n", result, old_canonic, new_canonic, error(result));
554 	return result;
555 }
556 
mkdir(const char * pathname,mode_t mode)557 int mkdir(const char *pathname, mode_t mode) {
558 	int result;
559 	char canonic[MAXPATHLEN];
560 
561 	REFCOUNT;
562 	canonicalize(pathname, canonic);
563 	result = true_mkdir(pathname, mode);
564 	log("%d\tmkdir\t%s\t#%s\n", result, canonic, error(result));
565 	return result;
566 }
567 
open(const char * pathname,int flags,...)568 int open(const char *pathname, int flags, ...) {
569 /* Eventually, there is a third parameter: it's mode_t mode */
570 	va_list ap;
571 	mode_t mode;
572 	int result;
573 	char canonic[MAXPATHLEN];
574 
575 	REFCOUNT;
576 	va_start(ap, flags);
577 	mode = va_arg(ap, int);
578 	va_end(ap);
579 	canonicalize(pathname, canonic);
580 
581 #if DEBUG
582 	printf ("open\n");
583 #endif
584 	if(flags & (O_WRONLY | O_RDWR))
585 	backup (canonic);
586 
587 	result = true_open(pathname, flags, mode);
588 	if(flags & (O_WRONLY | O_RDWR))
589 		log("%d\topen\t%s\t#%s\n", result, canonic, error(result));
590 	return result;
591 }
592 
rename(const char * oldpath,const char * newpath)593 int rename(const char *oldpath, const char *newpath) {
594 	int result;
595 	char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
596 
597 	REFCOUNT;
598 	canonicalize(oldpath, old_canonic);
599 
600 #if DEBUG
601 	puts ("rename\n");
602 #endif
603 	backup (old_canonic);
604 
605 	canonicalize(newpath, new_canonic);
606 	result = true_rename(oldpath, newpath);
607 	log("%d\trename\t%s\t%s\t#%s\n", result, old_canonic, new_canonic, error(result));
608 	return result;
609 }
610 
rmdir(const char * pathname)611 int rmdir(const char *pathname) {
612 	int result;
613 	char canonic[MAXPATHLEN];
614 
615 	REFCOUNT;
616 	canonicalize(pathname, canonic);
617 
618 #if DEBUG
619 	printf ("rmdir\n");
620 #endif
621 	backup(canonic);
622 
623 	result = true_rmdir(pathname);
624 	log("%d\trmdir\t%s\t#%s\n", result, canonic, error(result));
625 	return result;
626 }
627 
symlink(const char * oldpath,const char * newpath)628 int symlink(const char *oldpath, const char *newpath) {
629 	int result;
630 	char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
631 
632 	REFCOUNT;
633 
634 #if DEBUG
635 	puts ("symlink\n");
636 #endif
637 
638 	canonicalize(oldpath, old_canonic);
639 	canonicalize(newpath, new_canonic);
640 	result = true_symlink(oldpath, newpath);
641 	log("%d\tsymlink\t%s\t%s\t#%s\n", result, old_canonic, new_canonic, error(result));
642 	return result;
643 }
644 
truncate(const char * path,TRUNCATE_T length)645 int truncate(const char *path, TRUNCATE_T length) {
646 	int result;
647 	char canonic[MAXPATHLEN];
648 
649 	REFCOUNT;
650 
651 #if DEBUG
652 	puts ("truncate\n");
653 #endif
654 
655 	canonicalize(path, canonic);
656 
657 	backup (canonic);
658 
659 	result = true_truncate(path, length);
660 	log("%d\ttruncate\t%s\t%d\t#%s\n", result, path, (int)length, error(result));
661 	return result;
662 }
663 
unlink(const char * pathname)664 int unlink(const char *pathname) {
665 	int result;
666 	char canonic[MAXPATHLEN];
667 
668 	REFCOUNT;
669 	canonicalize(pathname, canonic);
670 
671 #if DEBUG
672 	printf ("unlink\n");
673 #endif
674 	backup(canonic);
675 
676 	result = true_unlink(pathname);
677 	log("%d\tunlink\t%s\t#%s\n", result, canonic, error(result));
678 	return result;
679 }
680 
681 #if(GLIBC_MINOR >= 1)
682 
creat64(const char * pathname,__mode_t mode)683 int creat64(const char *pathname, __mode_t mode) {
684 /* Is it a system call? */
685 	int result;
686 	char canonic[MAXPATHLEN];
687 
688 	REFCOUNT;
689 	canonicalize(pathname, canonic);
690 
691 #if DEBUG
692         puts ("creat64\n");
693 #endif
694 	backup (canonic);
695 
696 	result = true_open64(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
697 	log("%d\tcreat\t%s\t#%s\n", result, canonic, error(result));
698 	return result;
699 }
700 
ftruncate64(int fd,__off64_t length)701 int ftruncate64(int fd, __off64_t length) {
702 	int result;
703 
704 	REFCOUNT;
705 
706 #if DEBUG
707         puts ("ftruncate64\n");
708 #endif
709 
710 	result = true_ftruncate64(fd, length);
711 	log("%d\tftruncate\t%d\t%d\t#%s\n", result, fd, (int)length, error(result));
712 	return result;
713 }
714 
fopen64(const char * pathname,const char * mode)715 FILE *fopen64(const char *pathname, const char *mode) {
716 	FILE *result;
717 	char canonic[MAXPATHLEN];
718 
719 	REFCOUNT;
720 	canonicalize(pathname, canonic);
721 
722 #if DEBUG
723 	puts("fopen64\n");
724 #endif
725 	if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+')
726 	backup (canonic);
727 
728 	result = true_fopen(pathname,mode);
729 	if(mode[0]=='w'||mode[0]=='a'||mode[1]=='+')
730 		log("%d\tfopen64\t%s\t#%s\n", (int)result, canonic, error(result));
731 	return result;
732 }
733 
open64(const char * pathname,int flags,...)734 int open64(const char *pathname, int flags, ...) {
735 /* Eventually, there is a third parameter: it's mode_t mode */
736 	va_list ap;
737 	mode_t mode;
738 	int result;
739 	char canonic[MAXPATHLEN];
740 
741 	REFCOUNT;
742 
743 #if DEBUG
744         puts ("open64\n");
745 #endif
746 
747 	va_start(ap, flags);
748 	mode = va_arg(ap, mode_t);
749 	va_end(ap);
750 	canonicalize(pathname, canonic);
751 	if(flags & (O_WRONLY | O_RDWR))
752 	   backup(canonic);
753 	result = true_open64(pathname, flags, mode);
754 	if(flags & (O_WRONLY | O_RDWR))
755 		log("%d\topen\t%s\t#%s\n", result, canonic, error(result));
756 	return result;
757 }
758 
truncate64(const char * path,__off64_t length)759 int truncate64(const char *path, __off64_t length) {
760 	int result;
761 	char canonic[MAXPATHLEN];
762 
763 	REFCOUNT;
764 
765 #if DEBUG
766         puts ("truncate64\n");
767 #endif
768 
769 	canonicalize(path, canonic);
770 
771 	backup(canonic);
772 
773 	result = true_truncate64(path, length);
774 	log("%d\ttruncate\t%s\t%d\t#%s\n", result, path, (int)length, error(result));
775 	return result;
776 }
777 
778 #endif /* GLIBC_MINOR >= 1 */
779 
780