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