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