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