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