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