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