2 Unix SMB/CIFS implementation.
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/>.
24 #include "system/syslog.h"
25 #include "system/capability.h"
26 #include "system/passwd.h"
27 #include "system/filesys.h"
29 #ifdef HAVE_SYS_SYSCTL_H
30 #include <sys/sysctl.h>
33 #ifdef HAVE_SYS_PRCTL_H
34 #include <sys/prctl.h>
38 The idea is that this file will eventually have wrappers around all
39 important system calls in samba. The aims are:
41 - to enable easier porting by putting OS dependent stuff in here
43 - to allow for hooks into other "pseudo-filesystems"
45 - to allow easier integration of things like the japanese extensions
47 - to support the philosophy of Samba to expose the features of
48 the OS within the SMB model. In general whatever file/printer/variable
49 expansions/etc make sense to the OS should be acceptable to Samba.
54 /*******************************************************************
55 A read wrapper that will deal with EINTR.
56 ********************************************************************/
58 ssize_t sys_read(int fd, void *buf, size_t count)
63 ret = read(fd, buf, count);
64 #if defined(EWOULDBLOCK)
65 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
67 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
72 /*******************************************************************
73 A write wrapper that will deal with EINTR.
74 ********************************************************************/
76 ssize_t sys_write(int fd, const void *buf, size_t count)
81 ret = write(fd, buf, count);
82 #if defined(EWOULDBLOCK)
83 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
85 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
90 /*******************************************************************
91 A writev wrapper that will deal with EINTR.
92 ********************************************************************/
94 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
99 /* Try to confuse write_data_iov a bit */
100 if ((random() % 5) == 0) {
101 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
103 if (iov[0].iov_len > 1) {
104 return sys_write(fd, iov[0].iov_base,
105 (random() % (iov[0].iov_len-1)) + 1);
110 ret = writev(fd, iov, iovcnt);
111 #if defined(EWOULDBLOCK)
112 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
114 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
119 /*******************************************************************
120 A pread wrapper that will deal with EINTR
121 ********************************************************************/
123 #if defined(HAVE_PREAD)
124 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
129 ret = pread(fd, buf, count, off);
130 } while (ret == -1 && errno == EINTR);
135 /*******************************************************************
136 A write wrapper that will deal with EINTR
137 ********************************************************************/
139 #if defined(HAVE_PWRITE)
140 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
145 ret = pwrite(fd, buf, count, off);
146 } while (ret == -1 && errno == EINTR);
151 /*******************************************************************
152 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
153 ********************************************************************/
155 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
160 ret = send(s, msg, len, flags);
161 #if defined(EWOULDBLOCK)
162 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
164 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
169 /*******************************************************************
170 A recvfrom wrapper that will deal with EINTR.
171 ********************************************************************/
173 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
178 ret = recvfrom(s, buf, len, flags, from, fromlen);
179 #if defined(EWOULDBLOCK)
180 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
182 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
187 /*******************************************************************
188 A fcntl wrapper that will deal with EINTR.
189 ********************************************************************/
191 int sys_fcntl_ptr(int fd, int cmd, void *arg)
196 ret = fcntl(fd, cmd, arg);
197 } while (ret == -1 && errno == EINTR);
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)
210 /* Old system - no ns timestamp. */
211 ret.tv_sec = pst->st_atime;
215 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
217 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
219 ret.tv_sec = pst->st_atime;
220 ret.tv_nsec = pst->st_atimensec;
222 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
224 ret.tv_sec = pst->st_atime;
225 ret.tv_nsec = pst->st_atime_n;
227 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
229 ret.tv_sec = pst->st_atime;
230 ret.tv_nsec = pst->st_uatime * 1000;
232 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
233 return pst->st_atimespec;
235 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
240 static struct timespec get_mtimespec(const struct stat *pst)
242 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
245 /* Old system - no ns timestamp. */
246 ret.tv_sec = pst->st_mtime;
250 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
252 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
254 ret.tv_sec = pst->st_mtime;
255 ret.tv_nsec = pst->st_mtimensec;
257 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
259 ret.tv_sec = pst->st_mtime;
260 ret.tv_nsec = pst->st_mtime_n;
262 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
264 ret.tv_sec = pst->st_mtime;
265 ret.tv_nsec = pst->st_umtime * 1000;
267 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
268 return pst->st_mtimespec;
270 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
275 static struct timespec get_ctimespec(const struct stat *pst)
277 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
280 /* Old system - no ns timestamp. */
281 ret.tv_sec = pst->st_ctime;
285 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
287 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
289 ret.tv_sec = pst->st_ctime;
290 ret.tv_nsec = pst->st_ctimensec;
292 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
294 ret.tv_sec = pst->st_ctime;
295 ret.tv_nsec = pst->st_ctime_n;
297 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
299 ret.tv_sec = pst->st_ctime;
300 ret.tv_nsec = pst->st_uctime * 1000;
302 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
303 return pst->st_ctimespec;
305 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
310 /****************************************************************************
311 Return the best approximation to a 'create time' under UNIX from a stat
313 ****************************************************************************/
315 static struct timespec calc_create_time_stat(const struct stat *st)
317 struct timespec ret, ret1;
318 struct timespec c_time = get_ctimespec(st);
319 struct timespec m_time = get_mtimespec(st);
320 struct timespec a_time = get_atimespec(st);
322 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
323 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
325 if(!null_timespec(ret1)) {
330 * One of ctime, mtime or atime was zero (probably atime).
331 * Just return MIN(ctime, mtime).
336 /****************************************************************************
337 Return the best approximation to a 'create time' under UNIX from a stat_ex
339 ****************************************************************************/
341 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
343 struct timespec ret, ret1;
344 struct timespec c_time = st->st_ex_ctime;
345 struct timespec m_time = st->st_ex_mtime;
346 struct timespec a_time = st->st_ex_atime;
348 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
349 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
351 if(!null_timespec(ret1)) {
356 * One of ctime, mtime or atime was zero (probably atime).
357 * Just return MIN(ctime, mtime).
362 /****************************************************************************
363 Return the 'create time' from a stat struct if it exists (birthtime) or else
364 use the best approximation.
365 ****************************************************************************/
367 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
368 bool fake_dir_create_times)
370 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
371 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
372 dst->st_ex_btime.tv_nsec = 0;
375 dst->st_ex_calculated_birthtime = false;
377 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
378 dst->st_ex_btime = pst->st_birthtimespec;
379 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
380 dst->st_ex_btime.tv_sec = pst->st_birthtime;
381 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
382 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
383 dst->st_ex_btime.tv_sec = pst->st_birthtime;
384 dst->st_ex_btime.tv_nsec = 0;
386 dst->st_ex_btime = calc_create_time_stat(pst);
387 dst->st_ex_calculated_birthtime = true;
390 /* Deal with systems that don't initialize birthtime correctly.
391 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
393 if (null_timespec(dst->st_ex_btime)) {
394 dst->st_ex_btime = calc_create_time_stat(pst);
395 dst->st_ex_calculated_birthtime = true;
399 /****************************************************************************
400 If we update a timestamp in a stat_ex struct we may have to recalculate
401 the birthtime. For now only implement this for write time, but we may
402 also need to do it for atime and ctime. JRA.
403 ****************************************************************************/
405 void update_stat_ex_mtime(struct stat_ex *dst,
406 struct timespec write_ts)
408 dst->st_ex_mtime = write_ts;
410 /* We may have to recalculate btime. */
411 if (dst->st_ex_calculated_birthtime) {
412 dst->st_ex_btime = calc_create_time_stat_ex(dst);
416 void update_stat_ex_create_time(struct stat_ex *dst,
417 struct timespec create_time)
419 dst->st_ex_btime = create_time;
420 dst->st_ex_calculated_birthtime = false;
423 void init_stat_ex_from_stat (struct stat_ex *dst,
424 const struct stat *src,
425 bool fake_dir_create_times)
427 dst->st_ex_dev = src->st_dev;
428 dst->st_ex_ino = src->st_ino;
429 dst->st_ex_mode = src->st_mode;
430 dst->st_ex_nlink = src->st_nlink;
431 dst->st_ex_uid = src->st_uid;
432 dst->st_ex_gid = src->st_gid;
433 dst->st_ex_rdev = src->st_rdev;
434 dst->st_ex_size = src->st_size;
435 dst->st_ex_atime = get_atimespec(src);
436 dst->st_ex_mtime = get_mtimespec(src);
437 dst->st_ex_ctime = get_ctimespec(src);
438 make_create_timespec(src, dst, fake_dir_create_times);
439 #ifdef HAVE_STAT_ST_BLKSIZE
440 dst->st_ex_blksize = src->st_blksize;
442 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
445 #ifdef HAVE_STAT_ST_BLOCKS
446 dst->st_ex_blocks = src->st_blocks;
448 dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
451 #ifdef HAVE_STAT_ST_FLAGS
452 dst->st_ex_flags = src->st_flags;
454 dst->st_ex_flags = 0;
458 /*******************************************************************
460 ********************************************************************/
462 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
463 bool fake_dir_create_times)
467 ret = stat(fname, &statbuf);
469 /* we always want directories to appear zero size */
470 if (S_ISDIR(statbuf.st_mode)) {
473 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
478 /*******************************************************************
480 ********************************************************************/
482 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
486 ret = fstat(fd, &statbuf);
488 /* we always want directories to appear zero size */
489 if (S_ISDIR(statbuf.st_mode)) {
492 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
497 /*******************************************************************
499 ********************************************************************/
501 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
502 bool fake_dir_create_times)
506 ret = lstat(fname, &statbuf);
508 /* we always want directories to appear zero size */
509 if (S_ISDIR(statbuf.st_mode)) {
512 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
517 /*******************************************************************
518 An posix_fallocate() wrapper.
519 ********************************************************************/
520 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
522 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
523 return posix_fallocate(fd, offset, len);
524 #elif defined(F_RESVSP64)
525 /* this handles XFS on IRIX */
527 SMB_OFF_T new_len = offset + len;
531 /* unlikely to get a too large file on a 64bit system but ... */
535 fl.l_whence = SEEK_SET;
539 ret=fcntl(fd, F_RESVSP64, &fl);
544 /* Make sure the file gets enlarged after we allocated space: */
546 if (new_len > sbuf.st_size)
547 ftruncate64(fd, new_len);
554 /*******************************************************************
555 An fallocate() function that matches the semantics of the Linux one.
556 ********************************************************************/
558 #ifdef HAVE_LINUX_FALLOC_H
559 #include <linux/falloc.h>
562 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, SMB_OFF_T offset, SMB_OFF_T len)
564 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
567 case VFS_FALLOCATE_EXTEND_SIZE:
570 case VFS_FALLOCATE_KEEP_SIZE:
571 lmode = FALLOC_FL_KEEP_SIZE;
577 #if defined(HAVE_LINUX_FALLOCATE)
578 return fallocate(fd, lmode, offset, len);
581 /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
587 #if HAVE_KERNEL_SHARE_MODES
589 #define LOCK_MAND 32 /* This is a mandatory flock */
590 #define LOCK_READ 64 /* ... Which allows concurrent read operations */
591 #define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
592 #define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
596 /*******************************************************************
597 A flock() wrapper that will perform the kernel flock.
598 ********************************************************************/
600 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
602 #if HAVE_KERNEL_SHARE_MODES
604 if (share_mode == FILE_SHARE_WRITE) {
605 kernel_mode = LOCK_MAND|LOCK_WRITE;
606 } else if (share_mode == FILE_SHARE_READ) {
607 kernel_mode = LOCK_MAND|LOCK_READ;
608 } else if (share_mode == FILE_SHARE_NONE) {
609 kernel_mode = LOCK_MAND;
612 flock(fd, kernel_mode);
620 /*******************************************************************
621 An fdopendir wrapper.
622 Ugly hack - we need dirfd for this to work correctly in the
624 ********************************************************************/
626 SMB_STRUCT_DIR *sys_fdopendir(int fd)
628 #if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
629 return fdopendir(fd);
636 /*******************************************************************
638 ********************************************************************/
640 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
642 return readdir(dirp);
645 /*******************************************************************
647 ********************************************************************/
649 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
651 seekdir(dirp, offset);
654 /*******************************************************************
656 ********************************************************************/
658 long sys_telldir(SMB_STRUCT_DIR *dirp)
660 return (long)telldir(dirp);
663 /*******************************************************************
665 ********************************************************************/
667 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
672 /*******************************************************************
674 ********************************************************************/
676 int sys_closedir(SMB_STRUCT_DIR *dirp)
678 return closedir(dirp);
681 /*******************************************************************
683 ********************************************************************/
685 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
687 #if defined(HAVE_MKNOD)
688 return mknod(path, mode, dev);
690 /* No mknod system call. */
696 /*******************************************************************
697 The wait() calls vary between systems
698 ********************************************************************/
700 int sys_waitpid(pid_t pid,int *status,int options)
703 return waitpid(pid,status,options);
704 #else /* HAVE_WAITPID */
705 return wait4(pid, status, options, NULL);
706 #endif /* HAVE_WAITPID */
709 /*******************************************************************
710 System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
711 on error (malloc fail usually).
712 ********************************************************************/
714 char *sys_getwd(void)
716 #ifdef GETCWD_TAKES_NULL
717 return getcwd(NULL, 0);
719 char *wd = NULL, *s = NULL;
720 size_t allocated = PATH_MAX;
723 s = SMB_REALLOC_ARRAY(s, char, allocated);
727 wd = getcwd(s, allocated);
731 if (errno != ERANGE) {
736 if (allocated < PATH_MAX) {
743 char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
751 #if defined(HAVE_POSIX_CAPABILITIES)
753 /**************************************************************************
754 Try and abstract process capabilities (for systems that have them).
755 ****************************************************************************/
757 /* Set the POSIX capabilities needed for the given purpose into the effective
758 * capability set of the current process. Make sure they are always removed
759 * from the inheritable set, because there is no circumstance in which our
760 * children should inherit our elevated privileges.
762 static bool set_process_capability(enum smbd_capability capability,
765 cap_value_t cap_vals[2] = {0};
766 int num_cap_vals = 0;
770 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
771 /* On Linux, make sure that any capabilities we grab are sticky
772 * across UID changes. We expect that this would allow us to keep both
773 * the effective and permitted capability sets, but as of circa 2.6.16,
774 * only the permitted set is kept. It is a bug (which we work around)
775 * that the effective set is lost, but we still require the effective
778 if (!prctl(PR_GET_KEEPCAPS)) {
779 prctl(PR_SET_KEEPCAPS, 1);
783 cap = cap_get_proc();
785 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
790 switch (capability) {
791 case KERNEL_OPLOCK_CAPABILITY:
792 #ifdef CAP_NETWORK_MGT
793 /* IRIX has CAP_NETWORK_MGT for oplocks. */
794 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
797 case DMAPI_ACCESS_CAPABILITY:
798 #ifdef CAP_DEVICE_MGT
799 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
800 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
802 /* Linux has CAP_MKNOD for DMAPI access. */
803 cap_vals[num_cap_vals++] = CAP_MKNOD;
806 case LEASE_CAPABILITY:
808 cap_vals[num_cap_vals++] = CAP_LEASE;
813 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
815 if (num_cap_vals == 0) {
820 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
821 enable ? CAP_SET : CAP_CLEAR);
823 /* We never want to pass capabilities down to our children, so make
824 * sure they are not inherited.
826 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
828 if (cap_set_proc(cap) == -1) {
829 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
839 #endif /* HAVE_POSIX_CAPABILITIES */
841 /****************************************************************************
842 Gain the oplock capability from the kernel if possible.
843 ****************************************************************************/
845 void set_effective_capability(enum smbd_capability capability)
847 #if defined(HAVE_POSIX_CAPABILITIES)
848 set_process_capability(capability, True);
849 #endif /* HAVE_POSIX_CAPABILITIES */
852 void drop_effective_capability(enum smbd_capability capability)
854 #if defined(HAVE_POSIX_CAPABILITIES)
855 set_process_capability(capability, False);
856 #endif /* HAVE_POSIX_CAPABILITIES */
859 /**************************************************************************
860 Wrapper for random().
861 ****************************************************************************/
863 long sys_random(void)
865 #if defined(HAVE_RANDOM)
866 return (long)random();
867 #elif defined(HAVE_RAND)
870 DEBUG(0,("Error - no random function available !\n"));
875 /**************************************************************************
876 Wrapper for srandom().
877 ****************************************************************************/
879 void sys_srandom(unsigned int seed)
881 #if defined(HAVE_SRANDOM)
883 #elif defined(HAVE_SRAND)
886 DEBUG(0,("Error - no srandom function available !\n"));
892 #define NGROUPS_MAX 32 /* Guess... */
895 /**************************************************************************
896 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
897 ****************************************************************************/
901 #if defined(SYSCONF_SC_NGROUPS_MAX)
902 int ret = sysconf(_SC_NGROUPS_MAX);
903 return (ret == -1) ? NGROUPS_MAX : ret;
909 /**************************************************************************
910 Wrap setgroups and getgroups for systems that declare getgroups() as
911 returning an array of gid_t, but actuall return an array of int.
912 ****************************************************************************/
914 #if defined(HAVE_BROKEN_GETGROUPS)
916 #ifdef HAVE_BROKEN_GETGROUPS
922 static int sys_broken_getgroups(int setlen, gid_t *gidset)
929 return getgroups(setlen, &gid);
933 * Broken case. We need to allocate a
934 * GID_T array of size setlen.
943 setlen = groups_max();
945 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
946 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
950 if((ngroups = getgroups(setlen, group_list)) < 0) {
951 int saved_errno = errno;
952 SAFE_FREE(group_list);
957 for(i = 0; i < ngroups; i++)
958 gidset[i] = (gid_t)group_list[i];
960 SAFE_FREE(group_list);
964 static int sys_broken_setgroups(int setlen, gid_t *gidset)
972 if (setlen < 0 || setlen > groups_max()) {
978 * Broken case. We need to allocate a
979 * GID_T array of size setlen.
982 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
983 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
987 for(i = 0; i < setlen; i++)
988 group_list[i] = (GID_T) gidset[i];
990 if(setgroups(setlen, group_list) != 0) {
991 int saved_errno = errno;
992 SAFE_FREE(group_list);
997 SAFE_FREE(group_list);
1001 #endif /* HAVE_BROKEN_GETGROUPS */
1003 /* This is a list of systems that require the first GID passed to setgroups(2)
1004 * to be the effective GID. If your system is one of these, add it here.
1006 #if defined (FREEBSD) || defined (DARWINOS)
1007 #define USE_BSD_SETGROUPS
1010 #if defined(USE_BSD_SETGROUPS)
1011 /* Depending on the particular BSD implementation, the first GID that is
1012 * passed to setgroups(2) will either be ignored or will set the credential's
1013 * effective GID. In either case, the right thing to do is to guarantee that
1014 * gidset[0] is the effective GID.
1016 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1018 gid_t *new_gidset = NULL;
1022 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1025 /* No group list, just make sure we are setting the efective GID. */
1027 return setgroups(1, &primary_gid);
1030 /* If the primary gid is not the first array element, grow the array
1031 * and insert it at the front.
1033 if (gidset[0] != primary_gid) {
1034 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1035 if (new_gidset == NULL) {
1039 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1040 new_gidset[0] = primary_gid;
1045 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1050 #if defined(HAVE_BROKEN_GETGROUPS)
1051 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1053 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1058 SAFE_FREE(new_gidset);
1065 #endif /* USE_BSD_SETGROUPS */
1067 /**************************************************************************
1068 Wrapper for getgroups. Deals with broken (int) case.
1069 ****************************************************************************/
1071 int sys_getgroups(int setlen, gid_t *gidset)
1073 #if defined(HAVE_BROKEN_GETGROUPS)
1074 return sys_broken_getgroups(setlen, gidset);
1076 return getgroups(setlen, gidset);
1080 /**************************************************************************
1081 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1082 ****************************************************************************/
1084 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1086 #if !defined(HAVE_SETGROUPS)
1089 #endif /* HAVE_SETGROUPS */
1091 #if defined(USE_BSD_SETGROUPS)
1092 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1093 #elif defined(HAVE_BROKEN_GETGROUPS)
1094 return sys_broken_setgroups(setlen, gidset);
1096 return setgroups(setlen, gidset);
1100 /**************************************************************************
1101 Extract a command into an arg list.
1102 ****************************************************************************/
1104 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1113 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1114 DEBUG(0, ("talloc failed\n"));
1118 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1119 TALLOC_FREE(trunc_cmd);
1128 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1131 TALLOC_FREE(trunc_cmd);
1133 if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1138 * Now do the extraction.
1141 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1145 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1148 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1152 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1154 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1160 TALLOC_FREE(trunc_cmd);
1164 DEBUG(0, ("talloc failed\n"));
1165 TALLOC_FREE(trunc_cmd);
1171 /**************************************************************************
1172 Wrapper for popen. Safer as it doesn't search a path.
1173 Modified from the glibc sources.
1174 modified by tridge to return a file descriptor. We must kick our FILE* habit
1175 ****************************************************************************/
1177 typedef struct _popen_list
1181 struct _popen_list *next;
1184 static popen_list *popen_chain;
1186 int sys_popen(const char *command)
1188 int parent_end, child_end;
1190 popen_list *entry = NULL;
1193 if (pipe(pipe_fds) < 0)
1196 parent_end = pipe_fds[0];
1197 child_end = pipe_fds[1];
1204 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1207 ZERO_STRUCTP(entry);
1210 * Extract the command and args into a NULL terminated array.
1213 if(!(argl = extract_args(NULL, command)))
1216 entry->child_pid = fork();
1218 if (entry->child_pid == -1) {
1222 if (entry->child_pid == 0) {
1228 int child_std_end = STDOUT_FILENO;
1232 if (child_end != child_std_end) {
1233 dup2 (child_end, child_std_end);
1238 * POSIX.2: "popen() shall ensure that any streams from previous
1239 * popen() calls that remain open in the parent process are closed
1240 * in the new child process."
1243 for (p = popen_chain; p; p = p->next)
1246 execv(argl[0], argl);
1257 /* Link into popen_chain. */
1258 entry->next = popen_chain;
1259 popen_chain = entry;
1260 entry->fd = parent_end;
1273 /**************************************************************************
1274 Wrapper for pclose. Modified from the glibc sources.
1275 ****************************************************************************/
1277 int sys_pclose(int fd)
1280 popen_list **ptr = &popen_chain;
1281 popen_list *entry = NULL;
1285 /* Unlink from popen_chain. */
1286 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1287 if ((*ptr)->fd == fd) {
1289 *ptr = (*ptr)->next;
1295 if (status < 0 || close(entry->fd) < 0)
1299 * As Samba is catching and eating child process
1300 * exits we don't really care about the child exit
1301 * code, a -1 with errno = ECHILD will do fine for us.
1305 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1306 } while (wait_pid == -1 && errno == EINTR);
1315 /**************************************************************************
1316 Wrapper for Admin Logs.
1317 ****************************************************************************/
1319 void sys_adminlog(int priority, const char *format_str, ...)
1323 char *msgbuf = NULL;
1325 va_start( ap, format_str );
1326 ret = vasprintf( &msgbuf, format_str, ap );
1332 #if defined(HAVE_SYSLOG)
1333 syslog( priority, "%s", msgbuf );
1335 DEBUG(0,("%s", msgbuf ));
1340 /******** Solaris EA helper function prototypes ********/
1341 #ifdef HAVE_ATTROPEN
1342 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1343 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1344 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1345 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1346 static int solaris_unlinkat(int attrdirfd, const char *name);
1347 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1348 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1351 /**************************************************************************
1352 Wrappers for extented attribute calls. Based on the Linux package with
1353 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1354 ****************************************************************************/
1356 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1358 #if defined(HAVE_GETXATTR)
1359 #ifndef XATTR_ADD_OPT
1360 return getxattr(path, name, value, size);
1363 return getxattr(path, name, value, size, 0, options);
1365 #elif defined(HAVE_GETEA)
1366 return getea(path, name, value, size);
1367 #elif defined(HAVE_EXTATTR_GET_FILE)
1370 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1371 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1372 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1374 * The BSD implementation has a nasty habit of silently truncating
1375 * the returned value to the size of the buffer, so we have to check
1376 * that the buffer is large enough to fit the returned value.
1378 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1383 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1387 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1389 #elif defined(HAVE_ATTR_GET)
1390 int retval, flags = 0;
1391 int valuelength = (int)size;
1392 char *attrname = strchr(name,'.') + 1;
1394 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1396 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1398 return retval ? retval : valuelength;
1399 #elif defined(HAVE_ATTROPEN)
1401 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1403 ret = solaris_read_xattr(attrfd, value, size);
1413 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1415 #if defined(HAVE_LGETXATTR)
1416 return lgetxattr(path, name, value, size);
1417 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1418 int options = XATTR_NOFOLLOW;
1419 return getxattr(path, name, value, size, 0, options);
1420 #elif defined(HAVE_LGETEA)
1421 return lgetea(path, name, value, size);
1422 #elif defined(HAVE_EXTATTR_GET_LINK)
1425 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1426 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1427 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1429 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1434 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1438 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1440 #elif defined(HAVE_ATTR_GET)
1441 int retval, flags = ATTR_DONTFOLLOW;
1442 int valuelength = (int)size;
1443 char *attrname = strchr(name,'.') + 1;
1445 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1447 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1449 return retval ? retval : valuelength;
1450 #elif defined(HAVE_ATTROPEN)
1452 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1454 ret = solaris_read_xattr(attrfd, value, size);
1464 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1466 #if defined(HAVE_FGETXATTR)
1467 #ifndef XATTR_ADD_OPT
1468 return fgetxattr(filedes, name, value, size);
1471 return fgetxattr(filedes, name, value, size, 0, options);
1473 #elif defined(HAVE_FGETEA)
1474 return fgetea(filedes, name, value, size);
1475 #elif defined(HAVE_EXTATTR_GET_FD)
1478 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1479 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1480 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1482 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1487 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1491 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1493 #elif defined(HAVE_ATTR_GETF)
1494 int retval, flags = 0;
1495 int valuelength = (int)size;
1496 char *attrname = strchr(name,'.') + 1;
1498 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1500 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1502 return retval ? retval : valuelength;
1503 #elif defined(HAVE_ATTROPEN)
1505 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1507 ret = solaris_read_xattr(attrfd, value, size);
1517 #if defined(HAVE_EXTATTR_LIST_FILE)
1519 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1527 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1528 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1536 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1538 ssize_t list_size, total_size = 0;
1541 /* Iterate through extattr(2) namespaces */
1542 for(t = 0; t < ARRAY_SIZE(extattr); t++) {
1544 #if defined(HAVE_EXTATTR_LIST_FILE)
1546 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1549 #if defined(HAVE_EXTATTR_LIST_LINK)
1551 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1554 #if defined(HAVE_EXTATTR_LIST_FD)
1556 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1563 /* Some error happend. Errno should be set by the previous call */
1569 /* XXX: Call with an empty buffer may be used to calculate
1570 necessary buffer size. Unfortunately, we can't say, how
1571 many attributes were returned, so here is the potential
1572 problem with the emulation.
1575 /* Take the worse case of one char attribute names -
1576 two bytes per name plus one more for sanity.
1578 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1581 /* Count necessary offset to fit namespace prefixes */
1583 for(i = 0; i < list_size; i += list[i] + 1)
1584 len += extattr[t].len;
1586 total_size += list_size + len;
1587 /* Buffer is too small to fit the results */
1588 if(total_size > size) {
1592 /* Shift results back, so we can prepend prefixes */
1593 buf = (char *)memmove(list + len, list, list_size);
1595 for(i = 0; i < list_size; i += len + 1) {
1597 strncpy(list, extattr[t].name, extattr[t].len + 1);
1598 list += extattr[t].len;
1599 strncpy(list, buf + i + 1, len);
1610 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1611 static char attr_buffer[ATTR_MAX_VALUELEN];
1613 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1615 int retval = 0, index;
1616 attrlist_cursor_t *cursor = 0;
1618 attrlist_t * al = (attrlist_t *)attr_buffer;
1620 size_t ent_size, left = size;
1625 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1627 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1629 for (index = 0; index < al->al_count; index++) {
1630 ae = ATTR_ENTRY(attr_buffer, index);
1631 ent_size = strlen(ae->a_name) + sizeof("user.");
1632 if (left >= ent_size) {
1633 strncpy(bp, "user.", sizeof("user."));
1634 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1642 total_size += ent_size;
1644 if (al->al_more == 0) break;
1651 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1653 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1655 for (index = 0; index < al->al_count; index++) {
1656 ae = ATTR_ENTRY(attr_buffer, index);
1657 ent_size = strlen(ae->a_name) + sizeof("system.");
1658 if (left >= ent_size) {
1659 strncpy(bp, "system.", sizeof("system."));
1660 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1668 total_size += ent_size;
1670 if (al->al_more == 0) break;
1673 return (ssize_t)(retval ? retval : total_size);
1678 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1680 #if defined(HAVE_LISTXATTR)
1681 #ifndef XATTR_ADD_OPT
1682 return listxattr(path, list, size);
1685 return listxattr(path, list, size, options);
1687 #elif defined(HAVE_LISTEA)
1688 return listea(path, list, size);
1689 #elif defined(HAVE_EXTATTR_LIST_FILE)
1692 return bsd_attr_list(0, arg, list, size);
1693 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1694 return irix_attr_list(path, 0, list, size, 0);
1695 #elif defined(HAVE_ATTROPEN)
1697 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1698 if (attrdirfd >= 0) {
1699 ret = solaris_list_xattr(attrdirfd, list, size);
1709 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1711 #if defined(HAVE_LLISTXATTR)
1712 return llistxattr(path, list, size);
1713 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1714 int options = XATTR_NOFOLLOW;
1715 return listxattr(path, list, size, options);
1716 #elif defined(HAVE_LLISTEA)
1717 return llistea(path, list, size);
1718 #elif defined(HAVE_EXTATTR_LIST_LINK)
1721 return bsd_attr_list(1, arg, list, size);
1722 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1723 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1724 #elif defined(HAVE_ATTROPEN)
1726 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1727 if (attrdirfd >= 0) {
1728 ret = solaris_list_xattr(attrdirfd, list, size);
1738 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1740 #if defined(HAVE_FLISTXATTR)
1741 #ifndef XATTR_ADD_OPT
1742 return flistxattr(filedes, list, size);
1745 return flistxattr(filedes, list, size, options);
1747 #elif defined(HAVE_FLISTEA)
1748 return flistea(filedes, list, size);
1749 #elif defined(HAVE_EXTATTR_LIST_FD)
1751 arg.filedes = filedes;
1752 return bsd_attr_list(2, arg, list, size);
1753 #elif defined(HAVE_ATTR_LISTF)
1754 return irix_attr_list(NULL, filedes, list, size, 0);
1755 #elif defined(HAVE_ATTROPEN)
1757 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1758 if (attrdirfd >= 0) {
1759 ret = solaris_list_xattr(attrdirfd, list, size);
1769 int sys_removexattr (const char *path, const char *name)
1771 #if defined(HAVE_REMOVEXATTR)
1772 #ifndef XATTR_ADD_OPT
1773 return removexattr(path, name);
1776 return removexattr(path, name, options);
1778 #elif defined(HAVE_REMOVEEA)
1779 return removeea(path, name);
1780 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1782 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1783 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1784 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1786 return extattr_delete_file(path, attrnamespace, attrname);
1787 #elif defined(HAVE_ATTR_REMOVE)
1789 char *attrname = strchr(name,'.') + 1;
1791 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1793 return attr_remove(path, attrname, flags);
1794 #elif defined(HAVE_ATTROPEN)
1796 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1797 if (attrdirfd >= 0) {
1798 ret = solaris_unlinkat(attrdirfd, name);
1808 int sys_lremovexattr (const char *path, const char *name)
1810 #if defined(HAVE_LREMOVEXATTR)
1811 return lremovexattr(path, name);
1812 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1813 int options = XATTR_NOFOLLOW;
1814 return removexattr(path, name, options);
1815 #elif defined(HAVE_LREMOVEEA)
1816 return lremoveea(path, name);
1817 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1819 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1820 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1821 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1823 return extattr_delete_link(path, attrnamespace, attrname);
1824 #elif defined(HAVE_ATTR_REMOVE)
1825 int flags = ATTR_DONTFOLLOW;
1826 char *attrname = strchr(name,'.') + 1;
1828 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1830 return attr_remove(path, attrname, flags);
1831 #elif defined(HAVE_ATTROPEN)
1833 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1834 if (attrdirfd >= 0) {
1835 ret = solaris_unlinkat(attrdirfd, name);
1845 int sys_fremovexattr (int filedes, const char *name)
1847 #if defined(HAVE_FREMOVEXATTR)
1848 #ifndef XATTR_ADD_OPT
1849 return fremovexattr(filedes, name);
1852 return fremovexattr(filedes, name, options);
1854 #elif defined(HAVE_FREMOVEEA)
1855 return fremoveea(filedes, name);
1856 #elif defined(HAVE_EXTATTR_DELETE_FD)
1858 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1859 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1860 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1862 return extattr_delete_fd(filedes, attrnamespace, attrname);
1863 #elif defined(HAVE_ATTR_REMOVEF)
1865 char *attrname = strchr(name,'.') + 1;
1867 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1869 return attr_removef(filedes, attrname, flags);
1870 #elif defined(HAVE_ATTROPEN)
1872 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1873 if (attrdirfd >= 0) {
1874 ret = solaris_unlinkat(attrdirfd, name);
1884 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1886 #if defined(HAVE_SETXATTR)
1887 #ifndef XATTR_ADD_OPT
1888 return setxattr(path, name, value, size, flags);
1891 return setxattr(path, name, value, size, 0, options);
1893 #elif defined(HAVE_SETEA)
1894 return setea(path, name, value, size, flags);
1895 #elif defined(HAVE_EXTATTR_SET_FILE)
1898 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1899 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1900 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1902 /* Check attribute existence */
1903 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1905 /* REPLACE attribute, that doesn't exist */
1906 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1910 /* Ignore other errors */
1913 /* CREATE attribute, that already exists */
1914 if (flags & XATTR_CREATE) {
1920 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1921 return (retval < 0) ? -1 : 0;
1922 #elif defined(HAVE_ATTR_SET)
1924 char *attrname = strchr(name,'.') + 1;
1926 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1927 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1928 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1930 return attr_set(path, attrname, (const char *)value, size, myflags);
1931 #elif defined(HAVE_ATTROPEN)
1933 int myflags = O_RDWR;
1935 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1936 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1937 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1939 ret = solaris_write_xattr(attrfd, value, size);
1949 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1951 #if defined(HAVE_LSETXATTR)
1952 return lsetxattr(path, name, value, size, flags);
1953 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1954 int options = XATTR_NOFOLLOW;
1955 return setxattr(path, name, value, size, 0, options);
1956 #elif defined(LSETEA)
1957 return lsetea(path, name, value, size, flags);
1958 #elif defined(HAVE_EXTATTR_SET_LINK)
1961 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1962 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1963 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1965 /* Check attribute existence */
1966 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1968 /* REPLACE attribute, that doesn't exist */
1969 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1973 /* Ignore other errors */
1976 /* CREATE attribute, that already exists */
1977 if (flags & XATTR_CREATE) {
1984 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1985 return (retval < 0) ? -1 : 0;
1986 #elif defined(HAVE_ATTR_SET)
1987 int myflags = ATTR_DONTFOLLOW;
1988 char *attrname = strchr(name,'.') + 1;
1990 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1991 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1992 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1994 return attr_set(path, attrname, (const char *)value, size, myflags);
1995 #elif defined(HAVE_ATTROPEN)
1997 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1999 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2000 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2001 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2003 ret = solaris_write_xattr(attrfd, value, size);
2013 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2015 #if defined(HAVE_FSETXATTR)
2016 #ifndef XATTR_ADD_OPT
2017 return fsetxattr(filedes, name, value, size, flags);
2020 return fsetxattr(filedes, name, value, size, 0, options);
2022 #elif defined(HAVE_FSETEA)
2023 return fsetea(filedes, name, value, size, flags);
2024 #elif defined(HAVE_EXTATTR_SET_FD)
2027 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2028 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2029 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2031 /* Check attribute existence */
2032 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2034 /* REPLACE attribute, that doesn't exist */
2035 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2039 /* Ignore other errors */
2042 /* CREATE attribute, that already exists */
2043 if (flags & XATTR_CREATE) {
2049 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2050 return (retval < 0) ? -1 : 0;
2051 #elif defined(HAVE_ATTR_SETF)
2053 char *attrname = strchr(name,'.') + 1;
2055 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2056 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2057 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2059 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2060 #elif defined(HAVE_ATTROPEN)
2062 int myflags = O_RDWR | O_XATTR;
2064 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2065 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2066 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2068 ret = solaris_write_xattr(attrfd, value, size);
2078 /**************************************************************************
2079 helper functions for Solaris' EA support
2080 ****************************************************************************/
2081 #ifdef HAVE_ATTROPEN
2082 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2086 if (fstat(attrfd, &sbuf) == -1) {
2091 /* This is to return the current size of the named extended attribute */
2093 return sbuf.st_size;
2096 /* check size and read xattr */
2097 if (sbuf.st_size > size) {
2102 return read(attrfd, value, sbuf.st_size);
2105 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2110 int newfd = dup(attrdirfd);
2111 /* CAUTION: The originating file descriptor should not be
2112 used again following the call to fdopendir().
2113 For that reason we dup() the file descriptor
2114 here to make things more clear. */
2115 dirp = fdopendir(newfd);
2117 while ((de = readdir(dirp))) {
2118 size_t listlen = strlen(de->d_name) + 1;
2119 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2120 /* we don't want "." and ".." here: */
2121 DEBUG(10,("skipped EA %s\n",de->d_name));
2126 /* return the current size of the list of extended attribute names*/
2129 /* check size and copy entrieѕ + nul into list. */
2130 if ((len + listlen) > size) {
2135 strlcpy(list + len, de->d_name, listlen);
2141 if (closedir(dirp) == -1) {
2142 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2148 static int solaris_unlinkat(int attrdirfd, const char *name)
2150 if (unlinkat(attrdirfd, name, 0) == -1) {
2151 if (errno == ENOENT) {
2159 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2161 int filedes = attropen(path, attrpath, oflag, mode);
2162 if (filedes == -1) {
2163 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2164 if (errno == EINVAL) {
2173 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2175 int filedes = openat(fildes, path, oflag, mode);
2176 if (filedes == -1) {
2177 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2178 if (errno == EINVAL) {
2187 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2189 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2192 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2196 #endif /*HAVE_ATTROPEN*/
2199 /****************************************************************************
2200 Return the major devicenumber for UNIX extensions.
2201 ****************************************************************************/
2203 uint32 unix_dev_major(SMB_DEV_T dev)
2205 #if defined(HAVE_DEVICE_MAJOR_FN)
2206 return (uint32)major(dev);
2208 return (uint32)(dev >> 8);
2212 /****************************************************************************
2213 Return the minor devicenumber for UNIX extensions.
2214 ****************************************************************************/
2216 uint32 unix_dev_minor(SMB_DEV_T dev)
2218 #if defined(HAVE_DEVICE_MINOR_FN)
2219 return (uint32)minor(dev);
2221 return (uint32)(dev & 0xff);
2226 /*******************************************************************
2227 Return the number of CPUs.
2228 ********************************************************************/
2230 int sys_get_number_of_cores(void)
2234 #if defined(HAVE_SYSCONF)
2235 #if defined(_SC_NPROCESSORS_ONLN)
2236 ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
2238 #if defined(_SC_NPROCESSORS_CONF)
2240 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
2243 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
2245 unsigned int len = sizeof(ret);
2248 #if defined(HW_AVAILCPU)
2249 name[1] = HW_AVAILCPU;
2251 if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
2255 #if defined(HW_NCPU)
2259 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
2272 #if defined(WITH_AIO)
2274 /*******************************************************************
2275 An aio_read wrapper.
2276 ********************************************************************/
2278 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2280 #if defined(HAVE_AIO_READ)
2281 return aio_read(aiocb);
2288 /*******************************************************************
2289 An aio_write wrapper.
2290 ********************************************************************/
2292 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2294 #if defined(HAVE_AIO_WRITE)
2295 return aio_write(aiocb);
2302 /*******************************************************************
2303 An aio_return wrapper.
2304 ********************************************************************/
2306 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2308 #if defined(HAVE_AIO_RETURN)
2309 return aio_return(aiocb);
2316 /*******************************************************************
2317 An aio_cancel wrapper.
2318 ********************************************************************/
2320 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2322 #if defined(HAVE_AIO_CANCEL)
2323 return aio_cancel(fd, aiocb);
2330 /*******************************************************************
2331 An aio_error wrapper.
2332 ********************************************************************/
2334 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2336 #if defined(HAVE_AIO_ERROR)
2337 return aio_error(aiocb);
2344 /*******************************************************************
2345 An aio_fsync wrapper.
2346 ********************************************************************/
2348 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2350 #if defined(HAVE_AIO_FSYNC)
2351 return aio_fsync(op, aiocb);
2358 /*******************************************************************
2359 An aio_fsync wrapper.
2360 ********************************************************************/
2362 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2364 #if defined(HAVE_AIO_FSYNC)
2365 return aio_suspend(cblist, n, timeout);
2371 #else /* !WITH_AIO */
2373 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2379 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2385 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2391 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2397 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2403 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2409 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2414 #endif /* WITH_AIO */