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_stat(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 best approximation to a 'create time' under UNIX from a stat_ex
431 ****************************************************************************/
433 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
435 struct timespec ret, ret1;
436 struct timespec c_time = st->st_ex_ctime;
437 struct timespec m_time = st->st_ex_mtime;
438 struct timespec a_time = st->st_ex_atime;
440 ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
441 ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
443 if(!null_timespec(ret1)) {
448 * One of ctime, mtime or atime was zero (probably atime).
449 * Just return MIN(ctime, mtime).
454 /****************************************************************************
455 Return the 'create time' from a stat struct if it exists (birthtime) or else
456 use the best approximation.
457 ****************************************************************************/
459 static void get_create_timespec(const struct stat *pst, struct stat_ex *dst)
463 if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) {
464 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
465 dst->st_ex_btime.tv_nsec = 0;
468 dst->st_ex_calculated_birthtime = false;
470 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
471 dst->st_ex_btime = pst->st_birthtimespec;
472 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
473 dst->st_ex_btime.tv_sec = pst->st_birthtime;
474 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
475 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
476 dst->st_ex_btime.tv_sec = pst->st_birthtime;
477 dst->st_ex_btime.tv_nsec = 0;
479 dst->st_ex_btime = calc_create_time_stat(pst);
480 dst->st_ex_calculated_birthtime = true;
483 /* Deal with systems that don't initialize birthtime correctly.
484 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
486 if (null_timespec(ret)) {
487 dst->st_ex_btime = calc_create_time_stat(pst);
488 dst->st_ex_calculated_birthtime = true;
492 /****************************************************************************
493 If we update a timestamp in a stat_ex struct we may have to recalculate
494 the birthtime. For now only implement this for write time, but we may
495 also need to do it for atime and ctime. JRA.
496 ****************************************************************************/
498 void update_stat_ex_mtime(struct stat_ex *dst,
499 struct timespec write_ts)
501 dst->st_ex_mtime = write_ts;
503 /* We may have to recalculate btime. */
504 if (dst->st_ex_calculated_birthtime) {
505 dst->st_ex_btime = calc_create_time_stat_ex(dst);
509 static void init_stat_ex_from_stat (struct stat_ex *dst,
510 const struct stat *src)
512 dst->st_ex_dev = src->st_dev;
513 dst->st_ex_ino = src->st_ino;
514 dst->st_ex_mode = src->st_mode;
515 dst->st_ex_nlink = src->st_nlink;
516 dst->st_ex_uid = src->st_uid;
517 dst->st_ex_gid = src->st_gid;
518 dst->st_ex_rdev = src->st_rdev;
519 dst->st_ex_size = src->st_size;
520 dst->st_ex_atime = get_atimespec(src);
521 dst->st_ex_mtime = get_mtimespec(src);
522 dst->st_ex_ctime = get_ctimespec(src);
523 get_create_timespec(src, dst);
524 dst->st_ex_blksize = src->st_blksize;
525 dst->st_ex_blocks = src->st_blocks;
527 #ifdef HAVE_STAT_ST_FLAGS
528 dst->st_ex_flags = src->st_flags;
530 dst->st_ex_flags = 0;
534 /*******************************************************************
535 A stat() wrapper that will deal with 64 bit filesizes.
536 ********************************************************************/
538 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
541 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
542 ret = stat64(fname, sbuf);
545 ret = stat(fname, &statbuf);
548 /* we always want directories to appear zero size */
549 if (S_ISDIR(statbuf.st_mode)) {
552 init_stat_ex_from_stat(sbuf, &statbuf);
557 /*******************************************************************
558 An fstat() wrapper that will deal with 64 bit filesizes.
559 ********************************************************************/
561 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
564 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
565 ret = fstat64(fd, sbuf);
568 ret = fstat(fd, &statbuf);
571 /* we always want directories to appear zero size */
572 if (S_ISDIR(statbuf.st_mode)) {
575 init_stat_ex_from_stat(sbuf, &statbuf);
580 /*******************************************************************
581 An lstat() wrapper that will deal with 64 bit filesizes.
582 ********************************************************************/
584 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
587 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
588 ret = lstat64(fname, sbuf);
591 ret = lstat(fname, &statbuf);
594 /* we always want directories to appear zero size */
595 if (S_ISDIR(statbuf.st_mode)) {
598 init_stat_ex_from_stat(sbuf, &statbuf);
603 /*******************************************************************
604 An ftruncate() wrapper that will deal with 64 bit filesizes.
605 ********************************************************************/
607 int sys_ftruncate(int fd, SMB_OFF_T offset)
609 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
610 return ftruncate64(fd, offset);
612 return ftruncate(fd, offset);
616 /*******************************************************************
617 An lseek() wrapper that will deal with 64 bit filesizes.
618 ********************************************************************/
620 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
622 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
623 return lseek64(fd, offset, whence);
625 return lseek(fd, offset, whence);
629 /*******************************************************************
630 An fseek() wrapper that will deal with 64 bit filesizes.
631 ********************************************************************/
633 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
635 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
636 return fseek64(fp, offset, whence);
637 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
638 return fseeko64(fp, offset, whence);
640 return fseek(fp, offset, whence);
644 /*******************************************************************
645 An ftell() wrapper that will deal with 64 bit filesizes.
646 ********************************************************************/
648 SMB_OFF_T sys_ftell(FILE *fp)
650 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
651 return (SMB_OFF_T)ftell64(fp);
652 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
653 return (SMB_OFF_T)ftello64(fp);
655 return (SMB_OFF_T)ftell(fp);
659 /*******************************************************************
660 A creat() wrapper that will deal with 64 bit filesizes.
661 ********************************************************************/
663 int sys_creat(const char *path, mode_t mode)
665 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
666 return creat64(path, mode);
669 * If creat64 isn't defined then ensure we call a potential open64.
672 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
676 /*******************************************************************
677 An open() wrapper that will deal with 64 bit filesizes.
678 ********************************************************************/
680 int sys_open(const char *path, int oflag, mode_t mode)
682 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
683 return open64(path, oflag, mode);
685 return open(path, oflag, mode);
689 /*******************************************************************
690 An fopen() wrapper that will deal with 64 bit filesizes.
691 ********************************************************************/
693 FILE *sys_fopen(const char *path, const char *type)
695 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
696 return fopen64(path, type);
698 return fopen(path, type);
703 /*******************************************************************
704 A flock() wrapper that will perform the kernel flock.
705 ********************************************************************/
707 void kernel_flock(int fd, uint32 share_mode)
709 #if HAVE_KERNEL_SHARE_MODES
711 if (share_mode == FILE_SHARE_WRITE) {
712 kernel_mode = LOCK_MAND|LOCK_WRITE;
713 } else if (share_mode == FILE_SHARE_READ) {
714 kernel_mode = LOCK_MAND|LOCK_READ;
715 } else if (share_mode == FILE_SHARE_NONE) {
716 kernel_mode = LOCK_MAND;
719 flock(fd, kernel_mode);
727 /*******************************************************************
728 An opendir wrapper that will deal with 64 bit filesizes.
729 ********************************************************************/
731 SMB_STRUCT_DIR *sys_opendir(const char *name)
733 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
734 return opendir64(name);
736 return opendir(name);
740 /*******************************************************************
741 A readdir wrapper that will deal with 64 bit filesizes.
742 ********************************************************************/
744 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
746 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
747 return readdir64(dirp);
749 return readdir(dirp);
753 /*******************************************************************
754 A seekdir wrapper that will deal with 64 bit filesizes.
755 ********************************************************************/
757 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
759 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
760 seekdir64(dirp, offset);
762 seekdir(dirp, offset);
766 /*******************************************************************
767 A telldir wrapper that will deal with 64 bit filesizes.
768 ********************************************************************/
770 long sys_telldir(SMB_STRUCT_DIR *dirp)
772 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
773 return (long)telldir64(dirp);
775 return (long)telldir(dirp);
779 /*******************************************************************
780 A rewinddir wrapper that will deal with 64 bit filesizes.
781 ********************************************************************/
783 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
785 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
792 /*******************************************************************
793 A close wrapper that will deal with 64 bit filesizes.
794 ********************************************************************/
796 int sys_closedir(SMB_STRUCT_DIR *dirp)
798 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
799 return closedir64(dirp);
801 return closedir(dirp);
805 /*******************************************************************
806 An mknod() wrapper that will deal with 64 bit filesizes.
807 ********************************************************************/
809 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
811 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
812 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
813 return mknod64(path, mode, dev);
815 return mknod(path, mode, dev);
818 /* No mknod system call. */
824 /*******************************************************************
825 The wait() calls vary between systems
826 ********************************************************************/
828 int sys_waitpid(pid_t pid,int *status,int options)
831 return waitpid(pid,status,options);
832 #else /* HAVE_WAITPID */
833 return wait4(pid, status, options, NULL);
834 #endif /* HAVE_WAITPID */
837 /*******************************************************************
838 System wrapper for getwd
839 ********************************************************************/
841 char *sys_getwd(char *s)
845 wd = (char *)getcwd(s, PATH_MAX);
847 wd = (char *)getwd(s);
852 #if defined(HAVE_POSIX_CAPABILITIES)
854 /**************************************************************************
855 Try and abstract process capabilities (for systems that have them).
856 ****************************************************************************/
858 /* Set the POSIX capabilities needed for the given purpose into the effective
859 * capability set of the current process. Make sure they are always removed
860 * from the inheritable set, because there is no circumstance in which our
861 * children should inherit our elevated privileges.
863 static bool set_process_capability(enum smbd_capability capability,
866 cap_value_t cap_vals[2] = {0};
867 int num_cap_vals = 0;
871 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
872 /* On Linux, make sure that any capabilities we grab are sticky
873 * across UID changes. We expect that this would allow us to keep both
874 * the effective and permitted capability sets, but as of circa 2.6.16,
875 * only the permitted set is kept. It is a bug (which we work around)
876 * that the effective set is lost, but we still require the effective
879 if (!prctl(PR_GET_KEEPCAPS)) {
880 prctl(PR_SET_KEEPCAPS, 1);
884 cap = cap_get_proc();
886 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
891 switch (capability) {
892 case KERNEL_OPLOCK_CAPABILITY:
893 #ifdef CAP_NETWORK_MGT
894 /* IRIX has CAP_NETWORK_MGT for oplocks. */
895 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
898 case DMAPI_ACCESS_CAPABILITY:
899 #ifdef CAP_DEVICE_MGT
900 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
901 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
903 /* Linux has CAP_MKNOD for DMAPI access. */
904 cap_vals[num_cap_vals++] = CAP_MKNOD;
907 case LEASE_CAPABILITY:
909 cap_vals[num_cap_vals++] = CAP_LEASE;
914 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
916 if (num_cap_vals == 0) {
921 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
922 enable ? CAP_SET : CAP_CLEAR);
924 /* We never want to pass capabilities down to our children, so make
925 * sure they are not inherited.
927 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
929 if (cap_set_proc(cap) == -1) {
930 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
940 #endif /* HAVE_POSIX_CAPABILITIES */
942 /****************************************************************************
943 Gain the oplock capability from the kernel if possible.
944 ****************************************************************************/
946 void set_effective_capability(enum smbd_capability capability)
948 #if defined(HAVE_POSIX_CAPABILITIES)
949 set_process_capability(capability, True);
950 #endif /* HAVE_POSIX_CAPABILITIES */
953 void drop_effective_capability(enum smbd_capability capability)
955 #if defined(HAVE_POSIX_CAPABILITIES)
956 set_process_capability(capability, False);
957 #endif /* HAVE_POSIX_CAPABILITIES */
960 /**************************************************************************
961 Wrapper for random().
962 ****************************************************************************/
964 long sys_random(void)
966 #if defined(HAVE_RANDOM)
967 return (long)random();
968 #elif defined(HAVE_RAND)
971 DEBUG(0,("Error - no random function available !\n"));
976 /**************************************************************************
977 Wrapper for srandom().
978 ****************************************************************************/
980 void sys_srandom(unsigned int seed)
982 #if defined(HAVE_SRANDOM)
984 #elif defined(HAVE_SRAND)
987 DEBUG(0,("Error - no srandom function available !\n"));
992 /**************************************************************************
993 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
994 ****************************************************************************/
998 #if defined(SYSCONF_SC_NGROUPS_MAX)
999 int ret = sysconf(_SC_NGROUPS_MAX);
1000 return (ret == -1) ? NGROUPS_MAX : ret;
1006 /**************************************************************************
1007 Wrap setgroups and getgroups for systems that declare getgroups() as
1008 returning an array of gid_t, but actuall return an array of int.
1009 ****************************************************************************/
1011 #if defined(HAVE_BROKEN_GETGROUPS)
1012 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1019 return getgroups(setlen, &gid);
1023 * Broken case. We need to allocate a
1024 * GID_T array of size setlen.
1033 setlen = groups_max();
1035 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1036 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1040 if((ngroups = getgroups(setlen, group_list)) < 0) {
1041 int saved_errno = errno;
1042 SAFE_FREE(group_list);
1043 errno = saved_errno;
1047 for(i = 0; i < ngroups; i++)
1048 gidset[i] = (gid_t)group_list[i];
1050 SAFE_FREE(group_list);
1054 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1062 if (setlen < 0 || setlen > groups_max()) {
1068 * Broken case. We need to allocate a
1069 * GID_T array of size setlen.
1072 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1073 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1077 for(i = 0; i < setlen; i++)
1078 group_list[i] = (GID_T) gidset[i];
1080 if(setgroups(setlen, group_list) != 0) {
1081 int saved_errno = errno;
1082 SAFE_FREE(group_list);
1083 errno = saved_errno;
1087 SAFE_FREE(group_list);
1091 #endif /* HAVE_BROKEN_GETGROUPS */
1093 /* This is a list of systems that require the first GID passed to setgroups(2)
1094 * to be the effective GID. If your system is one of these, add it here.
1096 #if defined (FREEBSD) || defined (DARWINOS)
1097 #define USE_BSD_SETGROUPS
1100 #if defined(USE_BSD_SETGROUPS)
1101 /* Depending on the particular BSD implementation, the first GID that is
1102 * passed to setgroups(2) will either be ignored or will set the credential's
1103 * effective GID. In either case, the right thing to do is to guarantee that
1104 * gidset[0] is the effective GID.
1106 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1108 gid_t *new_gidset = NULL;
1112 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1115 /* No group list, just make sure we are setting the efective GID. */
1117 return setgroups(1, &primary_gid);
1120 /* If the primary gid is not the first array element, grow the array
1121 * and insert it at the front.
1123 if (gidset[0] != primary_gid) {
1124 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1125 if (new_gidset == NULL) {
1129 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1130 new_gidset[0] = primary_gid;
1135 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1140 #if defined(HAVE_BROKEN_GETGROUPS)
1141 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1143 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1148 SAFE_FREE(new_gidset);
1155 #endif /* USE_BSD_SETGROUPS */
1157 /**************************************************************************
1158 Wrapper for getgroups. Deals with broken (int) case.
1159 ****************************************************************************/
1161 int sys_getgroups(int setlen, gid_t *gidset)
1163 #if defined(HAVE_BROKEN_GETGROUPS)
1164 return sys_broken_getgroups(setlen, gidset);
1166 return getgroups(setlen, gidset);
1170 /**************************************************************************
1171 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1172 ****************************************************************************/
1174 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1176 #if !defined(HAVE_SETGROUPS)
1179 #endif /* HAVE_SETGROUPS */
1181 #if defined(USE_BSD_SETGROUPS)
1182 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1183 #elif defined(HAVE_BROKEN_GETGROUPS)
1184 return sys_broken_setgroups(setlen, gidset);
1186 return setgroups(setlen, gidset);
1190 /**************************************************************************
1191 Wrappers for setpwent(), getpwent() and endpwent()
1192 ****************************************************************************/
1194 void sys_setpwent(void)
1199 struct passwd *sys_getpwent(void)
1204 void sys_endpwent(void)
1209 /**************************************************************************
1210 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1211 ****************************************************************************/
1214 struct passwd *sys_getpwnam(const char *name)
1216 return getpwnam(name);
1219 struct passwd *sys_getpwuid(uid_t uid)
1221 return getpwuid(uid);
1224 struct group *sys_getgrnam(const char *name)
1226 return getgrnam(name);
1229 struct group *sys_getgrgid(gid_t gid)
1231 return getgrgid(gid);
1234 /**************************************************************************
1235 Extract a command into an arg list.
1236 ****************************************************************************/
1238 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1247 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1248 DEBUG(0, ("talloc failed\n"));
1252 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1253 TALLOC_FREE(trunc_cmd);
1262 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1265 TALLOC_FREE(trunc_cmd);
1267 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1272 * Now do the extraction.
1275 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1279 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1282 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1286 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1288 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1297 DEBUG(0, ("talloc failed\n"));
1298 TALLOC_FREE(trunc_cmd);
1304 /**************************************************************************
1305 Wrapper for popen. Safer as it doesn't search a path.
1306 Modified from the glibc sources.
1307 modified by tridge to return a file descriptor. We must kick our FILE* habit
1308 ****************************************************************************/
1310 typedef struct _popen_list
1314 struct _popen_list *next;
1317 static popen_list *popen_chain;
1319 int sys_popen(const char *command)
1321 int parent_end, child_end;
1323 popen_list *entry = NULL;
1326 if (pipe(pipe_fds) < 0)
1329 parent_end = pipe_fds[0];
1330 child_end = pipe_fds[1];
1337 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1340 ZERO_STRUCTP(entry);
1343 * Extract the command and args into a NULL terminated array.
1346 if(!(argl = extract_args(NULL, command)))
1349 entry->child_pid = sys_fork();
1351 if (entry->child_pid == -1) {
1355 if (entry->child_pid == 0) {
1361 int child_std_end = STDOUT_FILENO;
1365 if (child_end != child_std_end) {
1366 dup2 (child_end, child_std_end);
1371 * POSIX.2: "popen() shall ensure that any streams from previous
1372 * popen() calls that remain open in the parent process are closed
1373 * in the new child process."
1376 for (p = popen_chain; p; p = p->next)
1379 execv(argl[0], argl);
1390 /* Link into popen_chain. */
1391 entry->next = popen_chain;
1392 popen_chain = entry;
1393 entry->fd = parent_end;
1406 /**************************************************************************
1407 Wrapper for pclose. Modified from the glibc sources.
1408 ****************************************************************************/
1410 int sys_pclose(int fd)
1413 popen_list **ptr = &popen_chain;
1414 popen_list *entry = NULL;
1418 /* Unlink from popen_chain. */
1419 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1420 if ((*ptr)->fd == fd) {
1422 *ptr = (*ptr)->next;
1428 if (status < 0 || close(entry->fd) < 0)
1432 * As Samba is catching and eating child process
1433 * exits we don't really care about the child exit
1434 * code, a -1 with errno = ECHILD will do fine for us.
1438 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1439 } while (wait_pid == -1 && errno == EINTR);
1448 /**************************************************************************
1449 Wrapper for Admin Logs.
1450 ****************************************************************************/
1452 void sys_adminlog(int priority, const char *format_str, ...)
1456 char *msgbuf = NULL;
1458 va_start( ap, format_str );
1459 ret = vasprintf( &msgbuf, format_str, ap );
1465 #if defined(HAVE_SYSLOG)
1466 syslog( priority, "%s", msgbuf );
1468 DEBUG(0,("%s", msgbuf ));
1473 /******** Solaris EA helper function prototypes ********/
1474 #ifdef HAVE_ATTROPEN
1475 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1476 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1477 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1478 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1479 static int solaris_unlinkat(int attrdirfd, const char *name);
1480 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1481 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1484 /**************************************************************************
1485 Wrappers for extented attribute calls. Based on the Linux package with
1486 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1487 ****************************************************************************/
1489 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1491 #if defined(HAVE_GETXATTR)
1492 #ifndef XATTR_ADD_OPT
1493 return getxattr(path, name, value, size);
1496 return getxattr(path, name, value, size, 0, options);
1498 #elif defined(HAVE_GETEA)
1499 return getea(path, name, value, size);
1500 #elif defined(HAVE_EXTATTR_GET_FILE)
1503 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1504 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1505 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1507 * The BSD implementation has a nasty habit of silently truncating
1508 * the returned value to the size of the buffer, so we have to check
1509 * that the buffer is large enough to fit the returned value.
1511 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1516 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1520 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1522 #elif defined(HAVE_ATTR_GET)
1523 int retval, flags = 0;
1524 int valuelength = (int)size;
1525 char *attrname = strchr(name,'.') + 1;
1527 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1529 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1531 return retval ? retval : valuelength;
1532 #elif defined(HAVE_ATTROPEN)
1534 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1536 ret = solaris_read_xattr(attrfd, value, size);
1546 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1548 #if defined(HAVE_LGETXATTR)
1549 return lgetxattr(path, name, value, size);
1550 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1551 int options = XATTR_NOFOLLOW;
1552 return getxattr(path, name, value, size, 0, options);
1553 #elif defined(HAVE_LGETEA)
1554 return lgetea(path, name, value, size);
1555 #elif defined(HAVE_EXTATTR_GET_LINK)
1558 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1559 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1560 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1562 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1567 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1571 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1573 #elif defined(HAVE_ATTR_GET)
1574 int retval, flags = ATTR_DONTFOLLOW;
1575 int valuelength = (int)size;
1576 char *attrname = strchr(name,'.') + 1;
1578 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1580 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1582 return retval ? retval : valuelength;
1583 #elif defined(HAVE_ATTROPEN)
1585 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1587 ret = solaris_read_xattr(attrfd, value, size);
1597 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1599 #if defined(HAVE_FGETXATTR)
1600 #ifndef XATTR_ADD_OPT
1601 return fgetxattr(filedes, name, value, size);
1604 return fgetxattr(filedes, name, value, size, 0, options);
1606 #elif defined(HAVE_FGETEA)
1607 return fgetea(filedes, name, value, size);
1608 #elif defined(HAVE_EXTATTR_GET_FD)
1611 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1612 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1613 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1615 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1620 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1624 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1626 #elif defined(HAVE_ATTR_GETF)
1627 int retval, flags = 0;
1628 int valuelength = (int)size;
1629 char *attrname = strchr(name,'.') + 1;
1631 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1633 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1635 return retval ? retval : valuelength;
1636 #elif defined(HAVE_ATTROPEN)
1638 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1640 ret = solaris_read_xattr(attrfd, value, size);
1650 #if defined(HAVE_EXTATTR_LIST_FILE)
1652 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1660 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1661 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1669 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1671 ssize_t list_size, total_size = 0;
1674 /* Iterate through extattr(2) namespaces */
1675 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1677 #if defined(HAVE_EXTATTR_LIST_FILE)
1679 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1682 #if defined(HAVE_EXTATTR_LIST_LINK)
1684 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1687 #if defined(HAVE_EXTATTR_LIST_FD)
1689 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1696 /* Some error happend. Errno should be set by the previous call */
1702 /* XXX: Call with an empty buffer may be used to calculate
1703 necessary buffer size. Unfortunately, we can't say, how
1704 many attributes were returned, so here is the potential
1705 problem with the emulation.
1708 /* Take the worse case of one char attribute names -
1709 two bytes per name plus one more for sanity.
1711 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1714 /* Count necessary offset to fit namespace prefixes */
1716 for(i = 0; i < list_size; i += list[i] + 1)
1717 len += extattr[t].len;
1719 total_size += list_size + len;
1720 /* Buffer is too small to fit the results */
1721 if(total_size > size) {
1725 /* Shift results back, so we can prepend prefixes */
1726 buf = memmove(list + len, list, list_size);
1728 for(i = 0; i < list_size; i += len + 1) {
1730 strncpy(list, extattr[t].name, extattr[t].len + 1);
1731 list += extattr[t].len;
1732 strncpy(list, buf + i + 1, len);
1743 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1744 static char attr_buffer[ATTR_MAX_VALUELEN];
1746 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1748 int retval = 0, index;
1749 attrlist_cursor_t *cursor = 0;
1751 attrlist_t * al = (attrlist_t *)attr_buffer;
1753 size_t ent_size, left = size;
1758 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1760 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1762 for (index = 0; index < al->al_count; index++) {
1763 ae = ATTR_ENTRY(attr_buffer, index);
1764 ent_size = strlen(ae->a_name) + sizeof("user.");
1765 if (left >= ent_size) {
1766 strncpy(bp, "user.", sizeof("user."));
1767 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1775 total_size += ent_size;
1777 if (al->al_more == 0) break;
1784 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1786 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1788 for (index = 0; index < al->al_count; index++) {
1789 ae = ATTR_ENTRY(attr_buffer, index);
1790 ent_size = strlen(ae->a_name) + sizeof("system.");
1791 if (left >= ent_size) {
1792 strncpy(bp, "system.", sizeof("system."));
1793 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1801 total_size += ent_size;
1803 if (al->al_more == 0) break;
1806 return (ssize_t)(retval ? retval : total_size);
1811 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1813 #if defined(HAVE_LISTXATTR)
1814 #ifndef XATTR_ADD_OPT
1815 return listxattr(path, list, size);
1818 return listxattr(path, list, size, options);
1820 #elif defined(HAVE_LISTEA)
1821 return listea(path, list, size);
1822 #elif defined(HAVE_EXTATTR_LIST_FILE)
1825 return bsd_attr_list(0, arg, list, size);
1826 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1827 return irix_attr_list(path, 0, list, size, 0);
1828 #elif defined(HAVE_ATTROPEN)
1830 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1831 if (attrdirfd >= 0) {
1832 ret = solaris_list_xattr(attrdirfd, list, size);
1842 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1844 #if defined(HAVE_LLISTXATTR)
1845 return llistxattr(path, list, size);
1846 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1847 int options = XATTR_NOFOLLOW;
1848 return listxattr(path, list, size, options);
1849 #elif defined(HAVE_LLISTEA)
1850 return llistea(path, list, size);
1851 #elif defined(HAVE_EXTATTR_LIST_LINK)
1854 return bsd_attr_list(1, arg, list, size);
1855 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1856 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1857 #elif defined(HAVE_ATTROPEN)
1859 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1860 if (attrdirfd >= 0) {
1861 ret = solaris_list_xattr(attrdirfd, list, size);
1871 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1873 #if defined(HAVE_FLISTXATTR)
1874 #ifndef XATTR_ADD_OPT
1875 return flistxattr(filedes, list, size);
1878 return flistxattr(filedes, list, size, options);
1880 #elif defined(HAVE_FLISTEA)
1881 return flistea(filedes, list, size);
1882 #elif defined(HAVE_EXTATTR_LIST_FD)
1884 arg.filedes = filedes;
1885 return bsd_attr_list(2, arg, list, size);
1886 #elif defined(HAVE_ATTR_LISTF)
1887 return irix_attr_list(NULL, filedes, list, size, 0);
1888 #elif defined(HAVE_ATTROPEN)
1890 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1891 if (attrdirfd >= 0) {
1892 ret = solaris_list_xattr(attrdirfd, list, size);
1902 int sys_removexattr (const char *path, const char *name)
1904 #if defined(HAVE_REMOVEXATTR)
1905 #ifndef XATTR_ADD_OPT
1906 return removexattr(path, name);
1909 return removexattr(path, name, options);
1911 #elif defined(HAVE_REMOVEEA)
1912 return removeea(path, name);
1913 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1915 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1916 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1917 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1919 return extattr_delete_file(path, attrnamespace, attrname);
1920 #elif defined(HAVE_ATTR_REMOVE)
1922 char *attrname = strchr(name,'.') + 1;
1924 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1926 return attr_remove(path, attrname, flags);
1927 #elif defined(HAVE_ATTROPEN)
1929 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1930 if (attrdirfd >= 0) {
1931 ret = solaris_unlinkat(attrdirfd, name);
1941 int sys_lremovexattr (const char *path, const char *name)
1943 #if defined(HAVE_LREMOVEXATTR)
1944 return lremovexattr(path, name);
1945 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1946 int options = XATTR_NOFOLLOW;
1947 return removexattr(path, name, options);
1948 #elif defined(HAVE_LREMOVEEA)
1949 return lremoveea(path, name);
1950 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1952 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1953 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1954 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1956 return extattr_delete_link(path, attrnamespace, attrname);
1957 #elif defined(HAVE_ATTR_REMOVE)
1958 int flags = ATTR_DONTFOLLOW;
1959 char *attrname = strchr(name,'.') + 1;
1961 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1963 return attr_remove(path, attrname, flags);
1964 #elif defined(HAVE_ATTROPEN)
1966 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1967 if (attrdirfd >= 0) {
1968 ret = solaris_unlinkat(attrdirfd, name);
1978 int sys_fremovexattr (int filedes, const char *name)
1980 #if defined(HAVE_FREMOVEXATTR)
1981 #ifndef XATTR_ADD_OPT
1982 return fremovexattr(filedes, name);
1985 return fremovexattr(filedes, name, options);
1987 #elif defined(HAVE_FREMOVEEA)
1988 return fremoveea(filedes, name);
1989 #elif defined(HAVE_EXTATTR_DELETE_FD)
1991 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1992 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1993 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1995 return extattr_delete_fd(filedes, attrnamespace, attrname);
1996 #elif defined(HAVE_ATTR_REMOVEF)
1998 char *attrname = strchr(name,'.') + 1;
2000 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2002 return attr_removef(filedes, attrname, flags);
2003 #elif defined(HAVE_ATTROPEN)
2005 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2006 if (attrdirfd >= 0) {
2007 ret = solaris_unlinkat(attrdirfd, name);
2017 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2019 #if defined(HAVE_SETXATTR)
2020 #ifndef XATTR_ADD_OPT
2021 return setxattr(path, name, value, size, flags);
2024 return setxattr(path, name, value, size, 0, options);
2026 #elif defined(HAVE_SETEA)
2027 return setea(path, name, value, size, flags);
2028 #elif defined(HAVE_EXTATTR_SET_FILE)
2031 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2032 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2033 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2035 /* Check attribute existence */
2036 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2038 /* REPLACE attribute, that doesn't exist */
2039 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2043 /* Ignore other errors */
2046 /* CREATE attribute, that already exists */
2047 if (flags & XATTR_CREATE) {
2053 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2054 return (retval < 0) ? -1 : 0;
2055 #elif defined(HAVE_ATTR_SET)
2057 char *attrname = strchr(name,'.') + 1;
2059 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2060 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2061 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2063 return attr_set(path, attrname, (const char *)value, size, myflags);
2064 #elif defined(HAVE_ATTROPEN)
2066 int myflags = O_RDWR;
2068 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2069 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2070 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2072 ret = solaris_write_xattr(attrfd, value, size);
2082 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2084 #if defined(HAVE_LSETXATTR)
2085 return lsetxattr(path, name, value, size, flags);
2086 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2087 int options = XATTR_NOFOLLOW;
2088 return setxattr(path, name, value, size, 0, options);
2089 #elif defined(LSETEA)
2090 return lsetea(path, name, value, size, flags);
2091 #elif defined(HAVE_EXTATTR_SET_LINK)
2094 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2095 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2096 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2098 /* Check attribute existence */
2099 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2101 /* REPLACE attribute, that doesn't exist */
2102 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2106 /* Ignore other errors */
2109 /* CREATE attribute, that already exists */
2110 if (flags & XATTR_CREATE) {
2117 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2118 return (retval < 0) ? -1 : 0;
2119 #elif defined(HAVE_ATTR_SET)
2120 int myflags = ATTR_DONTFOLLOW;
2121 char *attrname = strchr(name,'.') + 1;
2123 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2124 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2125 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2127 return attr_set(path, attrname, (const char *)value, size, myflags);
2128 #elif defined(HAVE_ATTROPEN)
2130 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2132 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2133 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2134 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2136 ret = solaris_write_xattr(attrfd, value, size);
2146 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2148 #if defined(HAVE_FSETXATTR)
2149 #ifndef XATTR_ADD_OPT
2150 return fsetxattr(filedes, name, value, size, flags);
2153 return fsetxattr(filedes, name, value, size, 0, options);
2155 #elif defined(HAVE_FSETEA)
2156 return fsetea(filedes, name, value, size, flags);
2157 #elif defined(HAVE_EXTATTR_SET_FD)
2160 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2161 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2162 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2164 /* Check attribute existence */
2165 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2167 /* REPLACE attribute, that doesn't exist */
2168 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2172 /* Ignore other errors */
2175 /* CREATE attribute, that already exists */
2176 if (flags & XATTR_CREATE) {
2182 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2183 return (retval < 0) ? -1 : 0;
2184 #elif defined(HAVE_ATTR_SETF)
2186 char *attrname = strchr(name,'.') + 1;
2188 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2189 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2190 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2192 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2193 #elif defined(HAVE_ATTROPEN)
2195 int myflags = O_RDWR | O_XATTR;
2197 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2198 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2199 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2201 ret = solaris_write_xattr(attrfd, value, size);
2211 /**************************************************************************
2212 helper functions for Solaris' EA support
2213 ****************************************************************************/
2214 #ifdef HAVE_ATTROPEN
2215 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2219 if (fstat(attrfd, &sbuf) == -1) {
2224 /* This is to return the current size of the named extended attribute */
2226 return sbuf.st_size;
2229 /* check size and read xattr */
2230 if (sbuf.st_size > size) {
2235 return read(attrfd, value, sbuf.st_size);
2238 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2243 int newfd = dup(attrdirfd);
2244 /* CAUTION: The originating file descriptor should not be
2245 used again following the call to fdopendir().
2246 For that reason we dup() the file descriptor
2247 here to make things more clear. */
2248 dirp = fdopendir(newfd);
2250 while ((de = readdir(dirp))) {
2251 size_t listlen = strlen(de->d_name);
2252 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2253 /* we don't want "." and ".." here: */
2254 DEBUG(10,("skipped EA %s\n",de->d_name));
2259 /* return the current size of the list of extended attribute names*/
2262 /* check size and copy entrieѕ + nul into list. */
2263 if ((len + listlen + 1) > size) {
2268 safe_strcpy(list + len, de->d_name, listlen);
2276 if (closedir(dirp) == -1) {
2277 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2283 static int solaris_unlinkat(int attrdirfd, const char *name)
2285 if (unlinkat(attrdirfd, name, 0) == -1) {
2286 if (errno == ENOENT) {
2294 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2296 int filedes = attropen(path, attrpath, oflag, mode);
2297 if (filedes == -1) {
2298 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2299 if (errno == EINVAL) {
2308 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2310 int filedes = openat(fildes, path, oflag, mode);
2311 if (filedes == -1) {
2312 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2313 if (errno == EINVAL) {
2322 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2324 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2327 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2331 #endif /*HAVE_ATTROPEN*/
2334 /****************************************************************************
2335 Return the major devicenumber for UNIX extensions.
2336 ****************************************************************************/
2338 uint32 unix_dev_major(SMB_DEV_T dev)
2340 #if defined(HAVE_DEVICE_MAJOR_FN)
2341 return (uint32)major(dev);
2343 return (uint32)(dev >> 8);
2347 /****************************************************************************
2348 Return the minor devicenumber for UNIX extensions.
2349 ****************************************************************************/
2351 uint32 unix_dev_minor(SMB_DEV_T dev)
2353 #if defined(HAVE_DEVICE_MINOR_FN)
2354 return (uint32)minor(dev);
2356 return (uint32)(dev & 0xff);
2360 #if defined(WITH_AIO)
2362 /*******************************************************************
2363 An aio_read wrapper that will deal with 64-bit sizes.
2364 ********************************************************************/
2366 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2368 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2369 return aio_read64(aiocb);
2370 #elif defined(HAVE_AIO_READ)
2371 return aio_read(aiocb);
2378 /*******************************************************************
2379 An aio_write wrapper that will deal with 64-bit sizes.
2380 ********************************************************************/
2382 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2384 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2385 return aio_write64(aiocb);
2386 #elif defined(HAVE_AIO_WRITE)
2387 return aio_write(aiocb);
2394 /*******************************************************************
2395 An aio_return wrapper that will deal with 64-bit sizes.
2396 ********************************************************************/
2398 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2400 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2401 return aio_return64(aiocb);
2402 #elif defined(HAVE_AIO_RETURN)
2403 return aio_return(aiocb);
2410 /*******************************************************************
2411 An aio_cancel wrapper that will deal with 64-bit sizes.
2412 ********************************************************************/
2414 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2416 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2417 return aio_cancel64(fd, aiocb);
2418 #elif defined(HAVE_AIO_CANCEL)
2419 return aio_cancel(fd, aiocb);
2426 /*******************************************************************
2427 An aio_error wrapper that will deal with 64-bit sizes.
2428 ********************************************************************/
2430 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2432 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2433 return aio_error64(aiocb);
2434 #elif defined(HAVE_AIO_ERROR)
2435 return aio_error(aiocb);
2442 /*******************************************************************
2443 An aio_fsync wrapper that will deal with 64-bit sizes.
2444 ********************************************************************/
2446 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2448 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2449 return aio_fsync64(op, aiocb);
2450 #elif defined(HAVE_AIO_FSYNC)
2451 return aio_fsync(op, aiocb);
2458 /*******************************************************************
2459 An aio_fsync wrapper that will deal with 64-bit sizes.
2460 ********************************************************************/
2462 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2464 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2465 return aio_suspend64(cblist, n, timeout);
2466 #elif defined(HAVE_AIO_FSYNC)
2467 return aio_suspend(cblist, n, timeout);
2473 #else /* !WITH_AIO */
2475 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2481 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2487 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2493 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2499 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2505 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2511 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2516 #endif /* WITH_AIO */
2518 int sys_getpeereid( int s, uid_t *uid)
2520 #if defined(HAVE_PEERCRED)
2522 socklen_t cred_len = sizeof(struct ucred);
2525 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2530 if (cred_len != sizeof(struct ucred)) {
2543 int sys_getnameinfo(const struct sockaddr *psa,
2552 * For Solaris we must make sure salen is the
2553 * correct length for the incoming sa_family.
2556 if (salen == sizeof(struct sockaddr_storage)) {
2557 salen = sizeof(struct sockaddr_in);
2558 #if defined(HAVE_IPV6)
2559 if (psa->sa_family == AF_INET6) {
2560 salen = sizeof(struct sockaddr_in6);
2564 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2567 int sys_connect(int fd, const struct sockaddr * addr)
2569 socklen_t salen = -1;
2571 if (addr->sa_family == AF_INET) {
2572 salen = sizeof(struct sockaddr_in);
2573 } else if (addr->sa_family == AF_UNIX) {
2574 salen = sizeof(struct sockaddr_un);
2576 #if defined(HAVE_IPV6)
2577 else if (addr->sa_family == AF_INET6) {
2578 salen = sizeof(struct sockaddr_in6);
2582 return connect(fd, addr, salen);