s3:lib/system fix build on AIX 7
[gd/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 #include "../lib/util/setid.h"
29
30 #ifdef HAVE_SYS_SYSCTL_H
31 #include <sys/sysctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
37
38 /*
39    The idea is that this file will eventually have wrappers around all
40    important system calls in samba. The aims are:
41
42    - to enable easier porting by putting OS dependent stuff in here
43
44    - to allow for hooks into other "pseudo-filesystems"
45
46    - to allow easier integration of things like the japanese extensions
47
48    - to support the philosophy of Samba to expose the features of
49      the OS within the SMB model. In general whatever file/printer/variable
50      expansions/etc make sense to the OS should be acceptable to Samba.
51 */
52
53
54
55 /*******************************************************************
56 A read wrapper that will deal with EINTR.
57 ********************************************************************/
58
59 ssize_t sys_read(int fd, void *buf, size_t count)
60 {
61         ssize_t ret;
62
63         do {
64                 ret = read(fd, buf, count);
65 #if defined(EWOULDBLOCK)
66         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
67 #else
68         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
69 #endif
70         return ret;
71 }
72
73 /*******************************************************************
74 A write wrapper that will deal with EINTR.
75 ********************************************************************/
76
77 ssize_t sys_write(int fd, const void *buf, size_t count)
78 {
79         ssize_t ret;
80
81         do {
82                 ret = write(fd, buf, count);
83 #if defined(EWOULDBLOCK)
84         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
85 #else
86         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
87 #endif
88         return ret;
89 }
90
91 /*******************************************************************
92 A writev wrapper that will deal with EINTR.
93 ********************************************************************/
94
95 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
96 {
97         ssize_t ret;
98
99 #if 0
100         /* Try to confuse write_data_iov a bit */
101         if ((random() % 5) == 0) {
102                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
103         }
104         if (iov[0].iov_len > 1) {
105                 return sys_write(fd, iov[0].iov_base,
106                                  (random() % (iov[0].iov_len-1)) + 1);
107         }
108 #endif
109
110         do {
111                 ret = writev(fd, iov, iovcnt);
112 #if defined(EWOULDBLOCK)
113         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
114 #else
115         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
116 #endif
117         return ret;
118 }
119
120 /*******************************************************************
121 A pread wrapper that will deal with EINTR
122 ********************************************************************/
123
124 #if defined(HAVE_PREAD)
125 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
126 {
127         ssize_t ret;
128
129         do {
130                 ret = pread(fd, buf, count, off);
131         } while (ret == -1 && errno == EINTR);
132         return ret;
133 }
134 #endif
135
136 /*******************************************************************
137 A write wrapper that will deal with EINTR
138 ********************************************************************/
139
140 #if defined(HAVE_PWRITE)
141 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
142 {
143         ssize_t ret;
144
145         do {
146                 ret = pwrite(fd, buf, count, off);
147         } while (ret == -1 && errno == EINTR);
148         return ret;
149 }
150 #endif
151
152 /*******************************************************************
153 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
154 ********************************************************************/
155
156 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
157 {
158         ssize_t ret;
159
160         do {
161                 ret = send(s, msg, len, flags);
162 #if defined(EWOULDBLOCK)
163         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
164 #else
165         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
166 #endif
167         return ret;
168 }
169
170 /*******************************************************************
171 A recvfrom wrapper that will deal with EINTR.
172 ********************************************************************/
173
174 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
175 {
176         ssize_t ret;
177
178         do {
179                 ret = recvfrom(s, buf, len, flags, from, fromlen);
180 #if defined(EWOULDBLOCK)
181         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
182 #else
183         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
184 #endif
185         return ret;
186 }
187
188 /*******************************************************************
189 A fcntl wrapper that will deal with EINTR.
190 ********************************************************************/
191
192 int sys_fcntl_ptr(int fd, int cmd, void *arg)
193 {
194         int ret;
195
196         do {
197                 ret = fcntl(fd, cmd, arg);
198         } while (ret == -1 && errno == EINTR);
199         return ret;
200 }
201
202 /*******************************************************************
203 A fcntl wrapper that will deal with EINTR.
204 ********************************************************************/
205
206 int sys_fcntl_long(int fd, int cmd, long arg)
207 {
208         int ret;
209
210         do {
211                 ret = fcntl(fd, cmd, arg);
212         } while (ret == -1 && errno == EINTR);
213         return ret;
214 }
215
216 /****************************************************************************
217  Get/Set all the possible time fields from a stat struct as a timespec.
218 ****************************************************************************/
219
220 static struct timespec get_atimespec(const struct stat *pst)
221 {
222 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
223         struct timespec ret;
224
225         /* Old system - no ns timestamp. */
226         ret.tv_sec = pst->st_atime;
227         ret.tv_nsec = 0;
228         return ret;
229 #else
230 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
231         struct timespec ret;
232         ret.tv_sec = pst->st_atim.tv_sec;
233         ret.tv_nsec = pst->st_atim.tv_nsec;
234         return ret;
235 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
236         struct timespec ret;
237         ret.tv_sec = pst->st_atime;
238         ret.tv_nsec = pst->st_atimensec;
239         return ret;
240 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
241         struct timespec ret;
242         ret.tv_sec = pst->st_atime;
243         ret.tv_nsec = pst->st_atime_n;
244         return ret;
245 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
246         struct timespec ret;
247         ret.tv_sec = pst->st_atime;
248         ret.tv_nsec = pst->st_uatime * 1000;
249         return ret;
250 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
251         return pst->st_atimespec;
252 #else
253 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
254 #endif
255 #endif
256 }
257
258 static struct timespec get_mtimespec(const struct stat *pst)
259 {
260 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
261         struct timespec ret;
262
263         /* Old system - no ns timestamp. */
264         ret.tv_sec = pst->st_mtime;
265         ret.tv_nsec = 0;
266         return ret;
267 #else
268 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
269         struct timespec ret;
270         ret.tv_sec = pst->st_mtim.tv_sec;
271         ret.tv_nsec = pst->st_mtim.tv_nsec;
272         return ret;
273 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
274         struct timespec ret;
275         ret.tv_sec = pst->st_mtime;
276         ret.tv_nsec = pst->st_mtimensec;
277         return ret;
278 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
279         struct timespec ret;
280         ret.tv_sec = pst->st_mtime;
281         ret.tv_nsec = pst->st_mtime_n;
282         return ret;
283 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
284         struct timespec ret;
285         ret.tv_sec = pst->st_mtime;
286         ret.tv_nsec = pst->st_umtime * 1000;
287         return ret;
288 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
289         return pst->st_mtimespec;
290 #else
291 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
292 #endif
293 #endif
294 }
295
296 static struct timespec get_ctimespec(const struct stat *pst)
297 {
298 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
299         struct timespec ret;
300
301         /* Old system - no ns timestamp. */
302         ret.tv_sec = pst->st_ctime;
303         ret.tv_nsec = 0;
304         return ret;
305 #else
306 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
307         struct timespec ret;
308         ret.tv_sec = pst->st_ctim.tv_sec;
309         ret.tv_nsec = pst->st_ctim.tv_nsec;
310         return ret;
311 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
312         struct timespec ret;
313         ret.tv_sec = pst->st_ctime;
314         ret.tv_nsec = pst->st_ctimensec;
315         return ret;
316 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
317         struct timespec ret;
318         ret.tv_sec = pst->st_ctime;
319         ret.tv_nsec = pst->st_ctime_n;
320         return ret;
321 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
322         struct timespec ret;
323         ret.tv_sec = pst->st_ctime;
324         ret.tv_nsec = pst->st_uctime * 1000;
325         return ret;
326 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
327         return pst->st_ctimespec;
328 #else
329 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
330 #endif
331 #endif
332 }
333
334 /****************************************************************************
335  Return the best approximation to a 'create time' under UNIX from a stat
336  structure.
337 ****************************************************************************/
338
339 static struct timespec calc_create_time_stat(const struct stat *st)
340 {
341         struct timespec ret, ret1;
342         struct timespec c_time = get_ctimespec(st);
343         struct timespec m_time = get_mtimespec(st);
344         struct timespec a_time = get_atimespec(st);
345
346         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
347         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
348
349         if(!null_timespec(ret1)) {
350                 return ret1;
351         }
352
353         /*
354          * One of ctime, mtime or atime was zero (probably atime).
355          * Just return MIN(ctime, mtime).
356          */
357         return ret;
358 }
359
360 /****************************************************************************
361  Return the best approximation to a 'create time' under UNIX from a stat_ex
362  structure.
363 ****************************************************************************/
364
365 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
366 {
367         struct timespec ret, ret1;
368         struct timespec c_time = st->st_ex_ctime;
369         struct timespec m_time = st->st_ex_mtime;
370         struct timespec a_time = st->st_ex_atime;
371
372         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
373         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
374
375         if(!null_timespec(ret1)) {
376                 return ret1;
377         }
378
379         /*
380          * One of ctime, mtime or atime was zero (probably atime).
381          * Just return MIN(ctime, mtime).
382          */
383         return ret;
384 }
385
386 /****************************************************************************
387  Return the 'create time' from a stat struct if it exists (birthtime) or else
388  use the best approximation.
389 ****************************************************************************/
390
391 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
392                                  bool fake_dir_create_times)
393 {
394         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
395                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
396                 dst->st_ex_btime.tv_nsec = 0;
397         }
398
399         dst->st_ex_calculated_birthtime = false;
400
401 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
402         dst->st_ex_btime = pst->st_birthtimespec;
403 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
404         dst->st_ex_btime.tv_sec = pst->st_birthtime;
405         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
406 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
407         dst->st_ex_btime.tv_sec = pst->st_birthtime;
408         dst->st_ex_btime.tv_nsec = 0;
409 #else
410         dst->st_ex_btime = calc_create_time_stat(pst);
411         dst->st_ex_calculated_birthtime = true;
412 #endif
413
414         /* Deal with systems that don't initialize birthtime correctly.
415          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
416          */
417         if (null_timespec(dst->st_ex_btime)) {
418                 dst->st_ex_btime = calc_create_time_stat(pst);
419                 dst->st_ex_calculated_birthtime = true;
420         }
421 }
422
423 /****************************************************************************
424  If we update a timestamp in a stat_ex struct we may have to recalculate
425  the birthtime. For now only implement this for write time, but we may
426  also need to do it for atime and ctime. JRA.
427 ****************************************************************************/
428
429 void update_stat_ex_mtime(struct stat_ex *dst,
430                                 struct timespec write_ts)
431 {
432         dst->st_ex_mtime = write_ts;
433
434         /* We may have to recalculate btime. */
435         if (dst->st_ex_calculated_birthtime) {
436                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
437         }
438 }
439
440 void update_stat_ex_create_time(struct stat_ex *dst,
441                                 struct timespec create_time)
442 {
443         dst->st_ex_btime = create_time;
444         dst->st_ex_calculated_birthtime = false;
445 }
446
447 void init_stat_ex_from_stat (struct stat_ex *dst,
448                             const struct stat *src,
449                             bool fake_dir_create_times)
450 {
451         dst->st_ex_dev = src->st_dev;
452         dst->st_ex_ino = src->st_ino;
453         dst->st_ex_mode = src->st_mode;
454         dst->st_ex_nlink = src->st_nlink;
455         dst->st_ex_uid = src->st_uid;
456         dst->st_ex_gid = src->st_gid;
457         dst->st_ex_rdev = src->st_rdev;
458         dst->st_ex_size = src->st_size;
459         dst->st_ex_atime = get_atimespec(src);
460         dst->st_ex_mtime = get_mtimespec(src);
461         dst->st_ex_ctime = get_ctimespec(src);
462         make_create_timespec(src, dst, fake_dir_create_times);
463 #ifdef HAVE_STAT_ST_BLKSIZE
464         dst->st_ex_blksize = src->st_blksize;
465 #else
466         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
467 #endif
468
469 #ifdef HAVE_STAT_ST_BLOCKS
470         dst->st_ex_blocks = src->st_blocks;
471 #else
472         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
473 #endif
474
475 #ifdef HAVE_STAT_ST_FLAGS
476         dst->st_ex_flags = src->st_flags;
477 #else
478         dst->st_ex_flags = 0;
479 #endif
480 }
481
482 /*******************************************************************
483 A stat() wrapper.
484 ********************************************************************/
485
486 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
487              bool fake_dir_create_times)
488 {
489         int ret;
490         struct stat statbuf;
491         ret = stat(fname, &statbuf);
492         if (ret == 0) {
493                 /* we always want directories to appear zero size */
494                 if (S_ISDIR(statbuf.st_mode)) {
495                         statbuf.st_size = 0;
496                 }
497                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
498         }
499         return ret;
500 }
501
502 /*******************************************************************
503  An fstat() wrapper.
504 ********************************************************************/
505
506 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
507 {
508         int ret;
509         struct stat statbuf;
510         ret = fstat(fd, &statbuf);
511         if (ret == 0) {
512                 /* we always want directories to appear zero size */
513                 if (S_ISDIR(statbuf.st_mode)) {
514                         statbuf.st_size = 0;
515                 }
516                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
517         }
518         return ret;
519 }
520
521 /*******************************************************************
522  An lstat() wrapper.
523 ********************************************************************/
524
525 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
526               bool fake_dir_create_times)
527 {
528         int ret;
529         struct stat statbuf;
530         ret = lstat(fname, &statbuf);
531         if (ret == 0) {
532                 /* we always want directories to appear zero size */
533                 if (S_ISDIR(statbuf.st_mode)) {
534                         statbuf.st_size = 0;
535                 }
536                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
537         }
538         return ret;
539 }
540
541 /*******************************************************************
542  An posix_fallocate() wrapper.
543 ********************************************************************/
544 int sys_posix_fallocate(int fd, off_t offset, off_t len)
545 {
546 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
547         return posix_fallocate(fd, offset, len);
548 #elif defined(F_RESVSP64)
549         /* this handles XFS on IRIX */
550         struct flock64 fl;
551         off_t new_len = offset + len;
552         int ret;
553         struct stat64 sbuf;
554
555         /* unlikely to get a too large file on a 64bit system but ... */
556         if (new_len < 0)
557                 return EFBIG;
558
559         fl.l_whence = SEEK_SET;
560         fl.l_start = offset;
561         fl.l_len = len;
562
563         ret=fcntl(fd, F_RESVSP64, &fl);
564
565         if (ret != 0)
566                 return errno;
567
568         /* Make sure the file gets enlarged after we allocated space: */
569         fstat64(fd, &sbuf);
570         if (new_len > sbuf.st_size)
571                 ftruncate64(fd, new_len);
572         return 0;
573 #else
574         return ENOSYS;
575 #endif
576 }
577
578 /*******************************************************************
579  An fallocate() function that matches the semantics of the Linux one.
580 ********************************************************************/
581
582 #ifdef HAVE_LINUX_FALLOC_H
583 #include <linux/falloc.h>
584 #endif
585
586 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
587 {
588 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
589         int lmode;
590         switch (mode) {
591         case VFS_FALLOCATE_EXTEND_SIZE:
592                 lmode = 0;
593                 break;
594         case VFS_FALLOCATE_KEEP_SIZE:
595                 lmode = FALLOC_FL_KEEP_SIZE;
596                 break;
597         default:
598                 errno = EINVAL;
599                 return -1;
600         }
601 #if defined(HAVE_LINUX_FALLOCATE)
602         return fallocate(fd, lmode, offset, len);
603 #endif
604 #else
605         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
606         errno = ENOSYS;
607         return -1;
608 #endif
609 }
610
611 #if HAVE_KERNEL_SHARE_MODES
612 #ifndef LOCK_MAND
613 #define LOCK_MAND       32      /* This is a mandatory flock */
614 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
615 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
616 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
617 #endif
618 #endif
619
620 /*******************************************************************
621  A flock() wrapper that will perform the kernel flock.
622 ********************************************************************/
623
624 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
625 {
626 #if HAVE_KERNEL_SHARE_MODES
627         int kernel_mode = 0;
628         if (share_mode == FILE_SHARE_WRITE) {
629                 kernel_mode = LOCK_MAND|LOCK_WRITE;
630         } else if (share_mode == FILE_SHARE_READ) {
631                 kernel_mode = LOCK_MAND|LOCK_READ;
632         } else if (share_mode == FILE_SHARE_NONE) {
633                 kernel_mode = LOCK_MAND;
634         }
635         if (kernel_mode) {
636                 flock(fd, kernel_mode);
637         }
638 #endif
639         ;
640 }
641
642
643
644 /*******************************************************************
645  An fdopendir wrapper.
646 ********************************************************************/
647
648 DIR *sys_fdopendir(int fd)
649 {
650 #if defined(HAVE_FDOPENDIR)
651         return fdopendir(fd);
652 #else
653         errno = ENOSYS;
654         return NULL;
655 #endif
656 }
657
658 /*******************************************************************
659  An mknod() wrapper.
660 ********************************************************************/
661
662 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
663 {
664 #if defined(HAVE_MKNOD)
665         return mknod(path, mode, dev);
666 #else
667         /* No mknod system call. */
668         errno = ENOSYS;
669         return -1;
670 #endif
671 }
672
673 /*******************************************************************
674 The wait() calls vary between systems
675 ********************************************************************/
676
677 int sys_waitpid(pid_t pid,int *status,int options)
678 {
679 #ifdef HAVE_WAITPID
680         return waitpid(pid,status,options);
681 #else /* HAVE_WAITPID */
682         return wait4(pid, status, options, NULL);
683 #endif /* HAVE_WAITPID */
684 }
685
686 /*******************************************************************
687  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
688  on error (malloc fail usually).
689 ********************************************************************/
690
691 char *sys_getwd(void)
692 {
693 #ifdef GETCWD_TAKES_NULL
694         return getcwd(NULL, 0);
695 #elif HAVE_GETCWD
696         char *wd = NULL, *s = NULL;
697         size_t allocated = PATH_MAX;
698
699         while (1) {
700                 s = SMB_REALLOC_ARRAY(s, char, allocated);
701                 if (s == NULL) {
702                         return NULL;
703                 }
704                 wd = getcwd(s, allocated);
705                 if (wd) {
706                         break;
707                 }
708                 if (errno != ERANGE) {
709                         SAFE_FREE(s);
710                         break;
711                 }
712                 allocated *= 2;
713                 if (allocated < PATH_MAX) {
714                         SAFE_FREE(s);
715                         break;
716                 }
717         }
718         return wd;
719 #else
720         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
721         if (s == NULL) {
722                 return NULL;
723         }
724         return getwd(s);
725 #endif
726 }
727
728 #if defined(HAVE_POSIX_CAPABILITIES)
729
730 /**************************************************************************
731  Try and abstract process capabilities (for systems that have them).
732 ****************************************************************************/
733
734 /* Set the POSIX capabilities needed for the given purpose into the effective
735  * capability set of the current process. Make sure they are always removed
736  * from the inheritable set, because there is no circumstance in which our
737  * children should inherit our elevated privileges.
738  */
739 static bool set_process_capability(enum smbd_capability capability,
740                                    bool enable)
741 {
742         cap_value_t cap_vals[2] = {0};
743         int num_cap_vals = 0;
744
745         cap_t cap;
746
747 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
748         /* On Linux, make sure that any capabilities we grab are sticky
749          * across UID changes. We expect that this would allow us to keep both
750          * the effective and permitted capability sets, but as of circa 2.6.16,
751          * only the permitted set is kept. It is a bug (which we work around)
752          * that the effective set is lost, but we still require the effective
753          * set to be kept.
754          */
755         if (!prctl(PR_GET_KEEPCAPS)) {
756                 prctl(PR_SET_KEEPCAPS, 1);
757         }
758 #endif
759
760         cap = cap_get_proc();
761         if (cap == NULL) {
762                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
763                         strerror(errno)));
764                 return False;
765         }
766
767         switch (capability) {
768                 case KERNEL_OPLOCK_CAPABILITY:
769 #ifdef CAP_NETWORK_MGT
770                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
771                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
772 #endif
773                         break;
774                 case DMAPI_ACCESS_CAPABILITY:
775 #ifdef CAP_DEVICE_MGT
776                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
777                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
778 #elif CAP_MKNOD
779                         /* Linux has CAP_MKNOD for DMAPI access. */
780                         cap_vals[num_cap_vals++] = CAP_MKNOD;
781 #endif
782                         break;
783                 case LEASE_CAPABILITY:
784 #ifdef CAP_LEASE
785                         cap_vals[num_cap_vals++] = CAP_LEASE;
786 #endif
787                         break;
788         }
789
790         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
791
792         if (num_cap_vals == 0) {
793                 cap_free(cap);
794                 return True;
795         }
796
797         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
798                 enable ? CAP_SET : CAP_CLEAR);
799
800         /* We never want to pass capabilities down to our children, so make
801          * sure they are not inherited.
802          */
803         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
804
805         if (cap_set_proc(cap) == -1) {
806                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
807                         strerror(errno)));
808                 cap_free(cap);
809                 return False;
810         }
811
812         cap_free(cap);
813         return True;
814 }
815
816 #endif /* HAVE_POSIX_CAPABILITIES */
817
818 /****************************************************************************
819  Gain the oplock capability from the kernel if possible.
820 ****************************************************************************/
821
822 void set_effective_capability(enum smbd_capability capability)
823 {
824 #if defined(HAVE_POSIX_CAPABILITIES)
825         set_process_capability(capability, True);
826 #endif /* HAVE_POSIX_CAPABILITIES */
827 }
828
829 void drop_effective_capability(enum smbd_capability capability)
830 {
831 #if defined(HAVE_POSIX_CAPABILITIES)
832         set_process_capability(capability, False);
833 #endif /* HAVE_POSIX_CAPABILITIES */
834 }
835
836 /**************************************************************************
837  Wrapper for random().
838 ****************************************************************************/
839
840 long sys_random(void)
841 {
842 #if defined(HAVE_RANDOM)
843         return (long)random();
844 #elif defined(HAVE_RAND)
845         return (long)rand();
846 #else
847         DEBUG(0,("Error - no random function available !\n"));
848         exit(1);
849 #endif
850 }
851
852 /**************************************************************************
853  Wrapper for srandom().
854 ****************************************************************************/
855
856 void sys_srandom(unsigned int seed)
857 {
858 #if defined(HAVE_SRANDOM)
859         srandom(seed);
860 #elif defined(HAVE_SRAND)
861         srand(seed);
862 #else
863         DEBUG(0,("Error - no srandom function available !\n"));
864         exit(1);
865 #endif
866 }
867
868 #ifndef NGROUPS_MAX
869 #define NGROUPS_MAX 32 /* Guess... */
870 #endif
871
872 /**************************************************************************
873  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
874 ****************************************************************************/
875
876 int groups_max(void)
877 {
878 #if defined(SYSCONF_SC_NGROUPS_MAX)
879         int ret = sysconf(_SC_NGROUPS_MAX);
880         return (ret == -1) ? NGROUPS_MAX : ret;
881 #else
882         return NGROUPS_MAX;
883 #endif
884 }
885
886 /**************************************************************************
887  Wrap setgroups and getgroups for systems that declare getgroups() as
888  returning an array of gid_t, but actuall return an array of int.
889 ****************************************************************************/
890
891 #if defined(HAVE_BROKEN_GETGROUPS)
892
893 #ifdef HAVE_BROKEN_GETGROUPS
894 #define GID_T int
895 #else
896 #define GID_T gid_t
897 #endif
898
899 static int sys_broken_getgroups(int setlen, gid_t *gidset)
900 {
901         GID_T gid;
902         GID_T *group_list;
903         int i, ngroups;
904
905         if(setlen == 0) {
906                 return getgroups(setlen, &gid);
907         }
908
909         /*
910          * Broken case. We need to allocate a
911          * GID_T array of size setlen.
912          */
913
914         if(setlen < 0) {
915                 errno = EINVAL; 
916                 return -1;
917         } 
918
919         if (setlen == 0)
920                 setlen = groups_max();
921
922         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
923                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
924                 return -1;
925         }
926
927         if((ngroups = getgroups(setlen, group_list)) < 0) {
928                 int saved_errno = errno;
929                 SAFE_FREE(group_list);
930                 errno = saved_errno;
931                 return -1;
932         }
933
934         for(i = 0; i < ngroups; i++)
935                 gidset[i] = (gid_t)group_list[i];
936
937         SAFE_FREE(group_list);
938         return ngroups;
939 }
940
941 static int sys_broken_setgroups(int setlen, gid_t *gidset)
942 {
943         GID_T *group_list;
944         int i ; 
945
946         if (setlen == 0)
947                 return 0 ;
948
949         if (setlen < 0 || setlen > groups_max()) {
950                 errno = EINVAL; 
951                 return -1;   
952         }
953
954         /*
955          * Broken case. We need to allocate a
956          * GID_T array of size setlen.
957          */
958
959         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
960                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
961                 return -1;    
962         }
963
964         for(i = 0; i < setlen; i++) 
965                 group_list[i] = (GID_T) gidset[i]; 
966
967         if(samba_setgroups(setlen, group_list) != 0) {
968                 int saved_errno = errno;
969                 SAFE_FREE(group_list);
970                 errno = saved_errno;
971                 return -1;
972         }
973
974         SAFE_FREE(group_list);
975         return 0 ;
976 }
977
978 #endif /* HAVE_BROKEN_GETGROUPS */
979
980 /* This is a list of systems that require the first GID passed to setgroups(2)
981  * to be the effective GID. If your system is one of these, add it here.
982  */
983 #if defined (FREEBSD) || defined (DARWINOS)
984 #define USE_BSD_SETGROUPS
985 #endif
986
987 #if defined(USE_BSD_SETGROUPS)
988 /* Depending on the particular BSD implementation, the first GID that is
989  * passed to setgroups(2) will either be ignored or will set the credential's
990  * effective GID. In either case, the right thing to do is to guarantee that
991  * gidset[0] is the effective GID.
992  */
993 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
994 {
995         gid_t *new_gidset = NULL;
996         int max;
997         int ret;
998
999         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1000         max = groups_max();
1001
1002         /* No group list, just make sure we are setting the efective GID. */
1003         if (setlen == 0) {
1004                 return samba_setgroups(1, &primary_gid);
1005         }
1006
1007         /* If the primary gid is not the first array element, grow the array
1008          * and insert it at the front.
1009          */
1010         if (gidset[0] != primary_gid) {
1011                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1012                 if (new_gidset == NULL) {
1013                         return -1;
1014                 }
1015
1016                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1017                 new_gidset[0] = primary_gid;
1018                 setlen++;
1019         }
1020
1021         if (setlen > max) {
1022                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1023                         setlen, max));
1024                 setlen = max;
1025         }
1026
1027 #if defined(HAVE_BROKEN_GETGROUPS)
1028         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1029 #else
1030         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1031 #endif
1032
1033         if (new_gidset) {
1034                 int errsav = errno;
1035                 SAFE_FREE(new_gidset);
1036                 errno = errsav;
1037         }
1038
1039         return ret;
1040 }
1041
1042 #endif /* USE_BSD_SETGROUPS */
1043
1044 /**************************************************************************
1045  Wrapper for getgroups. Deals with broken (int) case.
1046 ****************************************************************************/
1047
1048 int sys_getgroups(int setlen, gid_t *gidset)
1049 {
1050 #if defined(HAVE_BROKEN_GETGROUPS)
1051         return sys_broken_getgroups(setlen, gidset);
1052 #else
1053         return getgroups(setlen, gidset);
1054 #endif
1055 }
1056
1057 /**************************************************************************
1058  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1059 ****************************************************************************/
1060
1061 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1062 {
1063 #if !defined(HAVE_SETGROUPS)
1064         errno = ENOSYS;
1065         return -1;
1066 #endif /* HAVE_SETGROUPS */
1067
1068 #if defined(USE_BSD_SETGROUPS)
1069         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1070 #elif defined(HAVE_BROKEN_GETGROUPS)
1071         return sys_broken_setgroups(setlen, gidset);
1072 #else
1073         return samba_setgroups(setlen, gidset);
1074 #endif
1075 }
1076
1077 /**************************************************************************
1078  Extract a command into an arg list.
1079 ****************************************************************************/
1080
1081 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1082 {
1083         char *trunc_cmd;
1084         char *saveptr;
1085         char *ptr;
1086         int argcl;
1087         char **argl = NULL;
1088         int i;
1089
1090         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1091                 DEBUG(0, ("talloc failed\n"));
1092                 goto nomem;
1093         }
1094
1095         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1096                 TALLOC_FREE(trunc_cmd);
1097                 errno = EINVAL;
1098                 return NULL;
1099         }
1100
1101         /*
1102          * Count the args.
1103          */
1104
1105         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1106                 argcl++;
1107
1108         TALLOC_FREE(trunc_cmd);
1109
1110         if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1111                 goto nomem;
1112         }
1113
1114         /*
1115          * Now do the extraction.
1116          */
1117
1118         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1119                 goto nomem;
1120         }
1121
1122         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1123         i = 0;
1124
1125         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1126                 goto nomem;
1127         }
1128
1129         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1130
1131                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1132                         goto nomem;
1133                 }
1134         }
1135
1136         argl[i++] = NULL;
1137         TALLOC_FREE(trunc_cmd);
1138         return argl;
1139
1140  nomem:
1141         DEBUG(0, ("talloc failed\n"));
1142         TALLOC_FREE(trunc_cmd);
1143         TALLOC_FREE(argl);
1144         errno = ENOMEM;
1145         return NULL;
1146 }
1147
1148 /**************************************************************************
1149  Wrapper for popen. Safer as it doesn't search a path.
1150  Modified from the glibc sources.
1151  modified by tridge to return a file descriptor. We must kick our FILE* habit
1152 ****************************************************************************/
1153
1154 typedef struct _popen_list
1155 {
1156         int fd;
1157         pid_t child_pid;
1158         struct _popen_list *next;
1159 } popen_list;
1160
1161 static popen_list *popen_chain;
1162
1163 int sys_popen(const char *command)
1164 {
1165         int parent_end, child_end;
1166         int pipe_fds[2];
1167         popen_list *entry = NULL;
1168         char **argl = NULL;
1169         int ret;
1170
1171         if (!*command) {
1172                 errno = EINVAL;
1173                 return -1;
1174         }
1175
1176         ret = pipe(pipe_fds);
1177         if (ret < 0) {
1178                 DEBUG(0, ("sys_popen: error opening pipe: %s\n",
1179                           strerror(errno)));
1180                 return -1;
1181         }
1182
1183         parent_end = pipe_fds[0];
1184         child_end = pipe_fds[1];
1185
1186         entry = SMB_MALLOC_P(popen_list);
1187         if (entry == NULL) {
1188                 DEBUG(0, ("sys_popen: malloc failed\n"));
1189                 goto err_exit;
1190         }
1191
1192         ZERO_STRUCTP(entry);
1193
1194         /*
1195          * Extract the command and args into a NULL terminated array.
1196          */
1197
1198         argl = extract_args(NULL, command);
1199         if (argl == NULL) {
1200                 DEBUG(0, ("sys_popen: extract_args() failed: %s\n", strerror(errno)));
1201                 goto err_exit;
1202         }
1203
1204         entry->child_pid = fork();
1205
1206         if (entry->child_pid == -1) {
1207                 DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
1208                 goto err_exit;
1209         }
1210
1211         if (entry->child_pid == 0) {
1212
1213                 /*
1214                  * Child !
1215                  */
1216
1217                 int child_std_end = STDOUT_FILENO;
1218                 popen_list *p;
1219
1220                 close(parent_end);
1221                 if (child_end != child_std_end) {
1222                         dup2 (child_end, child_std_end);
1223                         close (child_end);
1224                 }
1225
1226                 /*
1227                  * POSIX.2:  "popen() shall ensure that any streams from previous
1228                  * popen() calls that remain open in the parent process are closed
1229                  * in the new child process."
1230                  */
1231
1232                 for (p = popen_chain; p; p = p->next)
1233                         close(p->fd);
1234
1235                 ret = execv(argl[0], argl);
1236                 if (ret == -1) {
1237                         DEBUG(0, ("sys_popen: ERROR executing command "
1238                                   "'%s': %s\n", command, strerror(errno)));
1239                 }
1240                 _exit (127);
1241         }
1242
1243         /*
1244          * Parent.
1245          */
1246
1247         close (child_end);
1248         TALLOC_FREE(argl);
1249
1250         /* Link into popen_chain. */
1251         entry->next = popen_chain;
1252         popen_chain = entry;
1253         entry->fd = parent_end;
1254
1255         return entry->fd;
1256
1257 err_exit:
1258
1259         SAFE_FREE(entry);
1260         TALLOC_FREE(argl);
1261         close(pipe_fds[0]);
1262         close(pipe_fds[1]);
1263         return -1;
1264 }
1265
1266 /**************************************************************************
1267  Wrapper for pclose. Modified from the glibc sources.
1268 ****************************************************************************/
1269
1270 int sys_pclose(int fd)
1271 {
1272         int wstatus;
1273         popen_list **ptr = &popen_chain;
1274         popen_list *entry = NULL;
1275         pid_t wait_pid;
1276         int status = -1;
1277
1278         /* Unlink from popen_chain. */
1279         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1280                 if ((*ptr)->fd == fd) {
1281                         entry = *ptr;
1282                         *ptr = (*ptr)->next;
1283                         status = 0;
1284                         break;
1285                 }
1286         }
1287
1288         if (status < 0 || close(entry->fd) < 0)
1289                 return -1;
1290
1291         /*
1292          * As Samba is catching and eating child process
1293          * exits we don't really care about the child exit
1294          * code, a -1 with errno = ECHILD will do fine for us.
1295          */
1296
1297         do {
1298                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1299         } while (wait_pid == -1 && errno == EINTR);
1300
1301         SAFE_FREE(entry);
1302
1303         if (wait_pid == -1)
1304                 return -1;
1305         return wstatus;
1306 }
1307
1308 /**************************************************************************
1309  Wrapper for Admin Logs.
1310 ****************************************************************************/
1311
1312  void sys_adminlog(int priority, const char *format_str, ...) 
1313 {
1314         va_list ap;
1315         int ret;
1316         char *msgbuf = NULL;
1317
1318         va_start( ap, format_str );
1319         ret = vasprintf( &msgbuf, format_str, ap );
1320         va_end( ap );
1321
1322         if (ret == -1)
1323                 return;
1324
1325 #if defined(HAVE_SYSLOG)
1326         syslog( priority, "%s", msgbuf );
1327 #else
1328         DEBUG(0,("%s", msgbuf ));
1329 #endif
1330         SAFE_FREE(msgbuf);
1331 }
1332
1333 /****************************************************************************
1334  Return the major devicenumber for UNIX extensions.
1335 ****************************************************************************/
1336
1337 uint32 unix_dev_major(SMB_DEV_T dev)
1338 {
1339 #if defined(HAVE_DEVICE_MAJOR_FN)
1340         return (uint32)major(dev);
1341 #else
1342         return (uint32)(dev >> 8);
1343 #endif
1344 }
1345
1346 /****************************************************************************
1347  Return the minor devicenumber for UNIX extensions.
1348 ****************************************************************************/
1349
1350 uint32 unix_dev_minor(SMB_DEV_T dev)
1351 {
1352 #if defined(HAVE_DEVICE_MINOR_FN)
1353         return (uint32)minor(dev);
1354 #else
1355         return (uint32)(dev & 0xff);
1356 #endif
1357 }
1358
1359 #if 0
1360 /*******************************************************************
1361  Return the number of CPUs.
1362 ********************************************************************/
1363
1364 int sys_get_number_of_cores(void)
1365 {
1366         int ret = -1;
1367
1368 #if defined(HAVE_SYSCONF)
1369 #if defined(_SC_NPROCESSORS_ONLN)
1370         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1371 #endif
1372 #if defined(_SC_NPROCESSORS_CONF)
1373         if (ret < 1) {
1374                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1375         }
1376 #endif
1377 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1378         int name[2];
1379         unsigned int len = sizeof(ret);
1380
1381         name[0] = CTL_HW;
1382 #if defined(HW_AVAILCPU)
1383         name[1] = HW_AVAILCPU;
1384
1385         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1386                 ret = -1;
1387         }
1388 #endif
1389 #if defined(HW_NCPU)
1390         if(ret < 1) {
1391                 name[0] = CTL_HW;
1392                 name[1] = HW_NCPU;
1393                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1394                         ret = -1;
1395                 }
1396         }
1397 #endif
1398 #endif
1399         if (ret < 1) {
1400                 ret = 1;
1401         }
1402         return ret;
1403 }
1404 #endif