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