1. lib/system.c (xattr code for Solaris) could not be
[sfrench/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    Copyright (C) Bjoern Jacke    2006-2007
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
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, PATH_MAX);
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 #if defined(HAVE_POSIX_CAPABILITIES)
682
683 #ifdef HAVE_SYS_CAPABILITY_H
684
685 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
686 #define _I386_STATFS_H
687 #define _PPC_STATFS_H
688 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
689 #endif
690
691 #include <sys/capability.h>
692
693 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
694 #undef _I386_STATFS_H
695 #undef _PPC_STATFS_H
696 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
697 #endif
698
699 #endif /* HAVE_SYS_CAPABILITY_H */
700
701 /**************************************************************************
702  Try and abstract process capabilities (for systems that have them).
703 ****************************************************************************/
704
705 /* Set the POSIX capabilities needed for the given purpose into the effective
706  * capability set of the current process. Make sure they are always removed
707  * from the inheritable set, because there is no circumstance in which our
708  * children should inherit our elevated privileges.
709  */
710 static bool set_process_capability(enum smbd_capability capability,
711                                    bool enable)
712 {
713         cap_value_t cap_vals[2] = {0};
714         int num_cap_vals = 0;
715
716         cap_t cap;
717
718 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
719         /* On Linux, make sure that any capabilities we grab are sticky
720          * across UID changes. We expect that this would allow us to keep both
721          * the effective and permitted capability sets, but as of circa 2.6.16,
722          * only the permitted set is kept. It is a bug (which we work around)
723          * that the effective set is lost, but we still require the effective
724          * set to be kept.
725          */
726         if (!prctl(PR_GET_KEEPCAPS)) {
727                 prctl(PR_SET_KEEPCAPS, 1);
728         }
729 #endif
730
731         cap = cap_get_proc();
732         if (cap == NULL) {
733                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
734                         strerror(errno)));
735                 return False;
736         }
737
738         switch (capability) {
739                 case KERNEL_OPLOCK_CAPABILITY:
740 #ifdef CAP_NETWORK_MGT
741                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
742                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
743 #endif
744                         break;
745                 case DMAPI_ACCESS_CAPABILITY:
746 #ifdef CAP_DEVICE_MGT
747                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
748                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
749 #elif CAP_MKNOD
750                         /* Linux has CAP_MKNOD for DMAPI access. */
751                         cap_vals[num_cap_vals++] = CAP_MKNOD;
752 #endif
753                         break;
754         }
755
756         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
757
758         if (num_cap_vals == 0) {
759                 cap_free(cap);
760                 return True;
761         }
762
763         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
764                 enable ? CAP_SET : CAP_CLEAR);
765
766         /* We never want to pass capabilities down to our children, so make
767          * sure they are not inherited.
768          */
769         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
770
771         if (cap_set_proc(cap) == -1) {
772                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
773                         strerror(errno)));
774                 cap_free(cap);
775                 return False;
776         }
777
778         cap_free(cap);
779         return True;
780 }
781
782 #endif /* HAVE_POSIX_CAPABILITIES */
783
784 /****************************************************************************
785  Gain the oplock capability from the kernel if possible.
786 ****************************************************************************/
787
788 void set_effective_capability(enum smbd_capability capability)
789 {
790 #if defined(HAVE_POSIX_CAPABILITIES)
791         set_process_capability(capability, True);
792 #endif /* HAVE_POSIX_CAPABILITIES */
793 }
794
795 void drop_effective_capability(enum smbd_capability capability)
796 {
797 #if defined(HAVE_POSIX_CAPABILITIES)
798         set_process_capability(capability, False);
799 #endif /* HAVE_POSIX_CAPABILITIES */
800 }
801
802 /**************************************************************************
803  Wrapper for random().
804 ****************************************************************************/
805
806 long sys_random(void)
807 {
808 #if defined(HAVE_RANDOM)
809         return (long)random();
810 #elif defined(HAVE_RAND)
811         return (long)rand();
812 #else
813         DEBUG(0,("Error - no random function available !\n"));
814         exit(1);
815 #endif
816 }
817
818 /**************************************************************************
819  Wrapper for srandom().
820 ****************************************************************************/
821
822 void sys_srandom(unsigned int seed)
823 {
824 #if defined(HAVE_SRANDOM)
825         srandom(seed);
826 #elif defined(HAVE_SRAND)
827         srand(seed);
828 #else
829         DEBUG(0,("Error - no srandom function available !\n"));
830         exit(1);
831 #endif
832 }
833
834 /**************************************************************************
835  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
836 ****************************************************************************/
837
838 int groups_max(void)
839 {
840 #if defined(SYSCONF_SC_NGROUPS_MAX)
841         int ret = sysconf(_SC_NGROUPS_MAX);
842         return (ret == -1) ? NGROUPS_MAX : ret;
843 #else
844         return NGROUPS_MAX;
845 #endif
846 }
847
848 /**************************************************************************
849  Wrap setgroups and getgroups for systems that declare getgroups() as
850  returning an array of gid_t, but actuall return an array of int.
851 ****************************************************************************/
852
853 #if defined(HAVE_BROKEN_GETGROUPS)
854 static int sys_broken_getgroups(int setlen, gid_t *gidset)
855 {
856         GID_T gid;
857         GID_T *group_list;
858         int i, ngroups;
859
860         if(setlen == 0) {
861                 return getgroups(setlen, &gid);
862         }
863
864         /*
865          * Broken case. We need to allocate a
866          * GID_T array of size setlen.
867          */
868
869         if(setlen < 0) {
870                 errno = EINVAL; 
871                 return -1;
872         } 
873
874         if (setlen == 0)
875                 setlen = groups_max();
876
877         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
878                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
879                 return -1;
880         }
881
882         if((ngroups = getgroups(setlen, group_list)) < 0) {
883                 int saved_errno = errno;
884                 SAFE_FREE(group_list);
885                 errno = saved_errno;
886                 return -1;
887         }
888
889         for(i = 0; i < ngroups; i++)
890                 gidset[i] = (gid_t)group_list[i];
891
892         SAFE_FREE(group_list);
893         return ngroups;
894 }
895
896 static int sys_broken_setgroups(int setlen, gid_t *gidset)
897 {
898         GID_T *group_list;
899         int i ; 
900
901         if (setlen == 0)
902                 return 0 ;
903
904         if (setlen < 0 || setlen > groups_max()) {
905                 errno = EINVAL; 
906                 return -1;   
907         }
908
909         /*
910          * Broken case. We need to allocate a
911          * GID_T array of size setlen.
912          */
913
914         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
915                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
916                 return -1;    
917         }
918  
919         for(i = 0; i < setlen; i++) 
920                 group_list[i] = (GID_T) gidset[i]; 
921
922         if(setgroups(setlen, group_list) != 0) {
923                 int saved_errno = errno;
924                 SAFE_FREE(group_list);
925                 errno = saved_errno;
926                 return -1;
927         }
928  
929         SAFE_FREE(group_list);
930         return 0 ;
931 }
932
933 #endif /* HAVE_BROKEN_GETGROUPS */
934
935 /* This is a list of systems that require the first GID passed to setgroups(2)
936  * to be the effective GID. If your system is one of these, add it here.
937  */
938 #if defined (FREEBSD) || defined (DARWINOS)
939 #define USE_BSD_SETGROUPS
940 #endif
941
942 #if defined(USE_BSD_SETGROUPS)
943 /* Depending on the particular BSD implementation, the first GID that is
944  * passed to setgroups(2) will either be ignored or will set the credential's
945  * effective GID. In either case, the right thing to do is to guarantee that
946  * gidset[0] is the effective GID.
947  */
948 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
949 {
950         gid_t *new_gidset = NULL;
951         int max;
952         int ret;
953
954         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
955         max = groups_max();
956
957         /* No group list, just make sure we are setting the efective GID. */
958         if (setlen == 0) {
959                 return setgroups(1, &primary_gid);
960         }
961
962         /* If the primary gid is not the first array element, grow the array
963          * and insert it at the front.
964          */
965         if (gidset[0] != primary_gid) {
966                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
967                 if (new_gidset == NULL) {
968                         return -1;
969                 }
970
971                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
972                 new_gidset[0] = primary_gid;
973                 setlen++;
974         }
975
976         if (setlen > max) {
977                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
978                         setlen, max));
979                 setlen = max;
980         }
981
982 #if defined(HAVE_BROKEN_GETGROUPS)
983         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
984 #else
985         ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
986 #endif
987
988         if (new_gidset) {
989                 int errsav = errno;
990                 SAFE_FREE(new_gidset);
991                 errno = errsav;
992         }
993
994         return ret;
995 }
996
997 #endif /* USE_BSD_SETGROUPS */
998
999 /**************************************************************************
1000  Wrapper for getgroups. Deals with broken (int) case.
1001 ****************************************************************************/
1002
1003 int sys_getgroups(int setlen, gid_t *gidset)
1004 {
1005 #if defined(HAVE_BROKEN_GETGROUPS)
1006         return sys_broken_getgroups(setlen, gidset);
1007 #else
1008         return getgroups(setlen, gidset);
1009 #endif
1010 }
1011
1012 /**************************************************************************
1013  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1014 ****************************************************************************/
1015
1016 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1017 {
1018 #if !defined(HAVE_SETGROUPS)
1019         errno = ENOSYS;
1020         return -1;
1021 #endif /* HAVE_SETGROUPS */
1022
1023 #if defined(USE_BSD_SETGROUPS)
1024         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1025 #elif defined(HAVE_BROKEN_GETGROUPS)
1026         return sys_broken_setgroups(setlen, gidset);
1027 #else
1028         return setgroups(setlen, gidset);
1029 #endif
1030 }
1031
1032 /**************************************************************************
1033  Wrappers for setpwent(), getpwent() and endpwent()
1034 ****************************************************************************/
1035
1036 void sys_setpwent(void)
1037 {
1038         setpwent();
1039 }
1040
1041 struct passwd *sys_getpwent(void)
1042 {
1043         return getpwent();
1044 }
1045
1046 void sys_endpwent(void)
1047 {
1048         endpwent();
1049 }
1050
1051 /**************************************************************************
1052  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1053 ****************************************************************************/
1054
1055
1056 struct passwd *sys_getpwnam(const char *name)
1057 {
1058         return getpwnam(name);
1059 }
1060
1061 struct passwd *sys_getpwuid(uid_t uid)
1062 {
1063         return getpwuid(uid);
1064 }
1065
1066 struct group *sys_getgrnam(const char *name)
1067 {
1068         return getgrnam(name);
1069 }
1070
1071 struct group *sys_getgrgid(gid_t gid)
1072 {
1073         return getgrgid(gid);
1074 }
1075
1076 /**************************************************************************
1077  Extract a command into an arg list.
1078 ****************************************************************************/
1079
1080 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1081 {
1082         char *trunc_cmd;
1083         char *saveptr;
1084         char *ptr;
1085         int argcl;
1086         char **argl = NULL;
1087         int i;
1088
1089         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1090                 DEBUG(0, ("talloc failed\n"));
1091                 goto nomem;
1092         }
1093
1094         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1095                 TALLOC_FREE(trunc_cmd);
1096                 errno = EINVAL;
1097                 return NULL;
1098         }
1099
1100         /*
1101          * Count the args.
1102          */
1103
1104         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1105                 argcl++;
1106
1107         TALLOC_FREE(trunc_cmd);
1108
1109         if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1110                 goto nomem;
1111         }
1112
1113         /*
1114          * Now do the extraction.
1115          */
1116
1117         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1118                 goto nomem;
1119         }
1120
1121         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1122         i = 0;
1123
1124         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1125                 goto nomem;
1126         }
1127
1128         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1129
1130                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1131                         goto nomem;
1132                 }
1133         }
1134
1135         argl[i++] = NULL;
1136         return argl;
1137
1138  nomem:
1139         DEBUG(0, ("talloc failed\n"));
1140         TALLOC_FREE(trunc_cmd);
1141         TALLOC_FREE(argl);
1142         errno = ENOMEM;
1143         return NULL;
1144 }
1145
1146 /**************************************************************************
1147  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1148  a sys_getpid() that only does a system call *once*.
1149 ****************************************************************************/
1150
1151 static pid_t mypid = (pid_t)-1;
1152
1153 pid_t sys_fork(void)
1154 {
1155         pid_t forkret = fork();
1156
1157         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1158                 mypid = (pid_t) -1;
1159
1160         return forkret;
1161 }
1162
1163 /**************************************************************************
1164  Wrapper for getpid. Ensures we only do a system call *once*.
1165 ****************************************************************************/
1166
1167 pid_t sys_getpid(void)
1168 {
1169         if (mypid == (pid_t)-1)
1170                 mypid = getpid();
1171
1172         return mypid;
1173 }
1174
1175 /**************************************************************************
1176  Wrapper for popen. Safer as it doesn't search a path.
1177  Modified from the glibc sources.
1178  modified by tridge to return a file descriptor. We must kick our FILE* habit
1179 ****************************************************************************/
1180
1181 typedef struct _popen_list
1182 {
1183         int fd;
1184         pid_t child_pid;
1185         struct _popen_list *next;
1186 } popen_list;
1187
1188 static popen_list *popen_chain;
1189
1190 int sys_popen(const char *command)
1191 {
1192         int parent_end, child_end;
1193         int pipe_fds[2];
1194         popen_list *entry = NULL;
1195         char **argl = NULL;
1196
1197         if (pipe(pipe_fds) < 0)
1198                 return -1;
1199
1200         parent_end = pipe_fds[0];
1201         child_end = pipe_fds[1];
1202
1203         if (!*command) {
1204                 errno = EINVAL;
1205                 goto err_exit;
1206         }
1207
1208         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1209                 goto err_exit;
1210
1211         ZERO_STRUCTP(entry);
1212
1213         /*
1214          * Extract the command and args into a NULL terminated array.
1215          */
1216
1217         if(!(argl = extract_args(NULL, command)))
1218                 goto err_exit;
1219
1220         entry->child_pid = sys_fork();
1221
1222         if (entry->child_pid == -1) {
1223                 goto err_exit;
1224         }
1225
1226         if (entry->child_pid == 0) {
1227
1228                 /*
1229                  * Child !
1230                  */
1231
1232                 int child_std_end = STDOUT_FILENO;
1233                 popen_list *p;
1234
1235                 close(parent_end);
1236                 if (child_end != child_std_end) {
1237                         dup2 (child_end, child_std_end);
1238                         close (child_end);
1239                 }
1240
1241                 /*
1242                  * POSIX.2:  "popen() shall ensure that any streams from previous
1243                  * popen() calls that remain open in the parent process are closed
1244                  * in the new child process."
1245                  */
1246
1247                 for (p = popen_chain; p; p = p->next)
1248                         close(p->fd);
1249
1250                 execv(argl[0], argl);
1251                 _exit (127);
1252         }
1253
1254         /*
1255          * Parent.
1256          */
1257
1258         close (child_end);
1259         TALLOC_FREE(argl);
1260
1261         /* Link into popen_chain. */
1262         entry->next = popen_chain;
1263         popen_chain = entry;
1264         entry->fd = parent_end;
1265
1266         return entry->fd;
1267
1268 err_exit:
1269
1270         SAFE_FREE(entry);
1271         SAFE_FREE(argl);
1272         close(pipe_fds[0]);
1273         close(pipe_fds[1]);
1274         return -1;
1275 }
1276
1277 /**************************************************************************
1278  Wrapper for pclose. Modified from the glibc sources.
1279 ****************************************************************************/
1280
1281 int sys_pclose(int fd)
1282 {
1283         int wstatus;
1284         popen_list **ptr = &popen_chain;
1285         popen_list *entry = NULL;
1286         pid_t wait_pid;
1287         int status = -1;
1288
1289         /* Unlink from popen_chain. */
1290         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1291                 if ((*ptr)->fd == fd) {
1292                         entry = *ptr;
1293                         *ptr = (*ptr)->next;
1294                         status = 0;
1295                         break;
1296                 }
1297         }
1298
1299         if (status < 0 || close(entry->fd) < 0)
1300                 return -1;
1301
1302         /*
1303          * As Samba is catching and eating child process
1304          * exits we don't really care about the child exit
1305          * code, a -1 with errno = ECHILD will do fine for us.
1306          */
1307
1308         do {
1309                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1310         } while (wait_pid == -1 && errno == EINTR);
1311
1312         SAFE_FREE(entry);
1313
1314         if (wait_pid == -1)
1315                 return -1;
1316         return wstatus;
1317 }
1318
1319 /**************************************************************************
1320  Wrappers for dlopen, dlsym, dlclose.
1321 ****************************************************************************/
1322
1323 void *sys_dlopen(const char *name, int flags)
1324 {
1325 #if defined(HAVE_DLOPEN)
1326         return dlopen(name, flags);
1327 #else
1328         return NULL;
1329 #endif
1330 }
1331
1332 void *sys_dlsym(void *handle, const char *symbol)
1333 {
1334 #if defined(HAVE_DLSYM)
1335     return dlsym(handle, symbol);
1336 #else
1337     return NULL;
1338 #endif
1339 }
1340
1341 int sys_dlclose (void *handle)
1342 {
1343 #if defined(HAVE_DLCLOSE)
1344         return dlclose(handle);
1345 #else
1346         return 0;
1347 #endif
1348 }
1349
1350 const char *sys_dlerror(void)
1351 {
1352 #if defined(HAVE_DLERROR)
1353         return dlerror();
1354 #else
1355         return NULL;
1356 #endif
1357 }
1358
1359 int sys_dup2(int oldfd, int newfd) 
1360 {
1361 #if defined(HAVE_DUP2)
1362         return dup2(oldfd, newfd);
1363 #else
1364         errno = ENOSYS;
1365         return -1;
1366 #endif
1367 }
1368
1369 /**************************************************************************
1370  Wrapper for Admin Logs.
1371 ****************************************************************************/
1372
1373  void sys_adminlog(int priority, const char *format_str, ...) 
1374 {
1375         va_list ap;
1376         int ret;
1377         char *msgbuf = NULL;
1378
1379         va_start( ap, format_str );
1380         ret = vasprintf( &msgbuf, format_str, ap );
1381         va_end( ap );
1382
1383         if (ret == -1)
1384                 return;
1385
1386 #if defined(HAVE_SYSLOG)
1387         syslog( priority, "%s", msgbuf );
1388 #else
1389         DEBUG(0,("%s", msgbuf ));
1390 #endif
1391         SAFE_FREE(msgbuf);
1392 }
1393
1394 /******** Solaris EA helper function prototypes ********/
1395 #ifdef HAVE_ATTROPEN
1396 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1397 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1398 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1399 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1400 static int solaris_unlinkat(int attrdirfd, const char *name);
1401 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1402 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1403 #endif
1404
1405 /**************************************************************************
1406  Wrappers for extented attribute calls. Based on the Linux package with
1407  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1408 ****************************************************************************/
1409
1410 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1411 {
1412 #if defined(HAVE_GETXATTR)
1413 #ifndef XATTR_ADD_OPT
1414         return getxattr(path, name, value, size);
1415 #else
1416         int options = 0;
1417         return getxattr(path, name, value, size, 0, options);
1418 #endif
1419 #elif defined(HAVE_GETEA)
1420         return getea(path, name, value, size);
1421 #elif defined(HAVE_EXTATTR_GET_FILE)
1422         char *s;
1423         ssize_t retval;
1424         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1425                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1426         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1427         /*
1428          * The BSD implementation has a nasty habit of silently truncating
1429          * the returned value to the size of the buffer, so we have to check
1430          * that the buffer is large enough to fit the returned value.
1431          */
1432         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1433                 if(retval > size) {
1434                         errno = ERANGE;
1435                         return -1;
1436                 }
1437                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1438                         return retval;
1439         }
1440
1441         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1442         return -1;
1443 #elif defined(HAVE_ATTR_GET)
1444         int retval, flags = 0;
1445         int valuelength = (int)size;
1446         char *attrname = strchr(name,'.') + 1;
1447         
1448         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1449
1450         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1451
1452         return retval ? retval : valuelength;
1453 #elif defined(HAVE_ATTROPEN)
1454         ssize_t ret = -1;
1455         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1456         if (attrfd >= 0) {
1457                 ret = solaris_read_xattr(attrfd, value, size);
1458                 close(attrfd);
1459         }
1460         return ret;
1461 #else
1462         errno = ENOSYS;
1463         return -1;
1464 #endif
1465 }
1466
1467 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1468 {
1469 #if defined(HAVE_LGETXATTR)
1470         return lgetxattr(path, name, value, size);
1471 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1472         int options = XATTR_NOFOLLOW;
1473         return getxattr(path, name, value, size, 0, options);
1474 #elif defined(HAVE_LGETEA)
1475         return lgetea(path, name, value, size);
1476 #elif defined(HAVE_EXTATTR_GET_LINK)
1477         char *s;
1478         ssize_t retval;
1479         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1480                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1481         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1482
1483         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1484                 if(retval > size) {
1485                         errno = ERANGE;
1486                         return -1;
1487                 }
1488                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1489                         return retval;
1490         }
1491         
1492         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1493         return -1;
1494 #elif defined(HAVE_ATTR_GET)
1495         int retval, flags = ATTR_DONTFOLLOW;
1496         int valuelength = (int)size;
1497         char *attrname = strchr(name,'.') + 1;
1498         
1499         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1500
1501         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1502
1503         return retval ? retval : valuelength;
1504 #elif defined(HAVE_ATTROPEN)
1505         ssize_t ret = -1;
1506         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1507         if (attrfd >= 0) {
1508                 ret = solaris_read_xattr(attrfd, value, size);
1509                 close(attrfd);
1510         }
1511         return ret;
1512 #else
1513         errno = ENOSYS;
1514         return -1;
1515 #endif
1516 }
1517
1518 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1519 {
1520 #if defined(HAVE_FGETXATTR)
1521 #ifndef XATTR_ADD_OPT
1522         return fgetxattr(filedes, name, value, size);
1523 #else
1524         int options = 0;
1525         return fgetxattr(filedes, name, value, size, 0, options);
1526 #endif
1527 #elif defined(HAVE_FGETEA)
1528         return fgetea(filedes, name, value, size);
1529 #elif defined(HAVE_EXTATTR_GET_FD)
1530         char *s;
1531         ssize_t retval;
1532         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1533                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1534         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1535
1536         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1537                 if(retval > size) {
1538                         errno = ERANGE;
1539                         return -1;
1540                 }
1541                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1542                         return retval;
1543         }
1544         
1545         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1546         return -1;
1547 #elif defined(HAVE_ATTR_GETF)
1548         int retval, flags = 0;
1549         int valuelength = (int)size;
1550         char *attrname = strchr(name,'.') + 1;
1551         
1552         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1553
1554         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1555
1556         return retval ? retval : valuelength;
1557 #elif defined(HAVE_ATTROPEN)
1558         ssize_t ret = -1;
1559         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1560         if (attrfd >= 0) {
1561                 ret = solaris_read_xattr(attrfd, value, size);
1562                 close(attrfd);
1563         }
1564         return ret;
1565 #else
1566         errno = ENOSYS;
1567         return -1;
1568 #endif
1569 }
1570
1571 #if defined(HAVE_EXTATTR_LIST_FILE)
1572
1573 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1574
1575 static struct {
1576         int space;
1577         const char *name;
1578         size_t len;
1579
1580 extattr[] = {
1581         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1582         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1583 };
1584
1585 typedef union {
1586         const char *path;
1587         int filedes;
1588 } extattr_arg;
1589
1590 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1591 {
1592         ssize_t list_size, total_size = 0;
1593         int i, t, len;
1594         char *buf;
1595         /* Iterate through extattr(2) namespaces */
1596         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1597                 switch(type) {
1598 #if defined(HAVE_EXTATTR_LIST_FILE)
1599                         case 0:
1600                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1601                                 break;
1602 #endif
1603 #if defined(HAVE_EXTATTR_LIST_LINK)
1604                         case 1:
1605                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1606                                 break;
1607 #endif
1608 #if defined(HAVE_EXTATTR_LIST_FD)
1609                         case 2:
1610                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1611                                 break;
1612 #endif
1613                         default:
1614                                 errno = ENOSYS;
1615                                 return -1;
1616                 }
1617                 /* Some error happend. Errno should be set by the previous call */
1618                 if(list_size < 0)
1619                         return -1;
1620                 /* No attributes */
1621                 if(list_size == 0)
1622                         continue;
1623                 /* XXX: Call with an empty buffer may be used to calculate
1624                    necessary buffer size. Unfortunately, we can't say, how
1625                    many attributes were returned, so here is the potential
1626                    problem with the emulation.
1627                 */
1628                 if(list == NULL) {
1629                         /* Take the worse case of one char attribute names - 
1630                            two bytes per name plus one more for sanity.
1631                         */
1632                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1633                         continue;
1634                 }
1635                 /* Count necessary offset to fit namespace prefixes */
1636                 len = 0;
1637                 for(i = 0; i < list_size; i += list[i] + 1)
1638                         len += extattr[t].len;
1639
1640                 total_size += list_size + len;
1641                 /* Buffer is too small to fit the results */
1642                 if(total_size > size) {
1643                         errno = ERANGE;
1644                         return -1;
1645                 }
1646                 /* Shift results back, so we can prepend prefixes */
1647                 buf = memmove(list + len, list, list_size);
1648
1649                 for(i = 0; i < list_size; i += len + 1) {
1650                         len = buf[i];
1651                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1652                         list += extattr[t].len;
1653                         strncpy(list, buf + i + 1, len);
1654                         list[len] = '\0';
1655                         list += len + 1;
1656                 }
1657                 size -= total_size;
1658         }
1659         return total_size;
1660 }
1661
1662 #endif
1663
1664 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1665 static char attr_buffer[ATTR_MAX_VALUELEN];
1666
1667 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1668 {
1669         int retval = 0, index;
1670         attrlist_cursor_t *cursor = 0;
1671         int total_size = 0;
1672         attrlist_t * al = (attrlist_t *)attr_buffer;
1673         attrlist_ent_t *ae;
1674         size_t ent_size, left = size;
1675         char *bp = list;
1676
1677         while (True) {
1678             if (filedes)
1679                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1680             else
1681                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1682             if (retval) break;
1683             for (index = 0; index < al->al_count; index++) {
1684                 ae = ATTR_ENTRY(attr_buffer, index);
1685                 ent_size = strlen(ae->a_name) + sizeof("user.");
1686                 if (left >= ent_size) {
1687                     strncpy(bp, "user.", sizeof("user."));
1688                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1689                     bp += ent_size;
1690                     left -= ent_size;
1691                 } else if (size) {
1692                     errno = ERANGE;
1693                     retval = -1;
1694                     break;
1695                 }
1696                 total_size += ent_size;
1697             }
1698             if (al->al_more == 0) break;
1699         }
1700         if (retval == 0) {
1701             flags |= ATTR_ROOT;
1702             cursor = 0;
1703             while (True) {
1704                 if (filedes)
1705                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1706                 else
1707                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1708                 if (retval) break;
1709                 for (index = 0; index < al->al_count; index++) {
1710                     ae = ATTR_ENTRY(attr_buffer, index);
1711                     ent_size = strlen(ae->a_name) + sizeof("system.");
1712                     if (left >= ent_size) {
1713                         strncpy(bp, "system.", sizeof("system."));
1714                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1715                         bp += ent_size;
1716                         left -= ent_size;
1717                     } else if (size) {
1718                         errno = ERANGE;
1719                         retval = -1;
1720                         break;
1721                     }
1722                     total_size += ent_size;
1723                 }
1724                 if (al->al_more == 0) break;
1725             }
1726         }
1727         return (ssize_t)(retval ? retval : total_size);
1728 }
1729
1730 #endif
1731
1732 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1733 {
1734 #if defined(HAVE_LISTXATTR)
1735 #ifndef XATTR_ADD_OPT
1736         return listxattr(path, list, size);
1737 #else
1738         int options = 0;
1739         return listxattr(path, list, size, options);
1740 #endif
1741 #elif defined(HAVE_LISTEA)
1742         return listea(path, list, size);
1743 #elif defined(HAVE_EXTATTR_LIST_FILE)
1744         extattr_arg arg;
1745         arg.path = path;
1746         return bsd_attr_list(0, arg, list, size);
1747 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1748         return irix_attr_list(path, 0, list, size, 0);
1749 #elif defined(HAVE_ATTROPEN)
1750         ssize_t ret = -1;
1751         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1752         if (attrdirfd >= 0) {
1753                 ret = solaris_list_xattr(attrdirfd, list, size);
1754                 close(attrdirfd);
1755         }
1756         return ret;
1757 #else
1758         errno = ENOSYS;
1759         return -1;
1760 #endif
1761 }
1762
1763 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1764 {
1765 #if defined(HAVE_LLISTXATTR)
1766         return llistxattr(path, list, size);
1767 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1768         int options = XATTR_NOFOLLOW;
1769         return listxattr(path, list, size, options);
1770 #elif defined(HAVE_LLISTEA)
1771         return llistea(path, list, size);
1772 #elif defined(HAVE_EXTATTR_LIST_LINK)
1773         extattr_arg arg;
1774         arg.path = path;
1775         return bsd_attr_list(1, arg, list, size);
1776 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1777         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1778 #elif defined(HAVE_ATTROPEN)
1779         ssize_t ret = -1;
1780         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1781         if (attrdirfd >= 0) {
1782                 ret = solaris_list_xattr(attrdirfd, list, size);
1783                 close(attrdirfd);
1784         }
1785         return ret;
1786 #else
1787         errno = ENOSYS;
1788         return -1;
1789 #endif
1790 }
1791
1792 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1793 {
1794 #if defined(HAVE_FLISTXATTR)
1795 #ifndef XATTR_ADD_OPT
1796         return flistxattr(filedes, list, size);
1797 #else
1798         int options = 0;
1799         return flistxattr(filedes, list, size, options);
1800 #endif
1801 #elif defined(HAVE_FLISTEA)
1802         return flistea(filedes, list, size);
1803 #elif defined(HAVE_EXTATTR_LIST_FD)
1804         extattr_arg arg;
1805         arg.filedes = filedes;
1806         return bsd_attr_list(2, arg, list, size);
1807 #elif defined(HAVE_ATTR_LISTF)
1808         return irix_attr_list(NULL, filedes, list, size, 0);
1809 #elif defined(HAVE_ATTROPEN)
1810         ssize_t ret = -1;
1811         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1812         if (attrdirfd >= 0) {
1813                 ret = solaris_list_xattr(attrdirfd, list, size);
1814                 close(attrdirfd);
1815         }
1816         return ret;
1817 #else
1818         errno = ENOSYS;
1819         return -1;
1820 #endif
1821 }
1822
1823 int sys_removexattr (const char *path, const char *name)
1824 {
1825 #if defined(HAVE_REMOVEXATTR)
1826 #ifndef XATTR_ADD_OPT
1827         return removexattr(path, name);
1828 #else
1829         int options = 0;
1830         return removexattr(path, name, options);
1831 #endif
1832 #elif defined(HAVE_REMOVEEA)
1833         return removeea(path, name);
1834 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1835         char *s;
1836         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1837                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1838         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1839
1840         return extattr_delete_file(path, attrnamespace, attrname);
1841 #elif defined(HAVE_ATTR_REMOVE)
1842         int flags = 0;
1843         char *attrname = strchr(name,'.') + 1;
1844         
1845         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1846
1847         return attr_remove(path, attrname, flags);
1848 #elif defined(HAVE_ATTROPEN)
1849         int ret = -1;
1850         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1851         if (attrdirfd >= 0) {
1852                 ret = solaris_unlinkat(attrdirfd, name);
1853                 close(attrdirfd);
1854         }
1855         return ret;
1856 #else
1857         errno = ENOSYS;
1858         return -1;
1859 #endif
1860 }
1861
1862 int sys_lremovexattr (const char *path, const char *name)
1863 {
1864 #if defined(HAVE_LREMOVEXATTR)
1865         return lremovexattr(path, name);
1866 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1867         int options = XATTR_NOFOLLOW;
1868         return removexattr(path, name, options);
1869 #elif defined(HAVE_LREMOVEEA)
1870         return lremoveea(path, name);
1871 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1872         char *s;
1873         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1874                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1875         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1876
1877         return extattr_delete_link(path, attrnamespace, attrname);
1878 #elif defined(HAVE_ATTR_REMOVE)
1879         int flags = ATTR_DONTFOLLOW;
1880         char *attrname = strchr(name,'.') + 1;
1881         
1882         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1883
1884         return attr_remove(path, attrname, flags);
1885 #elif defined(HAVE_ATTROPEN)
1886         int ret = -1;
1887         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1888         if (attrdirfd >= 0) {
1889                 ret = solaris_unlinkat(attrdirfd, name);
1890                 close(attrdirfd);
1891         }
1892         return ret;
1893 #else
1894         errno = ENOSYS;
1895         return -1;
1896 #endif
1897 }
1898
1899 int sys_fremovexattr (int filedes, const char *name)
1900 {
1901 #if defined(HAVE_FREMOVEXATTR)
1902 #ifndef XATTR_ADD_OPT
1903         return fremovexattr(filedes, name);
1904 #else
1905         int options = 0;
1906         return fremovexattr(filedes, name, options);
1907 #endif
1908 #elif defined(HAVE_FREMOVEEA)
1909         return fremoveea(filedes, name);
1910 #elif defined(HAVE_EXTATTR_DELETE_FD)
1911         char *s;
1912         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1913                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1914         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1915
1916         return extattr_delete_fd(filedes, attrnamespace, attrname);
1917 #elif defined(HAVE_ATTR_REMOVEF)
1918         int flags = 0;
1919         char *attrname = strchr(name,'.') + 1;
1920         
1921         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1922
1923         return attr_removef(filedes, attrname, flags);
1924 #elif defined(HAVE_ATTROPEN)
1925         int ret = -1;
1926         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1927         if (attrdirfd >= 0) {
1928                 ret = solaris_unlinkat(attrdirfd, name);
1929                 close(attrdirfd);
1930         }
1931         return ret;
1932 #else
1933         errno = ENOSYS;
1934         return -1;
1935 #endif
1936 }
1937
1938 #if !defined(HAVE_SETXATTR)
1939 #define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
1940 #define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
1941 #endif
1942
1943 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1944 {
1945 #if defined(HAVE_SETXATTR)
1946 #ifndef XATTR_ADD_OPT
1947         return setxattr(path, name, value, size, flags);
1948 #else
1949         int options = 0;
1950         return setxattr(path, name, value, size, 0, options);
1951 #endif
1952 #elif defined(HAVE_SETEA)
1953         return setea(path, name, value, size, flags);
1954 #elif defined(HAVE_EXTATTR_SET_FILE)
1955         char *s;
1956         int retval = 0;
1957         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1958                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1959         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1960         if (flags) {
1961                 /* Check attribute existence */
1962                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1963                 if (retval < 0) {
1964                         /* REPLACE attribute, that doesn't exist */
1965                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1966                                 errno = ENOATTR;
1967                                 return -1;
1968                         }
1969                         /* Ignore other errors */
1970                 }
1971                 else {
1972                         /* CREATE attribute, that already exists */
1973                         if (flags & XATTR_CREATE) {
1974                                 errno = EEXIST;
1975                                 return -1;
1976                         }
1977                 }
1978         }
1979         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1980         return (retval < 0) ? -1 : 0;
1981 #elif defined(HAVE_ATTR_SET)
1982         int myflags = 0;
1983         char *attrname = strchr(name,'.') + 1;
1984         
1985         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1986         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1987         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1988
1989         return attr_set(path, attrname, (const char *)value, size, myflags);
1990 #elif defined(HAVE_ATTROPEN)
1991         int ret = -1;
1992         int myflags = O_RDWR;
1993         int attrfd;
1994         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1995         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1996         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1997         if (attrfd >= 0) {
1998                 ret = solaris_write_xattr(attrfd, value, size);
1999                 close(attrfd);
2000         }
2001         return ret;
2002 #else
2003         errno = ENOSYS;
2004         return -1;
2005 #endif
2006 }
2007
2008 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2009 {
2010 #if defined(HAVE_LSETXATTR)
2011         return lsetxattr(path, name, value, size, flags);
2012 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2013         int options = XATTR_NOFOLLOW;
2014         return setxattr(path, name, value, size, 0, options);
2015 #elif defined(LSETEA)
2016         return lsetea(path, name, value, size, flags);
2017 #elif defined(HAVE_EXTATTR_SET_LINK)
2018         char *s;
2019         int retval = 0;
2020         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2021                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2022         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2023         if (flags) {
2024                 /* Check attribute existence */
2025                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2026                 if (retval < 0) {
2027                         /* REPLACE attribute, that doesn't exist */
2028                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2029                                 errno = ENOATTR;
2030                                 return -1;
2031                         }
2032                         /* Ignore other errors */
2033                 }
2034                 else {
2035                         /* CREATE attribute, that already exists */
2036                         if (flags & XATTR_CREATE) {
2037                                 errno = EEXIST;
2038                                 return -1;
2039                         }
2040                 }
2041         }
2042
2043         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2044         return (retval < 0) ? -1 : 0;
2045 #elif defined(HAVE_ATTR_SET)
2046         int myflags = ATTR_DONTFOLLOW;
2047         char *attrname = strchr(name,'.') + 1;
2048         
2049         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2050         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2051         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2052
2053         return attr_set(path, attrname, (const char *)value, size, myflags);
2054 #elif defined(HAVE_ATTROPEN)
2055         int ret = -1;
2056         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2057         int attrfd;
2058         if (flags & XATTR_CREATE) myflags |= O_EXCL;
2059         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2060         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2061         if (attrfd >= 0) {
2062                 ret = solaris_write_xattr(attrfd, value, size);
2063                 close(attrfd);
2064         }
2065         return ret;
2066 #else
2067         errno = ENOSYS;
2068         return -1;
2069 #endif
2070 }
2071
2072 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2073 {
2074 #if defined(HAVE_FSETXATTR)
2075 #ifndef XATTR_ADD_OPT
2076         return fsetxattr(filedes, name, value, size, flags);
2077 #else
2078         int options = 0;
2079         return fsetxattr(filedes, name, value, size, 0, options);
2080 #endif
2081 #elif defined(HAVE_FSETEA)
2082         return fsetea(filedes, name, value, size, flags);
2083 #elif defined(HAVE_EXTATTR_SET_FD)
2084         char *s;
2085         int retval = 0;
2086         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
2087                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2088         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2089         if (flags) {
2090                 /* Check attribute existence */
2091                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2092                 if (retval < 0) {
2093                         /* REPLACE attribute, that doesn't exist */
2094                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
2095                                 errno = ENOATTR;
2096                                 return -1;
2097                         }
2098                         /* Ignore other errors */
2099                 }
2100                 else {
2101                         /* CREATE attribute, that already exists */
2102                         if (flags & XATTR_CREATE) {
2103                                 errno = EEXIST;
2104                                 return -1;
2105                         }
2106                 }
2107         }
2108         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2109         return (retval < 0) ? -1 : 0;
2110 #elif defined(HAVE_ATTR_SETF)
2111         int myflags = 0;
2112         char *attrname = strchr(name,'.') + 1;
2113         
2114         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2115         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2116         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2117
2118         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2119 #elif defined(HAVE_ATTROPEN)
2120         int ret = -1;
2121         int myflags = O_RDWR | O_XATTR;
2122         int attrfd;
2123         if (flags & XATTR_CREATE) myflags |= O_EXCL;
2124         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2125         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2126         if (attrfd >= 0) {
2127                 ret = solaris_write_xattr(attrfd, value, size);
2128                 close(attrfd);
2129         }
2130         return ret;
2131 #else
2132         errno = ENOSYS;
2133         return -1;
2134 #endif
2135 }
2136
2137 /**************************************************************************
2138  helper functions for Solaris' EA support
2139 ****************************************************************************/
2140 #ifdef HAVE_ATTROPEN
2141 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2142 {
2143         struct stat sbuf;
2144
2145         if (fstat(attrfd, &sbuf) == -1) {
2146                 errno = ENOATTR;
2147                 return -1;
2148         }
2149
2150         /* This is to return the current size of the named extended attribute */
2151         if (size == 0) {
2152                 return sbuf.st_size;
2153         }
2154
2155         /* check size and read xattr */
2156         if (sbuf.st_size > size) {
2157                 errno = ERANGE;
2158                 return -1;
2159         }
2160
2161         return read(attrfd, value, sbuf.st_size);
2162 }
2163
2164 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2165 {
2166         ssize_t len = 0;
2167         int stop = 0;
2168         DIR *dirp;
2169         struct dirent *de;
2170         int newfd = dup(attrdirfd);
2171         /* CAUTION: The originating file descriptor should not be
2172                     used again following the call to fdopendir().
2173                     For that reason we dup() the file descriptor
2174                     here to make things more clear. */
2175         dirp = fdopendir(newfd);
2176
2177         while ((de = readdir(dirp))) {
2178                 size_t listlen = strlen(de->d_name);
2179                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2180                         /* we don't want "." and ".." here: */
2181                         DEBUG(10,("skipped EA %s\n",de->d_name));
2182                         continue;
2183                 }
2184
2185                 if (size == 0) {
2186                         /* return the current size of the list of extended attribute names*/
2187                         len += listlen + 1;
2188                 } else {
2189                         /* check size and copy entrieÑ• + nul into list. */
2190                         if ((len + listlen + 1) > size) {
2191                                 errno = ERANGE;
2192                                 len = -1;
2193                                 break;
2194                         } else {
2195                                 safe_strcpy(list + len, de->d_name, listlen);
2196                                 pstrcpy(list + len, de->d_name);
2197                                 len += listlen;
2198                                 list[len] = '\0';
2199                                 ++len;
2200                         }
2201                 }
2202         }
2203
2204         if (closedir(dirp) == -1) {
2205                 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2206                 return -1;
2207         }
2208         return len;
2209 }
2210
2211 static int solaris_unlinkat(int attrdirfd, const char *name)
2212 {
2213         if (unlinkat(attrdirfd, name, 0) == -1) {
2214                 if (errno == ENOENT) {
2215                         errno = ENOATTR;
2216                 }
2217                 return -1;
2218         }
2219         return 0;
2220 }
2221
2222 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2223 {
2224         int filedes = attropen(path, attrpath, oflag, mode);
2225         if (filedes == -1) {
2226                 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2227                 if (errno == EINVAL) {
2228                         errno = ENOTSUP;
2229                 } else {
2230                         errno = ENOATTR;
2231                 }
2232         }
2233         return filedes;
2234 }
2235
2236 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2237 {
2238         int filedes = openat(fildes, path, oflag, mode);
2239         if (filedes == -1) {
2240                 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2241                 if (errno == EINVAL) {
2242                         errno = ENOTSUP;
2243                 } else {
2244                         errno = ENOATTR;
2245                 }
2246         }
2247         return filedes;
2248 }
2249
2250 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2251 {
2252         if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2253                 return 0;
2254         } else {
2255                 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2256                 return -1;
2257         }
2258 }
2259 #endif /*HAVE_ATTROPEN*/
2260
2261
2262 /****************************************************************************
2263  Return the major devicenumber for UNIX extensions.
2264 ****************************************************************************/
2265                                                                                                                 
2266 uint32 unix_dev_major(SMB_DEV_T dev)
2267 {
2268 #if defined(HAVE_DEVICE_MAJOR_FN)
2269         return (uint32)major(dev);
2270 #else
2271         return (uint32)(dev >> 8);
2272 #endif
2273 }
2274                                                                                                                 
2275 /****************************************************************************
2276  Return the minor devicenumber for UNIX extensions.
2277 ****************************************************************************/
2278                                                                                                                 
2279 uint32 unix_dev_minor(SMB_DEV_T dev)
2280 {
2281 #if defined(HAVE_DEVICE_MINOR_FN)
2282         return (uint32)minor(dev);
2283 #else
2284         return (uint32)(dev & 0xff);
2285 #endif
2286 }
2287
2288 #if defined(WITH_AIO)
2289
2290 /*******************************************************************
2291  An aio_read wrapper that will deal with 64-bit sizes.
2292 ********************************************************************/
2293                                                                                                                                            
2294 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2295 {
2296 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2297         return aio_read64(aiocb);
2298 #elif defined(HAVE_AIO_READ)
2299         return aio_read(aiocb);
2300 #else
2301         errno = ENOSYS;
2302         return -1;
2303 #endif
2304 }
2305
2306 /*******************************************************************
2307  An aio_write wrapper that will deal with 64-bit sizes.
2308 ********************************************************************/
2309                                                                                                                                            
2310 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2311 {
2312 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2313         return aio_write64(aiocb);
2314 #elif defined(HAVE_AIO_WRITE)
2315         return aio_write(aiocb);
2316 #else
2317         errno = ENOSYS;
2318         return -1;
2319 #endif
2320 }
2321
2322 /*******************************************************************
2323  An aio_return wrapper that will deal with 64-bit sizes.
2324 ********************************************************************/
2325                                                                                                                                            
2326 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2327 {
2328 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2329         return aio_return64(aiocb);
2330 #elif defined(HAVE_AIO_RETURN)
2331         return aio_return(aiocb);
2332 #else
2333         errno = ENOSYS;
2334         return -1;
2335 #endif
2336 }
2337
2338 /*******************************************************************
2339  An aio_cancel wrapper that will deal with 64-bit sizes.
2340 ********************************************************************/
2341
2342 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2343 {
2344 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2345         return aio_cancel64(fd, aiocb);
2346 #elif defined(HAVE_AIO_CANCEL)
2347         return aio_cancel(fd, aiocb);
2348 #else
2349         errno = ENOSYS;
2350         return -1;
2351 #endif
2352 }
2353
2354 /*******************************************************************
2355  An aio_error wrapper that will deal with 64-bit sizes.
2356 ********************************************************************/
2357
2358 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2359 {
2360 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2361         return aio_error64(aiocb);
2362 #elif defined(HAVE_AIO_ERROR)
2363         return aio_error(aiocb);
2364 #else
2365         errno = ENOSYS;
2366         return -1;
2367 #endif
2368 }
2369
2370 /*******************************************************************
2371  An aio_fsync wrapper that will deal with 64-bit sizes.
2372 ********************************************************************/
2373
2374 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2375 {
2376 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2377         return aio_fsync64(op, aiocb);
2378 #elif defined(HAVE_AIO_FSYNC)
2379         return aio_fsync(op, aiocb);
2380 #else
2381         errno = ENOSYS;
2382         return -1;
2383 #endif
2384 }
2385
2386 /*******************************************************************
2387  An aio_fsync wrapper that will deal with 64-bit sizes.
2388 ********************************************************************/
2389
2390 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2391 {
2392 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2393         return aio_suspend64(cblist, n, timeout);
2394 #elif defined(HAVE_AIO_FSYNC)
2395         return aio_suspend(cblist, n, timeout);
2396 #else
2397         errno = ENOSYS;
2398         return -1;
2399 #endif
2400 }
2401 #else /* !WITH_AIO */
2402
2403 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2404 {
2405         errno = ENOSYS;
2406         return -1;
2407 }
2408
2409 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2410 {
2411         errno = ENOSYS;
2412         return -1;
2413 }
2414
2415 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2416 {
2417         errno = ENOSYS;
2418         return -1;
2419 }
2420
2421 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2422 {
2423         errno = ENOSYS;
2424         return -1;
2425 }
2426
2427 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2428 {
2429         errno = ENOSYS;
2430         return -1;
2431 }
2432
2433 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2434 {
2435         errno = ENOSYS;
2436         return -1;
2437 }
2438
2439 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2440 {
2441         errno = ENOSYS;
2442         return -1;
2443 }
2444 #endif /* WITH_AIO */
2445
2446 int sys_getpeereid( int s, uid_t *uid)
2447 {
2448 #if defined(HAVE_PEERCRED)
2449         struct ucred cred;
2450         socklen_t cred_len = sizeof(struct ucred);
2451         int ret;
2452
2453         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2454         if (ret != 0) {
2455                 return -1;
2456         }
2457
2458         if (cred_len != sizeof(struct ucred)) {
2459                 errno = EINVAL;
2460                 return -1;
2461         }
2462
2463         *uid = cred.uid;
2464         return 0;
2465 #else
2466         errno = ENOSYS;
2467         return -1;
2468 #endif
2469 }
2470
2471 int sys_getnameinfo(const struct sockaddr *psa,
2472                         socklen_t salen,
2473                         char *host,
2474                         size_t hostlen,
2475                         char *service,
2476                         size_t servlen,
2477                         int flags)
2478 {
2479         /*
2480          * For Solaris we must make sure salen is the
2481          * correct length for the incoming sa_family.
2482          */
2483
2484         if (salen == sizeof(struct sockaddr_storage)) {
2485                 salen = sizeof(struct sockaddr_in);
2486 #if defined(HAVE_IPV6)
2487                 if (psa->sa_family == AF_INET6) {
2488                         salen = sizeof(struct sockaddr_in6);
2489                 }
2490 #endif
2491         }
2492         return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2493 }