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/>.
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
39 - to support the philosophy of Samba to expose the features of
40 the OS within the SMB model. In general whatever file/printer/variable
41 expansions/etc make sense to the OS should be acceptable to Samba.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align, size_t size )
52 #if defined(HAVE_POSIX_MEMALIGN)
54 int ret = posix_memalign( &p, align, size );
59 #elif defined(HAVE_MEMALIGN)
60 return memalign( align, size );
62 /* On *BSD systems memaligns doesn't exist, but memory will
63 * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67 size_t pagesize = (size_t)getpagesize();
69 size_t pagesize = (size_t)-1;
71 if (pagesize == (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
75 if (size < pagesize) {
78 return SMB_MALLOC(size);
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs)
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs < 0 || usecs > 999999) {
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
110 tval.tv_usec = usecs/1000;
111 select(0,NULL,NULL,NULL,&tval);
113 #endif /* HAVE_USLEEP */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_read(int fd, void *buf, size_t count)
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
134 ssize_t sys_write(int fd, const void *buf, size_t count)
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
144 /*******************************************************************
145 A writev wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
153 /* Try to confuse write_data_iov a bit */
154 if ((random() % 5) == 0) {
155 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
157 if (iov[0].iov_len > 1) {
158 return sys_write(fd, iov[0].iov_base,
159 (random() % (iov[0].iov_len-1)) + 1);
164 ret = writev(fd, iov, iovcnt);
165 } while (ret == -1 && errno == EINTR);
169 /*******************************************************************
170 A pread wrapper that will deal with EINTR and 64-bit file offsets.
171 ********************************************************************/
173 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
179 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
180 ret = pread64(fd, buf, count, off);
182 ret = pread(fd, buf, count, off);
184 } while (ret == -1 && errno == EINTR);
189 /*******************************************************************
190 A write wrapper that will deal with EINTR and 64-bit file offsets.
191 ********************************************************************/
193 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
199 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
200 ret = pwrite64(fd, buf, count, off);
202 ret = pwrite(fd, buf, count, off);
204 } while (ret == -1 && errno == EINTR);
209 /*******************************************************************
210 A send wrapper that will deal with EINTR.
211 ********************************************************************/
213 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
218 ret = send(s, msg, len, flags);
219 } while (ret == -1 && errno == EINTR);
223 /*******************************************************************
224 A sendto wrapper that will deal with EINTR.
225 ********************************************************************/
227 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
232 ret = sendto(s, msg, len, flags, to, tolen);
233 } while (ret == -1 && errno == EINTR);
237 /*******************************************************************
238 A recv wrapper that will deal with EINTR.
239 ********************************************************************/
241 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
246 ret = recv(fd, buf, count, flags);
247 } while (ret == -1 && errno == EINTR);
251 /*******************************************************************
252 A recvfrom wrapper that will deal with EINTR.
253 ********************************************************************/
255 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
260 ret = recvfrom(s, buf, len, flags, from, fromlen);
261 } while (ret == -1 && errno == EINTR);
265 /*******************************************************************
266 A fcntl wrapper that will deal with EINTR.
267 ********************************************************************/
269 int sys_fcntl_ptr(int fd, int cmd, void *arg)
274 ret = fcntl(fd, cmd, arg);
275 } while (ret == -1 && errno == EINTR);
279 /*******************************************************************
280 A fcntl wrapper that will deal with EINTR.
281 ********************************************************************/
283 int sys_fcntl_long(int fd, int cmd, long arg)
288 ret = fcntl(fd, cmd, arg);
289 } while (ret == -1 && errno == EINTR);
293 /****************************************************************************
294 Get/Set all the possible time fields from a stat struct as a timespec.
295 ****************************************************************************/
297 static struct timespec get_atimespec(const struct stat *pst)
299 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
302 /* Old system - no ns timestamp. */
303 ret.tv_sec = pst->st_atime;
307 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
309 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
311 ret.tv_sec = pst->st_atime;
312 ret.tv_nsec = pst->st_atimensec;
314 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
316 ret.tv_sec = pst->st_atime;
317 ret.tv_nsec = pst->st_atime_n;
319 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
321 ret.tv_sec = pst->st_atime;
322 ret.tv_nsec = pst->st_uatime * 1000;
324 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
325 return pst->st_atimespec;
327 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
332 static struct timespec get_mtimespec(const struct stat *pst)
334 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
337 /* Old system - no ns timestamp. */
338 ret.tv_sec = pst->st_mtime;
342 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
344 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
346 ret.tv_sec = pst->st_mtime;
347 ret.tv_nsec = pst->st_mtimensec;
349 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
351 ret.tv_sec = pst->st_mtime;
352 ret.tv_nsec = pst->st_mtime_n;
354 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
356 ret.tv_sec = pst->st_mtime;
357 ret.tv_nsec = pst->st_umtime * 1000;
359 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
360 return pst->st_mtimespec;
362 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
367 static struct timespec get_ctimespec(const struct stat *pst)
369 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
372 /* Old system - no ns timestamp. */
373 ret.tv_sec = pst->st_ctime;
377 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
379 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
381 ret.tv_sec = pst->st_ctime;
382 ret.tv_nsec = pst->st_ctimensec;
384 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
386 ret.tv_sec = pst->st_ctime;
387 ret.tv_nsec = pst->st_ctime_n;
389 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
391 ret.tv_sec = pst->st_ctime;
392 ret.tv_nsec = pst->st_uctime * 1000;
394 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
395 return pst->st_ctimespec;
397 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
402 /****************************************************************************
403 Return the best approximation to a 'create time' under UNIX from a stat
405 ****************************************************************************/
407 static struct timespec calc_create_time(const struct stat *st)
409 struct timespec ret, ret1;
410 struct timespec c_time = get_ctimespec(st);
411 struct timespec m_time = get_mtimespec(st);
412 struct timespec a_time = get_atimespec(st);
414 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
415 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
417 if(!null_timespec(ret1)) {
422 * One of ctime, mtime or atime was zero (probably atime).
423 * Just return MIN(ctime, mtime).
428 /****************************************************************************
429 Return the 'create time' from a stat struct if it exists (birthtime) or else
430 use the best approximation.
431 ****************************************************************************/
433 static struct timespec get_create_timespec(const struct stat *pst)
437 if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) {
438 ret.tv_sec = 315493200L; /* 1/1/1980 */
443 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
444 ret = pst->st_birthtimespec;
445 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
446 ret.tv_sec = pst->st_birthtime;
447 ret.tv_nsec = pst->st_birthtimenspec;
448 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
449 ret.tv_sec = pst->st_birthtime;
452 ret = calc_create_time(pst);
455 /* Deal with systems that don't initialize birthtime correctly.
456 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
458 if (null_timespec(ret)) {
459 ret = calc_create_time(pst);
465 static void init_stat_ex_from_stat (struct stat_ex *dst,
466 const struct stat *src)
468 dst->st_ex_dev = src->st_dev;
469 dst->st_ex_ino = src->st_ino;
470 dst->st_ex_mode = src->st_mode;
471 dst->st_ex_nlink = src->st_nlink;
472 dst->st_ex_uid = src->st_uid;
473 dst->st_ex_gid = src->st_gid;
474 dst->st_ex_rdev = src->st_rdev;
475 dst->st_ex_size = src->st_size;
476 dst->st_ex_atime = get_atimespec(src);
477 dst->st_ex_mtime = get_mtimespec(src);
478 dst->st_ex_ctime = get_ctimespec(src);
479 dst->st_ex_btime = get_create_timespec(src);
480 dst->st_ex_blksize = src->st_blksize;
481 dst->st_ex_blocks = src->st_blocks;
483 #ifdef HAVE_STAT_ST_FLAGS
484 dst->st_ex_flags = src->st_flags;
486 dst->st_ex_flags = 0;
490 /*******************************************************************
491 A stat() wrapper that will deal with 64 bit filesizes.
492 ********************************************************************/
494 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
497 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
498 ret = stat64(fname, sbuf);
501 ret = stat(fname, &statbuf);
504 /* we always want directories to appear zero size */
505 if (S_ISDIR(statbuf.st_mode)) {
508 init_stat_ex_from_stat(sbuf, &statbuf);
513 /*******************************************************************
514 An fstat() wrapper that will deal with 64 bit filesizes.
515 ********************************************************************/
517 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
520 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
521 ret = fstat64(fd, sbuf);
524 ret = fstat(fd, &statbuf);
527 /* we always want directories to appear zero size */
528 if (S_ISDIR(statbuf.st_mode)) {
531 init_stat_ex_from_stat(sbuf, &statbuf);
536 /*******************************************************************
537 An lstat() wrapper that will deal with 64 bit filesizes.
538 ********************************************************************/
540 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
543 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
544 ret = lstat64(fname, sbuf);
547 ret = lstat(fname, &statbuf);
550 /* we always want directories to appear zero size */
551 if (S_ISDIR(statbuf.st_mode)) {
554 init_stat_ex_from_stat(sbuf, &statbuf);
559 /*******************************************************************
560 An ftruncate() wrapper that will deal with 64 bit filesizes.
561 ********************************************************************/
563 int sys_ftruncate(int fd, SMB_OFF_T offset)
565 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
566 return ftruncate64(fd, offset);
568 return ftruncate(fd, offset);
572 /*******************************************************************
573 An lseek() wrapper that will deal with 64 bit filesizes.
574 ********************************************************************/
576 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
578 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
579 return lseek64(fd, offset, whence);
581 return lseek(fd, offset, whence);
585 /*******************************************************************
586 An fseek() wrapper that will deal with 64 bit filesizes.
587 ********************************************************************/
589 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
591 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
592 return fseek64(fp, offset, whence);
593 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
594 return fseeko64(fp, offset, whence);
596 return fseek(fp, offset, whence);
600 /*******************************************************************
601 An ftell() wrapper that will deal with 64 bit filesizes.
602 ********************************************************************/
604 SMB_OFF_T sys_ftell(FILE *fp)
606 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
607 return (SMB_OFF_T)ftell64(fp);
608 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
609 return (SMB_OFF_T)ftello64(fp);
611 return (SMB_OFF_T)ftell(fp);
615 /*******************************************************************
616 A creat() wrapper that will deal with 64 bit filesizes.
617 ********************************************************************/
619 int sys_creat(const char *path, mode_t mode)
621 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
622 return creat64(path, mode);
625 * If creat64 isn't defined then ensure we call a potential open64.
628 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
632 /*******************************************************************
633 An open() wrapper that will deal with 64 bit filesizes.
634 ********************************************************************/
636 int sys_open(const char *path, int oflag, mode_t mode)
638 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
639 return open64(path, oflag, mode);
641 return open(path, oflag, mode);
645 /*******************************************************************
646 An fopen() wrapper that will deal with 64 bit filesizes.
647 ********************************************************************/
649 FILE *sys_fopen(const char *path, const char *type)
651 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
652 return fopen64(path, type);
654 return fopen(path, type);
659 /*******************************************************************
660 A flock() wrapper that will perform the kernel flock.
661 ********************************************************************/
663 void kernel_flock(int fd, uint32 share_mode)
665 #if HAVE_KERNEL_SHARE_MODES
667 if (share_mode == FILE_SHARE_WRITE) {
668 kernel_mode = LOCK_MAND|LOCK_WRITE;
669 } else if (share_mode == FILE_SHARE_READ) {
670 kernel_mode = LOCK_MAND|LOCK_READ;
671 } else if (share_mode == FILE_SHARE_NONE) {
672 kernel_mode = LOCK_MAND;
675 flock(fd, kernel_mode);
683 /*******************************************************************
684 An opendir wrapper that will deal with 64 bit filesizes.
685 ********************************************************************/
687 SMB_STRUCT_DIR *sys_opendir(const char *name)
689 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
690 return opendir64(name);
692 return opendir(name);
696 /*******************************************************************
697 A readdir wrapper that will deal with 64 bit filesizes.
698 ********************************************************************/
700 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
702 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
703 return readdir64(dirp);
705 return readdir(dirp);
709 /*******************************************************************
710 A seekdir wrapper that will deal with 64 bit filesizes.
711 ********************************************************************/
713 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
715 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
716 seekdir64(dirp, offset);
718 seekdir(dirp, offset);
722 /*******************************************************************
723 A telldir wrapper that will deal with 64 bit filesizes.
724 ********************************************************************/
726 long sys_telldir(SMB_STRUCT_DIR *dirp)
728 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
729 return (long)telldir64(dirp);
731 return (long)telldir(dirp);
735 /*******************************************************************
736 A rewinddir wrapper that will deal with 64 bit filesizes.
737 ********************************************************************/
739 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
741 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
748 /*******************************************************************
749 A close wrapper that will deal with 64 bit filesizes.
750 ********************************************************************/
752 int sys_closedir(SMB_STRUCT_DIR *dirp)
754 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
755 return closedir64(dirp);
757 return closedir(dirp);
761 /*******************************************************************
762 An mknod() wrapper that will deal with 64 bit filesizes.
763 ********************************************************************/
765 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
767 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
768 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
769 return mknod64(path, mode, dev);
771 return mknod(path, mode, dev);
774 /* No mknod system call. */
780 /*******************************************************************
781 The wait() calls vary between systems
782 ********************************************************************/
784 int sys_waitpid(pid_t pid,int *status,int options)
787 return waitpid(pid,status,options);
788 #else /* HAVE_WAITPID */
789 return wait4(pid, status, options, NULL);
790 #endif /* HAVE_WAITPID */
793 /*******************************************************************
794 System wrapper for getwd
795 ********************************************************************/
797 char *sys_getwd(char *s)
801 wd = (char *)getcwd(s, PATH_MAX);
803 wd = (char *)getwd(s);
808 #if defined(HAVE_POSIX_CAPABILITIES)
810 /**************************************************************************
811 Try and abstract process capabilities (for systems that have them).
812 ****************************************************************************/
814 /* Set the POSIX capabilities needed for the given purpose into the effective
815 * capability set of the current process. Make sure they are always removed
816 * from the inheritable set, because there is no circumstance in which our
817 * children should inherit our elevated privileges.
819 static bool set_process_capability(enum smbd_capability capability,
822 cap_value_t cap_vals[2] = {0};
823 int num_cap_vals = 0;
827 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
828 /* On Linux, make sure that any capabilities we grab are sticky
829 * across UID changes. We expect that this would allow us to keep both
830 * the effective and permitted capability sets, but as of circa 2.6.16,
831 * only the permitted set is kept. It is a bug (which we work around)
832 * that the effective set is lost, but we still require the effective
835 if (!prctl(PR_GET_KEEPCAPS)) {
836 prctl(PR_SET_KEEPCAPS, 1);
840 cap = cap_get_proc();
842 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
847 switch (capability) {
848 case KERNEL_OPLOCK_CAPABILITY:
849 #ifdef CAP_NETWORK_MGT
850 /* IRIX has CAP_NETWORK_MGT for oplocks. */
851 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
854 case DMAPI_ACCESS_CAPABILITY:
855 #ifdef CAP_DEVICE_MGT
856 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
857 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
859 /* Linux has CAP_MKNOD for DMAPI access. */
860 cap_vals[num_cap_vals++] = CAP_MKNOD;
863 case LEASE_CAPABILITY:
865 cap_vals[num_cap_vals++] = CAP_LEASE;
870 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
872 if (num_cap_vals == 0) {
877 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
878 enable ? CAP_SET : CAP_CLEAR);
880 /* We never want to pass capabilities down to our children, so make
881 * sure they are not inherited.
883 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
885 if (cap_set_proc(cap) == -1) {
886 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
896 #endif /* HAVE_POSIX_CAPABILITIES */
898 /****************************************************************************
899 Gain the oplock capability from the kernel if possible.
900 ****************************************************************************/
902 void set_effective_capability(enum smbd_capability capability)
904 #if defined(HAVE_POSIX_CAPABILITIES)
905 set_process_capability(capability, True);
906 #endif /* HAVE_POSIX_CAPABILITIES */
909 void drop_effective_capability(enum smbd_capability capability)
911 #if defined(HAVE_POSIX_CAPABILITIES)
912 set_process_capability(capability, False);
913 #endif /* HAVE_POSIX_CAPABILITIES */
916 /**************************************************************************
917 Wrapper for random().
918 ****************************************************************************/
920 long sys_random(void)
922 #if defined(HAVE_RANDOM)
923 return (long)random();
924 #elif defined(HAVE_RAND)
927 DEBUG(0,("Error - no random function available !\n"));
932 /**************************************************************************
933 Wrapper for srandom().
934 ****************************************************************************/
936 void sys_srandom(unsigned int seed)
938 #if defined(HAVE_SRANDOM)
940 #elif defined(HAVE_SRAND)
943 DEBUG(0,("Error - no srandom function available !\n"));
948 /**************************************************************************
949 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
950 ****************************************************************************/
954 #if defined(SYSCONF_SC_NGROUPS_MAX)
955 int ret = sysconf(_SC_NGROUPS_MAX);
956 return (ret == -1) ? NGROUPS_MAX : ret;
962 /**************************************************************************
963 Wrap setgroups and getgroups for systems that declare getgroups() as
964 returning an array of gid_t, but actuall return an array of int.
965 ****************************************************************************/
967 #if defined(HAVE_BROKEN_GETGROUPS)
968 static int sys_broken_getgroups(int setlen, gid_t *gidset)
975 return getgroups(setlen, &gid);
979 * Broken case. We need to allocate a
980 * GID_T array of size setlen.
989 setlen = groups_max();
991 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
992 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
996 if((ngroups = getgroups(setlen, group_list)) < 0) {
997 int saved_errno = errno;
998 SAFE_FREE(group_list);
1003 for(i = 0; i < ngroups; i++)
1004 gidset[i] = (gid_t)group_list[i];
1006 SAFE_FREE(group_list);
1010 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1018 if (setlen < 0 || setlen > groups_max()) {
1024 * Broken case. We need to allocate a
1025 * GID_T array of size setlen.
1028 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1029 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1033 for(i = 0; i < setlen; i++)
1034 group_list[i] = (GID_T) gidset[i];
1036 if(setgroups(setlen, group_list) != 0) {
1037 int saved_errno = errno;
1038 SAFE_FREE(group_list);
1039 errno = saved_errno;
1043 SAFE_FREE(group_list);
1047 #endif /* HAVE_BROKEN_GETGROUPS */
1049 /* This is a list of systems that require the first GID passed to setgroups(2)
1050 * to be the effective GID. If your system is one of these, add it here.
1052 #if defined (FREEBSD) || defined (DARWINOS)
1053 #define USE_BSD_SETGROUPS
1056 #if defined(USE_BSD_SETGROUPS)
1057 /* Depending on the particular BSD implementation, the first GID that is
1058 * passed to setgroups(2) will either be ignored or will set the credential's
1059 * effective GID. In either case, the right thing to do is to guarantee that
1060 * gidset[0] is the effective GID.
1062 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1064 gid_t *new_gidset = NULL;
1068 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1071 /* No group list, just make sure we are setting the efective GID. */
1073 return setgroups(1, &primary_gid);
1076 /* If the primary gid is not the first array element, grow the array
1077 * and insert it at the front.
1079 if (gidset[0] != primary_gid) {
1080 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1081 if (new_gidset == NULL) {
1085 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1086 new_gidset[0] = primary_gid;
1091 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1096 #if defined(HAVE_BROKEN_GETGROUPS)
1097 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1099 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1104 SAFE_FREE(new_gidset);
1111 #endif /* USE_BSD_SETGROUPS */
1113 /**************************************************************************
1114 Wrapper for getgroups. Deals with broken (int) case.
1115 ****************************************************************************/
1117 int sys_getgroups(int setlen, gid_t *gidset)
1119 #if defined(HAVE_BROKEN_GETGROUPS)
1120 return sys_broken_getgroups(setlen, gidset);
1122 return getgroups(setlen, gidset);
1126 /**************************************************************************
1127 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1128 ****************************************************************************/
1130 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1132 #if !defined(HAVE_SETGROUPS)
1135 #endif /* HAVE_SETGROUPS */
1137 #if defined(USE_BSD_SETGROUPS)
1138 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1139 #elif defined(HAVE_BROKEN_GETGROUPS)
1140 return sys_broken_setgroups(setlen, gidset);
1142 return setgroups(setlen, gidset);
1146 /**************************************************************************
1147 Wrappers for setpwent(), getpwent() and endpwent()
1148 ****************************************************************************/
1150 void sys_setpwent(void)
1155 struct passwd *sys_getpwent(void)
1160 void sys_endpwent(void)
1165 /**************************************************************************
1166 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1167 ****************************************************************************/
1170 struct passwd *sys_getpwnam(const char *name)
1172 return getpwnam(name);
1175 struct passwd *sys_getpwuid(uid_t uid)
1177 return getpwuid(uid);
1180 struct group *sys_getgrnam(const char *name)
1182 return getgrnam(name);
1185 struct group *sys_getgrgid(gid_t gid)
1187 return getgrgid(gid);
1190 /**************************************************************************
1191 Extract a command into an arg list.
1192 ****************************************************************************/
1194 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1203 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1204 DEBUG(0, ("talloc failed\n"));
1208 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1209 TALLOC_FREE(trunc_cmd);
1218 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1221 TALLOC_FREE(trunc_cmd);
1223 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1228 * Now do the extraction.
1231 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1235 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1238 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1242 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1244 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1253 DEBUG(0, ("talloc failed\n"));
1254 TALLOC_FREE(trunc_cmd);
1260 /**************************************************************************
1261 Wrapper for popen. Safer as it doesn't search a path.
1262 Modified from the glibc sources.
1263 modified by tridge to return a file descriptor. We must kick our FILE* habit
1264 ****************************************************************************/
1266 typedef struct _popen_list
1270 struct _popen_list *next;
1273 static popen_list *popen_chain;
1275 int sys_popen(const char *command)
1277 int parent_end, child_end;
1279 popen_list *entry = NULL;
1282 if (pipe(pipe_fds) < 0)
1285 parent_end = pipe_fds[0];
1286 child_end = pipe_fds[1];
1293 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1296 ZERO_STRUCTP(entry);
1299 * Extract the command and args into a NULL terminated array.
1302 if(!(argl = extract_args(NULL, command)))
1305 entry->child_pid = sys_fork();
1307 if (entry->child_pid == -1) {
1311 if (entry->child_pid == 0) {
1317 int child_std_end = STDOUT_FILENO;
1321 if (child_end != child_std_end) {
1322 dup2 (child_end, child_std_end);
1327 * POSIX.2: "popen() shall ensure that any streams from previous
1328 * popen() calls that remain open in the parent process are closed
1329 * in the new child process."
1332 for (p = popen_chain; p; p = p->next)
1335 execv(argl[0], argl);
1346 /* Link into popen_chain. */
1347 entry->next = popen_chain;
1348 popen_chain = entry;
1349 entry->fd = parent_end;
1362 /**************************************************************************
1363 Wrapper for pclose. Modified from the glibc sources.
1364 ****************************************************************************/
1366 int sys_pclose(int fd)
1369 popen_list **ptr = &popen_chain;
1370 popen_list *entry = NULL;
1374 /* Unlink from popen_chain. */
1375 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1376 if ((*ptr)->fd == fd) {
1378 *ptr = (*ptr)->next;
1384 if (status < 0 || close(entry->fd) < 0)
1388 * As Samba is catching and eating child process
1389 * exits we don't really care about the child exit
1390 * code, a -1 with errno = ECHILD will do fine for us.
1394 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1395 } while (wait_pid == -1 && errno == EINTR);
1404 /**************************************************************************
1405 Wrapper for Admin Logs.
1406 ****************************************************************************/
1408 void sys_adminlog(int priority, const char *format_str, ...)
1412 char *msgbuf = NULL;
1414 va_start( ap, format_str );
1415 ret = vasprintf( &msgbuf, format_str, ap );
1421 #if defined(HAVE_SYSLOG)
1422 syslog( priority, "%s", msgbuf );
1424 DEBUG(0,("%s", msgbuf ));
1429 /******** Solaris EA helper function prototypes ********/
1430 #ifdef HAVE_ATTROPEN
1431 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1432 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1433 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1434 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1435 static int solaris_unlinkat(int attrdirfd, const char *name);
1436 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1437 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1440 /**************************************************************************
1441 Wrappers for extented attribute calls. Based on the Linux package with
1442 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1443 ****************************************************************************/
1445 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1447 #if defined(HAVE_GETXATTR)
1448 #ifndef XATTR_ADD_OPT
1449 return getxattr(path, name, value, size);
1452 return getxattr(path, name, value, size, 0, options);
1454 #elif defined(HAVE_GETEA)
1455 return getea(path, name, value, size);
1456 #elif defined(HAVE_EXTATTR_GET_FILE)
1459 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1460 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1461 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1463 * The BSD implementation has a nasty habit of silently truncating
1464 * the returned value to the size of the buffer, so we have to check
1465 * that the buffer is large enough to fit the returned value.
1467 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1472 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1476 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1478 #elif defined(HAVE_ATTR_GET)
1479 int retval, flags = 0;
1480 int valuelength = (int)size;
1481 char *attrname = strchr(name,'.') + 1;
1483 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1485 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1487 return retval ? retval : valuelength;
1488 #elif defined(HAVE_ATTROPEN)
1490 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1492 ret = solaris_read_xattr(attrfd, value, size);
1502 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1504 #if defined(HAVE_LGETXATTR)
1505 return lgetxattr(path, name, value, size);
1506 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1507 int options = XATTR_NOFOLLOW;
1508 return getxattr(path, name, value, size, 0, options);
1509 #elif defined(HAVE_LGETEA)
1510 return lgetea(path, name, value, size);
1511 #elif defined(HAVE_EXTATTR_GET_LINK)
1514 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1515 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1516 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1518 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1523 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1527 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1529 #elif defined(HAVE_ATTR_GET)
1530 int retval, flags = ATTR_DONTFOLLOW;
1531 int valuelength = (int)size;
1532 char *attrname = strchr(name,'.') + 1;
1534 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1536 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1538 return retval ? retval : valuelength;
1539 #elif defined(HAVE_ATTROPEN)
1541 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1543 ret = solaris_read_xattr(attrfd, value, size);
1553 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1555 #if defined(HAVE_FGETXATTR)
1556 #ifndef XATTR_ADD_OPT
1557 return fgetxattr(filedes, name, value, size);
1560 return fgetxattr(filedes, name, value, size, 0, options);
1562 #elif defined(HAVE_FGETEA)
1563 return fgetea(filedes, name, value, size);
1564 #elif defined(HAVE_EXTATTR_GET_FD)
1567 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1568 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1569 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1571 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1576 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1580 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1582 #elif defined(HAVE_ATTR_GETF)
1583 int retval, flags = 0;
1584 int valuelength = (int)size;
1585 char *attrname = strchr(name,'.') + 1;
1587 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1589 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1591 return retval ? retval : valuelength;
1592 #elif defined(HAVE_ATTROPEN)
1594 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1596 ret = solaris_read_xattr(attrfd, value, size);
1606 #if defined(HAVE_EXTATTR_LIST_FILE)
1608 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1616 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1617 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1625 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1627 ssize_t list_size, total_size = 0;
1630 /* Iterate through extattr(2) namespaces */
1631 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1633 #if defined(HAVE_EXTATTR_LIST_FILE)
1635 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1638 #if defined(HAVE_EXTATTR_LIST_LINK)
1640 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1643 #if defined(HAVE_EXTATTR_LIST_FD)
1645 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1652 /* Some error happend. Errno should be set by the previous call */
1658 /* XXX: Call with an empty buffer may be used to calculate
1659 necessary buffer size. Unfortunately, we can't say, how
1660 many attributes were returned, so here is the potential
1661 problem with the emulation.
1664 /* Take the worse case of one char attribute names -
1665 two bytes per name plus one more for sanity.
1667 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1670 /* Count necessary offset to fit namespace prefixes */
1672 for(i = 0; i < list_size; i += list[i] + 1)
1673 len += extattr[t].len;
1675 total_size += list_size + len;
1676 /* Buffer is too small to fit the results */
1677 if(total_size > size) {
1681 /* Shift results back, so we can prepend prefixes */
1682 buf = memmove(list + len, list, list_size);
1684 for(i = 0; i < list_size; i += len + 1) {
1686 strncpy(list, extattr[t].name, extattr[t].len + 1);
1687 list += extattr[t].len;
1688 strncpy(list, buf + i + 1, len);
1699 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1700 static char attr_buffer[ATTR_MAX_VALUELEN];
1702 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1704 int retval = 0, index;
1705 attrlist_cursor_t *cursor = 0;
1707 attrlist_t * al = (attrlist_t *)attr_buffer;
1709 size_t ent_size, left = size;
1714 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1716 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1718 for (index = 0; index < al->al_count; index++) {
1719 ae = ATTR_ENTRY(attr_buffer, index);
1720 ent_size = strlen(ae->a_name) + sizeof("user.");
1721 if (left >= ent_size) {
1722 strncpy(bp, "user.", sizeof("user."));
1723 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1731 total_size += ent_size;
1733 if (al->al_more == 0) break;
1740 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1742 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1744 for (index = 0; index < al->al_count; index++) {
1745 ae = ATTR_ENTRY(attr_buffer, index);
1746 ent_size = strlen(ae->a_name) + sizeof("system.");
1747 if (left >= ent_size) {
1748 strncpy(bp, "system.", sizeof("system."));
1749 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1757 total_size += ent_size;
1759 if (al->al_more == 0) break;
1762 return (ssize_t)(retval ? retval : total_size);
1767 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1769 #if defined(HAVE_LISTXATTR)
1770 #ifndef XATTR_ADD_OPT
1771 return listxattr(path, list, size);
1774 return listxattr(path, list, size, options);
1776 #elif defined(HAVE_LISTEA)
1777 return listea(path, list, size);
1778 #elif defined(HAVE_EXTATTR_LIST_FILE)
1781 return bsd_attr_list(0, arg, list, size);
1782 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1783 return irix_attr_list(path, 0, list, size, 0);
1784 #elif defined(HAVE_ATTROPEN)
1786 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1787 if (attrdirfd >= 0) {
1788 ret = solaris_list_xattr(attrdirfd, list, size);
1798 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1800 #if defined(HAVE_LLISTXATTR)
1801 return llistxattr(path, list, size);
1802 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1803 int options = XATTR_NOFOLLOW;
1804 return listxattr(path, list, size, options);
1805 #elif defined(HAVE_LLISTEA)
1806 return llistea(path, list, size);
1807 #elif defined(HAVE_EXTATTR_LIST_LINK)
1810 return bsd_attr_list(1, arg, list, size);
1811 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1812 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1813 #elif defined(HAVE_ATTROPEN)
1815 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1816 if (attrdirfd >= 0) {
1817 ret = solaris_list_xattr(attrdirfd, list, size);
1827 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1829 #if defined(HAVE_FLISTXATTR)
1830 #ifndef XATTR_ADD_OPT
1831 return flistxattr(filedes, list, size);
1834 return flistxattr(filedes, list, size, options);
1836 #elif defined(HAVE_FLISTEA)
1837 return flistea(filedes, list, size);
1838 #elif defined(HAVE_EXTATTR_LIST_FD)
1840 arg.filedes = filedes;
1841 return bsd_attr_list(2, arg, list, size);
1842 #elif defined(HAVE_ATTR_LISTF)
1843 return irix_attr_list(NULL, filedes, list, size, 0);
1844 #elif defined(HAVE_ATTROPEN)
1846 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1847 if (attrdirfd >= 0) {
1848 ret = solaris_list_xattr(attrdirfd, list, size);
1858 int sys_removexattr (const char *path, const char *name)
1860 #if defined(HAVE_REMOVEXATTR)
1861 #ifndef XATTR_ADD_OPT
1862 return removexattr(path, name);
1865 return removexattr(path, name, options);
1867 #elif defined(HAVE_REMOVEEA)
1868 return removeea(path, name);
1869 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1871 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1872 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1873 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1875 return extattr_delete_file(path, attrnamespace, attrname);
1876 #elif defined(HAVE_ATTR_REMOVE)
1878 char *attrname = strchr(name,'.') + 1;
1880 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1882 return attr_remove(path, attrname, flags);
1883 #elif defined(HAVE_ATTROPEN)
1885 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1886 if (attrdirfd >= 0) {
1887 ret = solaris_unlinkat(attrdirfd, name);
1897 int sys_lremovexattr (const char *path, const char *name)
1899 #if defined(HAVE_LREMOVEXATTR)
1900 return lremovexattr(path, name);
1901 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1902 int options = XATTR_NOFOLLOW;
1903 return removexattr(path, name, options);
1904 #elif defined(HAVE_LREMOVEEA)
1905 return lremoveea(path, name);
1906 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1908 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1909 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1910 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1912 return extattr_delete_link(path, attrnamespace, attrname);
1913 #elif defined(HAVE_ATTR_REMOVE)
1914 int flags = ATTR_DONTFOLLOW;
1915 char *attrname = strchr(name,'.') + 1;
1917 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1919 return attr_remove(path, attrname, flags);
1920 #elif defined(HAVE_ATTROPEN)
1922 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1923 if (attrdirfd >= 0) {
1924 ret = solaris_unlinkat(attrdirfd, name);
1934 int sys_fremovexattr (int filedes, const char *name)
1936 #if defined(HAVE_FREMOVEXATTR)
1937 #ifndef XATTR_ADD_OPT
1938 return fremovexattr(filedes, name);
1941 return fremovexattr(filedes, name, options);
1943 #elif defined(HAVE_FREMOVEEA)
1944 return fremoveea(filedes, name);
1945 #elif defined(HAVE_EXTATTR_DELETE_FD)
1947 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1948 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1949 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1951 return extattr_delete_fd(filedes, attrnamespace, attrname);
1952 #elif defined(HAVE_ATTR_REMOVEF)
1954 char *attrname = strchr(name,'.') + 1;
1956 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1958 return attr_removef(filedes, attrname, flags);
1959 #elif defined(HAVE_ATTROPEN)
1961 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1962 if (attrdirfd >= 0) {
1963 ret = solaris_unlinkat(attrdirfd, name);
1973 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1975 #if defined(HAVE_SETXATTR)
1976 #ifndef XATTR_ADD_OPT
1977 return setxattr(path, name, value, size, flags);
1980 return setxattr(path, name, value, size, 0, options);
1982 #elif defined(HAVE_SETEA)
1983 return setea(path, name, value, size, flags);
1984 #elif defined(HAVE_EXTATTR_SET_FILE)
1987 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1988 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1989 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1991 /* Check attribute existence */
1992 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1994 /* REPLACE attribute, that doesn't exist */
1995 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1999 /* Ignore other errors */
2002 /* CREATE attribute, that already exists */
2003 if (flags & XATTR_CREATE) {
2009 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2010 return (retval < 0) ? -1 : 0;
2011 #elif defined(HAVE_ATTR_SET)
2013 char *attrname = strchr(name,'.') + 1;
2015 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2016 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2017 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2019 return attr_set(path, attrname, (const char *)value, size, myflags);
2020 #elif defined(HAVE_ATTROPEN)
2022 int myflags = O_RDWR;
2024 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2025 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2026 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2028 ret = solaris_write_xattr(attrfd, value, size);
2038 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2040 #if defined(HAVE_LSETXATTR)
2041 return lsetxattr(path, name, value, size, flags);
2042 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2043 int options = XATTR_NOFOLLOW;
2044 return setxattr(path, name, value, size, 0, options);
2045 #elif defined(LSETEA)
2046 return lsetea(path, name, value, size, flags);
2047 #elif defined(HAVE_EXTATTR_SET_LINK)
2050 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2051 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2052 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2054 /* Check attribute existence */
2055 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2057 /* REPLACE attribute, that doesn't exist */
2058 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2062 /* Ignore other errors */
2065 /* CREATE attribute, that already exists */
2066 if (flags & XATTR_CREATE) {
2073 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2074 return (retval < 0) ? -1 : 0;
2075 #elif defined(HAVE_ATTR_SET)
2076 int myflags = ATTR_DONTFOLLOW;
2077 char *attrname = strchr(name,'.') + 1;
2079 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2080 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2081 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2083 return attr_set(path, attrname, (const char *)value, size, myflags);
2084 #elif defined(HAVE_ATTROPEN)
2086 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2088 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2089 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2090 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2092 ret = solaris_write_xattr(attrfd, value, size);
2102 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2104 #if defined(HAVE_FSETXATTR)
2105 #ifndef XATTR_ADD_OPT
2106 return fsetxattr(filedes, name, value, size, flags);
2109 return fsetxattr(filedes, name, value, size, 0, options);
2111 #elif defined(HAVE_FSETEA)
2112 return fsetea(filedes, name, value, size, flags);
2113 #elif defined(HAVE_EXTATTR_SET_FD)
2116 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2117 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2118 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2120 /* Check attribute existence */
2121 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2123 /* REPLACE attribute, that doesn't exist */
2124 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2128 /* Ignore other errors */
2131 /* CREATE attribute, that already exists */
2132 if (flags & XATTR_CREATE) {
2138 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2139 return (retval < 0) ? -1 : 0;
2140 #elif defined(HAVE_ATTR_SETF)
2142 char *attrname = strchr(name,'.') + 1;
2144 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2145 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2146 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2148 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2149 #elif defined(HAVE_ATTROPEN)
2151 int myflags = O_RDWR | O_XATTR;
2153 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2154 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2155 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2157 ret = solaris_write_xattr(attrfd, value, size);
2167 /**************************************************************************
2168 helper functions for Solaris' EA support
2169 ****************************************************************************/
2170 #ifdef HAVE_ATTROPEN
2171 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2175 if (fstat(attrfd, &sbuf) == -1) {
2180 /* This is to return the current size of the named extended attribute */
2182 return sbuf.st_size;
2185 /* check size and read xattr */
2186 if (sbuf.st_size > size) {
2191 return read(attrfd, value, sbuf.st_size);
2194 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2199 int newfd = dup(attrdirfd);
2200 /* CAUTION: The originating file descriptor should not be
2201 used again following the call to fdopendir().
2202 For that reason we dup() the file descriptor
2203 here to make things more clear. */
2204 dirp = fdopendir(newfd);
2206 while ((de = readdir(dirp))) {
2207 size_t listlen = strlen(de->d_name);
2208 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2209 /* we don't want "." and ".." here: */
2210 DEBUG(10,("skipped EA %s\n",de->d_name));
2215 /* return the current size of the list of extended attribute names*/
2218 /* check size and copy entrieѕ + nul into list. */
2219 if ((len + listlen + 1) > size) {
2224 safe_strcpy(list + len, de->d_name, listlen);
2232 if (closedir(dirp) == -1) {
2233 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2239 static int solaris_unlinkat(int attrdirfd, const char *name)
2241 if (unlinkat(attrdirfd, name, 0) == -1) {
2242 if (errno == ENOENT) {
2250 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2252 int filedes = attropen(path, attrpath, oflag, mode);
2253 if (filedes == -1) {
2254 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2255 if (errno == EINVAL) {
2264 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2266 int filedes = openat(fildes, path, oflag, mode);
2267 if (filedes == -1) {
2268 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2269 if (errno == EINVAL) {
2278 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2280 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2283 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2287 #endif /*HAVE_ATTROPEN*/
2290 /****************************************************************************
2291 Return the major devicenumber for UNIX extensions.
2292 ****************************************************************************/
2294 uint32 unix_dev_major(SMB_DEV_T dev)
2296 #if defined(HAVE_DEVICE_MAJOR_FN)
2297 return (uint32)major(dev);
2299 return (uint32)(dev >> 8);
2303 /****************************************************************************
2304 Return the minor devicenumber for UNIX extensions.
2305 ****************************************************************************/
2307 uint32 unix_dev_minor(SMB_DEV_T dev)
2309 #if defined(HAVE_DEVICE_MINOR_FN)
2310 return (uint32)minor(dev);
2312 return (uint32)(dev & 0xff);
2316 #if defined(WITH_AIO)
2318 /*******************************************************************
2319 An aio_read wrapper that will deal with 64-bit sizes.
2320 ********************************************************************/
2322 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2324 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2325 return aio_read64(aiocb);
2326 #elif defined(HAVE_AIO_READ)
2327 return aio_read(aiocb);
2334 /*******************************************************************
2335 An aio_write wrapper that will deal with 64-bit sizes.
2336 ********************************************************************/
2338 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2340 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2341 return aio_write64(aiocb);
2342 #elif defined(HAVE_AIO_WRITE)
2343 return aio_write(aiocb);
2350 /*******************************************************************
2351 An aio_return wrapper that will deal with 64-bit sizes.
2352 ********************************************************************/
2354 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2356 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2357 return aio_return64(aiocb);
2358 #elif defined(HAVE_AIO_RETURN)
2359 return aio_return(aiocb);
2366 /*******************************************************************
2367 An aio_cancel wrapper that will deal with 64-bit sizes.
2368 ********************************************************************/
2370 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2372 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2373 return aio_cancel64(fd, aiocb);
2374 #elif defined(HAVE_AIO_CANCEL)
2375 return aio_cancel(fd, aiocb);
2382 /*******************************************************************
2383 An aio_error wrapper that will deal with 64-bit sizes.
2384 ********************************************************************/
2386 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2388 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2389 return aio_error64(aiocb);
2390 #elif defined(HAVE_AIO_ERROR)
2391 return aio_error(aiocb);
2398 /*******************************************************************
2399 An aio_fsync wrapper that will deal with 64-bit sizes.
2400 ********************************************************************/
2402 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2404 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2405 return aio_fsync64(op, aiocb);
2406 #elif defined(HAVE_AIO_FSYNC)
2407 return aio_fsync(op, aiocb);
2414 /*******************************************************************
2415 An aio_fsync wrapper that will deal with 64-bit sizes.
2416 ********************************************************************/
2418 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2420 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2421 return aio_suspend64(cblist, n, timeout);
2422 #elif defined(HAVE_AIO_FSYNC)
2423 return aio_suspend(cblist, n, timeout);
2429 #else /* !WITH_AIO */
2431 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2437 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2443 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2449 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2455 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2461 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2467 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2472 #endif /* WITH_AIO */
2474 int sys_getpeereid( int s, uid_t *uid)
2476 #if defined(HAVE_PEERCRED)
2478 socklen_t cred_len = sizeof(struct ucred);
2481 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2486 if (cred_len != sizeof(struct ucred)) {
2499 int sys_getnameinfo(const struct sockaddr *psa,
2508 * For Solaris we must make sure salen is the
2509 * correct length for the incoming sa_family.
2512 if (salen == sizeof(struct sockaddr_storage)) {
2513 salen = sizeof(struct sockaddr_in);
2514 #if defined(HAVE_IPV6)
2515 if (psa->sa_family == AF_INET6) {
2516 salen = sizeof(struct sockaddr_in6);
2520 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2523 int sys_connect(int fd, const struct sockaddr * addr)
2525 socklen_t salen = -1;
2527 if (addr->sa_family == AF_INET) {
2528 salen = sizeof(struct sockaddr_in);
2529 } else if (addr->sa_family == AF_UNIX) {
2530 salen = sizeof(struct sockaddr_un);
2532 #if defined(HAVE_IPV6)
2533 else if (addr->sa_family == AF_INET6) {
2534 salen = sizeof(struct sockaddr_in6);
2538 return connect(fd, addr, salen);