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