r19102: fix typo, thanks derrell!
[abartlet/samba.git/.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba system utilities
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison  1998-2005
6    Copyright (C) Timur Bakeyev        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 #include "includes.h"
24
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
28
29 /*
30    The idea is that this file will eventually have wrappers around all
31    important system calls in samba. The aims are:
32
33    - to enable easier porting by putting OS dependent stuff in here
34
35    - to allow for hooks into other "pseudo-filesystems"
36
37    - to allow easier integration of things like the japanese extensions
38
39    - to support the philosophy of Samba to expose the features of
40      the OS within the SMB model. In general whatever file/printer/variable
41      expansions/etc make sense to the OS should be acceptable to Samba.
42 */
43
44
45
46 /*******************************************************************
47  A wrapper for usleep in case we don't have one.
48 ********************************************************************/
49
50 int sys_usleep(long usecs)
51 {
52 #ifndef HAVE_USLEEP
53         struct timeval tval;
54 #endif
55
56         /*
57          * We need this braindamage as the glibc usleep
58          * is not SPEC1170 complient... grumble... JRA.
59          */
60
61         if(usecs < 0 || usecs > 1000000) {
62                 errno = EINVAL;
63                 return -1;
64         }
65
66 #if HAVE_USLEEP
67         usleep(usecs);
68         return 0;
69 #else /* HAVE_USLEEP */
70         /*
71          * Fake it with select...
72          */
73         tval.tv_sec = 0;
74         tval.tv_usec = usecs/1000;
75         select(0,NULL,NULL,NULL,&tval);
76         return 0;
77 #endif /* HAVE_USLEEP */
78 }
79
80 /*******************************************************************
81 A read wrapper that will deal with EINTR.
82 ********************************************************************/
83
84 ssize_t sys_read(int fd, void *buf, size_t count)
85 {
86         ssize_t ret;
87
88         do {
89                 ret = read(fd, buf, count);
90         } while (ret == -1 && errno == EINTR);
91         return ret;
92 }
93
94 /*******************************************************************
95 A write wrapper that will deal with EINTR.
96 ********************************************************************/
97
98 ssize_t sys_write(int fd, const void *buf, size_t count)
99 {
100         ssize_t ret;
101
102         do {
103                 ret = write(fd, buf, count);
104         } while (ret == -1 && errno == EINTR);
105         return ret;
106 }
107
108 /*******************************************************************
109 A pread wrapper that will deal with EINTR and 64-bit file offsets.
110 ********************************************************************/
111
112 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
113 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
114 {
115         ssize_t ret;
116
117         do {
118 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
119                 ret = pread64(fd, buf, count, off);
120 #else
121                 ret = pread(fd, buf, count, off);
122 #endif
123         } while (ret == -1 && errno == EINTR);
124         return ret;
125 }
126 #endif
127
128 /*******************************************************************
129 A write wrapper that will deal with EINTR and 64-bit file offsets.
130 ********************************************************************/
131
132 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
133 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
134 {
135         ssize_t ret;
136
137         do {
138 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
139                 ret = pwrite64(fd, buf, count, off);
140 #else
141                 ret = pwrite(fd, buf, count, off);
142 #endif
143         } while (ret == -1 && errno == EINTR);
144         return ret;
145 }
146 #endif
147
148 /*******************************************************************
149 A send wrapper that will deal with EINTR.
150 ********************************************************************/
151
152 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
153 {
154         ssize_t ret;
155
156         do {
157                 ret = send(s, msg, len, flags);
158         } while (ret == -1 && errno == EINTR);
159         return ret;
160 }
161
162 /*******************************************************************
163 A sendto wrapper that will deal with EINTR.
164 ********************************************************************/
165
166 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
167 {
168         ssize_t ret;
169
170         do {
171                 ret = sendto(s, msg, len, flags, to, tolen);
172         } while (ret == -1 && errno == EINTR);
173         return ret;
174 }
175
176 /*******************************************************************
177 A recv wrapper that will deal with EINTR.
178 ********************************************************************/
179
180 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
181 {
182         ssize_t ret;
183
184         do {
185                 ret = recv(fd, buf, count, flags);
186         } while (ret == -1 && errno == EINTR);
187         return ret;
188 }
189
190 /*******************************************************************
191 A recvfrom wrapper that will deal with EINTR.
192 ********************************************************************/
193
194 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
195 {
196         ssize_t ret;
197
198         do {
199                 ret = recvfrom(s, buf, len, flags, from, fromlen);
200         } while (ret == -1 && errno == EINTR);
201         return ret;
202 }
203
204 /*******************************************************************
205 A fcntl wrapper that will deal with EINTR.
206 ********************************************************************/
207
208 int sys_fcntl_ptr(int fd, int cmd, void *arg)
209 {
210         int ret;
211
212         do {
213                 ret = fcntl(fd, cmd, arg);
214         } while (ret == -1 && errno == EINTR);
215         return ret;
216 }
217
218 /*******************************************************************
219 A fcntl wrapper that will deal with EINTR.
220 ********************************************************************/
221
222 int sys_fcntl_long(int fd, int cmd, long arg)
223 {
224         int ret;
225
226         do {
227                 ret = fcntl(fd, cmd, arg);
228         } while (ret == -1 && errno == EINTR);
229         return ret;
230 }
231
232 /*******************************************************************
233 A stat() wrapper that will deal with 64 bit filesizes.
234 ********************************************************************/
235
236 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
237 {
238         int ret;
239 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
240         ret = stat64(fname, sbuf);
241 #else
242         ret = stat(fname, sbuf);
243 #endif
244         /* we always want directories to appear zero size */
245         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
246         return ret;
247 }
248
249 /*******************************************************************
250  An fstat() wrapper that will deal with 64 bit filesizes.
251 ********************************************************************/
252
253 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
254 {
255         int ret;
256 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
257         ret = fstat64(fd, sbuf);
258 #else
259         ret = fstat(fd, sbuf);
260 #endif
261         /* we always want directories to appear zero size */
262         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
263         return ret;
264 }
265
266 /*******************************************************************
267  An lstat() wrapper that will deal with 64 bit filesizes.
268 ********************************************************************/
269
270 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
271 {
272         int ret;
273 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
274         ret = lstat64(fname, sbuf);
275 #else
276         ret = lstat(fname, sbuf);
277 #endif
278         /* we always want directories to appear zero size */
279         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
280         return ret;
281 }
282
283 /*******************************************************************
284  An ftruncate() wrapper that will deal with 64 bit filesizes.
285 ********************************************************************/
286
287 int sys_ftruncate(int fd, SMB_OFF_T offset)
288 {
289 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
290         return ftruncate64(fd, offset);
291 #else
292         return ftruncate(fd, offset);
293 #endif
294 }
295
296 /*******************************************************************
297  An lseek() wrapper that will deal with 64 bit filesizes.
298 ********************************************************************/
299
300 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
301 {
302 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
303         return lseek64(fd, offset, whence);
304 #else
305         return lseek(fd, offset, whence);
306 #endif
307 }
308
309 /*******************************************************************
310  An fseek() wrapper that will deal with 64 bit filesizes.
311 ********************************************************************/
312
313 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
314 {
315 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
316         return fseek64(fp, offset, whence);
317 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
318         return fseeko64(fp, offset, whence);
319 #else
320         return fseek(fp, offset, whence);
321 #endif
322 }
323
324 /*******************************************************************
325  An ftell() wrapper that will deal with 64 bit filesizes.
326 ********************************************************************/
327
328 SMB_OFF_T sys_ftell(FILE *fp)
329 {
330 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
331         return (SMB_OFF_T)ftell64(fp);
332 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
333         return (SMB_OFF_T)ftello64(fp);
334 #else
335         return (SMB_OFF_T)ftell(fp);
336 #endif
337 }
338
339 /*******************************************************************
340  A creat() wrapper that will deal with 64 bit filesizes.
341 ********************************************************************/
342
343 int sys_creat(const char *path, mode_t mode)
344 {
345 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
346         return creat64(path, mode);
347 #else
348         /*
349          * If creat64 isn't defined then ensure we call a potential open64.
350          * JRA.
351          */
352         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
353 #endif
354 }
355
356 /*******************************************************************
357  An open() wrapper that will deal with 64 bit filesizes.
358 ********************************************************************/
359
360 int sys_open(const char *path, int oflag, mode_t mode)
361 {
362 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
363         return open64(path, oflag, mode);
364 #else
365         return open(path, oflag, mode);
366 #endif
367 }
368
369 /*******************************************************************
370  An fopen() wrapper that will deal with 64 bit filesizes.
371 ********************************************************************/
372
373 FILE *sys_fopen(const char *path, const char *type)
374 {
375 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
376         return fopen64(path, type);
377 #else
378         return fopen(path, type);
379 #endif
380 }
381
382 /*******************************************************************
383  An opendir wrapper that will deal with 64 bit filesizes.
384 ********************************************************************/
385
386 SMB_STRUCT_DIR *sys_opendir(const char *name)
387 {
388 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
389         return opendir64(name);
390 #else
391         return opendir(name);
392 #endif
393 }
394
395 /*******************************************************************
396  A readdir wrapper that will deal with 64 bit filesizes.
397 ********************************************************************/
398
399 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
400 {
401 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
402         return readdir64(dirp);
403 #else
404         return readdir(dirp);
405 #endif
406 }
407
408 /*******************************************************************
409  A seekdir wrapper that will deal with 64 bit filesizes.
410 ********************************************************************/
411
412 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
413 {
414 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
415         seekdir64(dirp, offset);
416 #else
417         seekdir(dirp, offset);
418 #endif
419 }
420
421 /*******************************************************************
422  A telldir wrapper that will deal with 64 bit filesizes.
423 ********************************************************************/
424
425 long sys_telldir(SMB_STRUCT_DIR *dirp)
426 {
427 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
428         return (long)telldir64(dirp);
429 #else
430         return (long)telldir(dirp);
431 #endif
432 }
433
434 /*******************************************************************
435  A rewinddir wrapper that will deal with 64 bit filesizes.
436 ********************************************************************/
437
438 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
439 {
440 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
441         rewinddir64(dirp);
442 #else
443         rewinddir(dirp);
444 #endif
445 }
446
447 /*******************************************************************
448  A close wrapper that will deal with 64 bit filesizes.
449 ********************************************************************/
450
451 int sys_closedir(SMB_STRUCT_DIR *dirp)
452 {
453 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
454         return closedir64(dirp);
455 #else
456         return closedir(dirp);
457 #endif
458 }
459
460 /*******************************************************************
461  An mknod() wrapper that will deal with 64 bit filesizes.
462 ********************************************************************/
463
464 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
465 {
466 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
467 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
468         return mknod64(path, mode, dev);
469 #else
470         return mknod(path, mode, dev);
471 #endif
472 #else
473         /* No mknod system call. */
474         errno = ENOSYS;
475         return -1;
476 #endif
477 }
478
479 /*******************************************************************
480  Wrapper for realpath.
481 ********************************************************************/
482
483 char *sys_realpath(const char *path, char *resolved_path)
484 {
485 #if defined(HAVE_REALPATH)
486         return realpath(path, resolved_path);
487 #else
488         /* As realpath is not a system call we can't return ENOSYS. */
489         errno = EINVAL;
490         return NULL;
491 #endif
492 }
493
494 /*******************************************************************
495 The wait() calls vary between systems
496 ********************************************************************/
497
498 int sys_waitpid(pid_t pid,int *status,int options)
499 {
500 #ifdef HAVE_WAITPID
501         return waitpid(pid,status,options);
502 #else /* HAVE_WAITPID */
503         return wait4(pid, status, options, NULL);
504 #endif /* HAVE_WAITPID */
505 }
506
507 /*******************************************************************
508  System wrapper for getwd
509 ********************************************************************/
510
511 char *sys_getwd(char *s)
512 {
513         char *wd;
514 #ifdef HAVE_GETCWD
515         wd = (char *)getcwd(s, sizeof (pstring));
516 #else
517         wd = (char *)getwd(s);
518 #endif
519         return wd;
520 }
521
522 /*******************************************************************
523 system wrapper for symlink
524 ********************************************************************/
525
526 int sys_symlink(const char *oldpath, const char *newpath)
527 {
528 #ifndef HAVE_SYMLINK
529         errno = ENOSYS;
530         return -1;
531 #else
532         return symlink(oldpath, newpath);
533 #endif
534 }
535
536 /*******************************************************************
537 system wrapper for readlink
538 ********************************************************************/
539
540 int sys_readlink(const char *path, char *buf, size_t bufsiz)
541 {
542 #ifndef HAVE_READLINK
543         errno = ENOSYS;
544         return -1;
545 #else
546         return readlink(path, buf, bufsiz);
547 #endif
548 }
549
550 /*******************************************************************
551 system wrapper for link
552 ********************************************************************/
553
554 int sys_link(const char *oldpath, const char *newpath)
555 {
556 #ifndef HAVE_LINK
557         errno = ENOSYS;
558         return -1;
559 #else
560         return link(oldpath, newpath);
561 #endif
562 }
563
564 /*******************************************************************
565 chown isn't used much but OS/2 doesn't have it
566 ********************************************************************/
567
568 int sys_chown(const char *fname,uid_t uid,gid_t gid)
569 {
570 #ifndef HAVE_CHOWN
571         static int done;
572         if (!done) {
573                 DEBUG(1,("WARNING: no chown!\n"));
574                 done=1;
575         }
576         errno = ENOSYS;
577         return -1;
578 #else
579         return(chown(fname,uid,gid));
580 #endif
581 }
582
583 /*******************************************************************
584 os/2 also doesn't have chroot
585 ********************************************************************/
586 int sys_chroot(const char *dname)
587 {
588 #ifndef HAVE_CHROOT
589         static int done;
590         if (!done) {
591                 DEBUG(1,("WARNING: no chroot!\n"));
592                 done=1;
593         }
594         errno = ENOSYS;
595         return -1;
596 #else
597         return(chroot(dname));
598 #endif
599 }
600
601 /**************************************************************************
602 A wrapper for gethostbyname() that tries avoids looking up hostnames 
603 in the root domain, which can cause dial-on-demand links to come up for no
604 apparent reason.
605 ****************************************************************************/
606
607 struct hostent *sys_gethostbyname(const char *name)
608 {
609 #ifdef REDUCE_ROOT_DNS_LOOKUPS
610         char query[256], hostname[256];
611         char *domain;
612
613         /* Does this name have any dots in it? If so, make no change */
614
615         if (strchr_m(name, '.'))
616                 return(gethostbyname(name));
617
618         /* Get my hostname, which should have domain name 
619                 attached. If not, just do the gethostname on the
620                 original string. 
621         */
622
623         gethostname(hostname, sizeof(hostname) - 1);
624         hostname[sizeof(hostname) - 1] = 0;
625         if ((domain = strchr_m(hostname, '.')) == NULL)
626                 return(gethostbyname(name));
627
628         /* Attach domain name to query and do modified query.
629                 If names too large, just do gethostname on the
630                 original string.
631         */
632
633         if((strlen(name) + strlen(domain)) >= sizeof(query))
634                 return(gethostbyname(name));
635
636         slprintf(query, sizeof(query)-1, "%s%s", name, domain);
637         return(gethostbyname(query));
638 #else /* REDUCE_ROOT_DNS_LOOKUPS */
639         return(gethostbyname(name));
640 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
641 }
642
643
644 #if defined(HAVE_POSIX_CAPABILITIES)
645
646 #ifdef HAVE_SYS_CAPABILITY_H
647
648 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
649 #define _I386_STATFS_H
650 #define _PPC_STATFS_H
651 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
652 #endif
653
654 #include <sys/capability.h>
655
656 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
657 #undef _I386_STATFS_H
658 #undef _PPC_STATFS_H
659 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
660 #endif
661
662 #endif /* HAVE_SYS_CAPABILITY_H */
663
664 /**************************************************************************
665  Try and abstract process capabilities (for systems that have them).
666 ****************************************************************************/
667
668 /* Set the POSIX capabilities needed for the given purpose into the effective
669  * capability set of the current process. Make sure they are always removed
670  * from the inheritable set, because there is no circumstance in which our
671  * children should inherit our elevated privileges.
672  */
673 static BOOL set_process_capability(enum smbd_capability capability,
674                                    BOOL enable)
675 {
676         cap_value_t cap_vals[2] = {0};
677         int num_cap_vals = 0;
678
679         cap_t cap;
680
681 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
682         /* On Linux, make sure that any capabilities we grab are sticky
683          * across UID changes. We expect that this would allow us to keep both
684          * the effective and permitted capability sets, but as of circa 2.6.16,
685          * only the permitted set is kept. It is a bug (which we work around)
686          * that the effective set is lost, but we still require the effective
687          * set to be kept.
688          */
689         if (!prctl(PR_GET_KEEPCAPS)) {
690                 prctl(PR_SET_KEEPCAPS, 1);
691         }
692 #endif
693
694         cap = cap_get_proc();
695         if (cap == NULL) {
696                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
697                         strerror(errno)));
698                 return False;
699         }
700
701         switch (capability) {
702                 case KERNEL_OPLOCK_CAPABILITY:
703 #ifdef CAP_NETWORK_MGT
704                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
705                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
706 #endif
707                         break;
708                 case DMAPI_ACCESS_CAPABILITY:
709 #ifdef CAP_DEVICE_MGT
710                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
711                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
712 #elif CAP_MKNOD
713                         /* Linux has CAP_MKNOD for DMAPI access. */
714                         cap_vals[num_cap_vals++] = CAP_MKNOD;
715 #endif
716                         break;
717         }
718
719         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
720
721         if (num_cap_vals == 0) {
722                 cap_free(cap);
723                 return True;
724         }
725
726         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
727                 enable ? CAP_SET : CAP_CLEAR);
728
729         /* We never want to pass capabilities down to our children, so make
730          * sure they are not inherited.
731          */
732         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
733
734         if (cap_set_proc(cap) == -1) {
735                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
736                         strerror(errno)));
737                 cap_free(cap);
738                 return False;
739         }
740
741         cap_free(cap);
742         return True;
743 }
744
745 #endif /* HAVE_POSIX_CAPABILITIES */
746
747 /****************************************************************************
748  Gain the oplock capability from the kernel if possible.
749 ****************************************************************************/
750
751 void set_effective_capability(enum smbd_capability capability)
752 {
753 #if defined(HAVE_POSIX_CAPABILITIES)
754         set_process_capability(capability, True);
755 #endif /* HAVE_POSIX_CAPABILITIES */
756 }
757
758 void drop_effective_capability(enum smbd_capability capability)
759 {
760 #if defined(HAVE_POSIX_CAPABILITIES)
761         set_process_capability(capability, False);
762 #endif /* HAVE_POSIX_CAPABILITIES */
763 }
764
765 /**************************************************************************
766  Wrapper for random().
767 ****************************************************************************/
768
769 long sys_random(void)
770 {
771 #if defined(HAVE_RANDOM)
772         return (long)random();
773 #elif defined(HAVE_RAND)
774         return (long)rand();
775 #else
776         DEBUG(0,("Error - no random function available !\n"));
777         exit(1);
778 #endif
779 }
780
781 /**************************************************************************
782  Wrapper for srandom().
783 ****************************************************************************/
784
785 void sys_srandom(unsigned int seed)
786 {
787 #if defined(HAVE_SRANDOM)
788         srandom(seed);
789 #elif defined(HAVE_SRAND)
790         srand(seed);
791 #else
792         DEBUG(0,("Error - no srandom function available !\n"));
793         exit(1);
794 #endif
795 }
796
797 /**************************************************************************
798  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
799 ****************************************************************************/
800
801 int groups_max(void)
802 {
803 #if defined(SYSCONF_SC_NGROUPS_MAX)
804         int ret = sysconf(_SC_NGROUPS_MAX);
805         return (ret == -1) ? NGROUPS_MAX : ret;
806 #else
807         return NGROUPS_MAX;
808 #endif
809 }
810
811 /**************************************************************************
812  Wrapper for getgroups. Deals with broken (int) case.
813 ****************************************************************************/
814
815 int sys_getgroups(int setlen, gid_t *gidset)
816 {
817 #if !defined(HAVE_BROKEN_GETGROUPS)
818         return getgroups(setlen, gidset);
819 #else
820
821         GID_T gid;
822         GID_T *group_list;
823         int i, ngroups;
824
825         if(setlen == 0) {
826                 return getgroups(setlen, &gid);
827         }
828
829         /*
830          * Broken case. We need to allocate a
831          * GID_T array of size setlen.
832          */
833
834         if(setlen < 0) {
835                 errno = EINVAL; 
836                 return -1;
837         } 
838
839         if (setlen == 0)
840                 setlen = groups_max();
841
842         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
843                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
844                 return -1;
845         }
846
847         if((ngroups = getgroups(setlen, group_list)) < 0) {
848                 int saved_errno = errno;
849                 SAFE_FREE(group_list);
850                 errno = saved_errno;
851                 return -1;
852         }
853
854         for(i = 0; i < ngroups; i++)
855                 gidset[i] = (gid_t)group_list[i];
856
857         SAFE_FREE(group_list);
858         return ngroups;
859 #endif /* HAVE_BROKEN_GETGROUPS */
860 }
861
862
863 /**************************************************************************
864  Wrapper for setgroups. Deals with broken (int) case. Automatically used
865  if we have broken getgroups.
866 ****************************************************************************/
867
868 int sys_setgroups(int setlen, gid_t *gidset)
869 {
870 #if !defined(HAVE_SETGROUPS)
871         errno = ENOSYS;
872         return -1;
873 #endif /* HAVE_SETGROUPS */
874
875 #if !defined(HAVE_BROKEN_GETGROUPS)
876         return setgroups(setlen, gidset);
877 #else
878
879         GID_T *group_list;
880         int i ; 
881
882         if (setlen == 0)
883                 return 0 ;
884
885         if (setlen < 0 || setlen > groups_max()) {
886                 errno = EINVAL; 
887                 return -1;   
888         }
889
890         /*
891          * Broken case. We need to allocate a
892          * GID_T array of size setlen.
893          */
894
895         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
896                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
897                 return -1;    
898         }
899  
900         for(i = 0; i < setlen; i++) 
901                 group_list[i] = (GID_T) gidset[i]; 
902
903         if(setgroups(setlen, group_list) != 0) {
904                 int saved_errno = errno;
905                 SAFE_FREE(group_list);
906                 errno = saved_errno;
907                 return -1;
908         }
909  
910         SAFE_FREE(group_list);
911         return 0 ;
912 #endif /* HAVE_BROKEN_GETGROUPS */
913 }
914
915 /**************************************************************************
916  Wrappers for setpwent(), getpwent() and endpwent()
917 ****************************************************************************/
918
919 void sys_setpwent(void)
920 {
921         setpwent();
922 }
923
924 struct passwd *sys_getpwent(void)
925 {
926         return getpwent();
927 }
928
929 void sys_endpwent(void)
930 {
931         endpwent();
932 }
933
934 /**************************************************************************
935  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
936 ****************************************************************************/
937
938 #ifdef ENABLE_BUILD_FARM_HACKS
939
940 /*
941  * In the build farm we want to be able to join machines to the domain. As we
942  * don't have root access, we need to bypass direct access to /etc/passwd
943  * after a user has been created via samr. Fake those users.
944  */
945
946 static struct passwd *fake_pwd;
947 static int num_fake_pwd;
948
949 struct passwd *sys_getpwnam(const char *name)
950 {
951         int i;
952
953         for (i=0; i<num_fake_pwd; i++) {
954                 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
955                         DEBUG(10, ("Returning fake user %s\n", name));
956                         return &fake_pwd[i];
957                 }
958         }
959
960         return getpwnam(name);
961 }
962
963 struct passwd *sys_getpwuid(uid_t uid)
964 {
965         int i;
966
967         for (i=0; i<num_fake_pwd; i++) {
968                 if (fake_pwd[i].pw_uid == uid) {
969                         DEBUG(10, ("Returning fake user %s\n",
970                                    fake_pwd[i].pw_name));
971                         return &fake_pwd[i];
972                 }
973         }
974
975         return getpwuid(uid);
976 }
977
978 void faked_create_user(const char *name)
979 {
980         int i;
981         uid_t uid;
982         struct passwd new_pwd;
983
984         for (i=0; i<10; i++) {
985                 generate_random_buffer((unsigned char *)&uid,
986                                        sizeof(uid));
987                 if (getpwuid(uid) == NULL) {
988                         break;
989                 }
990         }
991
992         if (i==10) {
993                 /* Weird. No free uid found... */
994                 return;
995         }
996
997         new_pwd.pw_name = SMB_STRDUP(name);
998         new_pwd.pw_passwd = SMB_STRDUP("x");
999         new_pwd.pw_uid = uid;
1000         new_pwd.pw_gid = 100;
1001         new_pwd.pw_gecos = SMB_STRDUP("faked user");
1002         new_pwd.pw_dir = SMB_STRDUP("/nodir");
1003         new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1004
1005         ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1006                      &num_fake_pwd);
1007
1008         DEBUG(10, ("Added fake user %s, have %d fake users\n",
1009                    name, num_fake_pwd));
1010 }
1011
1012 #else
1013
1014 struct passwd *sys_getpwnam(const char *name)
1015 {
1016         return getpwnam(name);
1017 }
1018
1019 struct passwd *sys_getpwuid(uid_t uid)
1020 {
1021         return getpwuid(uid);
1022 }
1023
1024 #endif
1025
1026 struct group *sys_getgrnam(const char *name)
1027 {
1028         return getgrnam(name);
1029 }
1030
1031 struct group *sys_getgrgid(gid_t gid)
1032 {
1033         return getgrgid(gid);
1034 }
1035
1036 #if 0 /* NOT CURRENTLY USED - JRA */
1037 /**************************************************************************
1038  The following are the UNICODE versions of *all* system interface functions
1039  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1040  which currently are left as ascii as they are not used other than in name
1041  resolution.
1042 ****************************************************************************/
1043
1044 /**************************************************************************
1045  Wide stat. Just narrow and call sys_xxx.
1046 ****************************************************************************/
1047
1048 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1049 {
1050         pstring fname;
1051         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1052 }
1053
1054 /**************************************************************************
1055  Wide lstat. Just narrow and call sys_xxx.
1056 ****************************************************************************/
1057
1058 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1059 {
1060         pstring fname;
1061         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1062 }
1063
1064 /**************************************************************************
1065  Wide creat. Just narrow and call sys_xxx.
1066 ****************************************************************************/
1067
1068 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1069 {
1070         pstring fname;
1071         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1072 }
1073
1074 /**************************************************************************
1075  Wide open. Just narrow and call sys_xxx.
1076 ****************************************************************************/
1077
1078 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1079 {
1080         pstring fname;
1081         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1082 }
1083
1084 /**************************************************************************
1085  Wide fopen. Just narrow and call sys_xxx.
1086 ****************************************************************************/
1087
1088 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1089 {
1090         pstring fname;
1091         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1092 }
1093
1094 /**************************************************************************
1095  Wide opendir. Just narrow and call sys_xxx.
1096 ****************************************************************************/
1097
1098 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1099 {
1100         pstring fname;
1101         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1102 }
1103
1104 /**************************************************************************
1105  Wide readdir. Return a structure pointer containing a wide filename.
1106 ****************************************************************************/
1107
1108 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1109 {
1110         static SMB_STRUCT_WDIRENT retval;
1111         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1112
1113         if(!dirval)
1114                 return NULL;
1115
1116         /*
1117          * The only POSIX defined member of this struct is d_name.
1118          */
1119
1120         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1121
1122         return &retval;
1123 }
1124
1125 /**************************************************************************
1126  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1127 ****************************************************************************/
1128
1129 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1130 {
1131         pstring fname;
1132         char *p = sys_getwd(fname);
1133
1134         if(!p)
1135                 return NULL;
1136
1137         return unix_to_unicode(s, p, sizeof(wpstring));
1138 }
1139
1140 /**************************************************************************
1141  Wide chown. Just narrow and call sys_xxx.
1142 ****************************************************************************/
1143
1144 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1145 {
1146         pstring fname;
1147         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1148 }
1149
1150 /**************************************************************************
1151  Wide chroot. Just narrow and call sys_xxx.
1152 ****************************************************************************/
1153
1154 int wsys_chroot(const smb_ucs2_t *wfname)
1155 {
1156         pstring fname;
1157         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1158 }
1159
1160 /**************************************************************************
1161  Wide getpwnam. Return a structure pointer containing wide names.
1162 ****************************************************************************/
1163
1164 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1165 {
1166         static SMB_STRUCT_WPASSWD retval;
1167         fstring name;
1168         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1169
1170         if(!pwret)
1171                 return NULL;
1172
1173         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1174         retval.pw_passwd = pwret->pw_passwd;
1175         retval.pw_uid = pwret->pw_uid;
1176         retval.pw_gid = pwret->pw_gid;
1177         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1178         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1179         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1180
1181         return &retval;
1182 }
1183
1184 /**************************************************************************
1185  Wide getpwuid. Return a structure pointer containing wide names.
1186 ****************************************************************************/
1187
1188 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1189 {
1190         static SMB_STRUCT_WPASSWD retval;
1191         struct passwd *pwret = sys_getpwuid(uid);
1192
1193         if(!pwret)
1194                 return NULL;
1195
1196         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1197         retval.pw_passwd = pwret->pw_passwd;
1198         retval.pw_uid = pwret->pw_uid;
1199         retval.pw_gid = pwret->pw_gid;
1200         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1201         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1202         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1203
1204         return &retval;
1205 }
1206 #endif /* NOT CURRENTLY USED - JRA */
1207
1208 /**************************************************************************
1209  Extract a command into an arg list. Uses a static pstring for storage.
1210  Caller frees returned arg list (which contains pointers into the static pstring).
1211 ****************************************************************************/
1212
1213 static char **extract_args(const char *command)
1214 {
1215         static pstring trunc_cmd;
1216         char *ptr;
1217         int argcl;
1218         char **argl = NULL;
1219         int i;
1220
1221         pstrcpy(trunc_cmd, command);
1222
1223         if(!(ptr = strtok(trunc_cmd, " \t"))) {
1224                 errno = EINVAL;
1225                 return NULL;
1226         }
1227
1228         /*
1229          * Count the args.
1230          */
1231
1232         for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1233                 argcl++;
1234
1235         if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1236                 return NULL;
1237
1238         /*
1239          * Now do the extraction.
1240          */
1241
1242         pstrcpy(trunc_cmd, command);
1243
1244         ptr = strtok(trunc_cmd, " \t");
1245         i = 0;
1246         argl[i++] = ptr;
1247
1248         while((ptr = strtok(NULL, " \t")) != NULL)
1249                 argl[i++] = ptr;
1250
1251         argl[i++] = NULL;
1252         return argl;
1253 }
1254
1255 /**************************************************************************
1256  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1257  a sys_getpid() that only does a system call *once*.
1258 ****************************************************************************/
1259
1260 static pid_t mypid = (pid_t)-1;
1261
1262 pid_t sys_fork(void)
1263 {
1264         pid_t forkret = fork();
1265
1266         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1267                 mypid = (pid_t) -1;
1268
1269         return forkret;
1270 }
1271
1272 /**************************************************************************
1273  Wrapper for getpid. Ensures we only do a system call *once*.
1274 ****************************************************************************/
1275
1276 pid_t sys_getpid(void)
1277 {
1278         if (mypid == (pid_t)-1)
1279                 mypid = getpid();
1280
1281         return mypid;
1282 }
1283
1284 /**************************************************************************
1285  Wrapper for popen. Safer as it doesn't search a path.
1286  Modified from the glibc sources.
1287  modified by tridge to return a file descriptor. We must kick our FILE* habit
1288 ****************************************************************************/
1289
1290 typedef struct _popen_list
1291 {
1292         int fd;
1293         pid_t child_pid;
1294         struct _popen_list *next;
1295 } popen_list;
1296
1297 static popen_list *popen_chain;
1298
1299 int sys_popen(const char *command)
1300 {
1301         int parent_end, child_end;
1302         int pipe_fds[2];
1303         popen_list *entry = NULL;
1304         char **argl = NULL;
1305
1306         if (pipe(pipe_fds) < 0)
1307                 return -1;
1308
1309         parent_end = pipe_fds[0];
1310         child_end = pipe_fds[1];
1311
1312         if (!*command) {
1313                 errno = EINVAL;
1314                 goto err_exit;
1315         }
1316
1317         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1318                 goto err_exit;
1319
1320         ZERO_STRUCTP(entry);
1321
1322         /*
1323          * Extract the command and args into a NULL terminated array.
1324          */
1325
1326         if(!(argl = extract_args(command)))
1327                 goto err_exit;
1328
1329         entry->child_pid = sys_fork();
1330
1331         if (entry->child_pid == -1) {
1332                 goto err_exit;
1333         }
1334
1335         if (entry->child_pid == 0) {
1336
1337                 /*
1338                  * Child !
1339                  */
1340
1341                 int child_std_end = STDOUT_FILENO;
1342                 popen_list *p;
1343
1344                 close(parent_end);
1345                 if (child_end != child_std_end) {
1346                         dup2 (child_end, child_std_end);
1347                         close (child_end);
1348                 }
1349
1350                 /*
1351                  * POSIX.2:  "popen() shall ensure that any streams from previous
1352                  * popen() calls that remain open in the parent process are closed
1353                  * in the new child process."
1354                  */
1355
1356                 for (p = popen_chain; p; p = p->next)
1357                         close(p->fd);
1358
1359                 execv(argl[0], argl);
1360                 _exit (127);
1361         }
1362
1363         /*
1364          * Parent.
1365          */
1366
1367         close (child_end);
1368         SAFE_FREE(argl);
1369
1370         /* Link into popen_chain. */
1371         entry->next = popen_chain;
1372         popen_chain = entry;
1373         entry->fd = parent_end;
1374
1375         return entry->fd;
1376
1377 err_exit:
1378
1379         SAFE_FREE(entry);
1380         SAFE_FREE(argl);
1381         close(pipe_fds[0]);
1382         close(pipe_fds[1]);
1383         return -1;
1384 }
1385
1386 /**************************************************************************
1387  Wrapper for pclose. Modified from the glibc sources.
1388 ****************************************************************************/
1389
1390 int sys_pclose(int fd)
1391 {
1392         int wstatus;
1393         popen_list **ptr = &popen_chain;
1394         popen_list *entry = NULL;
1395         pid_t wait_pid;
1396         int status = -1;
1397
1398         /* Unlink from popen_chain. */
1399         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1400                 if ((*ptr)->fd == fd) {
1401                         entry = *ptr;
1402                         *ptr = (*ptr)->next;
1403                         status = 0;
1404                         break;
1405                 }
1406         }
1407
1408         if (status < 0 || close(entry->fd) < 0)
1409                 return -1;
1410
1411         /*
1412          * As Samba is catching and eating child process
1413          * exits we don't really care about the child exit
1414          * code, a -1 with errno = ECHILD will do fine for us.
1415          */
1416
1417         do {
1418                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1419         } while (wait_pid == -1 && errno == EINTR);
1420
1421         SAFE_FREE(entry);
1422
1423         if (wait_pid == -1)
1424                 return -1;
1425         return wstatus;
1426 }
1427
1428 /**************************************************************************
1429  Wrappers for dlopen, dlsym, dlclose.
1430 ****************************************************************************/
1431
1432 void *sys_dlopen(const char *name, int flags)
1433 {
1434 #if defined(HAVE_DLOPEN)
1435         return dlopen(name, flags);
1436 #else
1437         return NULL;
1438 #endif
1439 }
1440
1441 void *sys_dlsym(void *handle, const char *symbol)
1442 {
1443 #if defined(HAVE_DLSYM)
1444     return dlsym(handle, symbol);
1445 #else
1446     return NULL;
1447 #endif
1448 }
1449
1450 int sys_dlclose (void *handle)
1451 {
1452 #if defined(HAVE_DLCLOSE)
1453         return dlclose(handle);
1454 #else
1455         return 0;
1456 #endif
1457 }
1458
1459 const char *sys_dlerror(void)
1460 {
1461 #if defined(HAVE_DLERROR)
1462         return dlerror();
1463 #else
1464         return NULL;
1465 #endif
1466 }
1467
1468 int sys_dup2(int oldfd, int newfd) 
1469 {
1470 #if defined(HAVE_DUP2)
1471         return dup2(oldfd, newfd);
1472 #else
1473         errno = ENOSYS;
1474         return -1;
1475 #endif
1476 }
1477
1478 /**************************************************************************
1479  Wrapper for Admin Logs.
1480 ****************************************************************************/
1481
1482  void sys_adminlog(int priority, const char *format_str, ...) 
1483 {
1484         va_list ap;
1485         int ret;
1486         char *msgbuf = NULL;
1487
1488         va_start( ap, format_str );
1489         ret = vasprintf( &msgbuf, format_str, ap );
1490         va_end( ap );
1491
1492         if (ret == -1)
1493                 return;
1494
1495 #if defined(HAVE_SYSLOG)
1496         syslog( priority, "%s", msgbuf );
1497 #else
1498         DEBUG(0,("%s", msgbuf ));
1499 #endif
1500         SAFE_FREE(msgbuf);
1501 }
1502
1503 /**************************************************************************
1504  Wrappers for extented attribute calls. Based on the Linux package with
1505  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1506 ****************************************************************************/
1507
1508 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1509 {
1510 #if defined(HAVE_GETXATTR)
1511         return getxattr(path, name, value, size);
1512 #elif defined(HAVE_GETEA)
1513         return getea(path, name, value, size);
1514 #elif defined(HAVE_EXTATTR_GET_FILE)
1515         char *s;
1516         ssize_t retval;
1517         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1518                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1519         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1520         /*
1521          * The BSD implementation has a nasty habit of silently truncating
1522          * the returned value to the size of the buffer, so we have to check
1523          * that the buffer is large enough to fit the returned value.
1524          */
1525         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1526                 if(retval > size) {
1527                         errno = ERANGE;
1528                         return -1;
1529                 }
1530                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1531                         return retval;
1532         }
1533
1534         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1535         return -1;
1536 #elif defined(HAVE_ATTR_GET)
1537         int retval, flags = 0;
1538         int valuelength = (int)size;
1539         char *attrname = strchr(name,'.') + 1;
1540         
1541         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1542
1543         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1544
1545         return retval ? retval : valuelength;
1546 #else
1547         errno = ENOSYS;
1548         return -1;
1549 #endif
1550 }
1551
1552 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1553 {
1554 #if defined(HAVE_LGETXATTR)
1555         return lgetxattr(path, name, value, size);
1556 #elif defined(HAVE_LGETEA)
1557         return lgetea(path, name, value, size);
1558 #elif defined(HAVE_EXTATTR_GET_LINK)
1559         char *s;
1560         ssize_t retval;
1561         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1562                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1563         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1564
1565         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1566                 if(retval > size) {
1567                         errno = ERANGE;
1568                         return -1;
1569                 }
1570                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1571                         return retval;
1572         }
1573         
1574         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1575         return -1;
1576 #elif defined(HAVE_ATTR_GET)
1577         int retval, flags = ATTR_DONTFOLLOW;
1578         int valuelength = (int)size;
1579         char *attrname = strchr(name,'.') + 1;
1580         
1581         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1582
1583         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1584
1585         return retval ? retval : valuelength;
1586 #else
1587         errno = ENOSYS;
1588         return -1;
1589 #endif
1590 }
1591
1592 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1593 {
1594 #if defined(HAVE_FGETXATTR)
1595         return fgetxattr(filedes, name, value, size);
1596 #elif defined(HAVE_FGETEA)
1597         return fgetea(filedes, name, value, size);
1598 #elif defined(HAVE_EXTATTR_GET_FD)
1599         char *s;
1600         ssize_t retval;
1601         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1602                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1603         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1604
1605         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1606                 if(retval > size) {
1607                         errno = ERANGE;
1608                         return -1;
1609                 }
1610                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1611                         return retval;
1612         }
1613         
1614         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1615         return -1;
1616 #elif defined(HAVE_ATTR_GETF)
1617         int retval, flags = 0;
1618         int valuelength = (int)size;
1619         char *attrname = strchr(name,'.') + 1;
1620         
1621         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1622
1623         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1624
1625         return retval ? retval : valuelength;
1626 #else
1627         errno = ENOSYS;
1628         return -1;
1629 #endif
1630 }
1631
1632 #if defined(HAVE_EXTATTR_LIST_FILE)
1633
1634 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1635
1636 static struct {
1637         int space;
1638         const char *name;
1639         size_t len;
1640
1641 extattr[] = {
1642         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1643         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1644 };
1645
1646 typedef union {
1647         const char *path;
1648         int filedes;
1649 } extattr_arg;
1650
1651 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1652 {
1653         ssize_t list_size, total_size = 0;
1654         int i, t, len;
1655         char *buf;
1656         /* Iterate through extattr(2) namespaces */
1657         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1658                 switch(type) {
1659 #if defined(HAVE_EXTATTR_LIST_FILE)
1660                         case 0:
1661                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1662                                 break;
1663 #endif
1664 #if defined(HAVE_EXTATTR_LIST_LINK)
1665                         case 1:
1666                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1667                                 break;
1668 #endif
1669 #if defined(HAVE_EXTATTR_LIST_FD)
1670                         case 2:
1671                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1672                                 break;
1673 #endif
1674                         default:
1675                                 errno = ENOSYS;
1676                                 return -1;
1677                 }
1678                 /* Some error happend. Errno should be set by the previous call */
1679                 if(list_size < 0)
1680                         return -1;
1681                 /* No attributes */
1682                 if(list_size == 0)
1683                         continue;
1684                 /* XXX: Call with an empty buffer may be used to calculate
1685                    necessary buffer size. Unfortunately, we can't say, how
1686                    many attributes were returned, so here is the potential
1687                    problem with the emulation.
1688                 */
1689                 if(list == NULL) {
1690                         /* Take the worse case of one char attribute names - 
1691                            two bytes per name plus one more for sanity.
1692                         */
1693                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1694                         continue;
1695                 }
1696                 /* Count necessary offset to fit namespace prefixes */
1697                 len = 0;
1698                 for(i = 0; i < list_size; i += list[i] + 1)
1699                         len += extattr[t].len;
1700
1701                 total_size += list_size + len;
1702                 /* Buffer is too small to fit the results */
1703                 if(total_size > size) {
1704                         errno = ERANGE;
1705                         return -1;
1706                 }
1707                 /* Shift results back, so we can prepend prefixes */
1708                 buf = memmove(list + len, list, list_size);
1709
1710                 for(i = 0; i < list_size; i += len + 1) {
1711                         len = buf[i];
1712                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1713                         list += extattr[t].len;
1714                         strncpy(list, buf + i + 1, len);
1715                         list[len] = '\0';
1716                         list += len + 1;
1717                 }
1718                 size -= total_size;
1719         }
1720         return total_size;
1721 }
1722
1723 #endif
1724
1725 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1726 static char attr_buffer[ATTR_MAX_VALUELEN];
1727
1728 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1729 {
1730         int retval = 0, index;
1731         attrlist_cursor_t *cursor = 0;
1732         int total_size = 0;
1733         attrlist_t * al = (attrlist_t *)attr_buffer;
1734         attrlist_ent_t *ae;
1735         size_t ent_size, left = size;
1736         char *bp = list;
1737
1738         while (True) {
1739             if (filedes)
1740                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1741             else
1742                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1743             if (retval) break;
1744             for (index = 0; index < al->al_count; index++) {
1745                 ae = ATTR_ENTRY(attr_buffer, index);
1746                 ent_size = strlen(ae->a_name) + sizeof("user.");
1747                 if (left >= ent_size) {
1748                     strncpy(bp, "user.", sizeof("user."));
1749                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1750                     bp += ent_size;
1751                     left -= ent_size;
1752                 } else if (size) {
1753                     errno = ERANGE;
1754                     retval = -1;
1755                     break;
1756                 }
1757                 total_size += ent_size;
1758             }
1759             if (al->al_more == 0) break;
1760         }
1761         if (retval == 0) {
1762             flags |= ATTR_ROOT;
1763             cursor = 0;
1764             while (True) {
1765                 if (filedes)
1766                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1767                 else
1768                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1769                 if (retval) break;
1770                 for (index = 0; index < al->al_count; index++) {
1771                     ae = ATTR_ENTRY(attr_buffer, index);
1772                     ent_size = strlen(ae->a_name) + sizeof("system.");
1773                     if (left >= ent_size) {
1774                         strncpy(bp, "system.", sizeof("system."));
1775                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1776                         bp += ent_size;
1777                         left -= ent_size;
1778                     } else if (size) {
1779                         errno = ERANGE;
1780                         retval = -1;
1781                         break;
1782                     }
1783                     total_size += ent_size;
1784                 }
1785                 if (al->al_more == 0) break;
1786             }
1787         }
1788         return (ssize_t)(retval ? retval : total_size);
1789 }
1790
1791 #endif
1792
1793 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1794 {
1795 #if defined(HAVE_LISTXATTR)
1796         return listxattr(path, list, size);
1797 #elif defined(HAVE_LISTEA)
1798         return listea(path, list, size);
1799 #elif defined(HAVE_EXTATTR_LIST_FILE)
1800         extattr_arg arg;
1801         arg.path = path;
1802         return bsd_attr_list(0, arg, list, size);
1803 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1804         return irix_attr_list(path, 0, list, size, 0);
1805 #else
1806         errno = ENOSYS;
1807         return -1;
1808 #endif
1809 }
1810
1811 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1812 {
1813 #if defined(HAVE_LLISTXATTR)
1814         return llistxattr(path, list, size);
1815 #elif defined(HAVE_LLISTEA)
1816         return llistea(path, list, size);
1817 #elif defined(HAVE_EXTATTR_LIST_LINK)
1818         extattr_arg arg;
1819         arg.path = path;
1820         return bsd_attr_list(1, arg, list, size);
1821 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1822         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1823 #else
1824         errno = ENOSYS;
1825         return -1;
1826 #endif
1827 }
1828
1829 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1830 {
1831 #if defined(HAVE_FLISTXATTR)
1832         return flistxattr(filedes, list, size);
1833 #elif defined(HAVE_FLISTEA)
1834         return flistea(filedes, list, size);
1835 #elif defined(HAVE_EXTATTR_LIST_FD)
1836         extattr_arg arg;
1837         arg.filedes = filedes;
1838         return bsd_attr_list(2, arg, list, size);
1839 #elif defined(HAVE_ATTR_LISTF)
1840         return irix_attr_list(NULL, filedes, list, size, 0);
1841 #else
1842         errno = ENOSYS;
1843         return -1;
1844 #endif
1845 }
1846
1847 int sys_removexattr (const char *path, const char *name)
1848 {
1849 #if defined(HAVE_REMOVEXATTR)
1850         return removexattr(path, name);
1851 #elif defined(HAVE_REMOVEEA)
1852         return removeea(path, name);
1853 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1854         char *s;
1855         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1856                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1857         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1858
1859         return extattr_delete_file(path, attrnamespace, attrname);
1860 #elif defined(HAVE_ATTR_REMOVE)
1861         int flags = 0;
1862         char *attrname = strchr(name,'.') + 1;
1863         
1864         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1865
1866         return attr_remove(path, attrname, flags);
1867 #else
1868         errno = ENOSYS;
1869         return -1;
1870 #endif
1871 }
1872
1873 int sys_lremovexattr (const char *path, const char *name)
1874 {
1875 #if defined(HAVE_LREMOVEXATTR)
1876         return lremovexattr(path, name);
1877 #elif defined(HAVE_LREMOVEEA)
1878         return lremoveea(path, name);
1879 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1880         char *s;
1881         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1882                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1883         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1884
1885         return extattr_delete_link(path, attrnamespace, attrname);
1886 #elif defined(HAVE_ATTR_REMOVE)
1887         int flags = ATTR_DONTFOLLOW;
1888         char *attrname = strchr(name,'.') + 1;
1889         
1890         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1891
1892         return attr_remove(path, attrname, flags);
1893 #else
1894         errno = ENOSYS;
1895         return -1;
1896 #endif
1897 }
1898
1899 int sys_fremovexattr (int filedes, const char *name)
1900 {
1901 #if defined(HAVE_FREMOVEXATTR)
1902         return fremovexattr(filedes, name);
1903 #elif defined(HAVE_FREMOVEEA)
1904         return fremoveea(filedes, name);
1905 #elif defined(HAVE_EXTATTR_DELETE_FD)
1906         char *s;
1907         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1908                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1909         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1910
1911         return extattr_delete_fd(filedes, attrnamespace, attrname);
1912 #elif defined(HAVE_ATTR_REMOVEF)
1913         int flags = 0;
1914         char *attrname = strchr(name,'.') + 1;
1915         
1916         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1917
1918         return attr_removef(filedes, attrname, flags);
1919 #else
1920         errno = ENOSYS;
1921         return -1;
1922 #endif
1923 }
1924
1925 #if !defined(HAVE_SETXATTR)
1926 #define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
1927 #define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
1928 #endif
1929
1930 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1931 {
1932 #if defined(HAVE_SETXATTR)
1933         return setxattr(path, name, value, size, flags);
1934 #elif defined(HAVE_SETEA)
1935         return setea(path, name, value, size, flags);
1936 #elif defined(HAVE_EXTATTR_SET_FILE)
1937         char *s;
1938         int retval = 0;
1939         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1940                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1941         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1942         if (flags) {
1943                 /* Check attribute existence */
1944                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1945                 if (retval < 0) {
1946                         /* REPLACE attribute, that doesn't exist */
1947                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1948                                 errno = ENOATTR;
1949                                 return -1;
1950                         }
1951                         /* Ignore other errors */
1952                 }
1953                 else {
1954                         /* CREATE attribute, that already exists */
1955                         if (flags & XATTR_CREATE) {
1956                                 errno = EEXIST;
1957                                 return -1;
1958                         }
1959                 }
1960         }
1961         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1962         return (retval < 0) ? -1 : 0;
1963 #elif defined(HAVE_ATTR_SET)
1964         int myflags = 0;
1965         char *attrname = strchr(name,'.') + 1;
1966         
1967         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1968         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1969         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1970
1971         return attr_set(path, attrname, (const char *)value, size, myflags);
1972 #else
1973         errno = ENOSYS;
1974         return -1;
1975 #endif
1976 }
1977
1978 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1979 {
1980 #if defined(HAVE_LSETXATTR)
1981         return lsetxattr(path, name, value, size, flags);
1982 #elif defined(LSETEA)
1983         return lsetea(path, name, value, size, flags);
1984 #elif defined(HAVE_EXTATTR_SET_LINK)
1985         char *s;
1986         int retval = 0;
1987         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1988                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1989         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1990         if (flags) {
1991                 /* Check attribute existence */
1992                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1993                 if (retval < 0) {
1994                         /* REPLACE attribute, that doesn't exist */
1995                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1996                                 errno = ENOATTR;
1997                                 return -1;
1998                         }
1999                         /* Ignore other errors */
2000                 }
2001                 else {
2002                         /* CREATE attribute, that already exists */
2003                         if (flags & XATTR_CREATE) {
2004                                 errno = EEXIST;
2005                                 return -1;
2006                         }
2007                 }
2008         }
2009
2010         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2011         return (retval < 0) ? -1 : 0;
2012 #elif defined(HAVE_ATTR_SET)
2013         int myflags = ATTR_DONTFOLLOW;
2014         char *attrname = strchr(name,'.') + 1;
2015         
2016         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2017         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2018         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2019
2020         return attr_set(path, attrname, (const char *)value, size, myflags);
2021 #else
2022         errno = ENOSYS;
2023         return -1;
2024 #endif
2025 }
2026
2027 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2028 {
2029 #if defined(HAVE_FSETXATTR)
2030         return fsetxattr(filedes, name, value, size, flags);
2031 #elif defined(HAVE_FSETEA)
2032         return fsetea(filedes, name, value, size, flags);
2033 #elif defined(HAVE_EXTATTR_SET_FD)
2034         char *s;
2035         int retval = 0;
2036         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2037                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2038         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2039         if (flags) {
2040                 /* Check attribute existence */
2041                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2042                 if (retval < 0) {
2043                         /* REPLACE attribute, that doesn't exist */
2044                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2045                                 errno = ENOATTR;
2046                                 return -1;
2047                         }
2048                         /* Ignore other errors */
2049                 }
2050                 else {
2051                         /* CREATE attribute, that already exists */
2052                         if (flags & XATTR_CREATE) {
2053                                 errno = EEXIST;
2054                                 return -1;
2055                         }
2056                 }
2057         }
2058         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2059         return (retval < 0) ? -1 : 0;
2060 #elif defined(HAVE_ATTR_SETF)
2061         int myflags = 0;
2062         char *attrname = strchr(name,'.') + 1;
2063         
2064         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2065         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2066         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2067
2068         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2069 #else
2070         errno = ENOSYS;
2071         return -1;
2072 #endif
2073 }
2074
2075 /****************************************************************************
2076  Return the major devicenumber for UNIX extensions.
2077 ****************************************************************************/
2078                                                                                                                 
2079 uint32 unix_dev_major(SMB_DEV_T dev)
2080 {
2081 #if defined(HAVE_DEVICE_MAJOR_FN)
2082         return (uint32)major(dev);
2083 #else
2084         return (uint32)(dev >> 8);
2085 #endif
2086 }
2087                                                                                                                 
2088 /****************************************************************************
2089  Return the minor devicenumber for UNIX extensions.
2090 ****************************************************************************/
2091                                                                                                                 
2092 uint32 unix_dev_minor(SMB_DEV_T dev)
2093 {
2094 #if defined(HAVE_DEVICE_MINOR_FN)
2095         return (uint32)minor(dev);
2096 #else
2097         return (uint32)(dev & 0xff);
2098 #endif
2099 }
2100
2101 #if defined(WITH_AIO)
2102
2103 /*******************************************************************
2104  An aio_read wrapper that will deal with 64-bit sizes.
2105 ********************************************************************/
2106                                                                                                                                            
2107 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2108 {
2109 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2110         return aio_read64(aiocb);
2111 #elif defined(HAVE_AIO_READ)
2112         return aio_read(aiocb);
2113 #else
2114         errno = ENOSYS;
2115         return -1;
2116 #endif
2117 }
2118
2119 /*******************************************************************
2120  An aio_write wrapper that will deal with 64-bit sizes.
2121 ********************************************************************/
2122                                                                                                                                            
2123 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2124 {
2125 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2126         return aio_write64(aiocb);
2127 #elif defined(HAVE_AIO_WRITE)
2128         return aio_write(aiocb);
2129 #else
2130         errno = ENOSYS;
2131         return -1;
2132 #endif
2133 }
2134
2135 /*******************************************************************
2136  An aio_return wrapper that will deal with 64-bit sizes.
2137 ********************************************************************/
2138                                                                                                                                            
2139 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2140 {
2141 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2142         return aio_return64(aiocb);
2143 #elif defined(HAVE_AIO_RETURN)
2144         return aio_return(aiocb);
2145 #else
2146         errno = ENOSYS;
2147         return -1;
2148 #endif
2149 }
2150
2151 /*******************************************************************
2152  An aio_cancel wrapper that will deal with 64-bit sizes.
2153 ********************************************************************/
2154
2155 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2156 {
2157 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2158         return aio_cancel64(fd, aiocb);
2159 #elif defined(HAVE_AIO_CANCEL)
2160         return aio_cancel(fd, aiocb);
2161 #else
2162         errno = ENOSYS;
2163         return -1;
2164 #endif
2165 }
2166
2167 /*******************************************************************
2168  An aio_error wrapper that will deal with 64-bit sizes.
2169 ********************************************************************/
2170
2171 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2172 {
2173 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2174         return aio_error64(aiocb);
2175 #elif defined(HAVE_AIO_ERROR)
2176         return aio_error(aiocb);
2177 #else
2178         errno = ENOSYS;
2179         return -1;
2180 #endif
2181 }
2182
2183 /*******************************************************************
2184  An aio_fsync wrapper that will deal with 64-bit sizes.
2185 ********************************************************************/
2186
2187 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2188 {
2189 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2190         return aio_fsync64(op, aiocb);
2191 #elif defined(HAVE_AIO_FSYNC)
2192         return aio_fsync(op, aiocb);
2193 #else
2194         errno = ENOSYS;
2195         return -1;
2196 #endif
2197 }
2198
2199 /*******************************************************************
2200  An aio_fsync wrapper that will deal with 64-bit sizes.
2201 ********************************************************************/
2202
2203 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2204 {
2205 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2206         return aio_suspend64(cblist, n, timeout);
2207 #elif defined(HAVE_AIO_FSYNC)
2208         return aio_suspend(cblist, n, timeout);
2209 #else
2210         errno = ENOSYS;
2211         return -1;
2212 #endif
2213 }
2214 #else /* !WITH_AIO */
2215
2216 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2217 {
2218         errno = ENOSYS;
2219         return -1;
2220 }
2221
2222 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2223 {
2224         errno = ENOSYS;
2225         return -1;
2226 }
2227
2228 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2229 {
2230         errno = ENOSYS;
2231         return -1;
2232 }
2233
2234 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2235 {
2236         errno = ENOSYS;
2237         return -1;
2238 }
2239
2240 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2241 {
2242         errno = ENOSYS;
2243         return -1;
2244 }
2245
2246 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2247 {
2248         errno = ENOSYS;
2249         return -1;
2250 }
2251
2252 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2253 {
2254         errno = ENOSYS;
2255         return -1;
2256 }
2257 #endif /* WITH_AIO */
2258
2259 int sys_getpeereid( int s, uid_t *uid)
2260 {
2261 #if defined(HAVE_PEERCRED)
2262         struct ucred cred;
2263         socklen_t cred_len = sizeof(struct ucred);
2264         int ret;
2265
2266         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2267         if (ret != 0) {
2268                 return -1;
2269         }
2270
2271         if (cred_len != sizeof(struct ucred)) {
2272                 errno = EINVAL;
2273                 return -1;
2274         }
2275
2276         *uid = cred.uid;
2277         return 0;
2278 #else
2279         errno = ENOSYS;
2280         return -1;
2281 #endif
2282 }