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