Remove sys_dl*() - stubs are already provided by libreplace.
[ira/wip.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba system utilities
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison  1998-2005
6    Copyright (C) Timur Bakeyev        2005
7    Copyright (C) Bjoern Jacke    2006-2007
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
28
29 /*
30    The idea is that this file will eventually have wrappers around all
31    important system calls in samba. The aims are:
32
33    - to enable easier porting by putting OS dependent stuff in here
34
35    - to allow for hooks into other "pseudo-filesystems"
36
37    - to allow easier integration of things like the japanese extensions
38
39    - to support the philosophy of Samba to expose the features of
40      the OS within the SMB model. In general whatever file/printer/variable
41      expansions/etc make sense to the OS should be acceptable to Samba.
42 */
43
44
45
46 /*******************************************************************
47  A wrapper for memalign
48 ********************************************************************/
49
50 void *sys_memalign( size_t align, size_t size )
51 {
52 #if defined(HAVE_POSIX_MEMALIGN)
53         void *p = NULL;
54         int ret = posix_memalign( &p, align, size );
55         if ( ret == 0 )
56                 return p;
57                 
58         return NULL;
59 #elif defined(HAVE_MEMALIGN)
60         return memalign( align, size );
61 #else
62         /* On *BSD systems memaligns doesn't exist, but memory will
63          * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67         size_t pagesize = (size_t)getpagesize();
68 #else
69         size_t pagesize = (size_t)-1;
70 #endif
71         if (pagesize == (size_t)-1) {
72                 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73                 return NULL;
74         }
75         if (size < pagesize) {
76                 size = pagesize;
77         }
78         return SMB_MALLOC(size);
79 #endif
80 }
81
82 /*******************************************************************
83  A wrapper for usleep in case we don't have one.
84 ********************************************************************/
85
86 int sys_usleep(long usecs)
87 {
88 #ifndef HAVE_USLEEP
89         struct timeval tval;
90 #endif
91
92         /*
93          * We need this braindamage as the glibc usleep
94          * is not SPEC1170 complient... grumble... JRA.
95          */
96
97         if(usecs < 0 || usecs > 1000000) {
98                 errno = EINVAL;
99                 return -1;
100         }
101
102 #if HAVE_USLEEP
103         usleep(usecs);
104         return 0;
105 #else /* HAVE_USLEEP */
106         /*
107          * Fake it with select...
108          */
109         tval.tv_sec = 0;
110         tval.tv_usec = usecs/1000;
111         select(0,NULL,NULL,NULL,&tval);
112         return 0;
113 #endif /* HAVE_USLEEP */
114 }
115
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
119
120 ssize_t sys_read(int fd, void *buf, size_t count)
121 {
122         ssize_t ret;
123
124         do {
125                 ret = read(fd, buf, count);
126         } while (ret == -1 && errno == EINTR);
127         return ret;
128 }
129
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
133
134 ssize_t sys_write(int fd, const void *buf, size_t count)
135 {
136         ssize_t ret;
137
138         do {
139                 ret = write(fd, buf, count);
140         } while (ret == -1 && errno == EINTR);
141         return ret;
142 }
143
144 /*******************************************************************
145 A pread wrapper that will deal with EINTR and 64-bit file offsets.
146 ********************************************************************/
147
148 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
149 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
150 {
151         ssize_t ret;
152
153         do {
154 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
155                 ret = pread64(fd, buf, count, off);
156 #else
157                 ret = pread(fd, buf, count, off);
158 #endif
159         } while (ret == -1 && errno == EINTR);
160         return ret;
161 }
162 #endif
163
164 /*******************************************************************
165 A write wrapper that will deal with EINTR and 64-bit file offsets.
166 ********************************************************************/
167
168 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
169 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
170 {
171         ssize_t ret;
172
173         do {
174 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
175                 ret = pwrite64(fd, buf, count, off);
176 #else
177                 ret = pwrite(fd, buf, count, off);
178 #endif
179         } while (ret == -1 && errno == EINTR);
180         return ret;
181 }
182 #endif
183
184 /*******************************************************************
185 A send wrapper that will deal with EINTR.
186 ********************************************************************/
187
188 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
189 {
190         ssize_t ret;
191
192         do {
193                 ret = send(s, msg, len, flags);
194         } while (ret == -1 && errno == EINTR);
195         return ret;
196 }
197
198 /*******************************************************************
199 A sendto wrapper that will deal with EINTR.
200 ********************************************************************/
201
202 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
203 {
204         ssize_t ret;
205
206         do {
207                 ret = sendto(s, msg, len, flags, to, tolen);
208         } while (ret == -1 && errno == EINTR);
209         return ret;
210 }
211
212 /*******************************************************************
213 A recv wrapper that will deal with EINTR.
214 ********************************************************************/
215
216 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
217 {
218         ssize_t ret;
219
220         do {
221                 ret = recv(fd, buf, count, flags);
222         } while (ret == -1 && errno == EINTR);
223         return ret;
224 }
225
226 /*******************************************************************
227 A recvfrom wrapper that will deal with EINTR.
228 ********************************************************************/
229
230 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
231 {
232         ssize_t ret;
233
234         do {
235                 ret = recvfrom(s, buf, len, flags, from, fromlen);
236         } while (ret == -1 && errno == EINTR);
237         return ret;
238 }
239
240 /*******************************************************************
241 A fcntl wrapper that will deal with EINTR.
242 ********************************************************************/
243
244 int sys_fcntl_ptr(int fd, int cmd, void *arg)
245 {
246         int ret;
247
248         do {
249                 ret = fcntl(fd, cmd, arg);
250         } while (ret == -1 && errno == EINTR);
251         return ret;
252 }
253
254 /*******************************************************************
255 A fcntl wrapper that will deal with EINTR.
256 ********************************************************************/
257
258 int sys_fcntl_long(int fd, int cmd, long arg)
259 {
260         int ret;
261
262         do {
263                 ret = fcntl(fd, cmd, arg);
264         } while (ret == -1 && errno == EINTR);
265         return ret;
266 }
267
268 /*******************************************************************
269 A stat() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
271
272 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
273 {
274         int ret;
275 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
276         ret = stat64(fname, sbuf);
277 #else
278         ret = stat(fname, sbuf);
279 #endif
280         /* we always want directories to appear zero size */
281         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
282         return ret;
283 }
284
285 /*******************************************************************
286  An fstat() wrapper that will deal with 64 bit filesizes.
287 ********************************************************************/
288
289 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
290 {
291         int ret;
292 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
293         ret = fstat64(fd, sbuf);
294 #else
295         ret = fstat(fd, sbuf);
296 #endif
297         /* we always want directories to appear zero size */
298         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
299         return ret;
300 }
301
302 /*******************************************************************
303  An lstat() wrapper that will deal with 64 bit filesizes.
304 ********************************************************************/
305
306 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
307 {
308         int ret;
309 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
310         ret = lstat64(fname, sbuf);
311 #else
312         ret = lstat(fname, sbuf);
313 #endif
314         /* we always want directories to appear zero size */
315         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
316         return ret;
317 }
318
319 /*******************************************************************
320  An ftruncate() wrapper that will deal with 64 bit filesizes.
321 ********************************************************************/
322
323 int sys_ftruncate(int fd, SMB_OFF_T offset)
324 {
325 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
326         return ftruncate64(fd, offset);
327 #else
328         return ftruncate(fd, offset);
329 #endif
330 }
331
332 /*******************************************************************
333  An lseek() wrapper that will deal with 64 bit filesizes.
334 ********************************************************************/
335
336 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
337 {
338 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
339         return lseek64(fd, offset, whence);
340 #else
341         return lseek(fd, offset, whence);
342 #endif
343 }
344
345 /*******************************************************************
346  An fseek() wrapper that will deal with 64 bit filesizes.
347 ********************************************************************/
348
349 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
350 {
351 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
352         return fseek64(fp, offset, whence);
353 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
354         return fseeko64(fp, offset, whence);
355 #else
356         return fseek(fp, offset, whence);
357 #endif
358 }
359
360 /*******************************************************************
361  An ftell() wrapper that will deal with 64 bit filesizes.
362 ********************************************************************/
363
364 SMB_OFF_T sys_ftell(FILE *fp)
365 {
366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
367         return (SMB_OFF_T)ftell64(fp);
368 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
369         return (SMB_OFF_T)ftello64(fp);
370 #else
371         return (SMB_OFF_T)ftell(fp);
372 #endif
373 }
374
375 /*******************************************************************
376  A creat() wrapper that will deal with 64 bit filesizes.
377 ********************************************************************/
378
379 int sys_creat(const char *path, mode_t mode)
380 {
381 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
382         return creat64(path, mode);
383 #else
384         /*
385          * If creat64 isn't defined then ensure we call a potential open64.
386          * JRA.
387          */
388         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
389 #endif
390 }
391
392 /*******************************************************************
393  An open() wrapper that will deal with 64 bit filesizes.
394 ********************************************************************/
395
396 int sys_open(const char *path, int oflag, mode_t mode)
397 {
398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
399         return open64(path, oflag, mode);
400 #else
401         return open(path, oflag, mode);
402 #endif
403 }
404
405 /*******************************************************************
406  An fopen() wrapper that will deal with 64 bit filesizes.
407 ********************************************************************/
408
409 FILE *sys_fopen(const char *path, const char *type)
410 {
411 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
412         return fopen64(path, type);
413 #else
414         return fopen(path, type);
415 #endif
416 }
417
418
419 /*******************************************************************
420  A flock() wrapper that will perform the kernel flock.
421 ********************************************************************/
422
423 void kernel_flock(int fd, uint32 share_mode)
424 {
425 #if HAVE_KERNEL_SHARE_MODES
426         int kernel_mode = 0;
427         if (share_mode == FILE_SHARE_WRITE) {
428                 kernel_mode = LOCK_MAND|LOCK_WRITE;
429         } else if (share_mode == FILE_SHARE_READ) {
430                 kernel_mode = LOCK_MAND|LOCK_READ;
431         } else if (share_mode == FILE_SHARE_NONE) {
432                 kernel_mode = LOCK_MAND;
433         }
434         if (kernel_mode) {
435                 flock(fd, kernel_mode);
436         }
437 #endif
438         ;
439 }
440
441
442
443 /*******************************************************************
444  An opendir wrapper that will deal with 64 bit filesizes.
445 ********************************************************************/
446
447 SMB_STRUCT_DIR *sys_opendir(const char *name)
448 {
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
450         return opendir64(name);
451 #else
452         return opendir(name);
453 #endif
454 }
455
456 /*******************************************************************
457  A readdir wrapper that will deal with 64 bit filesizes.
458 ********************************************************************/
459
460 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
461 {
462 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
463         return readdir64(dirp);
464 #else
465         return readdir(dirp);
466 #endif
467 }
468
469 /*******************************************************************
470  A seekdir wrapper that will deal with 64 bit filesizes.
471 ********************************************************************/
472
473 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
474 {
475 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
476         seekdir64(dirp, offset);
477 #else
478         seekdir(dirp, offset);
479 #endif
480 }
481
482 /*******************************************************************
483  A telldir wrapper that will deal with 64 bit filesizes.
484 ********************************************************************/
485
486 long sys_telldir(SMB_STRUCT_DIR *dirp)
487 {
488 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
489         return (long)telldir64(dirp);
490 #else
491         return (long)telldir(dirp);
492 #endif
493 }
494
495 /*******************************************************************
496  A rewinddir wrapper that will deal with 64 bit filesizes.
497 ********************************************************************/
498
499 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
500 {
501 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
502         rewinddir64(dirp);
503 #else
504         rewinddir(dirp);
505 #endif
506 }
507
508 /*******************************************************************
509  A close wrapper that will deal with 64 bit filesizes.
510 ********************************************************************/
511
512 int sys_closedir(SMB_STRUCT_DIR *dirp)
513 {
514 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
515         return closedir64(dirp);
516 #else
517         return closedir(dirp);
518 #endif
519 }
520
521 /*******************************************************************
522  An mknod() wrapper that will deal with 64 bit filesizes.
523 ********************************************************************/
524
525 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
526 {
527 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
528 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
529         return mknod64(path, mode, dev);
530 #else
531         return mknod(path, mode, dev);
532 #endif
533 #else
534         /* No mknod system call. */
535         errno = ENOSYS;
536         return -1;
537 #endif
538 }
539
540 /*******************************************************************
541 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 int sys_dup2(int oldfd, int newfd) 
1194 {
1195 #if defined(HAVE_DUP2)
1196         return dup2(oldfd, newfd);
1197 #else
1198         errno = ENOSYS;
1199         return -1;
1200 #endif
1201 }
1202
1203 /**************************************************************************
1204  Wrapper for Admin Logs.
1205 ****************************************************************************/
1206
1207  void sys_adminlog(int priority, const char *format_str, ...) 
1208 {
1209         va_list ap;
1210         int ret;
1211         char *msgbuf = NULL;
1212
1213         va_start( ap, format_str );
1214         ret = vasprintf( &msgbuf, format_str, ap );
1215         va_end( ap );
1216
1217         if (ret == -1)
1218                 return;
1219
1220 #if defined(HAVE_SYSLOG)
1221         syslog( priority, "%s", msgbuf );
1222 #else
1223         DEBUG(0,("%s", msgbuf ));
1224 #endif
1225         SAFE_FREE(msgbuf);
1226 }
1227
1228 /******** Solaris EA helper function prototypes ********/
1229 #ifdef HAVE_ATTROPEN
1230 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1231 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1232 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1233 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1234 static int solaris_unlinkat(int attrdirfd, const char *name);
1235 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1236 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1237 #endif
1238
1239 /**************************************************************************
1240  Wrappers for extented attribute calls. Based on the Linux package with
1241  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1242 ****************************************************************************/
1243
1244 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1245 {
1246 #if defined(HAVE_GETXATTR)
1247 #ifndef XATTR_ADD_OPT
1248         return getxattr(path, name, value, size);
1249 #else
1250         int options = 0;
1251         return getxattr(path, name, value, size, 0, options);
1252 #endif
1253 #elif defined(HAVE_GETEA)
1254         return getea(path, name, value, size);
1255 #elif defined(HAVE_EXTATTR_GET_FILE)
1256         char *s;
1257         ssize_t retval;
1258         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1259                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1260         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1261         /*
1262          * The BSD implementation has a nasty habit of silently truncating
1263          * the returned value to the size of the buffer, so we have to check
1264          * that the buffer is large enough to fit the returned value.
1265          */
1266         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1267                 if(retval > size) {
1268                         errno = ERANGE;
1269                         return -1;
1270                 }
1271                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1272                         return retval;
1273         }
1274
1275         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1276         return -1;
1277 #elif defined(HAVE_ATTR_GET)
1278         int retval, flags = 0;
1279         int valuelength = (int)size;
1280         char *attrname = strchr(name,'.') + 1;
1281         
1282         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1283
1284         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1285
1286         return retval ? retval : valuelength;
1287 #elif defined(HAVE_ATTROPEN)
1288         ssize_t ret = -1;
1289         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1290         if (attrfd >= 0) {
1291                 ret = solaris_read_xattr(attrfd, value, size);
1292                 close(attrfd);
1293         }
1294         return ret;
1295 #else
1296         errno = ENOSYS;
1297         return -1;
1298 #endif
1299 }
1300
1301 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1302 {
1303 #if defined(HAVE_LGETXATTR)
1304         return lgetxattr(path, name, value, size);
1305 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1306         int options = XATTR_NOFOLLOW;
1307         return getxattr(path, name, value, size, 0, options);
1308 #elif defined(HAVE_LGETEA)
1309         return lgetea(path, name, value, size);
1310 #elif defined(HAVE_EXTATTR_GET_LINK)
1311         char *s;
1312         ssize_t retval;
1313         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1314                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1315         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1316
1317         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1318                 if(retval > size) {
1319                         errno = ERANGE;
1320                         return -1;
1321                 }
1322                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1323                         return retval;
1324         }
1325         
1326         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1327         return -1;
1328 #elif defined(HAVE_ATTR_GET)
1329         int retval, flags = ATTR_DONTFOLLOW;
1330         int valuelength = (int)size;
1331         char *attrname = strchr(name,'.') + 1;
1332         
1333         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1334
1335         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1336
1337         return retval ? retval : valuelength;
1338 #elif defined(HAVE_ATTROPEN)
1339         ssize_t ret = -1;
1340         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1341         if (attrfd >= 0) {
1342                 ret = solaris_read_xattr(attrfd, value, size);
1343                 close(attrfd);
1344         }
1345         return ret;
1346 #else
1347         errno = ENOSYS;
1348         return -1;
1349 #endif
1350 }
1351
1352 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1353 {
1354 #if defined(HAVE_FGETXATTR)
1355 #ifndef XATTR_ADD_OPT
1356         return fgetxattr(filedes, name, value, size);
1357 #else
1358         int options = 0;
1359         return fgetxattr(filedes, name, value, size, 0, options);
1360 #endif
1361 #elif defined(HAVE_FGETEA)
1362         return fgetea(filedes, name, value, size);
1363 #elif defined(HAVE_EXTATTR_GET_FD)
1364         char *s;
1365         ssize_t retval;
1366         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1367                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1368         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1369
1370         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1371                 if(retval > size) {
1372                         errno = ERANGE;
1373                         return -1;
1374                 }
1375                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1376                         return retval;
1377         }
1378         
1379         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1380         return -1;
1381 #elif defined(HAVE_ATTR_GETF)
1382         int retval, flags = 0;
1383         int valuelength = (int)size;
1384         char *attrname = strchr(name,'.') + 1;
1385         
1386         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1387
1388         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1389
1390         return retval ? retval : valuelength;
1391 #elif defined(HAVE_ATTROPEN)
1392         ssize_t ret = -1;
1393         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1394         if (attrfd >= 0) {
1395                 ret = solaris_read_xattr(attrfd, value, size);
1396                 close(attrfd);
1397         }
1398         return ret;
1399 #else
1400         errno = ENOSYS;
1401         return -1;
1402 #endif
1403 }
1404
1405 #if defined(HAVE_EXTATTR_LIST_FILE)
1406
1407 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1408
1409 static struct {
1410         int space;
1411         const char *name;
1412         size_t len;
1413
1414 extattr[] = {
1415         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1416         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1417 };
1418
1419 typedef union {
1420         const char *path;
1421         int filedes;
1422 } extattr_arg;
1423
1424 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1425 {
1426         ssize_t list_size, total_size = 0;
1427         int i, t, len;
1428         char *buf;
1429         /* Iterate through extattr(2) namespaces */
1430         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1431                 switch(type) {
1432 #if defined(HAVE_EXTATTR_LIST_FILE)
1433                         case 0:
1434                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1435                                 break;
1436 #endif
1437 #if defined(HAVE_EXTATTR_LIST_LINK)
1438                         case 1:
1439                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1440                                 break;
1441 #endif
1442 #if defined(HAVE_EXTATTR_LIST_FD)
1443                         case 2:
1444                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1445                                 break;
1446 #endif
1447                         default:
1448                                 errno = ENOSYS;
1449                                 return -1;
1450                 }
1451                 /* Some error happend. Errno should be set by the previous call */
1452                 if(list_size < 0)
1453                         return -1;
1454                 /* No attributes */
1455                 if(list_size == 0)
1456                         continue;
1457                 /* XXX: Call with an empty buffer may be used to calculate
1458                    necessary buffer size. Unfortunately, we can't say, how
1459                    many attributes were returned, so here is the potential
1460                    problem with the emulation.
1461                 */
1462                 if(list == NULL) {
1463                         /* Take the worse case of one char attribute names - 
1464                            two bytes per name plus one more for sanity.
1465                         */
1466                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1467                         continue;
1468                 }
1469                 /* Count necessary offset to fit namespace prefixes */
1470                 len = 0;
1471                 for(i = 0; i < list_size; i += list[i] + 1)
1472                         len += extattr[t].len;
1473
1474                 total_size += list_size + len;
1475                 /* Buffer is too small to fit the results */
1476                 if(total_size > size) {
1477                         errno = ERANGE;
1478                         return -1;
1479                 }
1480                 /* Shift results back, so we can prepend prefixes */
1481                 buf = memmove(list + len, list, list_size);
1482
1483                 for(i = 0; i < list_size; i += len + 1) {
1484                         len = buf[i];
1485                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1486                         list += extattr[t].len;
1487                         strncpy(list, buf + i + 1, len);
1488                         list[len] = '\0';
1489                         list += len + 1;
1490                 }
1491                 size -= total_size;
1492         }
1493         return total_size;
1494 }
1495
1496 #endif
1497
1498 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1499 static char attr_buffer[ATTR_MAX_VALUELEN];
1500
1501 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1502 {
1503         int retval = 0, index;
1504         attrlist_cursor_t *cursor = 0;
1505         int total_size = 0;
1506         attrlist_t * al = (attrlist_t *)attr_buffer;
1507         attrlist_ent_t *ae;
1508         size_t ent_size, left = size;
1509         char *bp = list;
1510
1511         while (True) {
1512             if (filedes)
1513                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1514             else
1515                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1516             if (retval) break;
1517             for (index = 0; index < al->al_count; index++) {
1518                 ae = ATTR_ENTRY(attr_buffer, index);
1519                 ent_size = strlen(ae->a_name) + sizeof("user.");
1520                 if (left >= ent_size) {
1521                     strncpy(bp, "user.", sizeof("user."));
1522                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1523                     bp += ent_size;
1524                     left -= ent_size;
1525                 } else if (size) {
1526                     errno = ERANGE;
1527                     retval = -1;
1528                     break;
1529                 }
1530                 total_size += ent_size;
1531             }
1532             if (al->al_more == 0) break;
1533         }
1534         if (retval == 0) {
1535             flags |= ATTR_ROOT;
1536             cursor = 0;
1537             while (True) {
1538                 if (filedes)
1539                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1540                 else
1541                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1542                 if (retval) break;
1543                 for (index = 0; index < al->al_count; index++) {
1544                     ae = ATTR_ENTRY(attr_buffer, index);
1545                     ent_size = strlen(ae->a_name) + sizeof("system.");
1546                     if (left >= ent_size) {
1547                         strncpy(bp, "system.", sizeof("system."));
1548                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1549                         bp += ent_size;
1550                         left -= ent_size;
1551                     } else if (size) {
1552                         errno = ERANGE;
1553                         retval = -1;
1554                         break;
1555                     }
1556                     total_size += ent_size;
1557                 }
1558                 if (al->al_more == 0) break;
1559             }
1560         }
1561         return (ssize_t)(retval ? retval : total_size);
1562 }
1563
1564 #endif
1565
1566 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1567 {
1568 #if defined(HAVE_LISTXATTR)
1569 #ifndef XATTR_ADD_OPT
1570         return listxattr(path, list, size);
1571 #else
1572         int options = 0;
1573         return listxattr(path, list, size, options);
1574 #endif
1575 #elif defined(HAVE_LISTEA)
1576         return listea(path, list, size);
1577 #elif defined(HAVE_EXTATTR_LIST_FILE)
1578         extattr_arg arg;
1579         arg.path = path;
1580         return bsd_attr_list(0, arg, list, size);
1581 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1582         return irix_attr_list(path, 0, list, size, 0);
1583 #elif defined(HAVE_ATTROPEN)
1584         ssize_t ret = -1;
1585         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1586         if (attrdirfd >= 0) {
1587                 ret = solaris_list_xattr(attrdirfd, list, size);
1588                 close(attrdirfd);
1589         }
1590         return ret;
1591 #else
1592         errno = ENOSYS;
1593         return -1;
1594 #endif
1595 }
1596
1597 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1598 {
1599 #if defined(HAVE_LLISTXATTR)
1600         return llistxattr(path, list, size);
1601 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1602         int options = XATTR_NOFOLLOW;
1603         return listxattr(path, list, size, options);
1604 #elif defined(HAVE_LLISTEA)
1605         return llistea(path, list, size);
1606 #elif defined(HAVE_EXTATTR_LIST_LINK)
1607         extattr_arg arg;
1608         arg.path = path;
1609         return bsd_attr_list(1, arg, list, size);
1610 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1611         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1612 #elif defined(HAVE_ATTROPEN)
1613         ssize_t ret = -1;
1614         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1615         if (attrdirfd >= 0) {
1616                 ret = solaris_list_xattr(attrdirfd, list, size);
1617                 close(attrdirfd);
1618         }
1619         return ret;
1620 #else
1621         errno = ENOSYS;
1622         return -1;
1623 #endif
1624 }
1625
1626 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1627 {
1628 #if defined(HAVE_FLISTXATTR)
1629 #ifndef XATTR_ADD_OPT
1630         return flistxattr(filedes, list, size);
1631 #else
1632         int options = 0;
1633         return flistxattr(filedes, list, size, options);
1634 #endif
1635 #elif defined(HAVE_FLISTEA)
1636         return flistea(filedes, list, size);
1637 #elif defined(HAVE_EXTATTR_LIST_FD)
1638         extattr_arg arg;
1639         arg.filedes = filedes;
1640         return bsd_attr_list(2, arg, list, size);
1641 #elif defined(HAVE_ATTR_LISTF)
1642         return irix_attr_list(NULL, filedes, list, size, 0);
1643 #elif defined(HAVE_ATTROPEN)
1644         ssize_t ret = -1;
1645         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1646         if (attrdirfd >= 0) {
1647                 ret = solaris_list_xattr(attrdirfd, list, size);
1648                 close(attrdirfd);
1649         }
1650         return ret;
1651 #else
1652         errno = ENOSYS;
1653         return -1;
1654 #endif
1655 }
1656
1657 int sys_removexattr (const char *path, const char *name)
1658 {
1659 #if defined(HAVE_REMOVEXATTR)
1660 #ifndef XATTR_ADD_OPT
1661         return removexattr(path, name);
1662 #else
1663         int options = 0;
1664         return removexattr(path, name, options);
1665 #endif
1666 #elif defined(HAVE_REMOVEEA)
1667         return removeea(path, name);
1668 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1669         char *s;
1670         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1671                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1672         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1673
1674         return extattr_delete_file(path, attrnamespace, attrname);
1675 #elif defined(HAVE_ATTR_REMOVE)
1676         int flags = 0;
1677         char *attrname = strchr(name,'.') + 1;
1678         
1679         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1680
1681         return attr_remove(path, attrname, flags);
1682 #elif defined(HAVE_ATTROPEN)
1683         int ret = -1;
1684         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1685         if (attrdirfd >= 0) {
1686                 ret = solaris_unlinkat(attrdirfd, name);
1687                 close(attrdirfd);
1688         }
1689         return ret;
1690 #else
1691         errno = ENOSYS;
1692         return -1;
1693 #endif
1694 }
1695
1696 int sys_lremovexattr (const char *path, const char *name)
1697 {
1698 #if defined(HAVE_LREMOVEXATTR)
1699         return lremovexattr(path, name);
1700 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1701         int options = XATTR_NOFOLLOW;
1702         return removexattr(path, name, options);
1703 #elif defined(HAVE_LREMOVEEA)
1704         return lremoveea(path, name);
1705 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1706         char *s;
1707         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1708                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1709         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1710
1711         return extattr_delete_link(path, attrnamespace, attrname);
1712 #elif defined(HAVE_ATTR_REMOVE)
1713         int flags = ATTR_DONTFOLLOW;
1714         char *attrname = strchr(name,'.') + 1;
1715         
1716         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1717
1718         return attr_remove(path, attrname, flags);
1719 #elif defined(HAVE_ATTROPEN)
1720         int ret = -1;
1721         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1722         if (attrdirfd >= 0) {
1723                 ret = solaris_unlinkat(attrdirfd, name);
1724                 close(attrdirfd);
1725         }
1726         return ret;
1727 #else
1728         errno = ENOSYS;
1729         return -1;
1730 #endif
1731 }
1732
1733 int sys_fremovexattr (int filedes, const char *name)
1734 {
1735 #if defined(HAVE_FREMOVEXATTR)
1736 #ifndef XATTR_ADD_OPT
1737         return fremovexattr(filedes, name);
1738 #else
1739         int options = 0;
1740         return fremovexattr(filedes, name, options);
1741 #endif
1742 #elif defined(HAVE_FREMOVEEA)
1743         return fremoveea(filedes, name);
1744 #elif defined(HAVE_EXTATTR_DELETE_FD)
1745         char *s;
1746         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1747                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1748         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1749
1750         return extattr_delete_fd(filedes, attrnamespace, attrname);
1751 #elif defined(HAVE_ATTR_REMOVEF)
1752         int flags = 0;
1753         char *attrname = strchr(name,'.') + 1;
1754         
1755         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1756
1757         return attr_removef(filedes, attrname, flags);
1758 #elif defined(HAVE_ATTROPEN)
1759         int ret = -1;
1760         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1761         if (attrdirfd >= 0) {
1762                 ret = solaris_unlinkat(attrdirfd, name);
1763                 close(attrdirfd);
1764         }
1765         return ret;
1766 #else
1767         errno = ENOSYS;
1768         return -1;
1769 #endif
1770 }
1771
1772 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1773 {
1774 #if defined(HAVE_SETXATTR)
1775 #ifndef XATTR_ADD_OPT
1776         return setxattr(path, name, value, size, flags);
1777 #else
1778         int options = 0;
1779         return setxattr(path, name, value, size, 0, options);
1780 #endif
1781 #elif defined(HAVE_SETEA)
1782         return setea(path, name, value, size, flags);
1783 #elif defined(HAVE_EXTATTR_SET_FILE)
1784         char *s;
1785         int retval = 0;
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         if (flags) {
1790                 /* Check attribute existence */
1791                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1792                 if (retval < 0) {
1793                         /* REPLACE attribute, that doesn't exist */
1794                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1795                                 errno = ENOATTR;
1796                                 return -1;
1797                         }
1798                         /* Ignore other errors */
1799                 }
1800                 else {
1801                         /* CREATE attribute, that already exists */
1802                         if (flags & XATTR_CREATE) {
1803                                 errno = EEXIST;
1804                                 return -1;
1805                         }
1806                 }
1807         }
1808         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1809         return (retval < 0) ? -1 : 0;
1810 #elif defined(HAVE_ATTR_SET)
1811         int myflags = 0;
1812         char *attrname = strchr(name,'.') + 1;
1813         
1814         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1815         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1816         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1817
1818         return attr_set(path, attrname, (const char *)value, size, myflags);
1819 #elif defined(HAVE_ATTROPEN)
1820         int ret = -1;
1821         int myflags = O_RDWR;
1822         int attrfd;
1823         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1824         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1825         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1826         if (attrfd >= 0) {
1827                 ret = solaris_write_xattr(attrfd, value, size);
1828                 close(attrfd);
1829         }
1830         return ret;
1831 #else
1832         errno = ENOSYS;
1833         return -1;
1834 #endif
1835 }
1836
1837 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1838 {
1839 #if defined(HAVE_LSETXATTR)
1840         return lsetxattr(path, name, value, size, flags);
1841 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1842         int options = XATTR_NOFOLLOW;
1843         return setxattr(path, name, value, size, 0, options);
1844 #elif defined(LSETEA)
1845         return lsetea(path, name, value, size, flags);
1846 #elif defined(HAVE_EXTATTR_SET_LINK)
1847         char *s;
1848         int retval = 0;
1849         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1850                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1851         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1852         if (flags) {
1853                 /* Check attribute existence */
1854                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1855                 if (retval < 0) {
1856                         /* REPLACE attribute, that doesn't exist */
1857                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1858                                 errno = ENOATTR;
1859                                 return -1;
1860                         }
1861                         /* Ignore other errors */
1862                 }
1863                 else {
1864                         /* CREATE attribute, that already exists */
1865                         if (flags & XATTR_CREATE) {
1866                                 errno = EEXIST;
1867                                 return -1;
1868                         }
1869                 }
1870         }
1871
1872         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1873         return (retval < 0) ? -1 : 0;
1874 #elif defined(HAVE_ATTR_SET)
1875         int myflags = ATTR_DONTFOLLOW;
1876         char *attrname = strchr(name,'.') + 1;
1877         
1878         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1879         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1880         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1881
1882         return attr_set(path, attrname, (const char *)value, size, myflags);
1883 #elif defined(HAVE_ATTROPEN)
1884         int ret = -1;
1885         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1886         int attrfd;
1887         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1888         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1889         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1890         if (attrfd >= 0) {
1891                 ret = solaris_write_xattr(attrfd, value, size);
1892                 close(attrfd);
1893         }
1894         return ret;
1895 #else
1896         errno = ENOSYS;
1897         return -1;
1898 #endif
1899 }
1900
1901 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1902 {
1903 #if defined(HAVE_FSETXATTR)
1904 #ifndef XATTR_ADD_OPT
1905         return fsetxattr(filedes, name, value, size, flags);
1906 #else
1907         int options = 0;
1908         return fsetxattr(filedes, name, value, size, 0, options);
1909 #endif
1910 #elif defined(HAVE_FSETEA)
1911         return fsetea(filedes, name, value, size, flags);
1912 #elif defined(HAVE_EXTATTR_SET_FD)
1913         char *s;
1914         int retval = 0;
1915         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1916                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1917         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1918         if (flags) {
1919                 /* Check attribute existence */
1920                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1921                 if (retval < 0) {
1922                         /* REPLACE attribute, that doesn't exist */
1923                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1924                                 errno = ENOATTR;
1925                                 return -1;
1926                         }
1927                         /* Ignore other errors */
1928                 }
1929                 else {
1930                         /* CREATE attribute, that already exists */
1931                         if (flags & XATTR_CREATE) {
1932                                 errno = EEXIST;
1933                                 return -1;
1934                         }
1935                 }
1936         }
1937         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1938         return (retval < 0) ? -1 : 0;
1939 #elif defined(HAVE_ATTR_SETF)
1940         int myflags = 0;
1941         char *attrname = strchr(name,'.') + 1;
1942         
1943         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1944         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1945         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1946
1947         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1948 #elif defined(HAVE_ATTROPEN)
1949         int ret = -1;
1950         int myflags = O_RDWR | O_XATTR;
1951         int attrfd;
1952         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1953         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1954         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1955         if (attrfd >= 0) {
1956                 ret = solaris_write_xattr(attrfd, value, size);
1957                 close(attrfd);
1958         }
1959         return ret;
1960 #else
1961         errno = ENOSYS;
1962         return -1;
1963 #endif
1964 }
1965
1966 /**************************************************************************
1967  helper functions for Solaris' EA support
1968 ****************************************************************************/
1969 #ifdef HAVE_ATTROPEN
1970 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
1971 {
1972         struct stat sbuf;
1973
1974         if (fstat(attrfd, &sbuf) == -1) {
1975                 errno = ENOATTR;
1976                 return -1;
1977         }
1978
1979         /* This is to return the current size of the named extended attribute */
1980         if (size == 0) {
1981                 return sbuf.st_size;
1982         }
1983
1984         /* check size and read xattr */
1985         if (sbuf.st_size > size) {
1986                 errno = ERANGE;
1987                 return -1;
1988         }
1989
1990         return read(attrfd, value, sbuf.st_size);
1991 }
1992
1993 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
1994 {
1995         ssize_t len = 0;
1996         int stop = 0;
1997         DIR *dirp;
1998         struct dirent *de;
1999         int newfd = dup(attrdirfd);
2000         /* CAUTION: The originating file descriptor should not be
2001                     used again following the call to fdopendir().
2002                     For that reason we dup() the file descriptor
2003                     here to make things more clear. */
2004         dirp = fdopendir(newfd);
2005
2006         while ((de = readdir(dirp))) {
2007                 size_t listlen = strlen(de->d_name);
2008                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2009                         /* we don't want "." and ".." here: */
2010                         DEBUG(10,("skipped EA %s\n",de->d_name));
2011                         continue;
2012                 }
2013
2014                 if (size == 0) {
2015                         /* return the current size of the list of extended attribute names*/
2016                         len += listlen + 1;
2017                 } else {
2018                         /* check size and copy entrieŃ• + nul into list. */
2019                         if ((len + listlen + 1) > size) {
2020                                 errno = ERANGE;
2021                                 len = -1;
2022                                 break;
2023                         } else {
2024                                 safe_strcpy(list + len, de->d_name, listlen);
2025                                 len += listlen;
2026                                 list[len] = '\0';
2027                                 ++len;
2028                         }
2029                 }
2030         }
2031
2032         if (closedir(dirp) == -1) {
2033                 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2034                 return -1;
2035         }
2036         return len;
2037 }
2038
2039 static int solaris_unlinkat(int attrdirfd, const char *name)
2040 {
2041         if (unlinkat(attrdirfd, name, 0) == -1) {
2042                 if (errno == ENOENT) {
2043                         errno = ENOATTR;
2044                 }
2045                 return -1;
2046         }
2047         return 0;
2048 }
2049
2050 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2051 {
2052         int filedes = attropen(path, attrpath, oflag, mode);
2053         if (filedes == -1) {
2054                 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2055                 if (errno == EINVAL) {
2056                         errno = ENOTSUP;
2057                 } else {
2058                         errno = ENOATTR;
2059                 }
2060         }
2061         return filedes;
2062 }
2063
2064 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2065 {
2066         int filedes = openat(fildes, path, oflag, mode);
2067         if (filedes == -1) {
2068                 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2069                 if (errno == EINVAL) {
2070                         errno = ENOTSUP;
2071                 } else {
2072                         errno = ENOATTR;
2073                 }
2074         }
2075         return filedes;
2076 }
2077
2078 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2079 {
2080         if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2081                 return 0;
2082         } else {
2083                 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2084                 return -1;
2085         }
2086 }
2087 #endif /*HAVE_ATTROPEN*/
2088
2089
2090 /****************************************************************************
2091  Return the major devicenumber for UNIX extensions.
2092 ****************************************************************************/
2093                                                                                                                 
2094 uint32 unix_dev_major(SMB_DEV_T dev)
2095 {
2096 #if defined(HAVE_DEVICE_MAJOR_FN)
2097         return (uint32)major(dev);
2098 #else
2099         return (uint32)(dev >> 8);
2100 #endif
2101 }
2102                                                                                                                 
2103 /****************************************************************************
2104  Return the minor devicenumber for UNIX extensions.
2105 ****************************************************************************/
2106                                                                                                                 
2107 uint32 unix_dev_minor(SMB_DEV_T dev)
2108 {
2109 #if defined(HAVE_DEVICE_MINOR_FN)
2110         return (uint32)minor(dev);
2111 #else
2112         return (uint32)(dev & 0xff);
2113 #endif
2114 }
2115
2116 #if defined(WITH_AIO)
2117
2118 /*******************************************************************
2119  An aio_read wrapper that will deal with 64-bit sizes.
2120 ********************************************************************/
2121                                                                                                                                            
2122 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2123 {
2124 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2125         return aio_read64(aiocb);
2126 #elif defined(HAVE_AIO_READ)
2127         return aio_read(aiocb);
2128 #else
2129         errno = ENOSYS;
2130         return -1;
2131 #endif
2132 }
2133
2134 /*******************************************************************
2135  An aio_write wrapper that will deal with 64-bit sizes.
2136 ********************************************************************/
2137                                                                                                                                            
2138 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2139 {
2140 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2141         return aio_write64(aiocb);
2142 #elif defined(HAVE_AIO_WRITE)
2143         return aio_write(aiocb);
2144 #else
2145         errno = ENOSYS;
2146         return -1;
2147 #endif
2148 }
2149
2150 /*******************************************************************
2151  An aio_return wrapper that will deal with 64-bit sizes.
2152 ********************************************************************/
2153                                                                                                                                            
2154 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2155 {
2156 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2157         return aio_return64(aiocb);
2158 #elif defined(HAVE_AIO_RETURN)
2159         return aio_return(aiocb);
2160 #else
2161         errno = ENOSYS;
2162         return -1;
2163 #endif
2164 }
2165
2166 /*******************************************************************
2167  An aio_cancel wrapper that will deal with 64-bit sizes.
2168 ********************************************************************/
2169
2170 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2171 {
2172 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2173         return aio_cancel64(fd, aiocb);
2174 #elif defined(HAVE_AIO_CANCEL)
2175         return aio_cancel(fd, aiocb);
2176 #else
2177         errno = ENOSYS;
2178         return -1;
2179 #endif
2180 }
2181
2182 /*******************************************************************
2183  An aio_error wrapper that will deal with 64-bit sizes.
2184 ********************************************************************/
2185
2186 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2187 {
2188 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2189         return aio_error64(aiocb);
2190 #elif defined(HAVE_AIO_ERROR)
2191         return aio_error(aiocb);
2192 #else
2193         errno = ENOSYS;
2194         return -1;
2195 #endif
2196 }
2197
2198 /*******************************************************************
2199  An aio_fsync wrapper that will deal with 64-bit sizes.
2200 ********************************************************************/
2201
2202 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2203 {
2204 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2205         return aio_fsync64(op, aiocb);
2206 #elif defined(HAVE_AIO_FSYNC)
2207         return aio_fsync(op, aiocb);
2208 #else
2209         errno = ENOSYS;
2210         return -1;
2211 #endif
2212 }
2213
2214 /*******************************************************************
2215  An aio_fsync wrapper that will deal with 64-bit sizes.
2216 ********************************************************************/
2217
2218 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2219 {
2220 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2221         return aio_suspend64(cblist, n, timeout);
2222 #elif defined(HAVE_AIO_FSYNC)
2223         return aio_suspend(cblist, n, timeout);
2224 #else
2225         errno = ENOSYS;
2226         return -1;
2227 #endif
2228 }
2229 #else /* !WITH_AIO */
2230
2231 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2232 {
2233         errno = ENOSYS;
2234         return -1;
2235 }
2236
2237 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2238 {
2239         errno = ENOSYS;
2240         return -1;
2241 }
2242
2243 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2244 {
2245         errno = ENOSYS;
2246         return -1;
2247 }
2248
2249 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2250 {
2251         errno = ENOSYS;
2252         return -1;
2253 }
2254
2255 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2256 {
2257         errno = ENOSYS;
2258         return -1;
2259 }
2260
2261 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2262 {
2263         errno = ENOSYS;
2264         return -1;
2265 }
2266
2267 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2268 {
2269         errno = ENOSYS;
2270         return -1;
2271 }
2272 #endif /* WITH_AIO */
2273
2274 int sys_getpeereid( int s, uid_t *uid)
2275 {
2276 #if defined(HAVE_PEERCRED)
2277         struct ucred cred;
2278         socklen_t cred_len = sizeof(struct ucred);
2279         int ret;
2280
2281         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2282         if (ret != 0) {
2283                 return -1;
2284         }
2285
2286         if (cred_len != sizeof(struct ucred)) {
2287                 errno = EINVAL;
2288                 return -1;
2289         }
2290
2291         *uid = cred.uid;
2292         return 0;
2293 #else
2294         errno = ENOSYS;
2295         return -1;
2296 #endif
2297 }
2298
2299 int sys_getnameinfo(const struct sockaddr *psa,
2300                         socklen_t salen,
2301                         char *host,
2302                         size_t hostlen,
2303                         char *service,
2304                         size_t servlen,
2305                         int flags)
2306 {
2307         /*
2308          * For Solaris we must make sure salen is the
2309          * correct length for the incoming sa_family.
2310          */
2311
2312         if (salen == sizeof(struct sockaddr_storage)) {
2313                 salen = sizeof(struct sockaddr_in);
2314 #if defined(HAVE_IPV6)
2315                 if (psa->sa_family == AF_INET6) {
2316                         salen = sizeof(struct sockaddr_in6);
2317                 }
2318 #endif
2319         }
2320         return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2321 }
2322
2323 int sys_connect(int fd, const struct sockaddr * addr)
2324 {
2325         socklen_t salen = -1;
2326
2327         if (addr->sa_family == AF_INET) {
2328             salen = sizeof(struct sockaddr_in);
2329         } else if (addr->sa_family == AF_UNIX) {
2330             salen = sizeof(struct sockaddr_un);
2331         }
2332 #if defined(HAVE_IPV6)
2333         else if (addr->sa_family == AF_INET6) {
2334             salen = sizeof(struct sockaddr_in6);
2335         }
2336 #endif
2337
2338         return connect(fd, addr, salen);
2339 }