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