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