librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source3 / lib / system.c
blob8dbf7dc33bc2ab954c494a559fd3d3876e18621b
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
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.
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.
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/>.
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"
30 #ifdef HAVE_SYS_SYSCTL_H
31 #include <sys/sysctl.h>
32 #endif
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
39 The idea is that this file will eventually have wrappers around all
40 important system calls in samba. The aims are:
42 - to enable easier porting by putting OS dependent stuff in here
44 - to allow for hooks into other "pseudo-filesystems"
46 - to allow easier integration of things like the japanese extensions
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.
55 /*******************************************************************
56 A read wrapper that will deal with EINTR.
57 ********************************************************************/
59 ssize_t sys_read(int fd, void *buf, size_t count)
61 ssize_t ret;
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;
73 /*******************************************************************
74 A write wrapper that will deal with EINTR.
75 ********************************************************************/
77 ssize_t sys_write(int fd, const void *buf, size_t count)
79 ssize_t ret;
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;
91 /*******************************************************************
92 A writev wrapper that will deal with EINTR.
93 ********************************************************************/
95 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
97 ssize_t ret;
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);
104 if (iov[0].iov_len > 1) {
105 return sys_write(fd, iov[0].iov_base,
106 (random() % (iov[0].iov_len-1)) + 1);
108 #endif
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;
120 /*******************************************************************
121 A pread wrapper that will deal with EINTR
122 ********************************************************************/
124 #if defined(HAVE_PREAD)
125 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
127 ssize_t ret;
129 do {
130 ret = pread(fd, buf, count, off);
131 } while (ret == -1 && errno == EINTR);
132 return ret;
134 #endif
136 /*******************************************************************
137 A write wrapper that will deal with EINTR
138 ********************************************************************/
140 #if defined(HAVE_PWRITE)
141 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
143 ssize_t ret;
145 do {
146 ret = pwrite(fd, buf, count, off);
147 } while (ret == -1 && errno == EINTR);
148 return ret;
150 #endif
152 /*******************************************************************
153 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
154 ********************************************************************/
156 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
158 ssize_t ret;
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;
170 /*******************************************************************
171 A recvfrom wrapper that will deal with EINTR.
172 ********************************************************************/
174 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
176 ssize_t ret;
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;
188 /*******************************************************************
189 A fcntl wrapper that will deal with EINTR.
190 ********************************************************************/
192 int sys_fcntl_ptr(int fd, int cmd, void *arg)
194 int ret;
196 do {
197 ret = fcntl(fd, cmd, arg);
198 } while (ret == -1 && errno == EINTR);
199 return ret;
202 /*******************************************************************
203 A fcntl wrapper that will deal with EINTR.
204 ********************************************************************/
206 int sys_fcntl_long(int fd, int cmd, long arg)
208 int ret;
210 do {
211 ret = fcntl(fd, cmd, arg);
212 } while (ret == -1 && errno == EINTR);
213 return ret;
216 /****************************************************************************
217 Get/Set all the possible time fields from a stat struct as a timespec.
218 ****************************************************************************/
220 static struct timespec get_atimespec(const struct stat *pst)
222 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
223 struct timespec ret;
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
255 static struct timespec get_mtimespec(const struct stat *pst)
257 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
258 struct timespec ret;
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
290 static struct timespec get_ctimespec(const struct stat *pst)
292 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
293 struct timespec ret;
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
325 /****************************************************************************
326 Return the best approximation to a 'create time' under UNIX from a stat
327 structure.
328 ****************************************************************************/
330 static struct timespec calc_create_time_stat(const struct stat *st)
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);
337 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
338 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
340 if(!null_timespec(ret1)) {
341 return ret1;
345 * One of ctime, mtime or atime was zero (probably atime).
346 * Just return MIN(ctime, mtime).
348 return ret;
351 /****************************************************************************
352 Return the best approximation to a 'create time' under UNIX from a stat_ex
353 structure.
354 ****************************************************************************/
356 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
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;
363 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
364 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
366 if(!null_timespec(ret1)) {
367 return ret1;
371 * One of ctime, mtime or atime was zero (probably atime).
372 * Just return MIN(ctime, mtime).
374 return ret;
377 /****************************************************************************
378 Return the 'create time' from a stat struct if it exists (birthtime) or else
379 use the best approximation.
380 ****************************************************************************/
382 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
383 bool fake_dir_create_times)
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;
390 dst->st_ex_calculated_birthtime = false;
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
405 /* Deal with systems that don't initialize birthtime correctly.
406 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
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;
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 ****************************************************************************/
420 void update_stat_ex_mtime(struct stat_ex *dst,
421 struct timespec write_ts)
423 dst->st_ex_mtime = write_ts;
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);
431 void update_stat_ex_create_time(struct stat_ex *dst,
432 struct timespec create_time)
434 dst->st_ex_btime = create_time;
435 dst->st_ex_calculated_birthtime = false;
438 void init_stat_ex_from_stat (struct stat_ex *dst,
439 const struct stat *src,
440 bool fake_dir_create_times)
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
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
466 #ifdef HAVE_STAT_ST_FLAGS
467 dst->st_ex_flags = src->st_flags;
468 #else
469 dst->st_ex_flags = 0;
470 #endif
473 /*******************************************************************
474 A stat() wrapper.
475 ********************************************************************/
477 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
478 bool fake_dir_create_times)
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;
488 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
490 return ret;
493 /*******************************************************************
494 An fstat() wrapper.
495 ********************************************************************/
497 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
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;
507 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
509 return ret;
512 /*******************************************************************
513 An lstat() wrapper.
514 ********************************************************************/
516 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
517 bool fake_dir_create_times)
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;
527 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
529 return ret;
532 /*******************************************************************
533 An posix_fallocate() wrapper.
534 ********************************************************************/
535 int sys_posix_fallocate(int fd, off_t offset, off_t len)
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;
546 /* unlikely to get a too large file on a 64bit system but ... */
547 if (new_len < 0)
548 return EFBIG;
550 fl.l_whence = SEEK_SET;
551 fl.l_start = offset;
552 fl.l_len = len;
554 ret=fcntl(fd, F_RESVSP64, &fl);
556 if (ret != 0)
557 return errno;
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
569 /*******************************************************************
570 An fallocate() function that matches the semantics of the Linux one.
571 ********************************************************************/
573 #ifdef HAVE_LINUX_FALLOC_H
574 #include <linux/falloc.h>
575 #endif
577 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
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;
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
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
611 /*******************************************************************
612 A flock() wrapper that will perform the kernel flock.
613 ********************************************************************/
615 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
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;
626 if (kernel_mode) {
627 flock(fd, kernel_mode);
629 #endif
635 /*******************************************************************
636 An fdopendir wrapper.
637 ********************************************************************/
639 DIR *sys_fdopendir(int fd)
641 #if defined(HAVE_FDOPENDIR)
642 return fdopendir(fd);
643 #else
644 errno = ENOSYS;
645 return NULL;
646 #endif
649 /*******************************************************************
650 An mknod() wrapper.
651 ********************************************************************/
653 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
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
664 /*******************************************************************
665 The wait() calls vary between systems
666 ********************************************************************/
668 int sys_waitpid(pid_t pid,int *status,int options)
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 */
677 /*******************************************************************
678 System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
679 on error (malloc fail usually).
680 ********************************************************************/
682 char *sys_getwd(void)
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;
690 while (1) {
691 s = SMB_REALLOC_ARRAY(s, char, allocated);
692 if (s == NULL) {
693 return NULL;
695 wd = getcwd(s, allocated);
696 if (wd) {
697 break;
699 if (errno != ERANGE) {
700 SAFE_FREE(s);
701 break;
703 allocated *= 2;
704 if (allocated < PATH_MAX) {
705 SAFE_FREE(s);
706 break;
709 return wd;
710 #else
711 char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
712 if (s == NULL) {
713 return NULL;
715 return getwd(s);
716 #endif
719 #if defined(HAVE_POSIX_CAPABILITIES)
721 /**************************************************************************
722 Try and abstract process capabilities (for systems that have them).
723 ****************************************************************************/
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.
730 static bool set_process_capability(enum smbd_capability capability,
731 bool enable)
733 cap_value_t cap_vals[2] = {0};
734 int num_cap_vals = 0;
736 cap_t cap;
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.
746 if (!prctl(PR_GET_KEEPCAPS)) {
747 prctl(PR_SET_KEEPCAPS, 1);
749 #endif
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;
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;
781 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
783 if (num_cap_vals == 0) {
784 cap_free(cap);
785 return True;
788 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
789 enable ? CAP_SET : CAP_CLEAR);
791 /* We never want to pass capabilities down to our children, so make
792 * sure they are not inherited.
794 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
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;
803 cap_free(cap);
804 return True;
807 #endif /* HAVE_POSIX_CAPABILITIES */
809 /****************************************************************************
810 Gain the oplock capability from the kernel if possible.
811 ****************************************************************************/
813 void set_effective_capability(enum smbd_capability capability)
815 #if defined(HAVE_POSIX_CAPABILITIES)
816 set_process_capability(capability, True);
817 #endif /* HAVE_POSIX_CAPABILITIES */
820 void drop_effective_capability(enum smbd_capability capability)
822 #if defined(HAVE_POSIX_CAPABILITIES)
823 set_process_capability(capability, False);
824 #endif /* HAVE_POSIX_CAPABILITIES */
827 /**************************************************************************
828 Wrapper for random().
829 ****************************************************************************/
831 long sys_random(void)
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
843 /**************************************************************************
844 Wrapper for srandom().
845 ****************************************************************************/
847 void sys_srandom(unsigned int seed)
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
859 #ifndef NGROUPS_MAX
860 #define NGROUPS_MAX 32 /* Guess... */
861 #endif
863 /**************************************************************************
864 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
865 ****************************************************************************/
867 int groups_max(void)
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
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 ****************************************************************************/
882 #if defined(HAVE_BROKEN_GETGROUPS)
884 #ifdef HAVE_BROKEN_GETGROUPS
885 #define GID_T int
886 #else
887 #define GID_T gid_t
888 #endif
890 static int sys_broken_getgroups(int setlen, gid_t *gidset)
892 GID_T gid;
893 GID_T *group_list;
894 int i, ngroups;
896 if(setlen == 0) {
897 return getgroups(setlen, &gid);
901 * Broken case. We need to allocate a
902 * GID_T array of size setlen.
905 if(setlen < 0) {
906 errno = EINVAL;
907 return -1;
910 if (setlen == 0)
911 setlen = groups_max();
913 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
914 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
915 return -1;
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;
925 for(i = 0; i < ngroups; i++)
926 gidset[i] = (gid_t)group_list[i];
928 SAFE_FREE(group_list);
929 return ngroups;
932 static int sys_broken_setgroups(int setlen, gid_t *gidset)
934 GID_T *group_list;
935 int i ;
937 if (setlen == 0)
938 return 0 ;
940 if (setlen < 0 || setlen > groups_max()) {
941 errno = EINVAL;
942 return -1;
946 * Broken case. We need to allocate a
947 * GID_T array of size setlen.
950 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
951 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
952 return -1;
955 for(i = 0; i < setlen; i++)
956 group_list[i] = (GID_T) gidset[i];
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;
965 SAFE_FREE(group_list);
966 return 0 ;
969 #endif /* HAVE_BROKEN_GETGROUPS */
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.
974 #if defined (FREEBSD) || defined (DARWINOS)
975 #define USE_BSD_SETGROUPS
976 #endif
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.
984 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
986 gid_t *new_gidset = NULL;
987 int max;
988 int ret;
990 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
991 max = groups_max();
993 /* No group list, just make sure we are setting the efective GID. */
994 if (setlen == 0) {
995 return samba_setgroups(1, &primary_gid);
998 /* If the primary gid is not the first array element, grow the array
999 * and insert it at the front.
1001 if (gidset[0] != primary_gid) {
1002 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1003 if (new_gidset == NULL) {
1004 return -1;
1007 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1008 new_gidset[0] = primary_gid;
1009 setlen++;
1012 if (setlen > max) {
1013 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1014 setlen, max));
1015 setlen = max;
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
1024 if (new_gidset) {
1025 int errsav = errno;
1026 SAFE_FREE(new_gidset);
1027 errno = errsav;
1030 return ret;
1033 #endif /* USE_BSD_SETGROUPS */
1035 /**************************************************************************
1036 Wrapper for getgroups. Deals with broken (int) case.
1037 ****************************************************************************/
1039 int sys_getgroups(int setlen, gid_t *gidset)
1041 #if defined(HAVE_BROKEN_GETGROUPS)
1042 return sys_broken_getgroups(setlen, gidset);
1043 #else
1044 return getgroups(setlen, gidset);
1045 #endif
1048 /**************************************************************************
1049 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1050 ****************************************************************************/
1052 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1054 #if !defined(HAVE_SETGROUPS)
1055 errno = ENOSYS;
1056 return -1;
1057 #endif /* HAVE_SETGROUPS */
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
1068 /**************************************************************************
1069 Extract a command into an arg list.
1070 ****************************************************************************/
1072 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1074 char *trunc_cmd;
1075 char *saveptr;
1076 char *ptr;
1077 int argcl;
1078 char **argl = NULL;
1079 int i;
1081 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1082 DEBUG(0, ("talloc failed\n"));
1083 goto nomem;
1086 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1087 TALLOC_FREE(trunc_cmd);
1088 errno = EINVAL;
1089 return NULL;
1093 * Count the args.
1096 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1097 argcl++;
1099 TALLOC_FREE(trunc_cmd);
1101 if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1102 goto nomem;
1106 * Now do the extraction.
1109 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1110 goto nomem;
1113 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1114 i = 0;
1116 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1117 goto nomem;
1120 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1122 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1123 goto nomem;
1127 argl[i++] = NULL;
1128 TALLOC_FREE(trunc_cmd);
1129 return argl;
1131 nomem:
1132 DEBUG(0, ("talloc failed\n"));
1133 TALLOC_FREE(trunc_cmd);
1134 TALLOC_FREE(argl);
1135 errno = ENOMEM;
1136 return NULL;
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 ****************************************************************************/
1145 typedef struct _popen_list
1147 int fd;
1148 pid_t child_pid;
1149 struct _popen_list *next;
1150 } popen_list;
1152 static popen_list *popen_chain;
1154 int sys_popen(const char *command)
1156 int parent_end, child_end;
1157 int pipe_fds[2];
1158 popen_list *entry = NULL;
1159 char **argl = NULL;
1160 int ret;
1162 if (!*command) {
1163 errno = EINVAL;
1164 return -1;
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;
1174 parent_end = pipe_fds[0];
1175 child_end = pipe_fds[1];
1177 entry = SMB_MALLOC_P(popen_list);
1178 if (entry == NULL) {
1179 DEBUG(0, ("sys_popen: malloc failed\n"));
1180 goto err_exit;
1183 ZERO_STRUCTP(entry);
1186 * Extract the command and args into a NULL terminated array.
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;
1195 entry->child_pid = fork();
1197 if (entry->child_pid == -1) {
1198 DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
1199 goto err_exit;
1202 if (entry->child_pid == 0) {
1205 * Child !
1208 int child_std_end = STDOUT_FILENO;
1209 popen_list *p;
1211 close(parent_end);
1212 if (child_end != child_std_end) {
1213 dup2 (child_end, child_std_end);
1214 close (child_end);
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."
1223 for (p = popen_chain; p; p = p->next)
1224 close(p->fd);
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)));
1231 _exit (127);
1235 * Parent.
1238 close (child_end);
1239 TALLOC_FREE(argl);
1241 /* Link into popen_chain. */
1242 entry->next = popen_chain;
1243 popen_chain = entry;
1244 entry->fd = parent_end;
1246 return entry->fd;
1248 err_exit:
1250 SAFE_FREE(entry);
1251 TALLOC_FREE(argl);
1252 close(pipe_fds[0]);
1253 close(pipe_fds[1]);
1254 return -1;
1257 /**************************************************************************
1258 Wrapper for pclose. Modified from the glibc sources.
1259 ****************************************************************************/
1261 int sys_pclose(int fd)
1263 int wstatus;
1264 popen_list **ptr = &popen_chain;
1265 popen_list *entry = NULL;
1266 pid_t wait_pid;
1267 int status = -1;
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;
1279 if (status < 0 || close(entry->fd) < 0)
1280 return -1;
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.
1288 do {
1289 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1290 } while (wait_pid == -1 && errno == EINTR);
1292 SAFE_FREE(entry);
1294 if (wait_pid == -1)
1295 return -1;
1296 return wstatus;
1299 /**************************************************************************
1300 Wrapper for Admin Logs.
1301 ****************************************************************************/
1303 void sys_adminlog(int priority, const char *format_str, ...)
1305 va_list ap;
1306 int ret;
1307 char *msgbuf = NULL;
1309 va_start( ap, format_str );
1310 ret = vasprintf( &msgbuf, format_str, ap );
1311 va_end( ap );
1313 if (ret == -1)
1314 return;
1316 #if defined(HAVE_SYSLOG)
1317 syslog( priority, "%s", msgbuf );
1318 #else
1319 DEBUG(0,("%s", msgbuf ));
1320 #endif
1321 SAFE_FREE(msgbuf);
1324 /****************************************************************************
1325 Return the major devicenumber for UNIX extensions.
1326 ****************************************************************************/
1328 uint32 unix_dev_major(SMB_DEV_T dev)
1330 #if defined(HAVE_DEVICE_MAJOR_FN)
1331 return (uint32)major(dev);
1332 #else
1333 return (uint32)(dev >> 8);
1334 #endif
1337 /****************************************************************************
1338 Return the minor devicenumber for UNIX extensions.
1339 ****************************************************************************/
1341 uint32 unix_dev_minor(SMB_DEV_T dev)
1343 #if defined(HAVE_DEVICE_MINOR_FN)
1344 return (uint32)minor(dev);
1345 #else
1346 return (uint32)(dev & 0xff);
1347 #endif
1350 #if 0
1351 /*******************************************************************
1352 Return the number of CPUs.
1353 ********************************************************************/
1355 int sys_get_number_of_cores(void)
1357 int ret = -1;
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);
1367 #endif
1368 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1369 int name[2];
1370 unsigned int len = sizeof(ret);
1372 name[0] = CTL_HW;
1373 #if defined(HW_AVAILCPU)
1374 name[1] = HW_AVAILCPU;
1376 if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1377 ret = -1;
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;
1388 #endif
1389 #endif
1390 if (ret < 1) {
1391 ret = 1;
1393 return ret;
1395 #endif