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