s3:vfs: add SMB_VFS_READDIR_ATTR()
[Samba.git] / source3 / lib / system.c
blob6478e6f512cc8266d8e2a2934946db6bf6dbcc0e
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 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
67 return ret;
70 /*******************************************************************
71 A write wrapper that will deal with EINTR.
72 ********************************************************************/
74 ssize_t sys_write(int fd, const void *buf, size_t count)
76 ssize_t ret;
78 do {
79 ret = write(fd, buf, count);
80 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
82 return ret;
85 /*******************************************************************
86 A writev wrapper that will deal with EINTR.
87 ********************************************************************/
89 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
91 ssize_t ret;
93 #if 0
94 /* Try to confuse write_data_iov a bit */
95 if ((random() % 5) == 0) {
96 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
98 if (iov[0].iov_len > 1) {
99 return sys_write(fd, iov[0].iov_base,
100 (random() % (iov[0].iov_len-1)) + 1);
102 #endif
104 do {
105 ret = writev(fd, iov, iovcnt);
106 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
108 return ret;
111 /*******************************************************************
112 A pread wrapper that will deal with EINTR
113 ********************************************************************/
115 #if defined(HAVE_PREAD)
116 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
118 ssize_t ret;
120 do {
121 ret = pread(fd, buf, count, off);
122 } while (ret == -1 && errno == EINTR);
123 return ret;
125 #endif
127 /*******************************************************************
128 A write wrapper that will deal with EINTR
129 ********************************************************************/
131 #if defined(HAVE_PWRITE)
132 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
134 ssize_t ret;
136 do {
137 ret = pwrite(fd, buf, count, off);
138 } while (ret == -1 && errno == EINTR);
139 return ret;
141 #endif
143 /*******************************************************************
144 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
145 ********************************************************************/
147 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
149 ssize_t ret;
151 do {
152 ret = send(s, msg, len, flags);
153 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
155 return ret;
158 /*******************************************************************
159 A recvfrom wrapper that will deal with EINTR.
160 NB. As used with non-blocking sockets, return on EAGAIN/EWOULDBLOCK
161 ********************************************************************/
163 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
165 ssize_t ret;
167 do {
168 ret = recvfrom(s, buf, len, flags, from, fromlen);
169 } while (ret == -1 && (errno == EINTR));
170 return ret;
173 /*******************************************************************
174 A fcntl wrapper that will deal with EINTR.
175 ********************************************************************/
177 int sys_fcntl_ptr(int fd, int cmd, void *arg)
179 int ret;
181 do {
182 ret = fcntl(fd, cmd, arg);
183 } while (ret == -1 && errno == EINTR);
184 return ret;
187 /*******************************************************************
188 A fcntl wrapper that will deal with EINTR.
189 ********************************************************************/
191 int sys_fcntl_long(int fd, int cmd, long arg)
193 int ret;
195 do {
196 ret = fcntl(fd, cmd, arg);
197 } while (ret == -1 && errno == EINTR);
198 return ret;
201 /****************************************************************************
202 Get/Set all the possible time fields from a stat struct as a timespec.
203 ****************************************************************************/
205 static struct timespec get_atimespec(const struct stat *pst)
207 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
208 struct timespec ret;
210 /* Old system - no ns timestamp. */
211 ret.tv_sec = pst->st_atime;
212 ret.tv_nsec = 0;
213 return ret;
214 #else
215 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
216 struct timespec ret;
217 ret.tv_sec = pst->st_atim.tv_sec;
218 ret.tv_nsec = pst->st_atim.tv_nsec;
219 return ret;
220 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
221 struct timespec ret;
222 ret.tv_sec = pst->st_atime;
223 ret.tv_nsec = pst->st_atimensec;
224 return ret;
225 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
226 struct timespec ret;
227 ret.tv_sec = pst->st_atime;
228 ret.tv_nsec = pst->st_atime_n;
229 return ret;
230 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
231 struct timespec ret;
232 ret.tv_sec = pst->st_atime;
233 ret.tv_nsec = pst->st_uatime * 1000;
234 return ret;
235 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
236 return pst->st_atimespec;
237 #else
238 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
239 #endif
240 #endif
243 static struct timespec get_mtimespec(const struct stat *pst)
245 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
246 struct timespec ret;
248 /* Old system - no ns timestamp. */
249 ret.tv_sec = pst->st_mtime;
250 ret.tv_nsec = 0;
251 return ret;
252 #else
253 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
254 struct timespec ret;
255 ret.tv_sec = pst->st_mtim.tv_sec;
256 ret.tv_nsec = pst->st_mtim.tv_nsec;
257 return ret;
258 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
259 struct timespec ret;
260 ret.tv_sec = pst->st_mtime;
261 ret.tv_nsec = pst->st_mtimensec;
262 return ret;
263 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
264 struct timespec ret;
265 ret.tv_sec = pst->st_mtime;
266 ret.tv_nsec = pst->st_mtime_n;
267 return ret;
268 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
269 struct timespec ret;
270 ret.tv_sec = pst->st_mtime;
271 ret.tv_nsec = pst->st_umtime * 1000;
272 return ret;
273 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
274 return pst->st_mtimespec;
275 #else
276 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
277 #endif
278 #endif
281 static struct timespec get_ctimespec(const struct stat *pst)
283 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
284 struct timespec ret;
286 /* Old system - no ns timestamp. */
287 ret.tv_sec = pst->st_ctime;
288 ret.tv_nsec = 0;
289 return ret;
290 #else
291 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
292 struct timespec ret;
293 ret.tv_sec = pst->st_ctim.tv_sec;
294 ret.tv_nsec = pst->st_ctim.tv_nsec;
295 return ret;
296 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
297 struct timespec ret;
298 ret.tv_sec = pst->st_ctime;
299 ret.tv_nsec = pst->st_ctimensec;
300 return ret;
301 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
302 struct timespec ret;
303 ret.tv_sec = pst->st_ctime;
304 ret.tv_nsec = pst->st_ctime_n;
305 return ret;
306 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
307 struct timespec ret;
308 ret.tv_sec = pst->st_ctime;
309 ret.tv_nsec = pst->st_uctime * 1000;
310 return ret;
311 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
312 return pst->st_ctimespec;
313 #else
314 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
315 #endif
316 #endif
319 /****************************************************************************
320 Return the best approximation to a 'create time' under UNIX from a stat
321 structure.
322 ****************************************************************************/
324 static struct timespec calc_create_time_stat(const struct stat *st)
326 struct timespec ret, ret1;
327 struct timespec c_time = get_ctimespec(st);
328 struct timespec m_time = get_mtimespec(st);
329 struct timespec a_time = get_atimespec(st);
331 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
332 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
334 if(!null_timespec(ret1)) {
335 return ret1;
339 * One of ctime, mtime or atime was zero (probably atime).
340 * Just return MIN(ctime, mtime).
342 return ret;
345 /****************************************************************************
346 Return the best approximation to a 'create time' under UNIX from a stat_ex
347 structure.
348 ****************************************************************************/
350 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
352 struct timespec ret, ret1;
353 struct timespec c_time = st->st_ex_ctime;
354 struct timespec m_time = st->st_ex_mtime;
355 struct timespec a_time = st->st_ex_atime;
357 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
358 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
360 if(!null_timespec(ret1)) {
361 return ret1;
365 * One of ctime, mtime or atime was zero (probably atime).
366 * Just return MIN(ctime, mtime).
368 return ret;
371 /****************************************************************************
372 Return the 'create time' from a stat struct if it exists (birthtime) or else
373 use the best approximation.
374 ****************************************************************************/
376 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
377 bool fake_dir_create_times)
379 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
380 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
381 dst->st_ex_btime.tv_nsec = 0;
384 dst->st_ex_calculated_birthtime = false;
386 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
387 dst->st_ex_btime = pst->st_birthtimespec;
388 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
389 dst->st_ex_btime.tv_sec = pst->st_birthtime;
390 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
391 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
392 dst->st_ex_btime.tv_sec = pst->st_birthtime;
393 dst->st_ex_btime.tv_nsec = 0;
394 #else
395 dst->st_ex_btime = calc_create_time_stat(pst);
396 dst->st_ex_calculated_birthtime = true;
397 #endif
399 /* Deal with systems that don't initialize birthtime correctly.
400 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
402 if (null_timespec(dst->st_ex_btime)) {
403 dst->st_ex_btime = calc_create_time_stat(pst);
404 dst->st_ex_calculated_birthtime = true;
408 /****************************************************************************
409 If we update a timestamp in a stat_ex struct we may have to recalculate
410 the birthtime. For now only implement this for write time, but we may
411 also need to do it for atime and ctime. JRA.
412 ****************************************************************************/
414 void update_stat_ex_mtime(struct stat_ex *dst,
415 struct timespec write_ts)
417 dst->st_ex_mtime = write_ts;
419 /* We may have to recalculate btime. */
420 if (dst->st_ex_calculated_birthtime) {
421 dst->st_ex_btime = calc_create_time_stat_ex(dst);
425 void update_stat_ex_create_time(struct stat_ex *dst,
426 struct timespec create_time)
428 dst->st_ex_btime = create_time;
429 dst->st_ex_calculated_birthtime = false;
432 void init_stat_ex_from_stat (struct stat_ex *dst,
433 const struct stat *src,
434 bool fake_dir_create_times)
436 dst->st_ex_dev = src->st_dev;
437 dst->st_ex_ino = src->st_ino;
438 dst->st_ex_mode = src->st_mode;
439 dst->st_ex_nlink = src->st_nlink;
440 dst->st_ex_uid = src->st_uid;
441 dst->st_ex_gid = src->st_gid;
442 dst->st_ex_rdev = src->st_rdev;
443 dst->st_ex_size = src->st_size;
444 dst->st_ex_atime = get_atimespec(src);
445 dst->st_ex_mtime = get_mtimespec(src);
446 dst->st_ex_ctime = get_ctimespec(src);
447 make_create_timespec(src, dst, fake_dir_create_times);
448 #ifdef HAVE_STAT_ST_BLKSIZE
449 dst->st_ex_blksize = src->st_blksize;
450 #else
451 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
452 #endif
454 #ifdef HAVE_STAT_ST_BLOCKS
455 dst->st_ex_blocks = src->st_blocks;
456 #else
457 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
458 #endif
460 #ifdef HAVE_STAT_ST_FLAGS
461 dst->st_ex_flags = src->st_flags;
462 #else
463 dst->st_ex_flags = 0;
464 #endif
467 /*******************************************************************
468 A stat() wrapper.
469 ********************************************************************/
471 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
472 bool fake_dir_create_times)
474 int ret;
475 struct stat statbuf;
476 ret = stat(fname, &statbuf);
477 if (ret == 0) {
478 /* we always want directories to appear zero size */
479 if (S_ISDIR(statbuf.st_mode)) {
480 statbuf.st_size = 0;
482 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
484 return ret;
487 /*******************************************************************
488 An fstat() wrapper.
489 ********************************************************************/
491 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
493 int ret;
494 struct stat statbuf;
495 ret = fstat(fd, &statbuf);
496 if (ret == 0) {
497 /* we always want directories to appear zero size */
498 if (S_ISDIR(statbuf.st_mode)) {
499 statbuf.st_size = 0;
501 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
503 return ret;
506 /*******************************************************************
507 An lstat() wrapper.
508 ********************************************************************/
510 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
511 bool fake_dir_create_times)
513 int ret;
514 struct stat statbuf;
515 ret = lstat(fname, &statbuf);
516 if (ret == 0) {
517 /* we always want directories to appear zero size */
518 if (S_ISDIR(statbuf.st_mode)) {
519 statbuf.st_size = 0;
521 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
523 return ret;
526 /*******************************************************************
527 An posix_fallocate() wrapper.
528 ********************************************************************/
529 int sys_posix_fallocate(int fd, off_t offset, off_t len)
531 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
532 return posix_fallocate(fd, offset, len);
533 #elif defined(F_RESVSP64)
534 /* this handles XFS on IRIX */
535 struct flock64 fl;
536 off_t new_len = offset + len;
537 int ret;
538 struct stat64 sbuf;
540 /* unlikely to get a too large file on a 64bit system but ... */
541 if (new_len < 0)
542 return EFBIG;
544 fl.l_whence = SEEK_SET;
545 fl.l_start = offset;
546 fl.l_len = len;
548 ret=fcntl(fd, F_RESVSP64, &fl);
550 if (ret != 0)
551 return errno;
553 /* Make sure the file gets enlarged after we allocated space: */
554 fstat64(fd, &sbuf);
555 if (new_len > sbuf.st_size)
556 ftruncate64(fd, new_len);
557 return 0;
558 #else
559 return ENOSYS;
560 #endif
563 /*******************************************************************
564 An fallocate() function that matches the semantics of the Linux one.
565 ********************************************************************/
567 #ifdef HAVE_LINUX_FALLOC_H
568 #include <linux/falloc.h>
569 #endif
571 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
573 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
574 int lmode;
575 switch (mode) {
576 case VFS_FALLOCATE_EXTEND_SIZE:
577 lmode = 0;
578 break;
579 case VFS_FALLOCATE_KEEP_SIZE:
580 lmode = FALLOC_FL_KEEP_SIZE;
581 break;
582 default:
583 errno = EINVAL;
584 return -1;
586 #if defined(HAVE_LINUX_FALLOCATE)
587 return fallocate(fd, lmode, offset, len);
588 #endif
589 #else
590 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
591 errno = ENOSYS;
592 return -1;
593 #endif
596 #if HAVE_KERNEL_SHARE_MODES
597 #ifndef LOCK_MAND
598 #define LOCK_MAND 32 /* This is a mandatory flock */
599 #define LOCK_READ 64 /* ... Which allows concurrent read operations */
600 #define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
601 #define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
602 #endif
603 #endif
605 /*******************************************************************
606 A flock() wrapper that will perform the kernel flock.
607 ********************************************************************/
609 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
611 #if HAVE_KERNEL_SHARE_MODES
612 int kernel_mode = 0;
613 if (share_mode == FILE_SHARE_WRITE) {
614 kernel_mode = LOCK_MAND|LOCK_WRITE;
615 } else if (share_mode == FILE_SHARE_READ) {
616 kernel_mode = LOCK_MAND|LOCK_READ;
617 } else if (share_mode == FILE_SHARE_NONE) {
618 kernel_mode = LOCK_MAND;
620 if (kernel_mode) {
621 flock(fd, kernel_mode);
623 #endif
629 /*******************************************************************
630 An fdopendir wrapper.
631 ********************************************************************/
633 DIR *sys_fdopendir(int fd)
635 #if defined(HAVE_FDOPENDIR)
636 return fdopendir(fd);
637 #else
638 errno = ENOSYS;
639 return NULL;
640 #endif
643 /*******************************************************************
644 An mknod() wrapper.
645 ********************************************************************/
647 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
649 #if defined(HAVE_MKNOD)
650 return mknod(path, mode, dev);
651 #else
652 /* No mknod system call. */
653 errno = ENOSYS;
654 return -1;
655 #endif
658 /*******************************************************************
659 The wait() calls vary between systems
660 ********************************************************************/
662 int sys_waitpid(pid_t pid,int *status,int options)
664 #ifdef HAVE_WAITPID
665 return waitpid(pid,status,options);
666 #else /* HAVE_WAITPID */
667 return wait4(pid, status, options, NULL);
668 #endif /* HAVE_WAITPID */
671 /*******************************************************************
672 System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
673 on error (malloc fail usually).
674 ********************************************************************/
676 char *sys_getwd(void)
678 #ifdef GETCWD_TAKES_NULL
679 return getcwd(NULL, 0);
680 #elif HAVE_GETCWD
681 char *wd = NULL, *s = NULL;
682 size_t allocated = PATH_MAX;
684 while (1) {
685 s = SMB_REALLOC_ARRAY(s, char, allocated);
686 if (s == NULL) {
687 return NULL;
689 wd = getcwd(s, allocated);
690 if (wd) {
691 break;
693 if (errno != ERANGE) {
694 SAFE_FREE(s);
695 break;
697 allocated *= 2;
698 if (allocated < PATH_MAX) {
699 SAFE_FREE(s);
700 break;
703 return wd;
704 #else
705 char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
706 if (s == NULL) {
707 return NULL;
709 return getwd(s);
710 #endif
713 #if defined(HAVE_POSIX_CAPABILITIES)
715 /**************************************************************************
716 Try and abstract process capabilities (for systems that have them).
717 ****************************************************************************/
719 /* Set the POSIX capabilities needed for the given purpose into the effective
720 * capability set of the current process. Make sure they are always removed
721 * from the inheritable set, because there is no circumstance in which our
722 * children should inherit our elevated privileges.
724 static bool set_process_capability(enum smbd_capability capability,
725 bool enable)
727 cap_value_t cap_vals[2] = {0};
728 int num_cap_vals = 0;
730 cap_t cap;
732 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
733 /* On Linux, make sure that any capabilities we grab are sticky
734 * across UID changes. We expect that this would allow us to keep both
735 * the effective and permitted capability sets, but as of circa 2.6.16,
736 * only the permitted set is kept. It is a bug (which we work around)
737 * that the effective set is lost, but we still require the effective
738 * set to be kept.
740 if (!prctl(PR_GET_KEEPCAPS)) {
741 prctl(PR_SET_KEEPCAPS, 1);
743 #endif
745 cap = cap_get_proc();
746 if (cap == NULL) {
747 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
748 strerror(errno)));
749 return False;
752 switch (capability) {
753 case KERNEL_OPLOCK_CAPABILITY:
754 #ifdef CAP_NETWORK_MGT
755 /* IRIX has CAP_NETWORK_MGT for oplocks. */
756 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
757 #endif
758 break;
759 case DMAPI_ACCESS_CAPABILITY:
760 #ifdef CAP_DEVICE_MGT
761 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
762 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
763 #elif CAP_MKNOD
764 /* Linux has CAP_MKNOD for DMAPI access. */
765 cap_vals[num_cap_vals++] = CAP_MKNOD;
766 #endif
767 break;
768 case LEASE_CAPABILITY:
769 #ifdef CAP_LEASE
770 cap_vals[num_cap_vals++] = CAP_LEASE;
771 #endif
772 break;
773 case DAC_OVERRIDE_CAPABILITY:
774 #ifdef CAP_DAC_OVERRIDE
775 cap_vals[num_cap_vals++] = CAP_DAC_OVERRIDE;
776 #endif
779 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
781 if (num_cap_vals == 0) {
782 cap_free(cap);
783 return True;
786 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
787 enable ? CAP_SET : CAP_CLEAR);
789 /* We never want to pass capabilities down to our children, so make
790 * sure they are not inherited.
792 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
794 if (cap_set_proc(cap) == -1) {
795 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
796 strerror(errno)));
797 cap_free(cap);
798 return False;
801 cap_free(cap);
802 return True;
805 #endif /* HAVE_POSIX_CAPABILITIES */
807 /****************************************************************************
808 Gain the oplock capability from the kernel if possible.
809 ****************************************************************************/
811 void set_effective_capability(enum smbd_capability capability)
813 #if defined(HAVE_POSIX_CAPABILITIES)
814 set_process_capability(capability, True);
815 #endif /* HAVE_POSIX_CAPABILITIES */
818 void drop_effective_capability(enum smbd_capability capability)
820 #if defined(HAVE_POSIX_CAPABILITIES)
821 set_process_capability(capability, False);
822 #endif /* HAVE_POSIX_CAPABILITIES */
825 /**************************************************************************
826 Wrapper for random().
827 ****************************************************************************/
829 long sys_random(void)
831 #if defined(HAVE_RANDOM)
832 return (long)random();
833 #elif defined(HAVE_RAND)
834 return (long)rand();
835 #else
836 DEBUG(0,("Error - no random function available !\n"));
837 exit(1);
838 #endif
841 /**************************************************************************
842 Wrapper for srandom().
843 ****************************************************************************/
845 void sys_srandom(unsigned int seed)
847 #if defined(HAVE_SRANDOM)
848 srandom(seed);
849 #elif defined(HAVE_SRAND)
850 srand(seed);
851 #else
852 DEBUG(0,("Error - no srandom function available !\n"));
853 exit(1);
854 #endif
857 #ifndef NGROUPS_MAX
858 #define NGROUPS_MAX 32 /* Guess... */
859 #endif
861 /**************************************************************************
862 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
863 ****************************************************************************/
865 int groups_max(void)
867 #if defined(SYSCONF_SC_NGROUPS_MAX)
868 int ret = sysconf(_SC_NGROUPS_MAX);
869 return (ret == -1) ? NGROUPS_MAX : ret;
870 #else
871 return NGROUPS_MAX;
872 #endif
875 /**************************************************************************
876 Wrap setgroups and getgroups for systems that declare getgroups() as
877 returning an array of gid_t, but actuall return an array of int.
878 ****************************************************************************/
880 #if defined(HAVE_BROKEN_GETGROUPS)
882 #ifdef HAVE_BROKEN_GETGROUPS
883 #define GID_T int
884 #else
885 #define GID_T gid_t
886 #endif
888 static int sys_broken_getgroups(int setlen, gid_t *gidset)
890 GID_T gid;
891 GID_T *group_list;
892 int i, ngroups;
894 if(setlen == 0) {
895 return getgroups(setlen, &gid);
899 * Broken case. We need to allocate a
900 * GID_T array of size setlen.
903 if(setlen < 0) {
904 errno = EINVAL;
905 return -1;
908 if (setlen == 0)
909 setlen = groups_max();
911 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
912 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
913 return -1;
916 if((ngroups = getgroups(setlen, group_list)) < 0) {
917 int saved_errno = errno;
918 SAFE_FREE(group_list);
919 errno = saved_errno;
920 return -1;
923 for(i = 0; i < ngroups; i++)
924 gidset[i] = (gid_t)group_list[i];
926 SAFE_FREE(group_list);
927 return ngroups;
930 static int sys_broken_setgroups(int setlen, gid_t *gidset)
932 GID_T *group_list;
933 int i ;
935 if (setlen == 0)
936 return 0 ;
938 if (setlen < 0 || setlen > groups_max()) {
939 errno = EINVAL;
940 return -1;
944 * Broken case. We need to allocate a
945 * GID_T array of size setlen.
948 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
949 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
950 return -1;
953 for(i = 0; i < setlen; i++)
954 group_list[i] = (GID_T) gidset[i];
956 if(samba_setgroups(setlen, group_list) != 0) {
957 int saved_errno = errno;
958 SAFE_FREE(group_list);
959 errno = saved_errno;
960 return -1;
963 SAFE_FREE(group_list);
964 return 0 ;
967 #endif /* HAVE_BROKEN_GETGROUPS */
969 /* This is a list of systems that require the first GID passed to setgroups(2)
970 * to be the effective GID. If your system is one of these, add it here.
972 #if defined (FREEBSD) || defined (DARWINOS)
973 #define USE_BSD_SETGROUPS
974 #endif
976 #if defined(USE_BSD_SETGROUPS)
977 /* Depending on the particular BSD implementation, the first GID that is
978 * passed to setgroups(2) will either be ignored or will set the credential's
979 * effective GID. In either case, the right thing to do is to guarantee that
980 * gidset[0] is the effective GID.
982 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
984 gid_t *new_gidset = NULL;
985 int max;
986 int ret;
988 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
989 max = groups_max();
991 /* No group list, just make sure we are setting the efective GID. */
992 if (setlen == 0) {
993 return samba_setgroups(1, &primary_gid);
996 /* If the primary gid is not the first array element, grow the array
997 * and insert it at the front.
999 if (gidset[0] != primary_gid) {
1000 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1001 if (new_gidset == NULL) {
1002 return -1;
1005 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1006 new_gidset[0] = primary_gid;
1007 setlen++;
1010 if (setlen > max) {
1011 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1012 setlen, max));
1013 setlen = max;
1016 #if defined(HAVE_BROKEN_GETGROUPS)
1017 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1018 #else
1019 ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1020 #endif
1022 if (new_gidset) {
1023 int errsav = errno;
1024 SAFE_FREE(new_gidset);
1025 errno = errsav;
1028 return ret;
1031 #endif /* USE_BSD_SETGROUPS */
1033 /**************************************************************************
1034 Wrapper for getgroups. Deals with broken (int) case.
1035 ****************************************************************************/
1037 int sys_getgroups(int setlen, gid_t *gidset)
1039 #if defined(HAVE_BROKEN_GETGROUPS)
1040 return sys_broken_getgroups(setlen, gidset);
1041 #else
1042 return getgroups(setlen, gidset);
1043 #endif
1046 /**************************************************************************
1047 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1048 ****************************************************************************/
1050 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1052 #if !defined(HAVE_SETGROUPS)
1053 errno = ENOSYS;
1054 return -1;
1055 #endif /* HAVE_SETGROUPS */
1057 #if defined(USE_BSD_SETGROUPS)
1058 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1059 #elif defined(HAVE_BROKEN_GETGROUPS)
1060 return sys_broken_setgroups(setlen, gidset);
1061 #else
1062 return samba_setgroups(setlen, gidset);
1063 #endif
1066 /**************************************************************************
1067 Extract a command into an arg list.
1068 ****************************************************************************/
1070 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1072 char *trunc_cmd;
1073 char *saveptr;
1074 char *ptr;
1075 int argcl;
1076 char **argl = NULL;
1077 int i;
1079 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1080 DEBUG(0, ("talloc failed\n"));
1081 goto nomem;
1084 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1085 TALLOC_FREE(trunc_cmd);
1086 errno = EINVAL;
1087 return NULL;
1091 * Count the args.
1094 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1095 argcl++;
1097 TALLOC_FREE(trunc_cmd);
1099 if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1100 goto nomem;
1104 * Now do the extraction.
1107 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1108 goto nomem;
1111 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1112 i = 0;
1114 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1115 goto nomem;
1118 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1120 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1121 goto nomem;
1125 argl[i++] = NULL;
1126 TALLOC_FREE(trunc_cmd);
1127 return argl;
1129 nomem:
1130 DEBUG(0, ("talloc failed\n"));
1131 TALLOC_FREE(trunc_cmd);
1132 TALLOC_FREE(argl);
1133 errno = ENOMEM;
1134 return NULL;
1137 /**************************************************************************
1138 Wrapper for popen. Safer as it doesn't search a path.
1139 Modified from the glibc sources.
1140 modified by tridge to return a file descriptor. We must kick our FILE* habit
1141 ****************************************************************************/
1143 typedef struct _popen_list
1145 int fd;
1146 pid_t child_pid;
1147 struct _popen_list *next;
1148 } popen_list;
1150 static popen_list *popen_chain;
1152 int sys_popen(const char *command)
1154 int parent_end, child_end;
1155 int pipe_fds[2];
1156 popen_list *entry = NULL;
1157 char **argl = NULL;
1158 int ret;
1160 if (!*command) {
1161 errno = EINVAL;
1162 return -1;
1165 ret = pipe(pipe_fds);
1166 if (ret < 0) {
1167 DEBUG(0, ("sys_popen: error opening pipe: %s\n",
1168 strerror(errno)));
1169 return -1;
1172 parent_end = pipe_fds[0];
1173 child_end = pipe_fds[1];
1175 entry = SMB_MALLOC_P(popen_list);
1176 if (entry == NULL) {
1177 DEBUG(0, ("sys_popen: malloc failed\n"));
1178 goto err_exit;
1181 ZERO_STRUCTP(entry);
1184 * Extract the command and args into a NULL terminated array.
1187 argl = extract_args(NULL, command);
1188 if (argl == NULL) {
1189 DEBUG(0, ("sys_popen: extract_args() failed: %s\n", strerror(errno)));
1190 goto err_exit;
1193 entry->child_pid = fork();
1195 if (entry->child_pid == -1) {
1196 DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
1197 goto err_exit;
1200 if (entry->child_pid == 0) {
1203 * Child !
1206 int child_std_end = STDOUT_FILENO;
1207 popen_list *p;
1209 close(parent_end);
1210 if (child_end != child_std_end) {
1211 dup2 (child_end, child_std_end);
1212 close (child_end);
1216 * POSIX.2: "popen() shall ensure that any streams from previous
1217 * popen() calls that remain open in the parent process are closed
1218 * in the new child process."
1221 for (p = popen_chain; p; p = p->next)
1222 close(p->fd);
1224 ret = execv(argl[0], argl);
1225 if (ret == -1) {
1226 DEBUG(0, ("sys_popen: ERROR executing command "
1227 "'%s': %s\n", command, strerror(errno)));
1229 _exit (127);
1233 * Parent.
1236 close (child_end);
1237 TALLOC_FREE(argl);
1239 /* Link into popen_chain. */
1240 entry->next = popen_chain;
1241 popen_chain = entry;
1242 entry->fd = parent_end;
1244 return entry->fd;
1246 err_exit:
1248 SAFE_FREE(entry);
1249 TALLOC_FREE(argl);
1250 close(pipe_fds[0]);
1251 close(pipe_fds[1]);
1252 return -1;
1255 /**************************************************************************
1256 Wrapper for pclose. Modified from the glibc sources.
1257 ****************************************************************************/
1259 int sys_pclose(int fd)
1261 int wstatus;
1262 popen_list **ptr = &popen_chain;
1263 popen_list *entry = NULL;
1264 pid_t wait_pid;
1265 int status = -1;
1267 /* Unlink from popen_chain. */
1268 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1269 if ((*ptr)->fd == fd) {
1270 entry = *ptr;
1271 *ptr = (*ptr)->next;
1272 status = 0;
1273 break;
1277 if (status < 0 || close(entry->fd) < 0)
1278 return -1;
1281 * As Samba is catching and eating child process
1282 * exits we don't really care about the child exit
1283 * code, a -1 with errno = ECHILD will do fine for us.
1286 do {
1287 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1288 } while (wait_pid == -1 && errno == EINTR);
1290 SAFE_FREE(entry);
1292 if (wait_pid == -1)
1293 return -1;
1294 return wstatus;
1297 /****************************************************************************
1298 Return the major devicenumber for UNIX extensions.
1299 ****************************************************************************/
1301 uint32 unix_dev_major(SMB_DEV_T dev)
1303 #if defined(HAVE_DEVICE_MAJOR_FN)
1304 return (uint32)major(dev);
1305 #else
1306 return (uint32)(dev >> 8);
1307 #endif
1310 /****************************************************************************
1311 Return the minor devicenumber for UNIX extensions.
1312 ****************************************************************************/
1314 uint32 unix_dev_minor(SMB_DEV_T dev)
1316 #if defined(HAVE_DEVICE_MINOR_FN)
1317 return (uint32)minor(dev);
1318 #else
1319 return (uint32)(dev & 0xff);
1320 #endif
1323 #if 0
1324 /*******************************************************************
1325 Return the number of CPUs.
1326 ********************************************************************/
1328 int sys_get_number_of_cores(void)
1330 int ret = -1;
1332 #if defined(HAVE_SYSCONF)
1333 #if defined(_SC_NPROCESSORS_ONLN)
1334 ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1335 #endif
1336 #if defined(_SC_NPROCESSORS_CONF)
1337 if (ret < 1) {
1338 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1340 #endif
1341 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1342 int name[2];
1343 unsigned int len = sizeof(ret);
1345 name[0] = CTL_HW;
1346 #if defined(HW_AVAILCPU)
1347 name[1] = HW_AVAILCPU;
1349 if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1350 ret = -1;
1352 #endif
1353 #if defined(HW_NCPU)
1354 if(ret < 1) {
1355 name[0] = CTL_HW;
1356 name[1] = HW_NCPU;
1357 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1358 ret = -1;
1361 #endif
1362 #endif
1363 if (ret < 1) {
1364 ret = 1;
1366 return ret;
1368 #endif