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