r23779: Change from v2 or later to v3 or later.
[ira/wip.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 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, 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(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                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1010                 if (new_gidset == NULL) {
1011                         return -1;
1012                 }
1013
1014                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1015                 new_gidset[0] = primary_gid;
1016                 setlen++;
1017         }
1018
1019         if (setlen > max) {
1020                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1021                         setlen, max));
1022                 setlen = max;
1023         }
1024
1025 #if defined(HAVE_BROKEN_GETGROUPS)
1026         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1027 #else
1028         ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1029 #endif
1030
1031         if (new_gidset) {
1032                 int errsav = errno;
1033                 SAFE_FREE(new_gidset);
1034                 errno = errsav;
1035         }
1036
1037         return ret;
1038 }
1039
1040 #endif /* USE_BSD_SETGROUPS */
1041
1042 /**************************************************************************
1043  Wrapper for getgroups. Deals with broken (int) case.
1044 ****************************************************************************/
1045
1046 int sys_getgroups(int setlen, gid_t *gidset)
1047 {
1048 #if defined(HAVE_BROKEN_GETGROUPS)
1049         return sys_broken_getgroups(setlen, gidset);
1050 #else
1051         return getgroups(setlen, gidset);
1052 #endif
1053 }
1054
1055 /**************************************************************************
1056  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1057 ****************************************************************************/
1058
1059 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1060 {
1061 #if !defined(HAVE_SETGROUPS)
1062         errno = ENOSYS;
1063         return -1;
1064 #endif /* HAVE_SETGROUPS */
1065
1066 #if defined(USE_BSD_SETGROUPS)
1067         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1068 #elif defined(HAVE_BROKEN_GETGROUPS)
1069         return sys_broken_setgroups(setlen, gidset);
1070 #else
1071         return setgroups(setlen, gidset);
1072 #endif
1073 }
1074
1075 /**************************************************************************
1076  Wrappers for setpwent(), getpwent() and endpwent()
1077 ****************************************************************************/
1078
1079 void sys_setpwent(void)
1080 {
1081         setpwent();
1082 }
1083
1084 struct passwd *sys_getpwent(void)
1085 {
1086         return getpwent();
1087 }
1088
1089 void sys_endpwent(void)
1090 {
1091         endpwent();
1092 }
1093
1094 /**************************************************************************
1095  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1096 ****************************************************************************/
1097
1098 #ifdef ENABLE_BUILD_FARM_HACKS
1099
1100 /*
1101  * In the build farm we want to be able to join machines to the domain. As we
1102  * don't have root access, we need to bypass direct access to /etc/passwd
1103  * after a user has been created via samr. Fake those users.
1104  */
1105
1106 static struct passwd *fake_pwd;
1107 static int num_fake_pwd;
1108
1109 struct passwd *sys_getpwnam(const char *name)
1110 {
1111         int i;
1112
1113         for (i=0; i<num_fake_pwd; i++) {
1114                 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1115                         DEBUG(10, ("Returning fake user %s\n", name));
1116                         return &fake_pwd[i];
1117                 }
1118         }
1119
1120         return getpwnam(name);
1121 }
1122
1123 struct passwd *sys_getpwuid(uid_t uid)
1124 {
1125         int i;
1126
1127         for (i=0; i<num_fake_pwd; i++) {
1128                 if (fake_pwd[i].pw_uid == uid) {
1129                         DEBUG(10, ("Returning fake user %s\n",
1130                                    fake_pwd[i].pw_name));
1131                         return &fake_pwd[i];
1132                 }
1133         }
1134
1135         return getpwuid(uid);
1136 }
1137
1138 void faked_create_user(const char *name)
1139 {
1140         int i;
1141         uid_t uid;
1142         struct passwd new_pwd;
1143
1144         for (i=0; i<10; i++) {
1145                 generate_random_buffer((unsigned char *)&uid,
1146                                        sizeof(uid));
1147                 if (getpwuid(uid) == NULL) {
1148                         break;
1149                 }
1150         }
1151
1152         if (i==10) {
1153                 /* Weird. No free uid found... */
1154                 return;
1155         }
1156
1157         new_pwd.pw_name = SMB_STRDUP(name);
1158         new_pwd.pw_passwd = SMB_STRDUP("x");
1159         new_pwd.pw_uid = uid;
1160         new_pwd.pw_gid = 100;
1161         new_pwd.pw_gecos = SMB_STRDUP("faked user");
1162         new_pwd.pw_dir = SMB_STRDUP("/nodir");
1163         new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1164
1165         ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1166                      &num_fake_pwd);
1167
1168         DEBUG(10, ("Added fake user %s, have %d fake users\n",
1169                    name, num_fake_pwd));
1170 }
1171
1172 #else
1173
1174 struct passwd *sys_getpwnam(const char *name)
1175 {
1176         return getpwnam(name);
1177 }
1178
1179 struct passwd *sys_getpwuid(uid_t uid)
1180 {
1181         return getpwuid(uid);
1182 }
1183
1184 #endif
1185
1186 struct group *sys_getgrnam(const char *name)
1187 {
1188         return getgrnam(name);
1189 }
1190
1191 struct group *sys_getgrgid(gid_t gid)
1192 {
1193         return getgrgid(gid);
1194 }
1195
1196 #if 0 /* NOT CURRENTLY USED - JRA */
1197 /**************************************************************************
1198  The following are the UNICODE versions of *all* system interface functions
1199  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1200  which currently are left as ascii as they are not used other than in name
1201  resolution.
1202 ****************************************************************************/
1203
1204 /**************************************************************************
1205  Wide stat. Just narrow and call sys_xxx.
1206 ****************************************************************************/
1207
1208 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1209 {
1210         pstring fname;
1211         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1212 }
1213
1214 /**************************************************************************
1215  Wide lstat. Just narrow and call sys_xxx.
1216 ****************************************************************************/
1217
1218 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1219 {
1220         pstring fname;
1221         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1222 }
1223
1224 /**************************************************************************
1225  Wide creat. Just narrow and call sys_xxx.
1226 ****************************************************************************/
1227
1228 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1229 {
1230         pstring fname;
1231         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1232 }
1233
1234 /**************************************************************************
1235  Wide open. Just narrow and call sys_xxx.
1236 ****************************************************************************/
1237
1238 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1239 {
1240         pstring fname;
1241         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1242 }
1243
1244 /**************************************************************************
1245  Wide fopen. Just narrow and call sys_xxx.
1246 ****************************************************************************/
1247
1248 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1249 {
1250         pstring fname;
1251         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1252 }
1253
1254 /**************************************************************************
1255  Wide opendir. Just narrow and call sys_xxx.
1256 ****************************************************************************/
1257
1258 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1259 {
1260         pstring fname;
1261         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1262 }
1263
1264 /**************************************************************************
1265  Wide readdir. Return a structure pointer containing a wide filename.
1266 ****************************************************************************/
1267
1268 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1269 {
1270         static SMB_STRUCT_WDIRENT retval;
1271         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1272
1273         if(!dirval)
1274                 return NULL;
1275
1276         /*
1277          * The only POSIX defined member of this struct is d_name.
1278          */
1279
1280         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1281
1282         return &retval;
1283 }
1284
1285 /**************************************************************************
1286  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1287 ****************************************************************************/
1288
1289 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1290 {
1291         pstring fname;
1292         char *p = sys_getwd(fname);
1293
1294         if(!p)
1295                 return NULL;
1296
1297         return unix_to_unicode(s, p, sizeof(wpstring));
1298 }
1299
1300 /**************************************************************************
1301  Wide chown. Just narrow and call sys_xxx.
1302 ****************************************************************************/
1303
1304 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1305 {
1306         pstring fname;
1307         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1308 }
1309
1310 /**************************************************************************
1311  Wide chroot. Just narrow and call sys_xxx.
1312 ****************************************************************************/
1313
1314 int wsys_chroot(const smb_ucs2_t *wfname)
1315 {
1316         pstring fname;
1317         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1318 }
1319
1320 /**************************************************************************
1321  Wide getpwnam. Return a structure pointer containing wide names.
1322 ****************************************************************************/
1323
1324 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1325 {
1326         static SMB_STRUCT_WPASSWD retval;
1327         fstring name;
1328         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1329
1330         if(!pwret)
1331                 return NULL;
1332
1333         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1334         retval.pw_passwd = pwret->pw_passwd;
1335         retval.pw_uid = pwret->pw_uid;
1336         retval.pw_gid = pwret->pw_gid;
1337         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1338         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1339         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1340
1341         return &retval;
1342 }
1343
1344 /**************************************************************************
1345  Wide getpwuid. Return a structure pointer containing wide names.
1346 ****************************************************************************/
1347
1348 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1349 {
1350         static SMB_STRUCT_WPASSWD retval;
1351         struct passwd *pwret = sys_getpwuid(uid);
1352
1353         if(!pwret)
1354                 return NULL;
1355
1356         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1357         retval.pw_passwd = pwret->pw_passwd;
1358         retval.pw_uid = pwret->pw_uid;
1359         retval.pw_gid = pwret->pw_gid;
1360         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1361         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1362         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1363
1364         return &retval;
1365 }
1366 #endif /* NOT CURRENTLY USED - JRA */
1367
1368 /**************************************************************************
1369  Extract a command into an arg list.
1370 ****************************************************************************/
1371
1372 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1373 {
1374         char *trunc_cmd;
1375         char *saveptr;
1376         char *ptr;
1377         int argcl;
1378         char **argl = NULL;
1379         int i;
1380
1381         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1382                 DEBUG(0, ("talloc failed\n"));
1383                 goto nomem;
1384         }
1385
1386         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1387                 TALLOC_FREE(trunc_cmd);
1388                 errno = EINVAL;
1389                 return NULL;
1390         }
1391
1392         /*
1393          * Count the args.
1394          */
1395
1396         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1397                 argcl++;
1398
1399         TALLOC_FREE(trunc_cmd);
1400
1401         if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1402                 goto nomem;
1403         }
1404
1405         /*
1406          * Now do the extraction.
1407          */
1408
1409         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1410                 goto nomem;
1411         }
1412
1413         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1414         i = 0;
1415
1416         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1417                 goto nomem;
1418         }
1419
1420         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1421
1422                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1423                         goto nomem;
1424                 }
1425         }
1426
1427         argl[i++] = NULL;
1428         return argl;
1429
1430  nomem:
1431         DEBUG(0, ("talloc failed\n"));
1432         TALLOC_FREE(trunc_cmd);
1433         TALLOC_FREE(argl);
1434         errno = ENOMEM;
1435         return NULL;
1436 }
1437
1438 /**************************************************************************
1439  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1440  a sys_getpid() that only does a system call *once*.
1441 ****************************************************************************/
1442
1443 static pid_t mypid = (pid_t)-1;
1444
1445 pid_t sys_fork(void)
1446 {
1447         pid_t forkret = fork();
1448
1449         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1450                 mypid = (pid_t) -1;
1451
1452         return forkret;
1453 }
1454
1455 /**************************************************************************
1456  Wrapper for getpid. Ensures we only do a system call *once*.
1457 ****************************************************************************/
1458
1459 pid_t sys_getpid(void)
1460 {
1461         if (mypid == (pid_t)-1)
1462                 mypid = getpid();
1463
1464         return mypid;
1465 }
1466
1467 /**************************************************************************
1468  Wrapper for popen. Safer as it doesn't search a path.
1469  Modified from the glibc sources.
1470  modified by tridge to return a file descriptor. We must kick our FILE* habit
1471 ****************************************************************************/
1472
1473 typedef struct _popen_list
1474 {
1475         int fd;
1476         pid_t child_pid;
1477         struct _popen_list *next;
1478 } popen_list;
1479
1480 static popen_list *popen_chain;
1481
1482 int sys_popen(const char *command)
1483 {
1484         int parent_end, child_end;
1485         int pipe_fds[2];
1486         popen_list *entry = NULL;
1487         char **argl = NULL;
1488
1489         if (pipe(pipe_fds) < 0)
1490                 return -1;
1491
1492         parent_end = pipe_fds[0];
1493         child_end = pipe_fds[1];
1494
1495         if (!*command) {
1496                 errno = EINVAL;
1497                 goto err_exit;
1498         }
1499
1500         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1501                 goto err_exit;
1502
1503         ZERO_STRUCTP(entry);
1504
1505         /*
1506          * Extract the command and args into a NULL terminated array.
1507          */
1508
1509         if(!(argl = extract_args(NULL, command)))
1510                 goto err_exit;
1511
1512         entry->child_pid = sys_fork();
1513
1514         if (entry->child_pid == -1) {
1515                 goto err_exit;
1516         }
1517
1518         if (entry->child_pid == 0) {
1519
1520                 /*
1521                  * Child !
1522                  */
1523
1524                 int child_std_end = STDOUT_FILENO;
1525                 popen_list *p;
1526
1527                 close(parent_end);
1528                 if (child_end != child_std_end) {
1529                         dup2 (child_end, child_std_end);
1530                         close (child_end);
1531                 }
1532
1533                 /*
1534                  * POSIX.2:  "popen() shall ensure that any streams from previous
1535                  * popen() calls that remain open in the parent process are closed
1536                  * in the new child process."
1537                  */
1538
1539                 for (p = popen_chain; p; p = p->next)
1540                         close(p->fd);
1541
1542                 execv(argl[0], argl);
1543                 _exit (127);
1544         }
1545
1546         /*
1547          * Parent.
1548          */
1549
1550         close (child_end);
1551         TALLOC_FREE(argl);
1552
1553         /* Link into popen_chain. */
1554         entry->next = popen_chain;
1555         popen_chain = entry;
1556         entry->fd = parent_end;
1557
1558         return entry->fd;
1559
1560 err_exit:
1561
1562         SAFE_FREE(entry);
1563         SAFE_FREE(argl);
1564         close(pipe_fds[0]);
1565         close(pipe_fds[1]);
1566         return -1;
1567 }
1568
1569 /**************************************************************************
1570  Wrapper for pclose. Modified from the glibc sources.
1571 ****************************************************************************/
1572
1573 int sys_pclose(int fd)
1574 {
1575         int wstatus;
1576         popen_list **ptr = &popen_chain;
1577         popen_list *entry = NULL;
1578         pid_t wait_pid;
1579         int status = -1;
1580
1581         /* Unlink from popen_chain. */
1582         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1583                 if ((*ptr)->fd == fd) {
1584                         entry = *ptr;
1585                         *ptr = (*ptr)->next;
1586                         status = 0;
1587                         break;
1588                 }
1589         }
1590
1591         if (status < 0 || close(entry->fd) < 0)
1592                 return -1;
1593
1594         /*
1595          * As Samba is catching and eating child process
1596          * exits we don't really care about the child exit
1597          * code, a -1 with errno = ECHILD will do fine for us.
1598          */
1599
1600         do {
1601                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1602         } while (wait_pid == -1 && errno == EINTR);
1603
1604         SAFE_FREE(entry);
1605
1606         if (wait_pid == -1)
1607                 return -1;
1608         return wstatus;
1609 }
1610
1611 /**************************************************************************
1612  Wrappers for dlopen, dlsym, dlclose.
1613 ****************************************************************************/
1614
1615 void *sys_dlopen(const char *name, int flags)
1616 {
1617 #if defined(HAVE_DLOPEN)
1618         return dlopen(name, flags);
1619 #else
1620         return NULL;
1621 #endif
1622 }
1623
1624 void *sys_dlsym(void *handle, const char *symbol)
1625 {
1626 #if defined(HAVE_DLSYM)
1627     return dlsym(handle, symbol);
1628 #else
1629     return NULL;
1630 #endif
1631 }
1632
1633 int sys_dlclose (void *handle)
1634 {
1635 #if defined(HAVE_DLCLOSE)
1636         return dlclose(handle);
1637 #else
1638         return 0;
1639 #endif
1640 }
1641
1642 const char *sys_dlerror(void)
1643 {
1644 #if defined(HAVE_DLERROR)
1645         return dlerror();
1646 #else
1647         return NULL;
1648 #endif
1649 }
1650
1651 int sys_dup2(int oldfd, int newfd) 
1652 {
1653 #if defined(HAVE_DUP2)
1654         return dup2(oldfd, newfd);
1655 #else
1656         errno = ENOSYS;
1657         return -1;
1658 #endif
1659 }
1660
1661 /**************************************************************************
1662  Wrapper for Admin Logs.
1663 ****************************************************************************/
1664
1665  void sys_adminlog(int priority, const char *format_str, ...) 
1666 {
1667         va_list ap;
1668         int ret;
1669         char *msgbuf = NULL;
1670
1671         va_start( ap, format_str );
1672         ret = vasprintf( &msgbuf, format_str, ap );
1673         va_end( ap );
1674
1675         if (ret == -1)
1676                 return;
1677
1678 #if defined(HAVE_SYSLOG)
1679         syslog( priority, "%s", msgbuf );
1680 #else
1681         DEBUG(0,("%s", msgbuf ));
1682 #endif
1683         SAFE_FREE(msgbuf);
1684 }
1685
1686 /**************************************************************************
1687  Wrappers for extented attribute calls. Based on the Linux package with
1688  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1689 ****************************************************************************/
1690
1691 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1692 {
1693 #if defined(HAVE_GETXATTR)
1694 #ifndef XATTR_ADD_OPT
1695         return getxattr(path, name, value, size);
1696 #else
1697         int options = 0;
1698         return getxattr(path, name, value, size, 0, options);
1699 #endif
1700 #elif defined(HAVE_GETEA)
1701         return getea(path, name, value, size);
1702 #elif defined(HAVE_EXTATTR_GET_FILE)
1703         char *s;
1704         ssize_t retval;
1705         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1706                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1707         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1708         /*
1709          * The BSD implementation has a nasty habit of silently truncating
1710          * the returned value to the size of the buffer, so we have to check
1711          * that the buffer is large enough to fit the returned value.
1712          */
1713         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1714                 if(retval > size) {
1715                         errno = ERANGE;
1716                         return -1;
1717                 }
1718                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1719                         return retval;
1720         }
1721
1722         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1723         return -1;
1724 #elif defined(HAVE_ATTR_GET)
1725         int retval, flags = 0;
1726         int valuelength = (int)size;
1727         char *attrname = strchr(name,'.') + 1;
1728         
1729         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1730
1731         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1732
1733         return retval ? retval : valuelength;
1734 #else
1735         errno = ENOSYS;
1736         return -1;
1737 #endif
1738 }
1739
1740 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1741 {
1742 #if defined(HAVE_LGETXATTR)
1743         return lgetxattr(path, name, value, size);
1744 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1745         int options = XATTR_NOFOLLOW;
1746         return getxattr(path, name, value, size, 0, options);
1747 #elif defined(HAVE_LGETEA)
1748         return lgetea(path, name, value, size);
1749 #elif defined(HAVE_EXTATTR_GET_LINK)
1750         char *s;
1751         ssize_t retval;
1752         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1753                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1754         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1755
1756         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1757                 if(retval > size) {
1758                         errno = ERANGE;
1759                         return -1;
1760                 }
1761                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1762                         return retval;
1763         }
1764         
1765         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1766         return -1;
1767 #elif defined(HAVE_ATTR_GET)
1768         int retval, flags = ATTR_DONTFOLLOW;
1769         int valuelength = (int)size;
1770         char *attrname = strchr(name,'.') + 1;
1771         
1772         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1773
1774         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1775
1776         return retval ? retval : valuelength;
1777 #else
1778         errno = ENOSYS;
1779         return -1;
1780 #endif
1781 }
1782
1783 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1784 {
1785 #if defined(HAVE_FGETXATTR)
1786 #ifndef XATTR_ADD_OPT
1787         return fgetxattr(filedes, name, value, size);
1788 #else
1789         int options = 0;
1790         return fgetxattr(filedes, name, value, size, 0, options);
1791 #endif
1792 #elif defined(HAVE_FGETEA)
1793         return fgetea(filedes, name, value, size);
1794 #elif defined(HAVE_EXTATTR_GET_FD)
1795         char *s;
1796         ssize_t retval;
1797         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1798                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1799         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1800
1801         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1802                 if(retval > size) {
1803                         errno = ERANGE;
1804                         return -1;
1805                 }
1806                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1807                         return retval;
1808         }
1809         
1810         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1811         return -1;
1812 #elif defined(HAVE_ATTR_GETF)
1813         int retval, flags = 0;
1814         int valuelength = (int)size;
1815         char *attrname = strchr(name,'.') + 1;
1816         
1817         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1818
1819         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1820
1821         return retval ? retval : valuelength;
1822 #else
1823         errno = ENOSYS;
1824         return -1;
1825 #endif
1826 }
1827
1828 #if defined(HAVE_EXTATTR_LIST_FILE)
1829
1830 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1831
1832 static struct {
1833         int space;
1834         const char *name;
1835         size_t len;
1836
1837 extattr[] = {
1838         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1839         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1840 };
1841
1842 typedef union {
1843         const char *path;
1844         int filedes;
1845 } extattr_arg;
1846
1847 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1848 {
1849         ssize_t list_size, total_size = 0;
1850         int i, t, len;
1851         char *buf;
1852         /* Iterate through extattr(2) namespaces */
1853         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1854                 switch(type) {
1855 #if defined(HAVE_EXTATTR_LIST_FILE)
1856                         case 0:
1857                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1858                                 break;
1859 #endif
1860 #if defined(HAVE_EXTATTR_LIST_LINK)
1861                         case 1:
1862                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1863                                 break;
1864 #endif
1865 #if defined(HAVE_EXTATTR_LIST_FD)
1866                         case 2:
1867                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1868                                 break;
1869 #endif
1870                         default:
1871                                 errno = ENOSYS;
1872                                 return -1;
1873                 }
1874                 /* Some error happend. Errno should be set by the previous call */
1875                 if(list_size < 0)
1876                         return -1;
1877                 /* No attributes */
1878                 if(list_size == 0)
1879                         continue;
1880                 /* XXX: Call with an empty buffer may be used to calculate
1881                    necessary buffer size. Unfortunately, we can't say, how
1882                    many attributes were returned, so here is the potential
1883                    problem with the emulation.
1884                 */
1885                 if(list == NULL) {
1886                         /* Take the worse case of one char attribute names - 
1887                            two bytes per name plus one more for sanity.
1888                         */
1889                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1890                         continue;
1891                 }
1892                 /* Count necessary offset to fit namespace prefixes */
1893                 len = 0;
1894                 for(i = 0; i < list_size; i += list[i] + 1)
1895                         len += extattr[t].len;
1896
1897                 total_size += list_size + len;
1898                 /* Buffer is too small to fit the results */
1899                 if(total_size > size) {
1900                         errno = ERANGE;
1901                         return -1;
1902                 }
1903                 /* Shift results back, so we can prepend prefixes */
1904                 buf = memmove(list + len, list, list_size);
1905
1906                 for(i = 0; i < list_size; i += len + 1) {
1907                         len = buf[i];
1908                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1909                         list += extattr[t].len;
1910                         strncpy(list, buf + i + 1, len);
1911                         list[len] = '\0';
1912                         list += len + 1;
1913                 }
1914                 size -= total_size;
1915         }
1916         return total_size;
1917 }
1918
1919 #endif
1920
1921 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1922 static char attr_buffer[ATTR_MAX_VALUELEN];
1923
1924 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1925 {
1926         int retval = 0, index;
1927         attrlist_cursor_t *cursor = 0;
1928         int total_size = 0;
1929         attrlist_t * al = (attrlist_t *)attr_buffer;
1930         attrlist_ent_t *ae;
1931         size_t ent_size, left = size;
1932         char *bp = list;
1933
1934         while (True) {
1935             if (filedes)
1936                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1937             else
1938                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1939             if (retval) break;
1940             for (index = 0; index < al->al_count; index++) {
1941                 ae = ATTR_ENTRY(attr_buffer, index);
1942                 ent_size = strlen(ae->a_name) + sizeof("user.");
1943                 if (left >= ent_size) {
1944                     strncpy(bp, "user.", sizeof("user."));
1945                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1946                     bp += ent_size;
1947                     left -= ent_size;
1948                 } else if (size) {
1949                     errno = ERANGE;
1950                     retval = -1;
1951                     break;
1952                 }
1953                 total_size += ent_size;
1954             }
1955             if (al->al_more == 0) break;
1956         }
1957         if (retval == 0) {
1958             flags |= ATTR_ROOT;
1959             cursor = 0;
1960             while (True) {
1961                 if (filedes)
1962                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1963                 else
1964                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1965                 if (retval) break;
1966                 for (index = 0; index < al->al_count; index++) {
1967                     ae = ATTR_ENTRY(attr_buffer, index);
1968                     ent_size = strlen(ae->a_name) + sizeof("system.");
1969                     if (left >= ent_size) {
1970                         strncpy(bp, "system.", sizeof("system."));
1971                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1972                         bp += ent_size;
1973                         left -= ent_size;
1974                     } else if (size) {
1975                         errno = ERANGE;
1976                         retval = -1;
1977                         break;
1978                     }
1979                     total_size += ent_size;
1980                 }
1981                 if (al->al_more == 0) break;
1982             }
1983         }
1984         return (ssize_t)(retval ? retval : total_size);
1985 }
1986
1987 #endif
1988
1989 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1990 {
1991 #if defined(HAVE_LISTXATTR)
1992 #ifndef XATTR_ADD_OPT
1993         return listxattr(path, list, size);
1994 #else
1995         int options = 0;
1996         return listxattr(path, list, size, options);
1997 #endif
1998 #elif defined(HAVE_LISTEA)
1999         return listea(path, list, size);
2000 #elif defined(HAVE_EXTATTR_LIST_FILE)
2001         extattr_arg arg;
2002         arg.path = path;
2003         return bsd_attr_list(0, arg, list, size);
2004 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2005         return irix_attr_list(path, 0, list, size, 0);
2006 #else
2007         errno = ENOSYS;
2008         return -1;
2009 #endif
2010 }
2011
2012 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
2013 {
2014 #if defined(HAVE_LLISTXATTR)
2015         return llistxattr(path, list, size);
2016 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
2017         int options = XATTR_NOFOLLOW;
2018         return listxattr(path, list, size, options);
2019 #elif defined(HAVE_LLISTEA)
2020         return llistea(path, list, size);
2021 #elif defined(HAVE_EXTATTR_LIST_LINK)
2022         extattr_arg arg;
2023         arg.path = path;
2024         return bsd_attr_list(1, arg, list, size);
2025 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2026         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
2027 #else
2028         errno = ENOSYS;
2029         return -1;
2030 #endif
2031 }
2032
2033 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
2034 {
2035 #if defined(HAVE_FLISTXATTR)
2036 #ifndef XATTR_ADD_OPT
2037         return flistxattr(filedes, list, size);
2038 #else
2039         int options = 0;
2040         return flistxattr(filedes, list, size, options);
2041 #endif
2042 #elif defined(HAVE_FLISTEA)
2043         return flistea(filedes, list, size);
2044 #elif defined(HAVE_EXTATTR_LIST_FD)
2045         extattr_arg arg;
2046         arg.filedes = filedes;
2047         return bsd_attr_list(2, arg, list, size);
2048 #elif defined(HAVE_ATTR_LISTF)
2049         return irix_attr_list(NULL, filedes, list, size, 0);
2050 #else
2051         errno = ENOSYS;
2052         return -1;
2053 #endif
2054 }
2055
2056 int sys_removexattr (const char *path, const char *name)
2057 {
2058 #if defined(HAVE_REMOVEXATTR)
2059 #ifndef XATTR_ADD_OPT
2060         return removexattr(path, name);
2061 #else
2062         int options = 0;
2063         return removexattr(path, name, options);
2064 #endif
2065 #elif defined(HAVE_REMOVEEA)
2066         return removeea(path, name);
2067 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2068         char *s;
2069         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2070                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2071         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2072
2073         return extattr_delete_file(path, attrnamespace, attrname);
2074 #elif defined(HAVE_ATTR_REMOVE)
2075         int flags = 0;
2076         char *attrname = strchr(name,'.') + 1;
2077         
2078         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2079
2080         return attr_remove(path, attrname, flags);
2081 #else
2082         errno = ENOSYS;
2083         return -1;
2084 #endif
2085 }
2086
2087 int sys_lremovexattr (const char *path, const char *name)
2088 {
2089 #if defined(HAVE_LREMOVEXATTR)
2090         return lremovexattr(path, name);
2091 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2092         int options = XATTR_NOFOLLOW;
2093         return removexattr(path, name, options);
2094 #elif defined(HAVE_LREMOVEEA)
2095         return lremoveea(path, name);
2096 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2097         char *s;
2098         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2099                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2100         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2101
2102         return extattr_delete_link(path, attrnamespace, attrname);
2103 #elif defined(HAVE_ATTR_REMOVE)
2104         int flags = ATTR_DONTFOLLOW;
2105         char *attrname = strchr(name,'.') + 1;
2106         
2107         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2108
2109         return attr_remove(path, attrname, flags);
2110 #else
2111         errno = ENOSYS;
2112         return -1;
2113 #endif
2114 }
2115
2116 int sys_fremovexattr (int filedes, const char *name)
2117 {
2118 #if defined(HAVE_FREMOVEXATTR)
2119 #ifndef XATTR_ADD_OPT
2120         return fremovexattr(filedes, name);
2121 #else
2122         int options = 0;
2123         return fremovexattr(filedes, name, options);
2124 #endif
2125 #elif defined(HAVE_FREMOVEEA)
2126         return fremoveea(filedes, name);
2127 #elif defined(HAVE_EXTATTR_DELETE_FD)
2128         char *s;
2129         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2130                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2131         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2132
2133         return extattr_delete_fd(filedes, attrnamespace, attrname);
2134 #elif defined(HAVE_ATTR_REMOVEF)
2135         int flags = 0;
2136         char *attrname = strchr(name,'.') + 1;
2137         
2138         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2139
2140         return attr_removef(filedes, attrname, flags);
2141 #else
2142         errno = ENOSYS;
2143         return -1;
2144 #endif
2145 }
2146
2147 #if !defined(HAVE_SETXATTR)
2148 #define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
2149 #define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
2150 #endif
2151
2152 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2153 {
2154 #if defined(HAVE_SETXATTR)
2155 #ifndef XATTR_ADD_OPT
2156         return setxattr(path, name, value, size, flags);
2157 #else
2158         int options = 0;
2159         return setxattr(path, name, value, size, 0, options);
2160 #endif
2161 #elif defined(HAVE_SETEA)
2162         return setea(path, name, value, size, flags);
2163 #elif defined(HAVE_EXTATTR_SET_FILE)
2164         char *s;
2165         int retval = 0;
2166         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2167                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2168         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2169         if (flags) {
2170                 /* Check attribute existence */
2171                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2172                 if (retval < 0) {
2173                         /* REPLACE attribute, that doesn't exist */
2174                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2175                                 errno = ENOATTR;
2176                                 return -1;
2177                         }
2178                         /* Ignore other errors */
2179                 }
2180                 else {
2181                         /* CREATE attribute, that already exists */
2182                         if (flags & XATTR_CREATE) {
2183                                 errno = EEXIST;
2184                                 return -1;
2185                         }
2186                 }
2187         }
2188         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2189         return (retval < 0) ? -1 : 0;
2190 #elif defined(HAVE_ATTR_SET)
2191         int myflags = 0;
2192         char *attrname = strchr(name,'.') + 1;
2193         
2194         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2195         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2196         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2197
2198         return attr_set(path, attrname, (const char *)value, size, myflags);
2199 #else
2200         errno = ENOSYS;
2201         return -1;
2202 #endif
2203 }
2204
2205 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2206 {
2207 #if defined(HAVE_LSETXATTR)
2208         return lsetxattr(path, name, value, size, flags);
2209 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2210         int options = XATTR_NOFOLLOW;
2211         return setxattr(path, name, value, size, 0, options);
2212 #elif defined(LSETEA)
2213         return lsetea(path, name, value, size, flags);
2214 #elif defined(HAVE_EXTATTR_SET_LINK)
2215         char *s;
2216         int retval = 0;
2217         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2218                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2219         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2220         if (flags) {
2221                 /* Check attribute existence */
2222                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2223                 if (retval < 0) {
2224                         /* REPLACE attribute, that doesn't exist */
2225                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2226                                 errno = ENOATTR;
2227                                 return -1;
2228                         }
2229                         /* Ignore other errors */
2230                 }
2231                 else {
2232                         /* CREATE attribute, that already exists */
2233                         if (flags & XATTR_CREATE) {
2234                                 errno = EEXIST;
2235                                 return -1;
2236                         }
2237                 }
2238         }
2239
2240         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2241         return (retval < 0) ? -1 : 0;
2242 #elif defined(HAVE_ATTR_SET)
2243         int myflags = ATTR_DONTFOLLOW;
2244         char *attrname = strchr(name,'.') + 1;
2245         
2246         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2247         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2248         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2249
2250         return attr_set(path, attrname, (const char *)value, size, myflags);
2251 #else
2252         errno = ENOSYS;
2253         return -1;
2254 #endif
2255 }
2256
2257 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2258 {
2259 #if defined(HAVE_FSETXATTR)
2260 #ifndef XATTR_ADD_OPT
2261         return fsetxattr(filedes, name, value, size, flags);
2262 #else
2263         int options = 0;
2264         return fsetxattr(filedes, name, value, size, 0, options);
2265 #endif
2266 #elif defined(HAVE_FSETEA)
2267         return fsetea(filedes, name, value, size, flags);
2268 #elif defined(HAVE_EXTATTR_SET_FD)
2269         char *s;
2270         int retval = 0;
2271         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2272                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2273         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2274         if (flags) {
2275                 /* Check attribute existence */
2276                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2277                 if (retval < 0) {
2278                         /* REPLACE attribute, that doesn't exist */
2279                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2280                                 errno = ENOATTR;
2281                                 return -1;
2282                         }
2283                         /* Ignore other errors */
2284                 }
2285                 else {
2286                         /* CREATE attribute, that already exists */
2287                         if (flags & XATTR_CREATE) {
2288                                 errno = EEXIST;
2289                                 return -1;
2290                         }
2291                 }
2292         }
2293         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2294         return (retval < 0) ? -1 : 0;
2295 #elif defined(HAVE_ATTR_SETF)
2296         int myflags = 0;
2297         char *attrname = strchr(name,'.') + 1;
2298         
2299         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2300         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2301         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2302
2303         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2304 #else
2305         errno = ENOSYS;
2306         return -1;
2307 #endif
2308 }
2309
2310 /****************************************************************************
2311  Return the major devicenumber for UNIX extensions.
2312 ****************************************************************************/
2313                                                                                                                 
2314 uint32 unix_dev_major(SMB_DEV_T dev)
2315 {
2316 #if defined(HAVE_DEVICE_MAJOR_FN)
2317         return (uint32)major(dev);
2318 #else
2319         return (uint32)(dev >> 8);
2320 #endif
2321 }
2322                                                                                                                 
2323 /****************************************************************************
2324  Return the minor devicenumber for UNIX extensions.
2325 ****************************************************************************/
2326                                                                                                                 
2327 uint32 unix_dev_minor(SMB_DEV_T dev)
2328 {
2329 #if defined(HAVE_DEVICE_MINOR_FN)
2330         return (uint32)minor(dev);
2331 #else
2332         return (uint32)(dev & 0xff);
2333 #endif
2334 }
2335
2336 #if defined(WITH_AIO)
2337
2338 /*******************************************************************
2339  An aio_read wrapper that will deal with 64-bit sizes.
2340 ********************************************************************/
2341                                                                                                                                            
2342 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2343 {
2344 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2345         return aio_read64(aiocb);
2346 #elif defined(HAVE_AIO_READ)
2347         return aio_read(aiocb);
2348 #else
2349         errno = ENOSYS;
2350         return -1;
2351 #endif
2352 }
2353
2354 /*******************************************************************
2355  An aio_write wrapper that will deal with 64-bit sizes.
2356 ********************************************************************/
2357                                                                                                                                            
2358 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2359 {
2360 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2361         return aio_write64(aiocb);
2362 #elif defined(HAVE_AIO_WRITE)
2363         return aio_write(aiocb);
2364 #else
2365         errno = ENOSYS;
2366         return -1;
2367 #endif
2368 }
2369
2370 /*******************************************************************
2371  An aio_return wrapper that will deal with 64-bit sizes.
2372 ********************************************************************/
2373                                                                                                                                            
2374 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2375 {
2376 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2377         return aio_return64(aiocb);
2378 #elif defined(HAVE_AIO_RETURN)
2379         return aio_return(aiocb);
2380 #else
2381         errno = ENOSYS;
2382         return -1;
2383 #endif
2384 }
2385
2386 /*******************************************************************
2387  An aio_cancel wrapper that will deal with 64-bit sizes.
2388 ********************************************************************/
2389
2390 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2391 {
2392 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2393         return aio_cancel64(fd, aiocb);
2394 #elif defined(HAVE_AIO_CANCEL)
2395         return aio_cancel(fd, aiocb);
2396 #else
2397         errno = ENOSYS;
2398         return -1;
2399 #endif
2400 }
2401
2402 /*******************************************************************
2403  An aio_error wrapper that will deal with 64-bit sizes.
2404 ********************************************************************/
2405
2406 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2407 {
2408 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2409         return aio_error64(aiocb);
2410 #elif defined(HAVE_AIO_ERROR)
2411         return aio_error(aiocb);
2412 #else
2413         errno = ENOSYS;
2414         return -1;
2415 #endif
2416 }
2417
2418 /*******************************************************************
2419  An aio_fsync wrapper that will deal with 64-bit sizes.
2420 ********************************************************************/
2421
2422 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2423 {
2424 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2425         return aio_fsync64(op, aiocb);
2426 #elif defined(HAVE_AIO_FSYNC)
2427         return aio_fsync(op, aiocb);
2428 #else
2429         errno = ENOSYS;
2430         return -1;
2431 #endif
2432 }
2433
2434 /*******************************************************************
2435  An aio_fsync wrapper that will deal with 64-bit sizes.
2436 ********************************************************************/
2437
2438 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2439 {
2440 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2441         return aio_suspend64(cblist, n, timeout);
2442 #elif defined(HAVE_AIO_FSYNC)
2443         return aio_suspend(cblist, n, timeout);
2444 #else
2445         errno = ENOSYS;
2446         return -1;
2447 #endif
2448 }
2449 #else /* !WITH_AIO */
2450
2451 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2452 {
2453         errno = ENOSYS;
2454         return -1;
2455 }
2456
2457 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2458 {
2459         errno = ENOSYS;
2460         return -1;
2461 }
2462
2463 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2464 {
2465         errno = ENOSYS;
2466         return -1;
2467 }
2468
2469 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2470 {
2471         errno = ENOSYS;
2472         return -1;
2473 }
2474
2475 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2476 {
2477         errno = ENOSYS;
2478         return -1;
2479 }
2480
2481 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2482 {
2483         errno = ENOSYS;
2484         return -1;
2485 }
2486
2487 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2488 {
2489         errno = ENOSYS;
2490         return -1;
2491 }
2492 #endif /* WITH_AIO */
2493
2494 int sys_getpeereid( int s, uid_t *uid)
2495 {
2496 #if defined(HAVE_PEERCRED)
2497         struct ucred cred;
2498         socklen_t cred_len = sizeof(struct ucred);
2499         int ret;
2500
2501         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2502         if (ret != 0) {
2503                 return -1;
2504         }
2505
2506         if (cred_len != sizeof(struct ucred)) {
2507                 errno = EINVAL;
2508                 return -1;
2509         }
2510
2511         *uid = cred.uid;
2512         return 0;
2513 #else
2514         errno = ENOSYS;
2515         return -1;
2516 #endif
2517 }