Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
[samba.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba system utilities
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison  1998-2005
6    Copyright (C) Timur Bakeyev        2005
7    Copyright (C) Bjoern Jacke    2006-2007
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
27 #endif
28
29 /*
30    The idea is that this file will eventually have wrappers around all
31    important system calls in samba. The aims are:
32
33    - to enable easier porting by putting OS dependent stuff in here
34
35    - to allow for hooks into other "pseudo-filesystems"
36
37    - to allow easier integration of things like the japanese extensions
38
39    - to support the philosophy of Samba to expose the features of
40      the OS within the SMB model. In general whatever file/printer/variable
41      expansions/etc make sense to the OS should be acceptable to Samba.
42 */
43
44
45
46 /*******************************************************************
47  A wrapper for memalign
48 ********************************************************************/
49
50 void *sys_memalign( size_t align, size_t size )
51 {
52 #if defined(HAVE_POSIX_MEMALIGN)
53         void *p = NULL;
54         int ret = posix_memalign( &p, align, size );
55         if ( ret == 0 )
56                 return p;
57                 
58         return NULL;
59 #elif defined(HAVE_MEMALIGN)
60         return memalign( align, size );
61 #else
62         /* On *BSD systems memaligns doesn't exist, but memory will
63          * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67         size_t pagesize = (size_t)getpagesize();
68 #else
69         size_t pagesize = (size_t)-1;
70 #endif
71         if (pagesize == (size_t)-1) {
72                 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73                 return NULL;
74         }
75         if (size < pagesize) {
76                 size = pagesize;
77         }
78         return SMB_MALLOC(size);
79 #endif
80 }
81
82 /*******************************************************************
83  A wrapper for usleep in case we don't have one.
84 ********************************************************************/
85
86 int sys_usleep(long usecs)
87 {
88 #ifndef HAVE_USLEEP
89         struct timeval tval;
90 #endif
91
92         /*
93          * We need this braindamage as the glibc usleep
94          * is not SPEC1170 complient... grumble... JRA.
95          */
96
97         if(usecs < 0 || usecs > 1000000) {
98                 errno = EINVAL;
99                 return -1;
100         }
101
102 #if HAVE_USLEEP
103         usleep(usecs);
104         return 0;
105 #else /* HAVE_USLEEP */
106         /*
107          * Fake it with select...
108          */
109         tval.tv_sec = 0;
110         tval.tv_usec = usecs/1000;
111         select(0,NULL,NULL,NULL,&tval);
112         return 0;
113 #endif /* HAVE_USLEEP */
114 }
115
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
119
120 ssize_t sys_read(int fd, void *buf, size_t count)
121 {
122         ssize_t ret;
123
124         do {
125                 ret = read(fd, buf, count);
126         } while (ret == -1 && errno == EINTR);
127         return ret;
128 }
129
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
133
134 ssize_t sys_write(int fd, const void *buf, size_t count)
135 {
136         ssize_t ret;
137
138         do {
139                 ret = write(fd, buf, count);
140         } while (ret == -1 && errno == EINTR);
141         return ret;
142 }
143
144 /*******************************************************************
145 A pread wrapper that will deal with EINTR and 64-bit file offsets.
146 ********************************************************************/
147
148 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
149 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
150 {
151         ssize_t ret;
152
153         do {
154 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
155                 ret = pread64(fd, buf, count, off);
156 #else
157                 ret = pread(fd, buf, count, off);
158 #endif
159         } while (ret == -1 && errno == EINTR);
160         return ret;
161 }
162 #endif
163
164 /*******************************************************************
165 A write wrapper that will deal with EINTR and 64-bit file offsets.
166 ********************************************************************/
167
168 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
169 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
170 {
171         ssize_t ret;
172
173         do {
174 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
175                 ret = pwrite64(fd, buf, count, off);
176 #else
177                 ret = pwrite(fd, buf, count, off);
178 #endif
179         } while (ret == -1 && errno == EINTR);
180         return ret;
181 }
182 #endif
183
184 /*******************************************************************
185 A send wrapper that will deal with EINTR.
186 ********************************************************************/
187
188 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
189 {
190         ssize_t ret;
191
192         do {
193                 ret = send(s, msg, len, flags);
194         } while (ret == -1 && errno == EINTR);
195         return ret;
196 }
197
198 /*******************************************************************
199 A sendto wrapper that will deal with EINTR.
200 ********************************************************************/
201
202 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
203 {
204         ssize_t ret;
205
206         do {
207                 ret = sendto(s, msg, len, flags, to, tolen);
208         } while (ret == -1 && errno == EINTR);
209         return ret;
210 }
211
212 /*******************************************************************
213 A recv wrapper that will deal with EINTR.
214 ********************************************************************/
215
216 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
217 {
218         ssize_t ret;
219
220         do {
221                 ret = recv(fd, buf, count, flags);
222         } while (ret == -1 && errno == EINTR);
223         return ret;
224 }
225
226 /*******************************************************************
227 A recvfrom wrapper that will deal with EINTR.
228 ********************************************************************/
229
230 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
231 {
232         ssize_t ret;
233
234         do {
235                 ret = recvfrom(s, buf, len, flags, from, fromlen);
236         } while (ret == -1 && errno == EINTR);
237         return ret;
238 }
239
240 /*******************************************************************
241 A fcntl wrapper that will deal with EINTR.
242 ********************************************************************/
243
244 int sys_fcntl_ptr(int fd, int cmd, void *arg)
245 {
246         int ret;
247
248         do {
249                 ret = fcntl(fd, cmd, arg);
250         } while (ret == -1 && errno == EINTR);
251         return ret;
252 }
253
254 /*******************************************************************
255 A fcntl wrapper that will deal with EINTR.
256 ********************************************************************/
257
258 int sys_fcntl_long(int fd, int cmd, long arg)
259 {
260         int ret;
261
262         do {
263                 ret = fcntl(fd, cmd, arg);
264         } while (ret == -1 && errno == EINTR);
265         return ret;
266 }
267
268 /*******************************************************************
269 A stat() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
271
272 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
273 {
274         int ret;
275 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
276         ret = stat64(fname, sbuf);
277 #else
278         ret = stat(fname, sbuf);
279 #endif
280         /* we always want directories to appear zero size */
281         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
282         return ret;
283 }
284
285 /*******************************************************************
286  An fstat() wrapper that will deal with 64 bit filesizes.
287 ********************************************************************/
288
289 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
290 {
291         int ret;
292 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
293         ret = fstat64(fd, sbuf);
294 #else
295         ret = fstat(fd, sbuf);
296 #endif
297         /* we always want directories to appear zero size */
298         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
299         return ret;
300 }
301
302 /*******************************************************************
303  An lstat() wrapper that will deal with 64 bit filesizes.
304 ********************************************************************/
305
306 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
307 {
308         int ret;
309 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
310         ret = lstat64(fname, sbuf);
311 #else
312         ret = lstat(fname, sbuf);
313 #endif
314         /* we always want directories to appear zero size */
315         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
316         return ret;
317 }
318
319 /*******************************************************************
320  An ftruncate() wrapper that will deal with 64 bit filesizes.
321 ********************************************************************/
322
323 int sys_ftruncate(int fd, SMB_OFF_T offset)
324 {
325 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
326         return ftruncate64(fd, offset);
327 #else
328         return ftruncate(fd, offset);
329 #endif
330 }
331
332 /*******************************************************************
333  An lseek() wrapper that will deal with 64 bit filesizes.
334 ********************************************************************/
335
336 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
337 {
338 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
339         return lseek64(fd, offset, whence);
340 #else
341         return lseek(fd, offset, whence);
342 #endif
343 }
344
345 /*******************************************************************
346  An fseek() wrapper that will deal with 64 bit filesizes.
347 ********************************************************************/
348
349 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
350 {
351 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
352         return fseek64(fp, offset, whence);
353 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
354         return fseeko64(fp, offset, whence);
355 #else
356         return fseek(fp, offset, whence);
357 #endif
358 }
359
360 /*******************************************************************
361  An ftell() wrapper that will deal with 64 bit filesizes.
362 ********************************************************************/
363
364 SMB_OFF_T sys_ftell(FILE *fp)
365 {
366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
367         return (SMB_OFF_T)ftell64(fp);
368 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
369         return (SMB_OFF_T)ftello64(fp);
370 #else
371         return (SMB_OFF_T)ftell(fp);
372 #endif
373 }
374
375 /*******************************************************************
376  A creat() wrapper that will deal with 64 bit filesizes.
377 ********************************************************************/
378
379 int sys_creat(const char *path, mode_t mode)
380 {
381 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
382         return creat64(path, mode);
383 #else
384         /*
385          * If creat64 isn't defined then ensure we call a potential open64.
386          * JRA.
387          */
388         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
389 #endif
390 }
391
392 /*******************************************************************
393  An open() wrapper that will deal with 64 bit filesizes.
394 ********************************************************************/
395
396 int sys_open(const char *path, int oflag, mode_t mode)
397 {
398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
399         return open64(path, oflag, mode);
400 #else
401         return open(path, oflag, mode);
402 #endif
403 }
404
405 /*******************************************************************
406  An fopen() wrapper that will deal with 64 bit filesizes.
407 ********************************************************************/
408
409 FILE *sys_fopen(const char *path, const char *type)
410 {
411 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
412         return fopen64(path, type);
413 #else
414         return fopen(path, type);
415 #endif
416 }
417
418
419 /*******************************************************************
420  A flock() wrapper that will perform the kernel flock.
421 ********************************************************************/
422
423 void kernel_flock(int fd, uint32 share_mode)
424 {
425 #if HAVE_KERNEL_SHARE_MODES
426         int kernel_mode = 0;
427         if (share_mode == FILE_SHARE_WRITE) {
428                 kernel_mode = LOCK_MAND|LOCK_WRITE;
429         } else if (share_mode == FILE_SHARE_READ) {
430                 kernel_mode = LOCK_MAND|LOCK_READ;
431         } else if (share_mode == FILE_SHARE_NONE) {
432                 kernel_mode = LOCK_MAND;
433         }
434         if (kernel_mode) {
435                 flock(fd, kernel_mode);
436         }
437 #endif
438         ;
439 }
440
441
442
443 /*******************************************************************
444  An opendir wrapper that will deal with 64 bit filesizes.
445 ********************************************************************/
446
447 SMB_STRUCT_DIR *sys_opendir(const char *name)
448 {
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
450         return opendir64(name);
451 #else
452         return opendir(name);
453 #endif
454 }
455
456 /*******************************************************************
457  A readdir wrapper that will deal with 64 bit filesizes.
458 ********************************************************************/
459
460 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
461 {
462 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
463         return readdir64(dirp);
464 #else
465         return readdir(dirp);
466 #endif
467 }
468
469 /*******************************************************************
470  A seekdir wrapper that will deal with 64 bit filesizes.
471 ********************************************************************/
472
473 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
474 {
475 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
476         seekdir64(dirp, offset);
477 #else
478         seekdir(dirp, offset);
479 #endif
480 }
481
482 /*******************************************************************
483  A telldir wrapper that will deal with 64 bit filesizes.
484 ********************************************************************/
485
486 long sys_telldir(SMB_STRUCT_DIR *dirp)
487 {
488 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
489         return (long)telldir64(dirp);
490 #else
491         return (long)telldir(dirp);
492 #endif
493 }
494
495 /*******************************************************************
496  A rewinddir wrapper that will deal with 64 bit filesizes.
497 ********************************************************************/
498
499 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
500 {
501 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
502         rewinddir64(dirp);
503 #else
504         rewinddir(dirp);
505 #endif
506 }
507
508 /*******************************************************************
509  A close wrapper that will deal with 64 bit filesizes.
510 ********************************************************************/
511
512 int sys_closedir(SMB_STRUCT_DIR *dirp)
513 {
514 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
515         return closedir64(dirp);
516 #else
517         return closedir(dirp);
518 #endif
519 }
520
521 /*******************************************************************
522  An mknod() wrapper that will deal with 64 bit filesizes.
523 ********************************************************************/
524
525 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
526 {
527 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
528 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
529         return mknod64(path, mode, dev);
530 #else
531         return mknod(path, mode, dev);
532 #endif
533 #else
534         /* No mknod system call. */
535         errno = ENOSYS;
536         return -1;
537 #endif
538 }
539
540 /*******************************************************************
541 The wait() calls vary between systems
542 ********************************************************************/
543
544 int sys_waitpid(pid_t pid,int *status,int options)
545 {
546 #ifdef HAVE_WAITPID
547         return waitpid(pid,status,options);
548 #else /* HAVE_WAITPID */
549         return wait4(pid, status, options, NULL);
550 #endif /* HAVE_WAITPID */
551 }
552
553 /*******************************************************************
554  System wrapper for getwd
555 ********************************************************************/
556
557 char *sys_getwd(char *s)
558 {
559         char *wd;
560 #ifdef HAVE_GETCWD
561         wd = (char *)getcwd(s, PATH_MAX);
562 #else
563         wd = (char *)getwd(s);
564 #endif
565         return wd;
566 }
567
568 #if defined(HAVE_POSIX_CAPABILITIES)
569
570 /**************************************************************************
571  Try and abstract process capabilities (for systems that have them).
572 ****************************************************************************/
573
574 /* Set the POSIX capabilities needed for the given purpose into the effective
575  * capability set of the current process. Make sure they are always removed
576  * from the inheritable set, because there is no circumstance in which our
577  * children should inherit our elevated privileges.
578  */
579 static bool set_process_capability(enum smbd_capability capability,
580                                    bool enable)
581 {
582         cap_value_t cap_vals[2] = {0};
583         int num_cap_vals = 0;
584
585         cap_t cap;
586
587 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
588         /* On Linux, make sure that any capabilities we grab are sticky
589          * across UID changes. We expect that this would allow us to keep both
590          * the effective and permitted capability sets, but as of circa 2.6.16,
591          * only the permitted set is kept. It is a bug (which we work around)
592          * that the effective set is lost, but we still require the effective
593          * set to be kept.
594          */
595         if (!prctl(PR_GET_KEEPCAPS)) {
596                 prctl(PR_SET_KEEPCAPS, 1);
597         }
598 #endif
599
600         cap = cap_get_proc();
601         if (cap == NULL) {
602                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
603                         strerror(errno)));
604                 return False;
605         }
606
607         switch (capability) {
608                 case KERNEL_OPLOCK_CAPABILITY:
609 #ifdef CAP_NETWORK_MGT
610                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
611                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
612 #endif
613                         break;
614                 case DMAPI_ACCESS_CAPABILITY:
615 #ifdef CAP_DEVICE_MGT
616                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
617                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
618 #elif CAP_MKNOD
619                         /* Linux has CAP_MKNOD for DMAPI access. */
620                         cap_vals[num_cap_vals++] = CAP_MKNOD;
621 #endif
622                         break;
623                 case LEASE_CAPABILITY:
624 #ifdef CAP_LEASE
625                         cap_vals[num_cap_vals++] = CAP_LEASE;
626 #endif
627                         break;
628         }
629
630         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
631
632         if (num_cap_vals == 0) {
633                 cap_free(cap);
634                 return True;
635         }
636
637         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
638                 enable ? CAP_SET : CAP_CLEAR);
639
640         /* We never want to pass capabilities down to our children, so make
641          * sure they are not inherited.
642          */
643         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
644
645         if (cap_set_proc(cap) == -1) {
646                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
647                         strerror(errno)));
648                 cap_free(cap);
649                 return False;
650         }
651
652         cap_free(cap);
653         return True;
654 }
655
656 #endif /* HAVE_POSIX_CAPABILITIES */
657
658 /****************************************************************************
659  Gain the oplock capability from the kernel if possible.
660 ****************************************************************************/
661
662 void set_effective_capability(enum smbd_capability capability)
663 {
664 #if defined(HAVE_POSIX_CAPABILITIES)
665         set_process_capability(capability, True);
666 #endif /* HAVE_POSIX_CAPABILITIES */
667 }
668
669 void drop_effective_capability(enum smbd_capability capability)
670 {
671 #if defined(HAVE_POSIX_CAPABILITIES)
672         set_process_capability(capability, False);
673 #endif /* HAVE_POSIX_CAPABILITIES */
674 }
675
676 /**************************************************************************
677  Wrapper for random().
678 ****************************************************************************/
679
680 long sys_random(void)
681 {
682 #if defined(HAVE_RANDOM)
683         return (long)random();
684 #elif defined(HAVE_RAND)
685         return (long)rand();
686 #else
687         DEBUG(0,("Error - no random function available !\n"));
688         exit(1);
689 #endif
690 }
691
692 /**************************************************************************
693  Wrapper for srandom().
694 ****************************************************************************/
695
696 void sys_srandom(unsigned int seed)
697 {
698 #if defined(HAVE_SRANDOM)
699         srandom(seed);
700 #elif defined(HAVE_SRAND)
701         srand(seed);
702 #else
703         DEBUG(0,("Error - no srandom function available !\n"));
704         exit(1);
705 #endif
706 }
707
708 /**************************************************************************
709  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
710 ****************************************************************************/
711
712 int groups_max(void)
713 {
714 #if defined(SYSCONF_SC_NGROUPS_MAX)
715         int ret = sysconf(_SC_NGROUPS_MAX);
716         return (ret == -1) ? NGROUPS_MAX : ret;
717 #else
718         return NGROUPS_MAX;
719 #endif
720 }
721
722 /**************************************************************************
723  Wrap setgroups and getgroups for systems that declare getgroups() as
724  returning an array of gid_t, but actuall return an array of int.
725 ****************************************************************************/
726
727 #if defined(HAVE_BROKEN_GETGROUPS)
728 static int sys_broken_getgroups(int setlen, gid_t *gidset)
729 {
730         GID_T gid;
731         GID_T *group_list;
732         int i, ngroups;
733
734         if(setlen == 0) {
735                 return getgroups(setlen, &gid);
736         }
737
738         /*
739          * Broken case. We need to allocate a
740          * GID_T array of size setlen.
741          */
742
743         if(setlen < 0) {
744                 errno = EINVAL; 
745                 return -1;
746         } 
747
748         if (setlen == 0)
749                 setlen = groups_max();
750
751         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
752                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
753                 return -1;
754         }
755
756         if((ngroups = getgroups(setlen, group_list)) < 0) {
757                 int saved_errno = errno;
758                 SAFE_FREE(group_list);
759                 errno = saved_errno;
760                 return -1;
761         }
762
763         for(i = 0; i < ngroups; i++)
764                 gidset[i] = (gid_t)group_list[i];
765
766         SAFE_FREE(group_list);
767         return ngroups;
768 }
769
770 static int sys_broken_setgroups(int setlen, gid_t *gidset)
771 {
772         GID_T *group_list;
773         int i ; 
774
775         if (setlen == 0)
776                 return 0 ;
777
778         if (setlen < 0 || setlen > groups_max()) {
779                 errno = EINVAL; 
780                 return -1;   
781         }
782
783         /*
784          * Broken case. We need to allocate a
785          * GID_T array of size setlen.
786          */
787
788         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
789                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
790                 return -1;    
791         }
792  
793         for(i = 0; i < setlen; i++) 
794                 group_list[i] = (GID_T) gidset[i]; 
795
796         if(setgroups(setlen, group_list) != 0) {
797                 int saved_errno = errno;
798                 SAFE_FREE(group_list);
799                 errno = saved_errno;
800                 return -1;
801         }
802  
803         SAFE_FREE(group_list);
804         return 0 ;
805 }
806
807 #endif /* HAVE_BROKEN_GETGROUPS */
808
809 /* This is a list of systems that require the first GID passed to setgroups(2)
810  * to be the effective GID. If your system is one of these, add it here.
811  */
812 #if defined (FREEBSD) || defined (DARWINOS)
813 #define USE_BSD_SETGROUPS
814 #endif
815
816 #if defined(USE_BSD_SETGROUPS)
817 /* Depending on the particular BSD implementation, the first GID that is
818  * passed to setgroups(2) will either be ignored or will set the credential's
819  * effective GID. In either case, the right thing to do is to guarantee that
820  * gidset[0] is the effective GID.
821  */
822 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
823 {
824         gid_t *new_gidset = NULL;
825         int max;
826         int ret;
827
828         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
829         max = groups_max();
830
831         /* No group list, just make sure we are setting the efective GID. */
832         if (setlen == 0) {
833                 return setgroups(1, &primary_gid);
834         }
835
836         /* If the primary gid is not the first array element, grow the array
837          * and insert it at the front.
838          */
839         if (gidset[0] != primary_gid) {
840                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
841                 if (new_gidset == NULL) {
842                         return -1;
843                 }
844
845                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
846                 new_gidset[0] = primary_gid;
847                 setlen++;
848         }
849
850         if (setlen > max) {
851                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
852                         setlen, max));
853                 setlen = max;
854         }
855
856 #if defined(HAVE_BROKEN_GETGROUPS)
857         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
858 #else
859         ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
860 #endif
861
862         if (new_gidset) {
863                 int errsav = errno;
864                 SAFE_FREE(new_gidset);
865                 errno = errsav;
866         }
867
868         return ret;
869 }
870
871 #endif /* USE_BSD_SETGROUPS */
872
873 /**************************************************************************
874  Wrapper for getgroups. Deals with broken (int) case.
875 ****************************************************************************/
876
877 int sys_getgroups(int setlen, gid_t *gidset)
878 {
879 #if defined(HAVE_BROKEN_GETGROUPS)
880         return sys_broken_getgroups(setlen, gidset);
881 #else
882         return getgroups(setlen, gidset);
883 #endif
884 }
885
886 /**************************************************************************
887  Wrapper for setgroups. Deals with broken (int) case and BSD case.
888 ****************************************************************************/
889
890 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
891 {
892 #if !defined(HAVE_SETGROUPS)
893         errno = ENOSYS;
894         return -1;
895 #endif /* HAVE_SETGROUPS */
896
897 #if defined(USE_BSD_SETGROUPS)
898         return sys_bsd_setgroups(primary_gid, setlen, gidset);
899 #elif defined(HAVE_BROKEN_GETGROUPS)
900         return sys_broken_setgroups(setlen, gidset);
901 #else
902         return setgroups(setlen, gidset);
903 #endif
904 }
905
906 /**************************************************************************
907  Wrappers for setpwent(), getpwent() and endpwent()
908 ****************************************************************************/
909
910 void sys_setpwent(void)
911 {
912         setpwent();
913 }
914
915 struct passwd *sys_getpwent(void)
916 {
917         return getpwent();
918 }
919
920 void sys_endpwent(void)
921 {
922         endpwent();
923 }
924
925 /**************************************************************************
926  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
927 ****************************************************************************/
928
929
930 struct passwd *sys_getpwnam(const char *name)
931 {
932         return getpwnam(name);
933 }
934
935 struct passwd *sys_getpwuid(uid_t uid)
936 {
937         return getpwuid(uid);
938 }
939
940 struct group *sys_getgrnam(const char *name)
941 {
942         return getgrnam(name);
943 }
944
945 struct group *sys_getgrgid(gid_t gid)
946 {
947         return getgrgid(gid);
948 }
949
950 /**************************************************************************
951  Extract a command into an arg list.
952 ****************************************************************************/
953
954 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
955 {
956         char *trunc_cmd;
957         char *saveptr;
958         char *ptr;
959         int argcl;
960         char **argl = NULL;
961         int i;
962
963         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
964                 DEBUG(0, ("talloc failed\n"));
965                 goto nomem;
966         }
967
968         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
969                 TALLOC_FREE(trunc_cmd);
970                 errno = EINVAL;
971                 return NULL;
972         }
973
974         /*
975          * Count the args.
976          */
977
978         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
979                 argcl++;
980
981         TALLOC_FREE(trunc_cmd);
982
983         if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
984                 goto nomem;
985         }
986
987         /*
988          * Now do the extraction.
989          */
990
991         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
992                 goto nomem;
993         }
994
995         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
996         i = 0;
997
998         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
999                 goto nomem;
1000         }
1001
1002         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1003
1004                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1005                         goto nomem;
1006                 }
1007         }
1008
1009         argl[i++] = NULL;
1010         return argl;
1011
1012  nomem:
1013         DEBUG(0, ("talloc failed\n"));
1014         TALLOC_FREE(trunc_cmd);
1015         TALLOC_FREE(argl);
1016         errno = ENOMEM;
1017         return NULL;
1018 }
1019
1020 /**************************************************************************
1021  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1022  a sys_getpid() that only does a system call *once*.
1023 ****************************************************************************/
1024
1025 static pid_t mypid = (pid_t)-1;
1026
1027 pid_t sys_fork(void)
1028 {
1029         pid_t forkret = fork();
1030
1031         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1032                 mypid = (pid_t) -1;
1033
1034         return forkret;
1035 }
1036
1037 /**************************************************************************
1038  Wrapper for getpid. Ensures we only do a system call *once*.
1039 ****************************************************************************/
1040
1041 pid_t sys_getpid(void)
1042 {
1043         if (mypid == (pid_t)-1)
1044                 mypid = getpid();
1045
1046         return mypid;
1047 }
1048
1049 /**************************************************************************
1050  Wrapper for popen. Safer as it doesn't search a path.
1051  Modified from the glibc sources.
1052  modified by tridge to return a file descriptor. We must kick our FILE* habit
1053 ****************************************************************************/
1054
1055 typedef struct _popen_list
1056 {
1057         int fd;
1058         pid_t child_pid;
1059         struct _popen_list *next;
1060 } popen_list;
1061
1062 static popen_list *popen_chain;
1063
1064 int sys_popen(const char *command)
1065 {
1066         int parent_end, child_end;
1067         int pipe_fds[2];
1068         popen_list *entry = NULL;
1069         char **argl = NULL;
1070
1071         if (pipe(pipe_fds) < 0)
1072                 return -1;
1073
1074         parent_end = pipe_fds[0];
1075         child_end = pipe_fds[1];
1076
1077         if (!*command) {
1078                 errno = EINVAL;
1079                 goto err_exit;
1080         }
1081
1082         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1083                 goto err_exit;
1084
1085         ZERO_STRUCTP(entry);
1086
1087         /*
1088          * Extract the command and args into a NULL terminated array.
1089          */
1090
1091         if(!(argl = extract_args(NULL, command)))
1092                 goto err_exit;
1093
1094         entry->child_pid = sys_fork();
1095
1096         if (entry->child_pid == -1) {
1097                 goto err_exit;
1098         }
1099
1100         if (entry->child_pid == 0) {
1101
1102                 /*
1103                  * Child !
1104                  */
1105
1106                 int child_std_end = STDOUT_FILENO;
1107                 popen_list *p;
1108
1109                 close(parent_end);
1110                 if (child_end != child_std_end) {
1111                         dup2 (child_end, child_std_end);
1112                         close (child_end);
1113                 }
1114
1115                 /*
1116                  * POSIX.2:  "popen() shall ensure that any streams from previous
1117                  * popen() calls that remain open in the parent process are closed
1118                  * in the new child process."
1119                  */
1120
1121                 for (p = popen_chain; p; p = p->next)
1122                         close(p->fd);
1123
1124                 execv(argl[0], argl);
1125                 _exit (127);
1126         }
1127
1128         /*
1129          * Parent.
1130          */
1131
1132         close (child_end);
1133         TALLOC_FREE(argl);
1134
1135         /* Link into popen_chain. */
1136         entry->next = popen_chain;
1137         popen_chain = entry;
1138         entry->fd = parent_end;
1139
1140         return entry->fd;
1141
1142 err_exit:
1143
1144         SAFE_FREE(entry);
1145         SAFE_FREE(argl);
1146         close(pipe_fds[0]);
1147         close(pipe_fds[1]);
1148         return -1;
1149 }
1150
1151 /**************************************************************************
1152  Wrapper for pclose. Modified from the glibc sources.
1153 ****************************************************************************/
1154
1155 int sys_pclose(int fd)
1156 {
1157         int wstatus;
1158         popen_list **ptr = &popen_chain;
1159         popen_list *entry = NULL;
1160         pid_t wait_pid;
1161         int status = -1;
1162
1163         /* Unlink from popen_chain. */
1164         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1165                 if ((*ptr)->fd == fd) {
1166                         entry = *ptr;
1167                         *ptr = (*ptr)->next;
1168                         status = 0;
1169                         break;
1170                 }
1171         }
1172
1173         if (status < 0 || close(entry->fd) < 0)
1174                 return -1;
1175
1176         /*
1177          * As Samba is catching and eating child process
1178          * exits we don't really care about the child exit
1179          * code, a -1 with errno = ECHILD will do fine for us.
1180          */
1181
1182         do {
1183                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1184         } while (wait_pid == -1 && errno == EINTR);
1185
1186         SAFE_FREE(entry);
1187
1188         if (wait_pid == -1)
1189                 return -1;
1190         return wstatus;
1191 }
1192
1193 /**************************************************************************
1194  Wrapper for Admin Logs.
1195 ****************************************************************************/
1196
1197  void sys_adminlog(int priority, const char *format_str, ...) 
1198 {
1199         va_list ap;
1200         int ret;
1201         char *msgbuf = NULL;
1202
1203         va_start( ap, format_str );
1204         ret = vasprintf( &msgbuf, format_str, ap );
1205         va_end( ap );
1206
1207         if (ret == -1)
1208                 return;
1209
1210 #if defined(HAVE_SYSLOG)
1211         syslog( priority, "%s", msgbuf );
1212 #else
1213         DEBUG(0,("%s", msgbuf ));
1214 #endif
1215         SAFE_FREE(msgbuf);
1216 }
1217
1218 /******** Solaris EA helper function prototypes ********/
1219 #ifdef HAVE_ATTROPEN
1220 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1221 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1222 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1223 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1224 static int solaris_unlinkat(int attrdirfd, const char *name);
1225 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1226 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1227 #endif
1228
1229 /**************************************************************************
1230  Wrappers for extented attribute calls. Based on the Linux package with
1231  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1232 ****************************************************************************/
1233
1234 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1235 {
1236 #if defined(HAVE_GETXATTR)
1237 #ifndef XATTR_ADD_OPT
1238         return getxattr(path, name, value, size);
1239 #else
1240         int options = 0;
1241         return getxattr(path, name, value, size, 0, options);
1242 #endif
1243 #elif defined(HAVE_GETEA)
1244         return getea(path, name, value, size);
1245 #elif defined(HAVE_EXTATTR_GET_FILE)
1246         char *s;
1247         ssize_t retval;
1248         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1249                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1250         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1251         /*
1252          * The BSD implementation has a nasty habit of silently truncating
1253          * the returned value to the size of the buffer, so we have to check
1254          * that the buffer is large enough to fit the returned value.
1255          */
1256         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1257                 if(retval > size) {
1258                         errno = ERANGE;
1259                         return -1;
1260                 }
1261                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1262                         return retval;
1263         }
1264
1265         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1266         return -1;
1267 #elif defined(HAVE_ATTR_GET)
1268         int retval, flags = 0;
1269         int valuelength = (int)size;
1270         char *attrname = strchr(name,'.') + 1;
1271         
1272         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1273
1274         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1275
1276         return retval ? retval : valuelength;
1277 #elif defined(HAVE_ATTROPEN)
1278         ssize_t ret = -1;
1279         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1280         if (attrfd >= 0) {
1281                 ret = solaris_read_xattr(attrfd, value, size);
1282                 close(attrfd);
1283         }
1284         return ret;
1285 #else
1286         errno = ENOSYS;
1287         return -1;
1288 #endif
1289 }
1290
1291 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1292 {
1293 #if defined(HAVE_LGETXATTR)
1294         return lgetxattr(path, name, value, size);
1295 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1296         int options = XATTR_NOFOLLOW;
1297         return getxattr(path, name, value, size, 0, options);
1298 #elif defined(HAVE_LGETEA)
1299         return lgetea(path, name, value, size);
1300 #elif defined(HAVE_EXTATTR_GET_LINK)
1301         char *s;
1302         ssize_t retval;
1303         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1304                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1305         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1306
1307         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1308                 if(retval > size) {
1309                         errno = ERANGE;
1310                         return -1;
1311                 }
1312                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1313                         return retval;
1314         }
1315         
1316         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1317         return -1;
1318 #elif defined(HAVE_ATTR_GET)
1319         int retval, flags = ATTR_DONTFOLLOW;
1320         int valuelength = (int)size;
1321         char *attrname = strchr(name,'.') + 1;
1322         
1323         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1324
1325         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1326
1327         return retval ? retval : valuelength;
1328 #elif defined(HAVE_ATTROPEN)
1329         ssize_t ret = -1;
1330         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1331         if (attrfd >= 0) {
1332                 ret = solaris_read_xattr(attrfd, value, size);
1333                 close(attrfd);
1334         }
1335         return ret;
1336 #else
1337         errno = ENOSYS;
1338         return -1;
1339 #endif
1340 }
1341
1342 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1343 {
1344 #if defined(HAVE_FGETXATTR)
1345 #ifndef XATTR_ADD_OPT
1346         return fgetxattr(filedes, name, value, size);
1347 #else
1348         int options = 0;
1349         return fgetxattr(filedes, name, value, size, 0, options);
1350 #endif
1351 #elif defined(HAVE_FGETEA)
1352         return fgetea(filedes, name, value, size);
1353 #elif defined(HAVE_EXTATTR_GET_FD)
1354         char *s;
1355         ssize_t retval;
1356         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1357                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1358         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1359
1360         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1361                 if(retval > size) {
1362                         errno = ERANGE;
1363                         return -1;
1364                 }
1365                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1366                         return retval;
1367         }
1368         
1369         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1370         return -1;
1371 #elif defined(HAVE_ATTR_GETF)
1372         int retval, flags = 0;
1373         int valuelength = (int)size;
1374         char *attrname = strchr(name,'.') + 1;
1375         
1376         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1377
1378         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1379
1380         return retval ? retval : valuelength;
1381 #elif defined(HAVE_ATTROPEN)
1382         ssize_t ret = -1;
1383         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1384         if (attrfd >= 0) {
1385                 ret = solaris_read_xattr(attrfd, value, size);
1386                 close(attrfd);
1387         }
1388         return ret;
1389 #else
1390         errno = ENOSYS;
1391         return -1;
1392 #endif
1393 }
1394
1395 #if defined(HAVE_EXTATTR_LIST_FILE)
1396
1397 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1398
1399 static struct {
1400         int space;
1401         const char *name;
1402         size_t len;
1403
1404 extattr[] = {
1405         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1406         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1407 };
1408
1409 typedef union {
1410         const char *path;
1411         int filedes;
1412 } extattr_arg;
1413
1414 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1415 {
1416         ssize_t list_size, total_size = 0;
1417         int i, t, len;
1418         char *buf;
1419         /* Iterate through extattr(2) namespaces */
1420         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1421                 switch(type) {
1422 #if defined(HAVE_EXTATTR_LIST_FILE)
1423                         case 0:
1424                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1425                                 break;
1426 #endif
1427 #if defined(HAVE_EXTATTR_LIST_LINK)
1428                         case 1:
1429                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1430                                 break;
1431 #endif
1432 #if defined(HAVE_EXTATTR_LIST_FD)
1433                         case 2:
1434                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1435                                 break;
1436 #endif
1437                         default:
1438                                 errno = ENOSYS;
1439                                 return -1;
1440                 }
1441                 /* Some error happend. Errno should be set by the previous call */
1442                 if(list_size < 0)
1443                         return -1;
1444                 /* No attributes */
1445                 if(list_size == 0)
1446                         continue;
1447                 /* XXX: Call with an empty buffer may be used to calculate
1448                    necessary buffer size. Unfortunately, we can't say, how
1449                    many attributes were returned, so here is the potential
1450                    problem with the emulation.
1451                 */
1452                 if(list == NULL) {
1453                         /* Take the worse case of one char attribute names - 
1454                            two bytes per name plus one more for sanity.
1455                         */
1456                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1457                         continue;
1458                 }
1459                 /* Count necessary offset to fit namespace prefixes */
1460                 len = 0;
1461                 for(i = 0; i < list_size; i += list[i] + 1)
1462                         len += extattr[t].len;
1463
1464                 total_size += list_size + len;
1465                 /* Buffer is too small to fit the results */
1466                 if(total_size > size) {
1467                         errno = ERANGE;
1468                         return -1;
1469                 }
1470                 /* Shift results back, so we can prepend prefixes */
1471                 buf = memmove(list + len, list, list_size);
1472
1473                 for(i = 0; i < list_size; i += len + 1) {
1474                         len = buf[i];
1475                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1476                         list += extattr[t].len;
1477                         strncpy(list, buf + i + 1, len);
1478                         list[len] = '\0';
1479                         list += len + 1;
1480                 }
1481                 size -= total_size;
1482         }
1483         return total_size;
1484 }
1485
1486 #endif
1487
1488 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1489 static char attr_buffer[ATTR_MAX_VALUELEN];
1490
1491 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1492 {
1493         int retval = 0, index;
1494         attrlist_cursor_t *cursor = 0;
1495         int total_size = 0;
1496         attrlist_t * al = (attrlist_t *)attr_buffer;
1497         attrlist_ent_t *ae;
1498         size_t ent_size, left = size;
1499         char *bp = list;
1500
1501         while (True) {
1502             if (filedes)
1503                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1504             else
1505                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1506             if (retval) break;
1507             for (index = 0; index < al->al_count; index++) {
1508                 ae = ATTR_ENTRY(attr_buffer, index);
1509                 ent_size = strlen(ae->a_name) + sizeof("user.");
1510                 if (left >= ent_size) {
1511                     strncpy(bp, "user.", sizeof("user."));
1512                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1513                     bp += ent_size;
1514                     left -= ent_size;
1515                 } else if (size) {
1516                     errno = ERANGE;
1517                     retval = -1;
1518                     break;
1519                 }
1520                 total_size += ent_size;
1521             }
1522             if (al->al_more == 0) break;
1523         }
1524         if (retval == 0) {
1525             flags |= ATTR_ROOT;
1526             cursor = 0;
1527             while (True) {
1528                 if (filedes)
1529                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1530                 else
1531                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1532                 if (retval) break;
1533                 for (index = 0; index < al->al_count; index++) {
1534                     ae = ATTR_ENTRY(attr_buffer, index);
1535                     ent_size = strlen(ae->a_name) + sizeof("system.");
1536                     if (left >= ent_size) {
1537                         strncpy(bp, "system.", sizeof("system."));
1538                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1539                         bp += ent_size;
1540                         left -= ent_size;
1541                     } else if (size) {
1542                         errno = ERANGE;
1543                         retval = -1;
1544                         break;
1545                     }
1546                     total_size += ent_size;
1547                 }
1548                 if (al->al_more == 0) break;
1549             }
1550         }
1551         return (ssize_t)(retval ? retval : total_size);
1552 }
1553
1554 #endif
1555
1556 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1557 {
1558 #if defined(HAVE_LISTXATTR)
1559 #ifndef XATTR_ADD_OPT
1560         return listxattr(path, list, size);
1561 #else
1562         int options = 0;
1563         return listxattr(path, list, size, options);
1564 #endif
1565 #elif defined(HAVE_LISTEA)
1566         return listea(path, list, size);
1567 #elif defined(HAVE_EXTATTR_LIST_FILE)
1568         extattr_arg arg;
1569         arg.path = path;
1570         return bsd_attr_list(0, arg, list, size);
1571 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1572         return irix_attr_list(path, 0, list, size, 0);
1573 #elif defined(HAVE_ATTROPEN)
1574         ssize_t ret = -1;
1575         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1576         if (attrdirfd >= 0) {
1577                 ret = solaris_list_xattr(attrdirfd, list, size);
1578                 close(attrdirfd);
1579         }
1580         return ret;
1581 #else
1582         errno = ENOSYS;
1583         return -1;
1584 #endif
1585 }
1586
1587 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1588 {
1589 #if defined(HAVE_LLISTXATTR)
1590         return llistxattr(path, list, size);
1591 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1592         int options = XATTR_NOFOLLOW;
1593         return listxattr(path, list, size, options);
1594 #elif defined(HAVE_LLISTEA)
1595         return llistea(path, list, size);
1596 #elif defined(HAVE_EXTATTR_LIST_LINK)
1597         extattr_arg arg;
1598         arg.path = path;
1599         return bsd_attr_list(1, arg, list, size);
1600 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1601         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1602 #elif defined(HAVE_ATTROPEN)
1603         ssize_t ret = -1;
1604         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1605         if (attrdirfd >= 0) {
1606                 ret = solaris_list_xattr(attrdirfd, list, size);
1607                 close(attrdirfd);
1608         }
1609         return ret;
1610 #else
1611         errno = ENOSYS;
1612         return -1;
1613 #endif
1614 }
1615
1616 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1617 {
1618 #if defined(HAVE_FLISTXATTR)
1619 #ifndef XATTR_ADD_OPT
1620         return flistxattr(filedes, list, size);
1621 #else
1622         int options = 0;
1623         return flistxattr(filedes, list, size, options);
1624 #endif
1625 #elif defined(HAVE_FLISTEA)
1626         return flistea(filedes, list, size);
1627 #elif defined(HAVE_EXTATTR_LIST_FD)
1628         extattr_arg arg;
1629         arg.filedes = filedes;
1630         return bsd_attr_list(2, arg, list, size);
1631 #elif defined(HAVE_ATTR_LISTF)
1632         return irix_attr_list(NULL, filedes, list, size, 0);
1633 #elif defined(HAVE_ATTROPEN)
1634         ssize_t ret = -1;
1635         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1636         if (attrdirfd >= 0) {
1637                 ret = solaris_list_xattr(attrdirfd, list, size);
1638                 close(attrdirfd);
1639         }
1640         return ret;
1641 #else
1642         errno = ENOSYS;
1643         return -1;
1644 #endif
1645 }
1646
1647 int sys_removexattr (const char *path, const char *name)
1648 {
1649 #if defined(HAVE_REMOVEXATTR)
1650 #ifndef XATTR_ADD_OPT
1651         return removexattr(path, name);
1652 #else
1653         int options = 0;
1654         return removexattr(path, name, options);
1655 #endif
1656 #elif defined(HAVE_REMOVEEA)
1657         return removeea(path, name);
1658 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1659         char *s;
1660         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1661                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1662         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1663
1664         return extattr_delete_file(path, attrnamespace, attrname);
1665 #elif defined(HAVE_ATTR_REMOVE)
1666         int flags = 0;
1667         char *attrname = strchr(name,'.') + 1;
1668         
1669         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1670
1671         return attr_remove(path, attrname, flags);
1672 #elif defined(HAVE_ATTROPEN)
1673         int ret = -1;
1674         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1675         if (attrdirfd >= 0) {
1676                 ret = solaris_unlinkat(attrdirfd, name);
1677                 close(attrdirfd);
1678         }
1679         return ret;
1680 #else
1681         errno = ENOSYS;
1682         return -1;
1683 #endif
1684 }
1685
1686 int sys_lremovexattr (const char *path, const char *name)
1687 {
1688 #if defined(HAVE_LREMOVEXATTR)
1689         return lremovexattr(path, name);
1690 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1691         int options = XATTR_NOFOLLOW;
1692         return removexattr(path, name, options);
1693 #elif defined(HAVE_LREMOVEEA)
1694         return lremoveea(path, name);
1695 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1696         char *s;
1697         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1698                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1699         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1700
1701         return extattr_delete_link(path, attrnamespace, attrname);
1702 #elif defined(HAVE_ATTR_REMOVE)
1703         int flags = ATTR_DONTFOLLOW;
1704         char *attrname = strchr(name,'.') + 1;
1705         
1706         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1707
1708         return attr_remove(path, attrname, flags);
1709 #elif defined(HAVE_ATTROPEN)
1710         int ret = -1;
1711         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1712         if (attrdirfd >= 0) {
1713                 ret = solaris_unlinkat(attrdirfd, name);
1714                 close(attrdirfd);
1715         }
1716         return ret;
1717 #else
1718         errno = ENOSYS;
1719         return -1;
1720 #endif
1721 }
1722
1723 int sys_fremovexattr (int filedes, const char *name)
1724 {
1725 #if defined(HAVE_FREMOVEXATTR)
1726 #ifndef XATTR_ADD_OPT
1727         return fremovexattr(filedes, name);
1728 #else
1729         int options = 0;
1730         return fremovexattr(filedes, name, options);
1731 #endif
1732 #elif defined(HAVE_FREMOVEEA)
1733         return fremoveea(filedes, name);
1734 #elif defined(HAVE_EXTATTR_DELETE_FD)
1735         char *s;
1736         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1737                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1738         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1739
1740         return extattr_delete_fd(filedes, attrnamespace, attrname);
1741 #elif defined(HAVE_ATTR_REMOVEF)
1742         int flags = 0;
1743         char *attrname = strchr(name,'.') + 1;
1744         
1745         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1746
1747         return attr_removef(filedes, attrname, flags);
1748 #elif defined(HAVE_ATTROPEN)
1749         int ret = -1;
1750         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1751         if (attrdirfd >= 0) {
1752                 ret = solaris_unlinkat(attrdirfd, name);
1753                 close(attrdirfd);
1754         }
1755         return ret;
1756 #else
1757         errno = ENOSYS;
1758         return -1;
1759 #endif
1760 }
1761
1762 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1763 {
1764 #if defined(HAVE_SETXATTR)
1765 #ifndef XATTR_ADD_OPT
1766         return setxattr(path, name, value, size, flags);
1767 #else
1768         int options = 0;
1769         return setxattr(path, name, value, size, 0, options);
1770 #endif
1771 #elif defined(HAVE_SETEA)
1772         return setea(path, name, value, size, flags);
1773 #elif defined(HAVE_EXTATTR_SET_FILE)
1774         char *s;
1775         int retval = 0;
1776         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1777                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1778         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1779         if (flags) {
1780                 /* Check attribute existence */
1781                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1782                 if (retval < 0) {
1783                         /* REPLACE attribute, that doesn't exist */
1784                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1785                                 errno = ENOATTR;
1786                                 return -1;
1787                         }
1788                         /* Ignore other errors */
1789                 }
1790                 else {
1791                         /* CREATE attribute, that already exists */
1792                         if (flags & XATTR_CREATE) {
1793                                 errno = EEXIST;
1794                                 return -1;
1795                         }
1796                 }
1797         }
1798         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1799         return (retval < 0) ? -1 : 0;
1800 #elif defined(HAVE_ATTR_SET)
1801         int myflags = 0;
1802         char *attrname = strchr(name,'.') + 1;
1803         
1804         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1805         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1806         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1807
1808         return attr_set(path, attrname, (const char *)value, size, myflags);
1809 #elif defined(HAVE_ATTROPEN)
1810         int ret = -1;
1811         int myflags = O_RDWR;
1812         int attrfd;
1813         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1814         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1815         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1816         if (attrfd >= 0) {
1817                 ret = solaris_write_xattr(attrfd, value, size);
1818                 close(attrfd);
1819         }
1820         return ret;
1821 #else
1822         errno = ENOSYS;
1823         return -1;
1824 #endif
1825 }
1826
1827 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1828 {
1829 #if defined(HAVE_LSETXATTR)
1830         return lsetxattr(path, name, value, size, flags);
1831 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1832         int options = XATTR_NOFOLLOW;
1833         return setxattr(path, name, value, size, 0, options);
1834 #elif defined(LSETEA)
1835         return lsetea(path, name, value, size, flags);
1836 #elif defined(HAVE_EXTATTR_SET_LINK)
1837         char *s;
1838         int retval = 0;
1839         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1840                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1841         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1842         if (flags) {
1843                 /* Check attribute existence */
1844                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1845                 if (retval < 0) {
1846                         /* REPLACE attribute, that doesn't exist */
1847                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1848                                 errno = ENOATTR;
1849                                 return -1;
1850                         }
1851                         /* Ignore other errors */
1852                 }
1853                 else {
1854                         /* CREATE attribute, that already exists */
1855                         if (flags & XATTR_CREATE) {
1856                                 errno = EEXIST;
1857                                 return -1;
1858                         }
1859                 }
1860         }
1861
1862         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1863         return (retval < 0) ? -1 : 0;
1864 #elif defined(HAVE_ATTR_SET)
1865         int myflags = ATTR_DONTFOLLOW;
1866         char *attrname = strchr(name,'.') + 1;
1867         
1868         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1869         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1870         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1871
1872         return attr_set(path, attrname, (const char *)value, size, myflags);
1873 #elif defined(HAVE_ATTROPEN)
1874         int ret = -1;
1875         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1876         int attrfd;
1877         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1878         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1879         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1880         if (attrfd >= 0) {
1881                 ret = solaris_write_xattr(attrfd, value, size);
1882                 close(attrfd);
1883         }
1884         return ret;
1885 #else
1886         errno = ENOSYS;
1887         return -1;
1888 #endif
1889 }
1890
1891 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1892 {
1893 #if defined(HAVE_FSETXATTR)
1894 #ifndef XATTR_ADD_OPT
1895         return fsetxattr(filedes, name, value, size, flags);
1896 #else
1897         int options = 0;
1898         return fsetxattr(filedes, name, value, size, 0, options);
1899 #endif
1900 #elif defined(HAVE_FSETEA)
1901         return fsetea(filedes, name, value, size, flags);
1902 #elif defined(HAVE_EXTATTR_SET_FD)
1903         char *s;
1904         int retval = 0;
1905         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1906                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1907         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1908         if (flags) {
1909                 /* Check attribute existence */
1910                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1911                 if (retval < 0) {
1912                         /* REPLACE attribute, that doesn't exist */
1913                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1914                                 errno = ENOATTR;
1915                                 return -1;
1916                         }
1917                         /* Ignore other errors */
1918                 }
1919                 else {
1920                         /* CREATE attribute, that already exists */
1921                         if (flags & XATTR_CREATE) {
1922                                 errno = EEXIST;
1923                                 return -1;
1924                         }
1925                 }
1926         }
1927         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1928         return (retval < 0) ? -1 : 0;
1929 #elif defined(HAVE_ATTR_SETF)
1930         int myflags = 0;
1931         char *attrname = strchr(name,'.') + 1;
1932         
1933         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1934         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1935         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1936
1937         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1938 #elif defined(HAVE_ATTROPEN)
1939         int ret = -1;
1940         int myflags = O_RDWR | O_XATTR;
1941         int attrfd;
1942         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1943         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1944         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1945         if (attrfd >= 0) {
1946                 ret = solaris_write_xattr(attrfd, value, size);
1947                 close(attrfd);
1948         }
1949         return ret;
1950 #else
1951         errno = ENOSYS;
1952         return -1;
1953 #endif
1954 }
1955
1956 /**************************************************************************
1957  helper functions for Solaris' EA support
1958 ****************************************************************************/
1959 #ifdef HAVE_ATTROPEN
1960 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
1961 {
1962         struct stat sbuf;
1963
1964         if (fstat(attrfd, &sbuf) == -1) {
1965                 errno = ENOATTR;
1966                 return -1;
1967         }
1968
1969         /* This is to return the current size of the named extended attribute */
1970         if (size == 0) {
1971                 return sbuf.st_size;
1972         }
1973
1974         /* check size and read xattr */
1975         if (sbuf.st_size > size) {
1976                 errno = ERANGE;
1977                 return -1;
1978         }
1979
1980         return read(attrfd, value, sbuf.st_size);
1981 }
1982
1983 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
1984 {
1985         ssize_t len = 0;
1986         int stop = 0;
1987         DIR *dirp;
1988         struct dirent *de;
1989         int newfd = dup(attrdirfd);
1990         /* CAUTION: The originating file descriptor should not be
1991                     used again following the call to fdopendir().
1992                     For that reason we dup() the file descriptor
1993                     here to make things more clear. */
1994         dirp = fdopendir(newfd);
1995
1996         while ((de = readdir(dirp))) {
1997                 size_t listlen = strlen(de->d_name);
1998                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
1999                         /* we don't want "." and ".." here: */
2000                         DEBUG(10,("skipped EA %s\n",de->d_name));
2001                         continue;
2002                 }
2003
2004                 if (size == 0) {
2005                         /* return the current size of the list of extended attribute names*/
2006                         len += listlen + 1;
2007                 } else {
2008                         /* check size and copy entrieÑ• + nul into list. */
2009                         if ((len + listlen + 1) > size) {
2010                                 errno = ERANGE;
2011                                 len = -1;
2012                                 break;
2013                         } else {
2014                                 safe_strcpy(list + len, de->d_name, listlen);
2015                                 len += listlen;
2016                                 list[len] = '\0';
2017                                 ++len;
2018                         }
2019                 }
2020         }
2021
2022         if (closedir(dirp) == -1) {
2023                 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2024                 return -1;
2025         }
2026         return len;
2027 }
2028
2029 static int solaris_unlinkat(int attrdirfd, const char *name)
2030 {
2031         if (unlinkat(attrdirfd, name, 0) == -1) {
2032                 if (errno == ENOENT) {
2033                         errno = ENOATTR;
2034                 }
2035                 return -1;
2036         }
2037         return 0;
2038 }
2039
2040 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2041 {
2042         int filedes = attropen(path, attrpath, oflag, mode);
2043         if (filedes == -1) {
2044                 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2045                 if (errno == EINVAL) {
2046                         errno = ENOTSUP;
2047                 } else {
2048                         errno = ENOATTR;
2049                 }
2050         }
2051         return filedes;
2052 }
2053
2054 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2055 {
2056         int filedes = openat(fildes, path, oflag, mode);
2057         if (filedes == -1) {
2058                 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2059                 if (errno == EINVAL) {
2060                         errno = ENOTSUP;
2061                 } else {
2062                         errno = ENOATTR;
2063                 }
2064         }
2065         return filedes;
2066 }
2067
2068 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2069 {
2070         if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2071                 return 0;
2072         } else {
2073                 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2074                 return -1;
2075         }
2076 }
2077 #endif /*HAVE_ATTROPEN*/
2078
2079
2080 /****************************************************************************
2081  Return the major devicenumber for UNIX extensions.
2082 ****************************************************************************/
2083                                                                                                                 
2084 uint32 unix_dev_major(SMB_DEV_T dev)
2085 {
2086 #if defined(HAVE_DEVICE_MAJOR_FN)
2087         return (uint32)major(dev);
2088 #else
2089         return (uint32)(dev >> 8);
2090 #endif
2091 }
2092                                                                                                                 
2093 /****************************************************************************
2094  Return the minor devicenumber for UNIX extensions.
2095 ****************************************************************************/
2096                                                                                                                 
2097 uint32 unix_dev_minor(SMB_DEV_T dev)
2098 {
2099 #if defined(HAVE_DEVICE_MINOR_FN)
2100         return (uint32)minor(dev);
2101 #else
2102         return (uint32)(dev & 0xff);
2103 #endif
2104 }
2105
2106 #if defined(WITH_AIO)
2107
2108 /*******************************************************************
2109  An aio_read wrapper that will deal with 64-bit sizes.
2110 ********************************************************************/
2111                                                                                                                                            
2112 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2113 {
2114 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2115         return aio_read64(aiocb);
2116 #elif defined(HAVE_AIO_READ)
2117         return aio_read(aiocb);
2118 #else
2119         errno = ENOSYS;
2120         return -1;
2121 #endif
2122 }
2123
2124 /*******************************************************************
2125  An aio_write wrapper that will deal with 64-bit sizes.
2126 ********************************************************************/
2127                                                                                                                                            
2128 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2129 {
2130 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2131         return aio_write64(aiocb);
2132 #elif defined(HAVE_AIO_WRITE)
2133         return aio_write(aiocb);
2134 #else
2135         errno = ENOSYS;
2136         return -1;
2137 #endif
2138 }
2139
2140 /*******************************************************************
2141  An aio_return wrapper that will deal with 64-bit sizes.
2142 ********************************************************************/
2143                                                                                                                                            
2144 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2145 {
2146 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2147         return aio_return64(aiocb);
2148 #elif defined(HAVE_AIO_RETURN)
2149         return aio_return(aiocb);
2150 #else
2151         errno = ENOSYS;
2152         return -1;
2153 #endif
2154 }
2155
2156 /*******************************************************************
2157  An aio_cancel wrapper that will deal with 64-bit sizes.
2158 ********************************************************************/
2159
2160 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2161 {
2162 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2163         return aio_cancel64(fd, aiocb);
2164 #elif defined(HAVE_AIO_CANCEL)
2165         return aio_cancel(fd, aiocb);
2166 #else
2167         errno = ENOSYS;
2168         return -1;
2169 #endif
2170 }
2171
2172 /*******************************************************************
2173  An aio_error wrapper that will deal with 64-bit sizes.
2174 ********************************************************************/
2175
2176 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2177 {
2178 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2179         return aio_error64(aiocb);
2180 #elif defined(HAVE_AIO_ERROR)
2181         return aio_error(aiocb);
2182 #else
2183         errno = ENOSYS;
2184         return -1;
2185 #endif
2186 }
2187
2188 /*******************************************************************
2189  An aio_fsync wrapper that will deal with 64-bit sizes.
2190 ********************************************************************/
2191
2192 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2193 {
2194 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2195         return aio_fsync64(op, aiocb);
2196 #elif defined(HAVE_AIO_FSYNC)
2197         return aio_fsync(op, aiocb);
2198 #else
2199         errno = ENOSYS;
2200         return -1;
2201 #endif
2202 }
2203
2204 /*******************************************************************
2205  An aio_fsync wrapper that will deal with 64-bit sizes.
2206 ********************************************************************/
2207
2208 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2209 {
2210 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2211         return aio_suspend64(cblist, n, timeout);
2212 #elif defined(HAVE_AIO_FSYNC)
2213         return aio_suspend(cblist, n, timeout);
2214 #else
2215         errno = ENOSYS;
2216         return -1;
2217 #endif
2218 }
2219 #else /* !WITH_AIO */
2220
2221 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2222 {
2223         errno = ENOSYS;
2224         return -1;
2225 }
2226
2227 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2228 {
2229         errno = ENOSYS;
2230         return -1;
2231 }
2232
2233 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2234 {
2235         errno = ENOSYS;
2236         return -1;
2237 }
2238
2239 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2240 {
2241         errno = ENOSYS;
2242         return -1;
2243 }
2244
2245 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2246 {
2247         errno = ENOSYS;
2248         return -1;
2249 }
2250
2251 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2252 {
2253         errno = ENOSYS;
2254         return -1;
2255 }
2256
2257 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2258 {
2259         errno = ENOSYS;
2260         return -1;
2261 }
2262 #endif /* WITH_AIO */
2263
2264 int sys_getpeereid( int s, uid_t *uid)
2265 {
2266 #if defined(HAVE_PEERCRED)
2267         struct ucred cred;
2268         socklen_t cred_len = sizeof(struct ucred);
2269         int ret;
2270
2271         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2272         if (ret != 0) {
2273                 return -1;
2274         }
2275
2276         if (cred_len != sizeof(struct ucred)) {
2277                 errno = EINVAL;
2278                 return -1;
2279         }
2280
2281         *uid = cred.uid;
2282         return 0;
2283 #else
2284         errno = ENOSYS;
2285         return -1;
2286 #endif
2287 }
2288
2289 int sys_getnameinfo(const struct sockaddr *psa,
2290                         socklen_t salen,
2291                         char *host,
2292                         size_t hostlen,
2293                         char *service,
2294                         size_t servlen,
2295                         int flags)
2296 {
2297         /*
2298          * For Solaris we must make sure salen is the
2299          * correct length for the incoming sa_family.
2300          */
2301
2302         if (salen == sizeof(struct sockaddr_storage)) {
2303                 salen = sizeof(struct sockaddr_in);
2304 #if defined(HAVE_IPV6)
2305                 if (psa->sa_family == AF_INET6) {
2306                         salen = sizeof(struct sockaddr_in6);
2307                 }
2308 #endif
2309         }
2310         return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2311 }
2312
2313 int sys_connect(int fd, const struct sockaddr * addr)
2314 {
2315         socklen_t salen = -1;
2316
2317         if (addr->sa_family == AF_INET) {
2318             salen = sizeof(struct sockaddr_in);
2319         } else if (addr->sa_family == AF_UNIX) {
2320             salen = sizeof(struct sockaddr_un);
2321         }
2322 #if defined(HAVE_IPV6)
2323         else if (addr->sa_family == AF_INET6) {
2324             salen = sizeof(struct sockaddr_in6);
2325         }
2326 #endif
2327
2328         return connect(fd, addr, salen);
2329 }