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