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