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