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