r23785: use the GPLv3 boilerplate as recommended by the FSF and the license text
[samba.git] / examples / libsmbclient / smbwrapper / wrapper.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0
4    SMB wrapper functions
5    Copyright (C) Andrew Tridgell 1998
6    Copyright (C) Derrell Lipman 2002-2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  * This is a rewrite of the original wrapped.c file, using libdl to obtain
24  * pointers into the C library rather than attempting to find undocumented
25  * functions in the C library to call for native file access.  The problem
26  * with the original implementation's paradigm is that samba manipulates
27  * defines such that it gets the sizes of structures that it wants
28  * (e.g. mapping 32-bit functions to 64-bit functions with their associated
29  * 64-bit structure fields), but programs run under smbsh or using
30  * smbwrapper.so were not necessarily compiled with the same flags.  As an
31  * example of the problem, a program calling stat() passes a pointer to a
32  * "struct stat" but the fields in that structure are different in samba than
33  * they are in the calling program if the calling program was not compiled to
34  * force stat() to be mapped to stat64().
35  *
36  * In this version, we provide an interface to each of the native functions,
37  * not just the ones that samba is compiled to map to.  We obtain the function
38  * pointers from the C library using dlsym(), and for native file operations,
39  * directly call the same function that the calling application was
40  * requesting.  Since the size of the calling application's structures vary
41  * depending on what function was called, we use our own internal structures
42  * for passing information to/from the SMB equivalent functions, and map them
43  * back to the native structures before returning the result to the caller.
44  *
45  * This implementation was completed 25 December 2002.
46  * Derrell Lipman
47  */
48
49 /* We do not want auto munging of 32->64 bit names in this file (only) */
50 #undef _FILE_OFFSET_BITS
51 #undef _GNU_SOURCE
52
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <sys/time.h>
56 #include <stdlib.h>
57 #include <fcntl.h>
58 #include <unistd.h>
59 #include <utime.h>
60 #include <stdio.h>
61 #include <dirent.h>
62 #include <signal.h>
63 #include <stdarg.h>
64 #ifdef __USE_GNU
65 # define SMBW_USE_GNU
66 #endif
67 #define __USE_GNU             /* need this to have RTLD_NEXT defined */
68 #include <dlfcn.h>
69 #ifndef SMBW_USE_GNU
70 # undef __USE_GNU
71 #endif
72 #include <errno.h>
73 #include "libsmbclient.h"
74 #include "bsd-strlfunc.h"
75 #include "wrapper.h"
76
77 /*
78  * Debug bits:
79  * 0x0 = none
80  * 0x1 = display symbol definitions not found in C library
81  * 0x2 = show wrapper functions being called
82  * 0x4 = log to file SMBW_DEBUG_FILE instead of stderr
83  */
84 #define SMBW_DEBUG      0x0
85 #define SMBW_DEBUG_FILE "/tmp/smbw.log"
86
87 int      smbw_debug = 0;
88
89 #if SMBW_DEBUG & 0x2
90 static int      debugFd = 2;
91 #endif
92
93 #ifndef ENOTSUP
94 #define ENOTSUP EOPNOTSUPP
95 #endif
96
97 /*
98  * None of the methods of having the initialization function called
99  * automatically upon shared library startup are effective in all situations.
100  * We provide the "-init" parameter to the linker which is effective most of
101  * the time, but fails for applications that provide their own shared
102  * libraries with _init() functions (e.g. ps).  We can't use "-z initfirst"
103  * because the environment isn't yet set up at that point, so we can't find
104  * our shared memory identifier (see shared.c).  We therefore must resort to
105  * this tried-and-true method of keeping an "initialized" flag.  We check it
106  * prior to calling the initialize() function to save a function call (a slow
107  * operation on x86).
108  */
109 #if SMBW_DEBUG & 0x2
110 #  define check_init(buf)                                               \
111         do {                                                            \
112                 int saved_errno = errno;                                \
113                 if (! initialized) initialize();                        \
114                 (* smbw_libc.write)(debugFd, "["buf"]", sizeof(buf)+1); \
115                 errno = saved_errno;                                    \
116         } while (0)
117 #else
118 #  define check_init(buf)                               \
119         do {                                            \
120                 if (! initialized) smbw_initialize();   \
121         } while (0)
122 #endif
123
124 static void initialize(void);
125
126 static int initialized = 0;
127
128 SMBW_libc_pointers smbw_libc;
129
130 /*
131  * A public entry point used by the "-init" option to the linker.
132  */
133 void smbw_initialize(void)
134 {
135         initialize();
136 }
137
138 static void initialize(void)
139 {
140         int saved_errno;
141 #if SMBW_DEBUG & 0x1
142         char *error;
143 #endif
144         
145         saved_errno = errno;
146         
147         if (initialized) {
148                 return;
149         }
150         initialized = 1;
151         
152 #if SMBW_DEBUG & 0x1
153 # define GETSYM(symname, symstring)                                      \
154         if ((smbw_libc.symname = dlsym(RTLD_NEXT, symstring)) == NULL) { \
155                 if (smbw_libc.write != NULL &&                           \
156                     (error = dlerror()) != NULL) {                       \
157                         (* smbw_libc.write)(1, error, strlen(error));    \
158                         (* smbw_libc.write)(1, "\n", 1);                 \
159                 }                                                        \
160         }
161 #else
162 # define GETSYM(symname, symstring)                     \
163         smbw_libc.symname = dlsym(RTLD_NEXT, symstring);
164 #endif
165         
166         /*
167          * Get pointers to each of the symbols we'll need, from the C library
168          *
169          * Some of these symbols may not be found in the C library.  That's
170          * fine.  We declare all of them here, and if the C library supports
171          * them, they may be called so we have the wrappers for them.  If the
172          * C library doesn't support them, then the wrapper function will
173          * never be called, and the null pointer will never be dereferenced.
174          */
175         GETSYM(write, "write"); /* first, to allow debugging */
176         GETSYM(open, "open");
177         GETSYM(_open, "_open");
178         GETSYM(__open, "__open");
179         GETSYM(open64, "open64");
180         GETSYM(_open64, "_open64");
181         GETSYM(__open64, "__open64");
182         GETSYM(pread, "pread");
183         GETSYM(pread64, "pread64");
184         GETSYM(pwrite, "pwrite");
185         GETSYM(pwrite64, "pwrite64");
186         GETSYM(close, "close");
187         GETSYM(__close, "__close");
188         GETSYM(_close, "_close");
189         GETSYM(fcntl, "fcntl");
190         GETSYM(__fcntl, "__fcntl");
191         GETSYM(_fcntl, "_fcntl");
192         GETSYM(getdents, "getdents");
193         GETSYM(__getdents, "__getdents");
194         GETSYM(_getdents, "_getdents");
195         GETSYM(getdents64, "getdents64");
196         GETSYM(lseek, "lseek");
197         GETSYM(__lseek, "__lseek");
198         GETSYM(_lseek, "_lseek");
199         GETSYM(lseek64, "lseek64");
200         GETSYM(__lseek64, "__lseek64");
201         GETSYM(_lseek64, "_lseek64");
202         GETSYM(read, "read");
203         GETSYM(__read, "__read");
204         GETSYM(_read, "_read");
205         GETSYM(__write, "__write");
206         GETSYM(_write, "_write");
207         GETSYM(access, "access");
208         GETSYM(chmod, "chmod");
209         GETSYM(fchmod, "fchmod");
210         GETSYM(chown, "chown");
211         GETSYM(fchown, "fchown");
212         GETSYM(__xstat, "__xstat");
213         GETSYM(getcwd, "getcwd");
214         GETSYM(mkdir, "mkdir");
215         GETSYM(__fxstat, "__fxstat");
216         GETSYM(__lxstat, "__lxstat");
217         GETSYM(stat, "stat");
218         GETSYM(lstat, "lstat");
219         GETSYM(fstat, "fstat");
220         GETSYM(unlink, "unlink");
221         GETSYM(utime, "utime");
222         GETSYM(utimes, "utimes");
223         GETSYM(readlink, "readlink");
224         GETSYM(rename, "rename");
225         GETSYM(rmdir, "rmdir");
226         GETSYM(symlink, "symlink");
227         GETSYM(dup, "dup");
228         GETSYM(dup2, "dup2");
229         GETSYM(opendir, "opendir");
230         GETSYM(readdir, "readdir");
231         GETSYM(closedir, "closedir");
232         GETSYM(telldir, "telldir");
233         GETSYM(seekdir, "seekdir");
234         GETSYM(creat, "creat");
235         GETSYM(creat64, "creat64");
236         GETSYM(__xstat64, "__xstat64");
237         GETSYM(stat64, "stat64");
238         GETSYM(__fxstat64, "__fxstat64");
239         GETSYM(fstat64, "fstat64");
240         GETSYM(__lxstat64, "__lxstat64");
241         GETSYM(lstat64, "lstat64");
242         GETSYM(_llseek, "_llseek");
243         GETSYM(readdir64, "readdir64");
244         GETSYM(readdir_r, "readdir_r");
245         GETSYM(readdir64_r, "readdir64_r");
246         GETSYM(setxattr, "setxattr");
247         GETSYM(lsetxattr, "lsetxattr");
248         GETSYM(fsetxattr, "fsetxattr");
249         GETSYM(getxattr, "getxattr");
250         GETSYM(lgetxattr, "lgetxattr");
251         GETSYM(fgetxattr, "fgetxattr");
252         GETSYM(removexattr, "removexattr");
253         GETSYM(lremovexattr, "lremovexattr");
254         GETSYM(fremovexattr, "fremovexattr");
255         GETSYM(listxattr, "listxattr");
256         GETSYM(llistxattr, "llistxattr");
257         GETSYM(flistxattr, "flistxattr");
258         GETSYM(chdir, "chdir");
259         GETSYM(fchdir, "fchdir");
260         GETSYM(fork, "fork");
261         GETSYM(select, "select");
262         GETSYM(_select, "_select");
263         GETSYM(__select, "__select");
264         
265 #if SMBW_DEBUG & 4
266         {
267                 if ((debugFd =
268                      open(SMBW_DEBUG_FILE, O_WRONLY | O_CREAT | O_APPEND)) < 0)
269                 {
270 #               define SMBW_MESSAGE    "Could not create " SMBW_DEBUG_FILE "\n" 
271                         (* smbw_libc.write)(1, SMBW_MESSAGE, sizeof(SMBW_MESSAGE));
272 #               undef SMBW_MESSAGE
273                         exit(1);
274                 }
275         }
276 #endif
277         
278         errno = saved_errno;
279 }
280
281 /**
282  ** Static Functions
283  **/
284
285 static void stat_convert(struct SMBW_stat *src, struct stat *dest)
286 {
287         memset(dest, '\0', sizeof(*dest));
288         dest->st_size = src->s_size;
289         dest->st_mode = src->s_mode;
290         dest->st_ino = src->s_ino;
291         dest->st_dev = src->s_dev;
292         dest->st_rdev = src->s_rdev;
293         dest->st_nlink = src->s_nlink;
294         dest->st_uid = src->s_uid;
295         dest->st_gid = src->s_gid;
296         dest->st_atime = src->s_atime;
297         dest->st_mtime = src->s_mtime;
298         dest->st_ctime = src->s_ctime;
299         dest->st_blksize = src->s_blksize;
300         dest->st_blocks = src->s_blocks;
301 }
302
303 static void stat64_convert(struct SMBW_stat *src, struct stat64 *dest)
304 {
305         memset(dest, '\0', sizeof(*dest));
306         dest->st_size = src->s_size;
307         dest->st_mode = src->s_mode;
308         dest->st_ino = src->s_ino;
309         dest->st_dev = src->s_dev;
310         dest->st_rdev = src->s_rdev;
311         dest->st_nlink = src->s_nlink;
312         dest->st_uid = src->s_uid;
313         dest->st_gid = src->s_gid;
314         dest->st_atime = src->s_atime;
315         dest->st_mtime = src->s_mtime;
316         dest->st_ctime = src->s_ctime;
317         dest->st_blksize = src->s_blksize;
318         dest->st_blocks = src->s_blocks;
319 }
320
321 static void dirent_convert(struct SMBW_dirent *src, struct dirent *dest)
322 {
323         char *p;
324         
325         memset(dest, '\0', sizeof(*dest));
326         dest->d_ino = src->d_ino;
327         dest->d_off = src->d_off;
328         
329         switch(src->d_type)
330         {
331         case SMBC_WORKGROUP:
332         case SMBC_SERVER:
333         case SMBC_FILE_SHARE:
334         case SMBC_DIR:
335                 dest->d_type = DT_DIR;
336                 break;
337                 
338         case SMBC_FILE:
339                 dest->d_type = DT_REG;
340                 break;
341                 
342         case SMBC_PRINTER_SHARE:
343                 dest->d_type = DT_CHR;
344                 break;
345                 
346         case SMBC_COMMS_SHARE:
347                 dest->d_type = DT_SOCK;
348                 break;
349                 
350         case SMBC_IPC_SHARE:
351                 dest->d_type = DT_FIFO;
352                 break;
353                 
354         case SMBC_LINK:
355                 dest->d_type = DT_LNK;
356                 break;
357         }
358         
359         dest->d_reclen = src->d_reclen;
360         smbw_strlcpy(dest->d_name, src->d_name, sizeof(dest->d_name));
361         p = dest->d_name + strlen(dest->d_name) + 1;
362         smbw_strlcpy(p,
363                      src->d_comment,
364                      sizeof(dest->d_name) - (p - dest->d_name));
365 }
366
367 static void dirent64_convert(struct SMBW_dirent *src, struct dirent64 *dest)
368 {
369         char *p;
370         
371         memset(dest, '\0', sizeof(*dest));
372         dest->d_ino = src->d_ino;
373         dest->d_off = src->d_off;
374         
375         switch(src->d_type)
376         {
377         case SMBC_WORKGROUP:
378         case SMBC_SERVER:
379         case SMBC_FILE_SHARE:
380         case SMBC_DIR:
381                 dest->d_type = DT_DIR;
382                 break;
383                 
384         case SMBC_FILE:
385                 dest->d_type = DT_REG;
386                 break;
387                 
388         case SMBC_PRINTER_SHARE:
389                 dest->d_type = DT_CHR;
390                 break;
391                 
392         case SMBC_COMMS_SHARE:
393                 dest->d_type = DT_SOCK;
394                 break;
395                 
396         case SMBC_IPC_SHARE:
397                 dest->d_type = DT_FIFO;
398                 break;
399                 
400         case SMBC_LINK:
401                 dest->d_type = DT_LNK;
402                 break;
403         }
404         
405         dest->d_reclen = src->d_reclen;
406         smbw_strlcpy(dest->d_name, src->d_name, sizeof(dest->d_name));
407         p = dest->d_name + strlen(dest->d_name) + 1;
408         smbw_strlcpy(p,
409                      src->d_comment,
410                      sizeof(dest->d_name) - (p - dest->d_name));
411 }
412
413 static int openx(char *name, int flags, mode_t mode, int (* f)(char *, int, mode_t))
414 {
415         if (smbw_path(name)) {
416                 return smbw_open(name, flags, mode);
417         }
418         
419         return (* f)(name, flags, mode);
420 }
421
422 static int closex(int fd, int (* f)(int fd))
423 {
424         if (smbw_fd(fd)) {
425                 return smbw_close(fd);
426         }
427         
428         return (* f)(fd);
429 }
430
431 static int fcntlx(int fd, int cmd, long arg, int (* f)(int, int, long))
432 {
433         if (smbw_fd(fd)) {
434                 return smbw_fcntl(fd, cmd, arg);
435         }
436         
437         return (* f)(fd, cmd, arg);
438 }
439
440 static int getdentsx(int fd, struct dirent *external, unsigned int count, int (* f)(int, struct dirent *, unsigned int))
441 {
442         if (smbw_fd(fd)) {
443                 int i;
444                 int internal_count;
445                 struct SMBW_dirent *internal;
446                 int ret;
447                 int n;
448                 
449                 /*
450                  * LIMITATION: If they pass a count which is not a multiple of
451                  * the size of struct dirent, they will not get a partial
452                  * structure; we ignore the excess count.
453                  */
454                 n = (count / sizeof(struct dirent));
455                 
456                 internal_count = sizeof(struct SMBW_dirent) * n;
457                 internal = malloc(internal_count);
458                 if (internal == NULL) {
459                         errno = ENOMEM;
460                         return -1;
461                 }
462                 ret = smbw_getdents(fd, internal, internal_count);
463                 if (ret <= 0)
464                         return ret;
465                 
466                 ret = sizeof(struct dirent) * n;
467                 
468                 for (i = 0; i < n; i++)
469                         dirent_convert(&internal[i], &external[i]);
470                 
471                 return ret;
472         }
473         
474         return (* f)(fd, external, count);
475 }
476
477 static off_t lseekx(int fd,
478                     off_t offset,
479                     int whence,
480                     off_t (* f)(int, off_t, int))
481 {
482         off_t           ret;
483         
484         /*
485          * We have left the definitions of the smbw_ functions undefined,
486          * because types such as off_t can differ in meaning betweent his
487          * function and smbw.c et al.  Functions that return other than an
488          * integer value, however, MUST have their return value defined.
489          */
490         off64_t         smbw_lseek();
491         
492         if (smbw_fd(fd)) {
493                 return (off_t) smbw_lseek(fd, offset, whence);
494         }
495         
496         ret = (* f)(fd, offset, whence);
497         if (smbw_debug)
498         {
499                 printf("lseekx(%d, 0x%llx) returned 0x%llx\n",
500                        fd,
501                        (unsigned long long) offset,
502                        (unsigned long long) ret);
503         }
504         return ret;
505 }
506
507 static off64_t lseek64x(int fd,
508                         off64_t offset,
509                         int whence,
510                         off64_t (* f)(int, off64_t, int))
511 {
512         off64_t         ret;
513         
514         /*
515          * We have left the definitions of the smbw_ functions undefined,
516          * because types such as off_t can differ in meaning betweent his
517          * function and smbw.c et al.  Functions that return other than an
518          * integer value, however, MUST have their return value defined.
519          */
520         off64_t         smbw_lseek();
521         
522         if (smbw_fd(fd))
523                 ret = smbw_lseek(fd, offset, whence);
524         else
525                 ret = (* f)(fd, offset, whence);
526         if (smbw_debug)
527         {
528                 printf("lseek64x(%d, 0x%llx) returned 0x%llx\n",
529                        fd,
530                        (unsigned long long) offset,
531                        (unsigned long long) ret);
532         }
533         return ret;
534 }
535
536 static ssize_t readx(int fd, void *buf, size_t count, ssize_t (* f)(int, void *, size_t))
537 {
538         if (smbw_fd(fd)) {
539                 return smbw_read(fd, buf, count);
540         }
541         
542         return (* f)(fd, buf, count);
543 }
544
545 static ssize_t writex(int fd, void *buf, size_t count, ssize_t (* f)(int, void *, size_t))
546 {
547         if (smbw_fd(fd)) {
548                 return smbw_write(fd, buf, count);
549         }
550         
551         return (* f)(fd, buf, count);
552 }
553
554
555 /**
556  ** Wrapper Functions
557  **/
558
559 int open(__const char *name, int flags, ...)
560 {
561         va_list ap;
562         mode_t mode;
563         
564         va_start(ap, flags);
565         mode = va_arg(ap, mode_t);
566         va_end(ap);
567         
568         check_init("open");
569         
570         return openx((char *) name, flags, mode, smbw_libc.open);
571 }
572
573 int _open(char *name, int flags, mode_t mode)
574 {
575         check_init("open");
576         
577         return openx(name, flags, mode, smbw_libc._open);
578 }
579
580 int __open(char *name, int flags, mode_t mode)
581 {
582         check_init("open");
583         
584         return openx(name, flags, mode, smbw_libc.__open);
585 }
586
587 int open64 (__const char *name, int flags, ...)
588 {
589         va_list ap;
590         mode_t mode;
591         
592         va_start(ap, flags);
593         mode = va_arg(ap, mode_t);
594         va_end(ap);
595         
596         check_init("open64");
597         return openx((char *) name, flags, mode, smbw_libc.open64);
598 }
599
600 int _open64(char *name, int flags, mode_t mode)
601 {
602         check_init("_open64");
603         return openx(name, flags, mode, smbw_libc._open64);
604 }
605
606 int __open64(char *name, int flags, mode_t mode)
607 {
608         check_init("__open64");
609         return openx(name, flags, mode, smbw_libc.__open64);
610 }
611
612 ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
613 {
614         check_init("pread");
615         
616         if (smbw_fd(fd)) {
617                 return smbw_pread(fd, buf, size, ofs);
618         }
619         
620         return (* smbw_libc.pread)(fd, buf, size, ofs);
621 }
622
623 ssize_t pread64(int fd, void *buf, size_t size, off64_t ofs)
624 {
625         check_init("pread64");
626         
627         if (smbw_fd(fd)) {
628                 return smbw_pread(fd, buf, size, (off_t) ofs);
629         }
630         
631         return (* smbw_libc.pread64)(fd, buf, size, ofs);
632 }
633
634 ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
635 {
636         check_init("pwrite");
637         
638         if (smbw_fd(fd)) {
639                 return smbw_pwrite(fd, (void *) buf, size, ofs);
640         }
641         
642         return (* smbw_libc.pwrite)(fd, (void *) buf, size, ofs);
643 }
644
645 ssize_t pwrite64(int fd,  const void *buf, size_t size, off64_t ofs)
646 {
647         check_init("pwrite64");
648         
649         if (smbw_fd(fd)) {
650                 return smbw_pwrite(fd, (void *) buf, size, (off_t) ofs);
651         }
652         
653         return (* smbw_libc.pwrite64)(fd, (void *) buf, size, ofs);
654 }
655
656 int chdir(const char *name)
657 {
658         check_init("chdir");
659         return smbw_chdir((char *) name);;
660 }
661
662 int __chdir(char *name)
663 {
664         check_init("__chdir");
665         return smbw_chdir(name);
666 }
667
668 int _chdir(char *name)
669 {
670         check_init("_chdir");
671         return smbw_chdir(name);
672 }
673
674 int close(int fd)
675 {
676         check_init("close");
677         return closex(fd, smbw_libc.close);
678 }
679
680 int __close(int fd)
681 {
682         check_init("__close");
683         return closex(fd, smbw_libc.__close);
684 }
685
686 int _close(int fd)
687 {
688         check_init("_close");
689         return closex(fd, smbw_libc._close);
690 }
691
692 int fchdir(int fd)
693 {
694         check_init("fchdir");
695         return smbw_fchdir(fd);
696 }
697
698 int __fchdir(int fd)
699 {
700         check_init("__fchdir");
701         return fchdir(fd);
702 }
703
704 int _fchdir(int fd)
705 {
706         check_init("_fchdir");
707         return fchdir(fd);
708 }
709
710 int fcntl (int fd, int cmd, ...)
711 {
712         va_list ap;
713         long arg;
714         
715         va_start(ap, cmd);
716         arg = va_arg(ap, long);
717         va_end(ap);
718         
719         check_init("fcntl");
720         return fcntlx(fd, cmd, arg, smbw_libc.fcntl);
721 }
722
723 int __fcntl(int fd, int cmd, ...)
724 {
725         va_list ap;
726         long arg;
727         
728         va_start(ap, cmd);
729         arg = va_arg(ap, long);
730         va_end(ap);
731         
732         check_init("__fcntl");
733         return fcntlx(fd, cmd, arg, smbw_libc.__fcntl);
734 }
735
736 int _fcntl(int fd, int cmd, ...)
737 {
738         va_list ap;
739         long arg;
740         
741         va_start(ap, cmd);
742         arg = va_arg(ap, long);
743         va_end(ap);
744         
745         check_init("_fcntl");
746         return fcntlx(fd, cmd, arg, smbw_libc._fcntl);
747 }
748
749 int getdents(int fd, struct dirent *dirp, unsigned int count)
750 {
751         check_init("getdents");
752         return getdentsx(fd, dirp, count, smbw_libc.getdents);
753 }
754
755 int __getdents(int fd, struct dirent *dirp, unsigned int count)
756 {
757         check_init("__getdents");
758         return getdentsx(fd, dirp, count, smbw_libc.__getdents);
759 }
760
761 int _getdents(int fd, struct dirent *dirp, unsigned int count)
762 {
763         check_init("_getdents");
764         return getdentsx(fd, dirp, count, smbw_libc._getdents);
765 }
766
767 int getdents64(int fd, struct dirent64 *external, unsigned int count)
768 {
769         check_init("getdents64");
770         if (smbw_fd(fd)) {
771                 int i;
772                 struct SMBW_dirent *internal;
773                 int ret;
774                 int n;
775                 
776                 /*
777                  * LIMITATION: If they pass a count which is not a multiple of
778                  * the size of struct dirent, they will not get a partial
779                  * structure; we ignore the excess count.
780                  */
781                 n = (count / sizeof(struct dirent64));
782                 
783                 internal = malloc(sizeof(struct SMBW_dirent) * n);
784                 if (internal == NULL) {
785                         errno = ENOMEM;
786                         return -1;
787                 }
788                 ret = smbw_getdents(fd, internal, count);
789                 if (ret <= 0)
790                         return ret;
791                 
792                 ret = sizeof(struct dirent) * count;
793                 
794                 for (i = 0; count; i++, count--)
795                         dirent64_convert(&internal[i], &external[i]);
796                 
797                 return ret;
798         }
799         
800         return (* smbw_libc.getdents64)(fd, external, count);
801 }
802
803 off_t lseek(int fd, off_t offset, int whence)
804 {
805         off_t           ret;
806         check_init("lseek");
807         ret = lseekx(fd, offset, whence, smbw_libc.lseek);
808         if (smbw_debug)
809         {
810                 printf("lseek(%d, 0x%llx) returned 0x%llx\n",
811                        fd,
812                        (unsigned long long) offset,
813                        (unsigned long long) ret);
814         }
815         return ret;
816 }
817
818 off_t __lseek(int fd, off_t offset, int whence)
819 {
820         off_t           ret;
821         check_init("__lseek");
822         ret = lseekx(fd, offset, whence, smbw_libc.__lseek);
823         if (smbw_debug)
824         {
825                 printf("__lseek(%d, 0x%llx) returned 0x%llx\n",
826                        fd,
827                        (unsigned long long) offset,
828                        (unsigned long long) ret);
829         }
830         return ret;
831 }
832
833 off_t _lseek(int fd, off_t offset, int whence)
834 {
835         off_t           ret;
836         check_init("_lseek");
837         ret = lseekx(fd, offset, whence, smbw_libc._lseek);
838         if (smbw_debug)
839         {
840                 printf("_lseek(%d, 0x%llx) returned 0x%llx\n",
841                        fd,
842                        (unsigned long long) offset,
843                        (unsigned long long) ret);
844         }
845         return ret;
846 }
847
848 off64_t lseek64(int fd, off64_t offset, int whence)
849 {
850         off64_t         ret;
851         check_init("lseek64");
852         ret = lseek64x(fd, offset, whence, smbw_libc.lseek64);
853         if (smbw_debug)
854         {
855                 printf("lseek64(%d, 0x%llx) returned 0x%llx\n",
856                        fd,
857                        (unsigned long long) offset,
858                        (unsigned long long) ret);
859         }
860         return ret;
861 }
862
863 off64_t __lseek64(int fd, off64_t offset, int whence)
864 {
865         check_init("__lseek64");
866         return lseek64x(fd, offset, whence, smbw_libc.__lseek64);
867 }
868
869 off64_t _lseek64(int fd, off64_t offset, int whence)
870 {
871         off64_t         ret;
872         check_init("_lseek64");
873         ret = lseek64x(fd, offset, whence, smbw_libc._lseek64);
874         if (smbw_debug)
875         {
876                 printf("_lseek64(%d, 0x%llx) returned 0x%llx\n",
877                        fd,
878                        (unsigned long long) offset,
879                        (unsigned long long) ret);
880         }
881         return ret;
882 }
883
884 ssize_t read(int fd, void *buf, size_t count)
885 {
886         check_init("read");
887         return readx(fd, buf, count, smbw_libc.read);
888 }
889
890 ssize_t __read(int fd, void *buf, size_t count)
891 {
892         check_init("__read");
893         return readx(fd, buf, count, smbw_libc.__read);
894 }
895
896 ssize_t _read(int fd, void *buf, size_t count)
897 {
898         check_init("_read");
899         return readx(fd, buf, count, smbw_libc._read);
900 }
901
902 ssize_t write(int fd, const void *buf, size_t count)
903 {
904         check_init("write");
905         return writex(fd, (void *) buf, count, smbw_libc.write);
906 }
907
908 ssize_t __write(int fd, const void *buf, size_t count)
909 {
910         check_init("__write");
911         return writex(fd, (void *) buf, count, smbw_libc.__write);
912 }
913
914 ssize_t _write(int fd, const void *buf, size_t count)
915 {
916         check_init("_write");
917         return writex(fd, (void *) buf, count, smbw_libc._write);
918 }
919
920 int access(const char *name, int mode)
921 {
922         check_init("access");
923         
924         if (smbw_path((char *) name)) {
925                 return smbw_access((char *) name, mode);
926         }
927         
928         return (* smbw_libc.access)((char *) name, mode);
929 }
930
931 int chmod(const char *name, mode_t mode)
932 {
933         check_init("chmod");
934         
935         if (smbw_path((char *) name)) {
936                 return smbw_chmod((char *) name, mode);
937         }
938         
939         return (* smbw_libc.chmod)((char *) name, mode);
940 }
941
942 int fchmod(int fd, mode_t mode)
943 {
944         check_init("fchmod");
945         
946         if (smbw_fd(fd)) {
947                 /* Not yet implemented in libsmbclient */
948                 return ENOTSUP;
949         }
950         
951         return (* smbw_libc.fchmod)(fd, mode);
952 }
953
954 int chown(const char *name, uid_t owner, gid_t group)
955 {
956         check_init("chown");
957         
958         if (smbw_path((char *) name)) {
959                 return smbw_chown((char *) name, owner, group);
960         }
961         
962         return (* smbw_libc.chown)((char *) name, owner, group);
963 }
964
965 int fchown(int fd, uid_t owner, gid_t group)
966 {
967         check_init("fchown");
968         
969         if (smbw_fd(fd)) {
970                 /* Not yet implemented in libsmbclient */
971                 return ENOTSUP;
972         }
973         
974         return (* smbw_libc.fchown)(fd, owner, group);
975 }
976
977 char *getcwd(char *buf, size_t size)
978 {
979         check_init("getcwd");
980         return (char *)smbw_getcwd(buf, size);
981 }
982
983 int mkdir(const char *name, mode_t mode)
984 {
985         check_init("mkdir");
986         
987         if (smbw_path((char *) name)) {
988                 return smbw_mkdir((char *) name, mode);
989         }
990         
991         return (* smbw_libc.mkdir)((char *) name, mode);
992 }
993
994 int __fxstat(int vers, int fd, struct stat *st)
995 {
996         check_init("__fxstat");
997         
998         if (smbw_fd(fd)) {
999                 struct SMBW_stat statbuf;
1000                 int ret = smbw_fstat(fd, &statbuf);
1001                 stat_convert(&statbuf, st);
1002                 return ret;
1003         }
1004         
1005         return (* smbw_libc.__fxstat)(vers, fd, st);
1006 }
1007
1008 int __xstat(int vers, const char *name, struct stat *st)
1009 {
1010         check_init("__xstat");
1011         
1012         if (smbw_path((char *) name)) {
1013                 struct SMBW_stat statbuf;
1014                 int ret = smbw_stat((char *) name, &statbuf);
1015                 stat_convert(&statbuf, st);
1016                 return ret;
1017         }
1018         
1019         return (* smbw_libc.__xstat)(vers, (char *) name, st);
1020 }
1021
1022 int __lxstat(int vers, const char *name, struct stat *st)
1023 {
1024         check_init("__lxstat");
1025         
1026         if (smbw_path((char *) name)) {
1027                 struct SMBW_stat statbuf;
1028                 int ret = smbw_stat((char *) name, &statbuf);
1029                 stat_convert(&statbuf, st);
1030                 return ret;
1031         }
1032         
1033         return (* smbw_libc.__lxstat)(vers, (char *) name, st);
1034 }
1035
1036 int stat(const char *name, struct stat *st)
1037 {
1038         check_init("stat");
1039         
1040         if (smbw_path((char *) name)) {
1041                 struct SMBW_stat statbuf;
1042                 int ret = smbw_stat((char *) name, &statbuf);
1043                 stat_convert(&statbuf, st);
1044                 return ret;
1045         }
1046         
1047         return (* smbw_libc.stat)((char *) name, st);
1048 }
1049
1050 int lstat(const char *name, struct stat *st)
1051 {
1052         check_init("lstat");
1053         
1054         if (smbw_path((char *) name)) {
1055                 struct SMBW_stat statbuf;
1056                 int ret = smbw_stat((char *) name, &statbuf);
1057                 stat_convert(&statbuf, st);
1058                 return ret;
1059         }
1060         
1061         return (* smbw_libc.lstat)((char *) name, st);
1062 }
1063
1064 int fstat(int fd, struct stat *st)
1065 {
1066         check_init("fstat");
1067         
1068         if (smbw_fd(fd)) {
1069                 struct SMBW_stat statbuf;
1070                 int ret = smbw_fstat(fd, &statbuf);
1071                 stat_convert(&statbuf, st);
1072                 return ret;
1073         }
1074         
1075         return (* smbw_libc.fstat)(fd, st);
1076 }
1077
1078 int unlink(const char *name)
1079 {
1080         check_init("unlink");
1081         
1082         if (smbw_path((char *) name)) {
1083                 return smbw_unlink((char *) name);
1084         }
1085         
1086         return (* smbw_libc.unlink)((char *) name);
1087 }
1088
1089 int utime(const char *name, const struct utimbuf *tvp)
1090 {
1091         check_init("utime");
1092         
1093         if (smbw_path(name)) {
1094                 return smbw_utime(name, (struct utimbuf *) tvp);
1095         }
1096         
1097         return (* smbw_libc.utime)((char *) name, (struct utimbuf *) tvp);
1098 }
1099
1100 int utimes(const char *name, const struct timeval *tvp)
1101 {
1102         check_init("utimes");
1103         
1104         if (smbw_path(name)) {
1105                 return smbw_utimes(name, (struct timeval *) tvp);
1106         }
1107         
1108         return (* smbw_libc.utimes)((char *) name, (struct timeval *) tvp);
1109 }
1110
1111 int readlink(const char *path, char *buf, size_t bufsize)
1112 {
1113         check_init("readlink");
1114         
1115         if (smbw_path((char *) path)) {
1116                 return smbw_readlink(path, (char *) buf, bufsize);
1117         }
1118         
1119         return (* smbw_libc.readlink)((char *) path, buf, bufsize);
1120 }
1121
1122 int rename(const char *oldname, const char *newname)
1123 {
1124         int p1, p2;
1125         
1126         check_init("rename");
1127         
1128         p1 = smbw_path((char *) oldname); 
1129         p2 = smbw_path((char *) newname); 
1130         if (p1 ^ p2) {
1131                 /* can't cross filesystem boundaries */
1132                 errno = EXDEV;
1133                 return -1;
1134         }
1135         if (p1 && p2) {
1136                 return smbw_rename((char *) oldname, (char *) newname);
1137         }
1138         
1139         return (* smbw_libc.rename)((char *) oldname, (char *) newname);
1140 }
1141
1142 int rmdir(const char *name)
1143 {
1144         check_init("rmdir");
1145         
1146         if (smbw_path((char *) name)) {
1147                 return smbw_rmdir((char *) name);
1148         }
1149         
1150         return (* smbw_libc.rmdir)((char *) name);
1151 }
1152
1153 int symlink(const char *topath, const char *frompath)
1154 {
1155         int p1, p2;
1156         
1157         check_init("symlink");
1158         
1159         p1 = smbw_path((char *) topath); 
1160         p2 = smbw_path((char *) frompath); 
1161         if (p1 || p2) {
1162                 /* can't handle symlinks */
1163                 errno = EPERM;
1164                 return -1;
1165         }
1166         
1167         return (* smbw_libc.symlink)((char *) topath, (char *) frompath);
1168 }
1169
1170 int dup(int fd)
1171 {
1172         check_init("dup");
1173         
1174         if (smbw_fd(fd)) {
1175                 return smbw_dup(fd);
1176         }
1177         
1178         return (* smbw_libc.dup)(fd);
1179 }
1180
1181 int dup2(int oldfd, int newfd)
1182 {
1183         check_init("dup2");
1184         
1185         if (smbw_fd(newfd)) {
1186                 (* smbw_libc.close)(newfd);
1187         }
1188         
1189         if (smbw_fd(oldfd)) {
1190                 return smbw_dup2(oldfd, newfd);
1191         }
1192         
1193         return (* smbw_libc.dup2)(oldfd, newfd);
1194 }
1195
1196
1197 DIR *opendir(const char *name)
1198 {
1199         check_init("opendir");
1200         
1201         if (smbw_path((char *) name)) {
1202                 return (void *)smbw_opendir((char *) name);
1203         }
1204         
1205         return (* smbw_libc.opendir)((char *) name);
1206 }
1207
1208 struct dirent *readdir(DIR *dir)
1209 {
1210         check_init("readdir");
1211         
1212         if (smbw_dirp(dir)) {
1213                 static struct dirent external;
1214                 struct SMBW_dirent * internal = (void *)smbw_readdir(dir);
1215                 if (internal != NULL) {
1216                         dirent_convert(internal, &external);
1217                         return &external;
1218                 }
1219                 return NULL;
1220         }
1221         return (* smbw_libc.readdir)(dir);
1222 }
1223
1224 int closedir(DIR *dir)
1225 {
1226         check_init("closedir");
1227         
1228         if (smbw_dirp(dir)) {
1229                 return smbw_closedir(dir);
1230         }
1231         
1232         return (* smbw_libc.closedir)(dir);
1233 }
1234
1235 long telldir(DIR *dir)
1236 {
1237         check_init("telldir");
1238         
1239         if (smbw_dirp(dir)) {
1240                 return (long) smbw_telldir(dir);
1241         }
1242         
1243         return (* smbw_libc.telldir)(dir);
1244 }
1245
1246 void seekdir(DIR *dir, long offset)
1247 {
1248         check_init("seekdir");
1249         
1250         if (smbw_dirp(dir)) {
1251                 smbw_seekdir(dir, (long long) offset);
1252                 return;
1253         }
1254         
1255         (* smbw_libc.seekdir)(dir, offset);
1256 }
1257
1258 int creat(const char *path, mode_t mode)
1259 {
1260         extern int creat_bits;
1261         
1262         check_init("creat");
1263         return openx((char *) path, creat_bits, mode, smbw_libc.open);
1264 }
1265
1266 int creat64(const char *path, mode_t mode)
1267 {
1268         extern int creat_bits;
1269         
1270         check_init("creat64");
1271         return openx((char *) path, creat_bits, mode, smbw_libc.open64);
1272 }
1273
1274 int __xstat64 (int ver, const char *name, struct stat64 *st64)
1275 {
1276         check_init("__xstat64");
1277         
1278         if (smbw_path((char *) name)) {
1279                 struct SMBW_stat statbuf;
1280                 int ret = smbw_stat((char *) name, &statbuf);
1281                 stat64_convert(&statbuf, st64);
1282                 return ret;
1283         }
1284         
1285         return (* smbw_libc.__xstat64)(ver, (char *) name, st64);
1286 }
1287
1288 int stat64(const char *name, struct stat64 *st64)
1289 {
1290         check_init("stat64");
1291         
1292         if (smbw_path((char *) name)) {
1293                 struct SMBW_stat statbuf;
1294                 int ret = smbw_stat((char *) name, &statbuf);
1295                 stat64_convert(&statbuf, st64);
1296                 return ret;
1297         }
1298         
1299         return (* smbw_libc.stat64)((char *) name, st64);
1300 }
1301
1302 int __fxstat64(int ver, int fd, struct stat64 *st64)
1303 {
1304         check_init("__fxstat64");
1305         
1306         if (smbw_fd(fd)) {
1307                 struct SMBW_stat statbuf;
1308                 int ret = smbw_fstat(fd, &statbuf);
1309                 stat64_convert(&statbuf, st64);
1310                 return ret;
1311         }
1312         
1313         return (* smbw_libc.__fxstat64)(ver, fd, st64);
1314 }
1315
1316 int fstat64(int fd, struct stat64 *st64)
1317 {
1318         check_init("fstat64");
1319         
1320         if (smbw_fd(fd)) {
1321                 struct SMBW_stat statbuf;
1322                 int ret = smbw_fstat(fd, &statbuf);
1323                 stat64_convert(&statbuf, st64);
1324                 return ret;
1325         }
1326         
1327         return (* smbw_libc.fstat64)(fd, st64);
1328 }
1329
1330 int __lxstat64(int ver, const char *name, struct stat64 *st64)
1331 {
1332         check_init("__lxstat64");
1333         
1334         if (smbw_path((char *) name)) {
1335                 struct SMBW_stat statbuf;
1336                 int ret = smbw_stat(name, &statbuf);
1337                 stat64_convert(&statbuf, st64);
1338                 return ret;
1339         }
1340         
1341         return (* smbw_libc.__lxstat64)(ver, (char *) name, st64);
1342 }
1343
1344 int lstat64(const char *name, struct stat64 *st64)
1345 {
1346         check_init("lstat64");
1347         
1348         if (smbw_path((char *) name)) {
1349                 struct SMBW_stat statbuf;
1350                 int ret = smbw_stat((char *) name, &statbuf);
1351                 stat64_convert(&statbuf, st64);
1352                 return ret;
1353         }
1354         
1355         return (* smbw_libc.lstat64)((char *) name, st64);
1356 }
1357
1358 int _llseek(unsigned int fd,  unsigned  long  offset_high, unsigned  long  offset_low,  loff_t  *result, unsigned int whence)
1359 {
1360         check_init("_llseek");
1361         
1362         if (smbw_fd(fd)) {
1363                 *result = lseek(fd, offset_low, whence);
1364                 return (*result < 0 ? -1 : 0);
1365         }
1366         
1367         return (* smbw_libc._llseek)(fd, offset_high, offset_low, result, whence);
1368 }
1369
1370 struct dirent64 *readdir64(DIR *dir)
1371 {
1372         check_init("readdir64");
1373         
1374         if (smbw_dirp(dir)) {
1375                 static struct dirent64 external;
1376                 struct SMBW_dirent * internal = (void *)smbw_readdir(dir);
1377                 if (internal != NULL) {
1378                         dirent64_convert(internal, &external);
1379                         return &external;
1380                 }
1381                 return NULL;
1382         }
1383         
1384         return (* smbw_libc.readdir64)(dir);
1385 }
1386
1387 int readdir_r(DIR *dir, struct dirent *external, struct dirent **result)
1388 {
1389         check_init("readdir_r");
1390         
1391         if (smbw_dirp(dir)) {
1392                 struct SMBW_dirent internal;
1393                 int ret = smbw_readdir_r(dir, &internal, NULL);
1394                 if (ret == 0) {
1395                         dirent_convert(&internal, external);
1396                         *result = external;
1397                 }
1398                 return ret;
1399         }
1400         
1401         return (* smbw_libc.readdir_r)(dir, external, result);
1402 }
1403
1404 int readdir64_r(DIR *dir, struct dirent64 *external, struct dirent64 **result)
1405 {
1406         check_init("readdir64_r");
1407         
1408         if (smbw_dirp(dir)) {
1409                 struct SMBW_dirent internal;
1410                 int ret = smbw_readdir_r(dir, &internal, NULL);
1411                 if (ret == 0) {
1412                         dirent64_convert(&internal, external);
1413                         *result = external;
1414                 }
1415                 return ret;
1416         }
1417         
1418         return (* smbw_libc.readdir64_r)(dir, external, result);
1419 }
1420
1421 int fork(void)
1422 {
1423         check_init("fork");
1424         return smbw_fork();
1425 }
1426
1427 int setxattr(const char *fname,
1428              const char *name,
1429              const void *value,
1430              size_t size,
1431              int flags)
1432 {
1433         if (smbw_path(fname)) {
1434                 return smbw_setxattr(fname, name, value, size, flags);
1435         }
1436         
1437         return (* smbw_libc.setxattr)(fname, name, value, size, flags);
1438 }
1439
1440 int lsetxattr(const char *fname,
1441               const char *name,
1442               const void *value,
1443               size_t size,
1444               int flags)
1445 {
1446         if (smbw_path(fname)) {
1447                 return smbw_lsetxattr(fname, name, value, size, flags);
1448         }
1449         
1450         return (* smbw_libc.lsetxattr)(fname, name, value, size, flags);
1451 }
1452
1453 int fsetxattr(int fd,
1454               const char *name,
1455               const void *value,
1456               size_t size,
1457               int flags)
1458 {
1459         if (smbw_fd(fd)) {
1460                 return smbw_fsetxattr(fd, name, value, size, flags);
1461         }
1462         
1463         return (* smbw_libc.fsetxattr)(fd, name, value, size, flags);
1464 }
1465
1466 int getxattr(const char *fname,
1467              const char *name,
1468              const void *value,
1469              size_t size)
1470 {
1471         if (smbw_path(fname)) {
1472                 return smbw_getxattr(fname, name, value, size);
1473         }
1474         
1475         return (* smbw_libc.getxattr)(fname, name, value, size);
1476 }
1477
1478 int lgetxattr(const char *fname,
1479               const char *name,
1480               const void *value,
1481               size_t size)
1482 {
1483         if (smbw_path(fname)) {
1484                 return smbw_lgetxattr(fname, name, value, size);
1485         }
1486         
1487         return (* smbw_libc.lgetxattr)(fname, name, value, size);
1488 }
1489
1490 int fgetxattr(int fd,
1491               const char *name,
1492               const void *value,
1493               size_t size)
1494 {
1495         if (smbw_fd(fd)) {
1496                 return smbw_fgetxattr(fd, name, value, size);
1497         }
1498         
1499         return (* smbw_libc.fgetxattr)(fd, name, value, size);
1500 }
1501
1502 int removexattr(const char *fname,
1503                 const char *name)
1504 {
1505         if (smbw_path(fname)) {
1506                 return smbw_removexattr(fname, name);
1507         }
1508         
1509         return (* smbw_libc.removexattr)(fname, name);
1510 }
1511
1512 int lremovexattr(const char *fname,
1513                  const char *name)
1514 {
1515         if (smbw_path(fname)) {
1516                 return smbw_lremovexattr(fname, name);
1517         }
1518         
1519         return (* smbw_libc.lremovexattr)(fname, name);
1520 }
1521
1522 int fremovexattr(int fd,
1523                  const char *name)
1524 {
1525         if (smbw_fd(fd)) {
1526                 return smbw_fremovexattr(fd, name);
1527         }
1528         
1529         return (* smbw_libc.fremovexattr)(fd, name);
1530 }
1531
1532 int listxattr(const char *fname,
1533               char *list,
1534               size_t size)
1535 {
1536         if (smbw_path(fname)) {
1537                 return smbw_listxattr(fname, list, size);
1538         }
1539         
1540         return (* smbw_libc.listxattr)(fname, list, size);
1541 }
1542
1543 int llistxattr(const char *fname,
1544                char *list,
1545                size_t size)
1546 {
1547         if (smbw_path(fname)) {
1548                 return smbw_llistxattr(fname, list, size);
1549         }
1550         
1551         return (* smbw_libc.llistxattr)(fname, list, size);
1552 }
1553
1554 int flistxattr(int fd,
1555                char *list,
1556                size_t size)
1557 {
1558         if (smbw_fd(fd)) {
1559                 return smbw_flistxattr(fd, list, size);
1560         }
1561         
1562         return (* smbw_libc.flistxattr)(fd, list, size);
1563 }
1564
1565
1566 /*
1567  * We're ending up with a different implementation of malloc() with smbwrapper
1568  * than without it.  The one with it does not support returning a non-NULL
1569  * pointer from a call to malloc(0), and many apps depend on getting a valid
1570  * pointer when requesting zero length (e.g. df, emacs).
1571  *
1572  * Unfortunately, initializing the smbw_libc[] array via the dynamic link
1573  * library (libdl) requires malloc so we can't just do the same type of
1574  * mapping to the C library as we do with everything else.  We need to
1575  * implement a different way of allocating memory that ensures that the C
1576  * library version of malloc() gets used.  This is the only place where we
1577  * kludge the code to use an undocumented interface to the C library.
1578  *
1579  * If anyone can come up with a way to dynamically link to the C library
1580  * rather than using this undocumented interface, I'd sure love to hear about
1581  * it.  Better yet, if you can figure out where the alternate malloc()
1582  * functions are coming from and arrange for them not to be called, that would
1583  * be even better.  We should try to avoid wrapping functions that don't
1584  * really require it.
1585  */
1586
1587 void *malloc(size_t size)
1588 {
1589         void *__libc_malloc(size_t size);
1590         return __libc_malloc(size);
1591 }
1592
1593 void *calloc(size_t nmemb, size_t size)
1594 {
1595         void *__libc_calloc(size_t nmemb, size_t size);
1596         return __libc_calloc(nmemb, size);
1597 }
1598
1599 void *realloc(void *ptr, size_t size)
1600 {
1601         void *__libc_realloc(void *ptr, size_t size);
1602         return __libc_realloc(ptr, size);
1603 }
1604
1605 void free(void *ptr)
1606 {
1607         static int      in_progress = 0;
1608         void __libc_free(void *ptr);
1609         
1610         if (in_progress) return;
1611         in_progress = 1;
1612         __libc_free(ptr);
1613         in_progress = 0;
1614 }
1615
1616
1617 #if 0                           /* SELECT */
1618
1619 static struct sigaction user_action[_NSIG];
1620
1621 static void
1622 smbw_sigaction_handler(int signum,
1623                        siginfo_t *info,
1624                        void *context)
1625 {
1626         /* Our entire purpose for trapping signals is to call this! */
1627         sys_select_signal();
1628         
1629         /* Call the user's handler */
1630         if (user_action[signum].sa_handler != SIG_IGN &&
1631             user_action[signum].sa_handler != SIG_DFL &&
1632             user_action[signum].sa_handler != SIG_ERR) {
1633                 (* user_action[signum].sa_sigaction)(signum, info, context);
1634         }
1635 }
1636
1637
1638 /*
1639  * Every Samba signal handler must call sys_select_signal() to avoid a race
1640  * condition, so we'll take whatever signal handler is currently assigned,
1641  * call call sys_select_signal() in addition to their call.
1642  */
1643 static int
1644 do_select(int n,
1645           fd_set *readfds,
1646           fd_set *writefds,
1647           fd_set *exceptfds,
1648           struct timeval *timeout,
1649           int (* select_fn)(int n,
1650                             fd_set *readfds,
1651                             fd_set *writefds,
1652                             fd_set *exceptfds,
1653                             struct timeval *timeout))
1654 {
1655         int i;
1656         int ret;
1657         int saved_errno;
1658         sigset_t sigset;
1659         struct sigaction new_action;
1660         
1661         saved_errno = errno;
1662         for (i=1; i<_NSIG; i++) {
1663                 sigemptyset(&sigset);
1664                 new_action.sa_mask = sigset;
1665                 new_action.sa_flags = SA_SIGINFO;
1666                 new_action.sa_sigaction = smbw_sigaction_handler;
1667                 
1668                 if (sigaction(i, &new_action, &user_action[i]) < 0) {
1669                         if (errno != EINVAL) {
1670                                 return -1;
1671                         }
1672                 }
1673         }
1674         errno = saved_errno;
1675         
1676         ret = (* select_fn)(n, readfds, writefds, exceptfds, timeout);
1677         saved_errno = errno;
1678         
1679         for (i=0; i<_NSIG; i++) {
1680                 (void) sigaction(i, &user_action[i], NULL);
1681         }
1682         
1683         errno = saved_errno;
1684         return ret;
1685 }
1686
1687 int
1688 select(int n,
1689        fd_set *readfds,
1690        fd_set *writefds,
1691        fd_set *exceptfds,
1692        struct timeval *timeout)
1693 {
1694         check_init("select");
1695         
1696         return do_select(n, readfds, writefds, exceptfds,
1697                          timeout, smbw_libc.select);
1698 }
1699
1700 int
1701 _select(int n,
1702         fd_set *readfds,
1703         fd_set *writefds,
1704         fd_set *exceptfds,
1705         struct timeval *timeout)
1706 {
1707         check_init("_select");
1708         
1709         return do_select(n, readfds, writefds, exceptfds,
1710                          timeout, smbw_libc._select);
1711 }
1712
1713 int
1714 __select(int n,
1715          fd_set *readfds,
1716          fd_set *writefds,
1717          fd_set *exceptfds,
1718          struct timeval *timeout)
1719 {
1720         check_init("__select");
1721         
1722         return do_select(n, readfds, writefds, exceptfds,
1723                          timeout, smbw_libc.__select);
1724 }
1725
1726 #endif