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