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