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