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 make_create_timespec(const struct stat *pst, struct stat_ex *dst,
460 bool fake_dir_create_times)
462 if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
463 dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
464 dst->st_ex_btime.tv_nsec = 0;
467 dst->st_ex_calculated_birthtime = false;
469 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
470 dst->st_ex_btime = pst->st_birthtimespec;
471 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
472 dst->st_ex_btime.tv_sec = pst->st_birthtime;
473 dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
474 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
475 dst->st_ex_btime.tv_sec = pst->st_birthtime;
476 dst->st_ex_btime.tv_nsec = 0;
478 dst->st_ex_btime = calc_create_time_stat(pst);
479 dst->st_ex_calculated_birthtime = true;
482 /* Deal with systems that don't initialize birthtime correctly.
483 * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
485 if (null_timespec(dst->st_ex_btime)) {
486 dst->st_ex_btime = calc_create_time_stat(pst);
487 dst->st_ex_calculated_birthtime = true;
491 /****************************************************************************
492 If we update a timestamp in a stat_ex struct we may have to recalculate
493 the birthtime. For now only implement this for write time, but we may
494 also need to do it for atime and ctime. JRA.
495 ****************************************************************************/
497 void update_stat_ex_mtime(struct stat_ex *dst,
498 struct timespec write_ts)
500 dst->st_ex_mtime = write_ts;
502 /* We may have to recalculate btime. */
503 if (dst->st_ex_calculated_birthtime) {
504 dst->st_ex_btime = calc_create_time_stat_ex(dst);
508 void update_stat_ex_create_time(struct stat_ex *dst,
509 struct timespec create_time)
511 dst->st_ex_btime = create_time;
512 dst->st_ex_calculated_birthtime = false;
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
516 static void init_stat_ex_from_stat (struct stat_ex *dst,
517 const struct stat64 *src,
518 bool fake_dir_create_times)
520 static void init_stat_ex_from_stat (struct stat_ex *dst,
521 const struct stat *src,
522 bool fake_dir_create_times)
525 dst->st_ex_dev = src->st_dev;
526 dst->st_ex_ino = src->st_ino;
527 dst->st_ex_mode = src->st_mode;
528 dst->st_ex_nlink = src->st_nlink;
529 dst->st_ex_uid = src->st_uid;
530 dst->st_ex_gid = src->st_gid;
531 dst->st_ex_rdev = src->st_rdev;
532 dst->st_ex_size = src->st_size;
533 dst->st_ex_atime = get_atimespec(src);
534 dst->st_ex_mtime = get_mtimespec(src);
535 dst->st_ex_ctime = get_ctimespec(src);
536 make_create_timespec(src, dst, fake_dir_create_times);
537 #ifdef HAVE_STAT_ST_BLKSIZE
538 dst->st_ex_blksize = src->st_blksize;
540 dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
543 #ifdef HAVE_STAT_ST_BLOCKS
544 dst->st_ex_blocks = src->st_blocks;
546 dst->st_ex_blocks = src->st_size % STAT_ST_BLOCKSIZE + 1;
549 #ifdef HAVE_STAT_ST_FLAGS
550 dst->st_ex_flags = src->st_flags;
552 dst->st_ex_flags = 0;
556 /*******************************************************************
557 A stat() wrapper that will deal with 64 bit filesizes.
558 ********************************************************************/
560 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
561 bool fake_dir_create_times)
564 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
565 struct stat64 statbuf;
566 ret = stat64(fname, &statbuf);
569 ret = stat(fname, &statbuf);
572 /* we always want directories to appear zero size */
573 if (S_ISDIR(statbuf.st_mode)) {
576 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
581 /*******************************************************************
582 An fstat() wrapper that will deal with 64 bit filesizes.
583 ********************************************************************/
585 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
588 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
589 struct stat64 statbuf;
590 ret = fstat64(fd, &statbuf);
593 ret = fstat(fd, &statbuf);
596 /* we always want directories to appear zero size */
597 if (S_ISDIR(statbuf.st_mode)) {
600 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
605 /*******************************************************************
606 An lstat() wrapper that will deal with 64 bit filesizes.
607 ********************************************************************/
609 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
610 bool fake_dir_create_times)
613 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
614 struct stat64 statbuf;
615 ret = lstat64(fname, &statbuf);
618 ret = lstat(fname, &statbuf);
621 /* we always want directories to appear zero size */
622 if (S_ISDIR(statbuf.st_mode)) {
625 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
630 /*******************************************************************
631 An posix_fallocate() wrapper that will deal with 64 bit filesizes.
632 ********************************************************************/
633 int sys_posix_fallocate(int fd, SMB_OFF_T offset, SMB_OFF_T len)
635 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_POSIX_FALLOCATE64) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
636 return posix_fallocate64(fd, offset, len);
637 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
638 return posix_fallocate(fd, offset, len);
639 #elif defined(F_RESVSP64)
640 /* this handles XFS on IRIX */
642 SMB_OFF_T new_len = offset + len;
646 /* unlikely to get a too large file on a 64bit system but ... */
650 fl.l_whence = SEEK_SET;
654 ret=fcntl(fd, F_RESVSP64, &fl);
659 /* Make sure the file gets enlarged after we allocated space: */
661 if (new_len > sbuf.st_size)
662 ftruncate64(fd, new_len);
669 /*******************************************************************
670 An ftruncate() wrapper that will deal with 64 bit filesizes.
671 ********************************************************************/
673 int sys_ftruncate(int fd, SMB_OFF_T offset)
675 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
676 return ftruncate64(fd, offset);
678 return ftruncate(fd, offset);
682 /*******************************************************************
683 An lseek() wrapper that will deal with 64 bit filesizes.
684 ********************************************************************/
686 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
688 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
689 return lseek64(fd, offset, whence);
691 return lseek(fd, offset, whence);
695 /*******************************************************************
696 An fseek() wrapper that will deal with 64 bit filesizes.
697 ********************************************************************/
699 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
701 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
702 return fseek64(fp, offset, whence);
703 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
704 return fseeko64(fp, offset, whence);
706 return fseek(fp, offset, whence);
710 /*******************************************************************
711 An ftell() wrapper that will deal with 64 bit filesizes.
712 ********************************************************************/
714 SMB_OFF_T sys_ftell(FILE *fp)
716 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
717 return (SMB_OFF_T)ftell64(fp);
718 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
719 return (SMB_OFF_T)ftello64(fp);
721 return (SMB_OFF_T)ftell(fp);
725 /*******************************************************************
726 A creat() wrapper that will deal with 64 bit filesizes.
727 ********************************************************************/
729 int sys_creat(const char *path, mode_t mode)
731 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
732 return creat64(path, mode);
735 * If creat64 isn't defined then ensure we call a potential open64.
738 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
742 /*******************************************************************
743 An open() wrapper that will deal with 64 bit filesizes.
744 ********************************************************************/
746 int sys_open(const char *path, int oflag, mode_t mode)
748 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
749 return open64(path, oflag, mode);
751 return open(path, oflag, mode);
755 /*******************************************************************
756 An fopen() wrapper that will deal with 64 bit filesizes.
757 ********************************************************************/
759 FILE *sys_fopen(const char *path, const char *type)
761 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
762 return fopen64(path, type);
764 return fopen(path, type);
769 /*******************************************************************
770 A flock() wrapper that will perform the kernel flock.
771 ********************************************************************/
773 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
775 #if HAVE_KERNEL_SHARE_MODES
777 if (share_mode == FILE_SHARE_WRITE) {
778 kernel_mode = LOCK_MAND|LOCK_WRITE;
779 } else if (share_mode == FILE_SHARE_READ) {
780 kernel_mode = LOCK_MAND|LOCK_READ;
781 } else if (share_mode == FILE_SHARE_NONE) {
782 kernel_mode = LOCK_MAND;
785 flock(fd, kernel_mode);
793 /*******************************************************************
794 An opendir wrapper that will deal with 64 bit filesizes.
795 ********************************************************************/
797 SMB_STRUCT_DIR *sys_opendir(const char *name)
799 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
800 return opendir64(name);
802 return opendir(name);
806 /*******************************************************************
807 A readdir wrapper that will deal with 64 bit filesizes.
808 ********************************************************************/
810 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
812 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
813 return readdir64(dirp);
815 return readdir(dirp);
819 /*******************************************************************
820 A seekdir wrapper that will deal with 64 bit filesizes.
821 ********************************************************************/
823 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
825 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
826 seekdir64(dirp, offset);
828 seekdir(dirp, offset);
832 /*******************************************************************
833 A telldir wrapper that will deal with 64 bit filesizes.
834 ********************************************************************/
836 long sys_telldir(SMB_STRUCT_DIR *dirp)
838 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
839 return (long)telldir64(dirp);
841 return (long)telldir(dirp);
845 /*******************************************************************
846 A rewinddir wrapper that will deal with 64 bit filesizes.
847 ********************************************************************/
849 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
851 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
858 /*******************************************************************
859 A close wrapper that will deal with 64 bit filesizes.
860 ********************************************************************/
862 int sys_closedir(SMB_STRUCT_DIR *dirp)
864 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
865 return closedir64(dirp);
867 return closedir(dirp);
871 /*******************************************************************
872 An mknod() wrapper that will deal with 64 bit filesizes.
873 ********************************************************************/
875 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
877 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
878 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
879 return mknod64(path, mode, dev);
881 return mknod(path, mode, dev);
884 /* No mknod system call. */
890 /*******************************************************************
891 The wait() calls vary between systems
892 ********************************************************************/
894 int sys_waitpid(pid_t pid,int *status,int options)
897 return waitpid(pid,status,options);
898 #else /* HAVE_WAITPID */
899 return wait4(pid, status, options, NULL);
900 #endif /* HAVE_WAITPID */
903 /*******************************************************************
904 System wrapper for getwd
905 ********************************************************************/
907 char *sys_getwd(char *s)
911 wd = (char *)getcwd(s, PATH_MAX);
913 wd = (char *)getwd(s);
918 #if defined(HAVE_POSIX_CAPABILITIES)
920 /**************************************************************************
921 Try and abstract process capabilities (for systems that have them).
922 ****************************************************************************/
924 /* Set the POSIX capabilities needed for the given purpose into the effective
925 * capability set of the current process. Make sure they are always removed
926 * from the inheritable set, because there is no circumstance in which our
927 * children should inherit our elevated privileges.
929 static bool set_process_capability(enum smbd_capability capability,
932 cap_value_t cap_vals[2] = {0};
933 int num_cap_vals = 0;
937 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
938 /* On Linux, make sure that any capabilities we grab are sticky
939 * across UID changes. We expect that this would allow us to keep both
940 * the effective and permitted capability sets, but as of circa 2.6.16,
941 * only the permitted set is kept. It is a bug (which we work around)
942 * that the effective set is lost, but we still require the effective
945 if (!prctl(PR_GET_KEEPCAPS)) {
946 prctl(PR_SET_KEEPCAPS, 1);
950 cap = cap_get_proc();
952 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
957 switch (capability) {
958 case KERNEL_OPLOCK_CAPABILITY:
959 #ifdef CAP_NETWORK_MGT
960 /* IRIX has CAP_NETWORK_MGT for oplocks. */
961 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
964 case DMAPI_ACCESS_CAPABILITY:
965 #ifdef CAP_DEVICE_MGT
966 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
967 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
969 /* Linux has CAP_MKNOD for DMAPI access. */
970 cap_vals[num_cap_vals++] = CAP_MKNOD;
973 case LEASE_CAPABILITY:
975 cap_vals[num_cap_vals++] = CAP_LEASE;
980 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
982 if (num_cap_vals == 0) {
987 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
988 enable ? CAP_SET : CAP_CLEAR);
990 /* We never want to pass capabilities down to our children, so make
991 * sure they are not inherited.
993 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
995 if (cap_set_proc(cap) == -1) {
996 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
1006 #endif /* HAVE_POSIX_CAPABILITIES */
1008 /****************************************************************************
1009 Gain the oplock capability from the kernel if possible.
1010 ****************************************************************************/
1012 void set_effective_capability(enum smbd_capability capability)
1014 #if defined(HAVE_POSIX_CAPABILITIES)
1015 set_process_capability(capability, True);
1016 #endif /* HAVE_POSIX_CAPABILITIES */
1019 void drop_effective_capability(enum smbd_capability capability)
1021 #if defined(HAVE_POSIX_CAPABILITIES)
1022 set_process_capability(capability, False);
1023 #endif /* HAVE_POSIX_CAPABILITIES */
1026 /**************************************************************************
1027 Wrapper for random().
1028 ****************************************************************************/
1030 long sys_random(void)
1032 #if defined(HAVE_RANDOM)
1033 return (long)random();
1034 #elif defined(HAVE_RAND)
1035 return (long)rand();
1037 DEBUG(0,("Error - no random function available !\n"));
1042 /**************************************************************************
1043 Wrapper for srandom().
1044 ****************************************************************************/
1046 void sys_srandom(unsigned int seed)
1048 #if defined(HAVE_SRANDOM)
1050 #elif defined(HAVE_SRAND)
1053 DEBUG(0,("Error - no srandom function available !\n"));
1058 /**************************************************************************
1059 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
1060 ****************************************************************************/
1062 int groups_max(void)
1064 #if defined(SYSCONF_SC_NGROUPS_MAX)
1065 int ret = sysconf(_SC_NGROUPS_MAX);
1066 return (ret == -1) ? NGROUPS_MAX : ret;
1072 /**************************************************************************
1073 Wrap setgroups and getgroups for systems that declare getgroups() as
1074 returning an array of gid_t, but actuall return an array of int.
1075 ****************************************************************************/
1077 #if defined(HAVE_BROKEN_GETGROUPS)
1078 static int sys_broken_getgroups(int setlen, gid_t *gidset)
1085 return getgroups(setlen, &gid);
1089 * Broken case. We need to allocate a
1090 * GID_T array of size setlen.
1099 setlen = groups_max();
1101 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1102 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
1106 if((ngroups = getgroups(setlen, group_list)) < 0) {
1107 int saved_errno = errno;
1108 SAFE_FREE(group_list);
1109 errno = saved_errno;
1113 for(i = 0; i < ngroups; i++)
1114 gidset[i] = (gid_t)group_list[i];
1116 SAFE_FREE(group_list);
1120 static int sys_broken_setgroups(int setlen, gid_t *gidset)
1128 if (setlen < 0 || setlen > groups_max()) {
1134 * Broken case. We need to allocate a
1135 * GID_T array of size setlen.
1138 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
1139 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
1143 for(i = 0; i < setlen; i++)
1144 group_list[i] = (GID_T) gidset[i];
1146 if(setgroups(setlen, group_list) != 0) {
1147 int saved_errno = errno;
1148 SAFE_FREE(group_list);
1149 errno = saved_errno;
1153 SAFE_FREE(group_list);
1157 #endif /* HAVE_BROKEN_GETGROUPS */
1159 /* This is a list of systems that require the first GID passed to setgroups(2)
1160 * to be the effective GID. If your system is one of these, add it here.
1162 #if defined (FREEBSD) || defined (DARWINOS)
1163 #define USE_BSD_SETGROUPS
1166 #if defined(USE_BSD_SETGROUPS)
1167 /* Depending on the particular BSD implementation, the first GID that is
1168 * passed to setgroups(2) will either be ignored or will set the credential's
1169 * effective GID. In either case, the right thing to do is to guarantee that
1170 * gidset[0] is the effective GID.
1172 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1174 gid_t *new_gidset = NULL;
1178 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1181 /* No group list, just make sure we are setting the efective GID. */
1183 return setgroups(1, &primary_gid);
1186 /* If the primary gid is not the first array element, grow the array
1187 * and insert it at the front.
1189 if (gidset[0] != primary_gid) {
1190 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1191 if (new_gidset == NULL) {
1195 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1196 new_gidset[0] = primary_gid;
1201 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1206 #if defined(HAVE_BROKEN_GETGROUPS)
1207 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1209 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1214 SAFE_FREE(new_gidset);
1221 #endif /* USE_BSD_SETGROUPS */
1223 /**************************************************************************
1224 Wrapper for getgroups. Deals with broken (int) case.
1225 ****************************************************************************/
1227 int sys_getgroups(int setlen, gid_t *gidset)
1229 #if defined(HAVE_BROKEN_GETGROUPS)
1230 return sys_broken_getgroups(setlen, gidset);
1232 return getgroups(setlen, gidset);
1236 /**************************************************************************
1237 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1238 ****************************************************************************/
1240 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1242 #if !defined(HAVE_SETGROUPS)
1245 #endif /* HAVE_SETGROUPS */
1247 #if defined(USE_BSD_SETGROUPS)
1248 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1249 #elif defined(HAVE_BROKEN_GETGROUPS)
1250 return sys_broken_setgroups(setlen, gidset);
1252 return setgroups(setlen, gidset);
1256 /**************************************************************************
1257 Wrappers for setpwent(), getpwent() and endpwent()
1258 ****************************************************************************/
1260 void sys_setpwent(void)
1265 struct passwd *sys_getpwent(void)
1270 void sys_endpwent(void)
1275 /**************************************************************************
1276 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1277 ****************************************************************************/
1280 struct passwd *sys_getpwnam(const char *name)
1282 return getpwnam(name);
1285 struct passwd *sys_getpwuid(uid_t uid)
1287 return getpwuid(uid);
1290 struct group *sys_getgrnam(const char *name)
1292 return getgrnam(name);
1295 struct group *sys_getgrgid(gid_t gid)
1297 return getgrgid(gid);
1300 /**************************************************************************
1301 Extract a command into an arg list.
1302 ****************************************************************************/
1304 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1313 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1314 DEBUG(0, ("talloc failed\n"));
1318 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1319 TALLOC_FREE(trunc_cmd);
1328 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1331 TALLOC_FREE(trunc_cmd);
1333 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1338 * Now do the extraction.
1341 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1345 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1348 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1352 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1354 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1360 TALLOC_FREE(trunc_cmd);
1364 DEBUG(0, ("talloc failed\n"));
1365 TALLOC_FREE(trunc_cmd);
1371 /**************************************************************************
1372 Wrapper for popen. Safer as it doesn't search a path.
1373 Modified from the glibc sources.
1374 modified by tridge to return a file descriptor. We must kick our FILE* habit
1375 ****************************************************************************/
1377 typedef struct _popen_list
1381 struct _popen_list *next;
1384 static popen_list *popen_chain;
1386 int sys_popen(const char *command)
1388 int parent_end, child_end;
1390 popen_list *entry = NULL;
1393 if (pipe(pipe_fds) < 0)
1396 parent_end = pipe_fds[0];
1397 child_end = pipe_fds[1];
1404 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1407 ZERO_STRUCTP(entry);
1410 * Extract the command and args into a NULL terminated array.
1413 if(!(argl = extract_args(NULL, command)))
1416 entry->child_pid = sys_fork();
1418 if (entry->child_pid == -1) {
1422 if (entry->child_pid == 0) {
1428 int child_std_end = STDOUT_FILENO;
1432 if (child_end != child_std_end) {
1433 dup2 (child_end, child_std_end);
1438 * POSIX.2: "popen() shall ensure that any streams from previous
1439 * popen() calls that remain open in the parent process are closed
1440 * in the new child process."
1443 for (p = popen_chain; p; p = p->next)
1446 execv(argl[0], argl);
1457 /* Link into popen_chain. */
1458 entry->next = popen_chain;
1459 popen_chain = entry;
1460 entry->fd = parent_end;
1473 /**************************************************************************
1474 Wrapper for pclose. Modified from the glibc sources.
1475 ****************************************************************************/
1477 int sys_pclose(int fd)
1480 popen_list **ptr = &popen_chain;
1481 popen_list *entry = NULL;
1485 /* Unlink from popen_chain. */
1486 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1487 if ((*ptr)->fd == fd) {
1489 *ptr = (*ptr)->next;
1495 if (status < 0 || close(entry->fd) < 0)
1499 * As Samba is catching and eating child process
1500 * exits we don't really care about the child exit
1501 * code, a -1 with errno = ECHILD will do fine for us.
1505 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1506 } while (wait_pid == -1 && errno == EINTR);
1515 /**************************************************************************
1516 Wrapper for Admin Logs.
1517 ****************************************************************************/
1519 void sys_adminlog(int priority, const char *format_str, ...)
1523 char *msgbuf = NULL;
1525 va_start( ap, format_str );
1526 ret = vasprintf( &msgbuf, format_str, ap );
1532 #if defined(HAVE_SYSLOG)
1533 syslog( priority, "%s", msgbuf );
1535 DEBUG(0,("%s", msgbuf ));
1540 /******** Solaris EA helper function prototypes ********/
1541 #ifdef HAVE_ATTROPEN
1542 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1543 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1544 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1545 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1546 static int solaris_unlinkat(int attrdirfd, const char *name);
1547 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1548 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1551 /**************************************************************************
1552 Wrappers for extented attribute calls. Based on the Linux package with
1553 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1554 ****************************************************************************/
1556 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1558 #if defined(HAVE_GETXATTR)
1559 #ifndef XATTR_ADD_OPT
1560 return getxattr(path, name, value, size);
1563 return getxattr(path, name, value, size, 0, options);
1565 #elif defined(HAVE_GETEA)
1566 return getea(path, name, value, size);
1567 #elif defined(HAVE_EXTATTR_GET_FILE)
1570 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1571 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1572 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1574 * The BSD implementation has a nasty habit of silently truncating
1575 * the returned value to the size of the buffer, so we have to check
1576 * that the buffer is large enough to fit the returned value.
1578 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1583 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1587 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1589 #elif defined(HAVE_ATTR_GET)
1590 int retval, flags = 0;
1591 int valuelength = (int)size;
1592 char *attrname = strchr(name,'.') + 1;
1594 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1596 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1598 return retval ? retval : valuelength;
1599 #elif defined(HAVE_ATTROPEN)
1601 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1603 ret = solaris_read_xattr(attrfd, value, size);
1613 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1615 #if defined(HAVE_LGETXATTR)
1616 return lgetxattr(path, name, value, size);
1617 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1618 int options = XATTR_NOFOLLOW;
1619 return getxattr(path, name, value, size, 0, options);
1620 #elif defined(HAVE_LGETEA)
1621 return lgetea(path, name, value, size);
1622 #elif defined(HAVE_EXTATTR_GET_LINK)
1625 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1626 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1627 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1629 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1634 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1638 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1640 #elif defined(HAVE_ATTR_GET)
1641 int retval, flags = ATTR_DONTFOLLOW;
1642 int valuelength = (int)size;
1643 char *attrname = strchr(name,'.') + 1;
1645 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1647 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1649 return retval ? retval : valuelength;
1650 #elif defined(HAVE_ATTROPEN)
1652 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1654 ret = solaris_read_xattr(attrfd, value, size);
1664 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1666 #if defined(HAVE_FGETXATTR)
1667 #ifndef XATTR_ADD_OPT
1668 return fgetxattr(filedes, name, value, size);
1671 return fgetxattr(filedes, name, value, size, 0, options);
1673 #elif defined(HAVE_FGETEA)
1674 return fgetea(filedes, name, value, size);
1675 #elif defined(HAVE_EXTATTR_GET_FD)
1678 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1679 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1680 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1682 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1687 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1691 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1693 #elif defined(HAVE_ATTR_GETF)
1694 int retval, flags = 0;
1695 int valuelength = (int)size;
1696 char *attrname = strchr(name,'.') + 1;
1698 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1700 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1702 return retval ? retval : valuelength;
1703 #elif defined(HAVE_ATTROPEN)
1705 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1707 ret = solaris_read_xattr(attrfd, value, size);
1717 #if defined(HAVE_EXTATTR_LIST_FILE)
1719 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1727 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1728 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1736 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1738 ssize_t list_size, total_size = 0;
1741 /* Iterate through extattr(2) namespaces */
1742 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1744 #if defined(HAVE_EXTATTR_LIST_FILE)
1746 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1749 #if defined(HAVE_EXTATTR_LIST_LINK)
1751 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1754 #if defined(HAVE_EXTATTR_LIST_FD)
1756 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1763 /* Some error happend. Errno should be set by the previous call */
1769 /* XXX: Call with an empty buffer may be used to calculate
1770 necessary buffer size. Unfortunately, we can't say, how
1771 many attributes were returned, so here is the potential
1772 problem with the emulation.
1775 /* Take the worse case of one char attribute names -
1776 two bytes per name plus one more for sanity.
1778 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1781 /* Count necessary offset to fit namespace prefixes */
1783 for(i = 0; i < list_size; i += list[i] + 1)
1784 len += extattr[t].len;
1786 total_size += list_size + len;
1787 /* Buffer is too small to fit the results */
1788 if(total_size > size) {
1792 /* Shift results back, so we can prepend prefixes */
1793 buf = memmove(list + len, list, list_size);
1795 for(i = 0; i < list_size; i += len + 1) {
1797 strncpy(list, extattr[t].name, extattr[t].len + 1);
1798 list += extattr[t].len;
1799 strncpy(list, buf + i + 1, len);
1810 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1811 static char attr_buffer[ATTR_MAX_VALUELEN];
1813 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1815 int retval = 0, index;
1816 attrlist_cursor_t *cursor = 0;
1818 attrlist_t * al = (attrlist_t *)attr_buffer;
1820 size_t ent_size, left = size;
1825 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1827 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1829 for (index = 0; index < al->al_count; index++) {
1830 ae = ATTR_ENTRY(attr_buffer, index);
1831 ent_size = strlen(ae->a_name) + sizeof("user.");
1832 if (left >= ent_size) {
1833 strncpy(bp, "user.", sizeof("user."));
1834 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1842 total_size += ent_size;
1844 if (al->al_more == 0) break;
1851 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1853 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1855 for (index = 0; index < al->al_count; index++) {
1856 ae = ATTR_ENTRY(attr_buffer, index);
1857 ent_size = strlen(ae->a_name) + sizeof("system.");
1858 if (left >= ent_size) {
1859 strncpy(bp, "system.", sizeof("system."));
1860 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1868 total_size += ent_size;
1870 if (al->al_more == 0) break;
1873 return (ssize_t)(retval ? retval : total_size);
1878 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1880 #if defined(HAVE_LISTXATTR)
1881 #ifndef XATTR_ADD_OPT
1882 return listxattr(path, list, size);
1885 return listxattr(path, list, size, options);
1887 #elif defined(HAVE_LISTEA)
1888 return listea(path, list, size);
1889 #elif defined(HAVE_EXTATTR_LIST_FILE)
1892 return bsd_attr_list(0, arg, list, size);
1893 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1894 return irix_attr_list(path, 0, list, size, 0);
1895 #elif defined(HAVE_ATTROPEN)
1897 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1898 if (attrdirfd >= 0) {
1899 ret = solaris_list_xattr(attrdirfd, list, size);
1909 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1911 #if defined(HAVE_LLISTXATTR)
1912 return llistxattr(path, list, size);
1913 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1914 int options = XATTR_NOFOLLOW;
1915 return listxattr(path, list, size, options);
1916 #elif defined(HAVE_LLISTEA)
1917 return llistea(path, list, size);
1918 #elif defined(HAVE_EXTATTR_LIST_LINK)
1921 return bsd_attr_list(1, arg, list, size);
1922 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1923 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1924 #elif defined(HAVE_ATTROPEN)
1926 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1927 if (attrdirfd >= 0) {
1928 ret = solaris_list_xattr(attrdirfd, list, size);
1938 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1940 #if defined(HAVE_FLISTXATTR)
1941 #ifndef XATTR_ADD_OPT
1942 return flistxattr(filedes, list, size);
1945 return flistxattr(filedes, list, size, options);
1947 #elif defined(HAVE_FLISTEA)
1948 return flistea(filedes, list, size);
1949 #elif defined(HAVE_EXTATTR_LIST_FD)
1951 arg.filedes = filedes;
1952 return bsd_attr_list(2, arg, list, size);
1953 #elif defined(HAVE_ATTR_LISTF)
1954 return irix_attr_list(NULL, filedes, list, size, 0);
1955 #elif defined(HAVE_ATTROPEN)
1957 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1958 if (attrdirfd >= 0) {
1959 ret = solaris_list_xattr(attrdirfd, list, size);
1969 int sys_removexattr (const char *path, const char *name)
1971 #if defined(HAVE_REMOVEXATTR)
1972 #ifndef XATTR_ADD_OPT
1973 return removexattr(path, name);
1976 return removexattr(path, name, options);
1978 #elif defined(HAVE_REMOVEEA)
1979 return removeea(path, name);
1980 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1982 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1983 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1984 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1986 return extattr_delete_file(path, attrnamespace, attrname);
1987 #elif defined(HAVE_ATTR_REMOVE)
1989 char *attrname = strchr(name,'.') + 1;
1991 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1993 return attr_remove(path, attrname, flags);
1994 #elif defined(HAVE_ATTROPEN)
1996 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1997 if (attrdirfd >= 0) {
1998 ret = solaris_unlinkat(attrdirfd, name);
2008 int sys_lremovexattr (const char *path, const char *name)
2010 #if defined(HAVE_LREMOVEXATTR)
2011 return lremovexattr(path, name);
2012 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2013 int options = XATTR_NOFOLLOW;
2014 return removexattr(path, name, options);
2015 #elif defined(HAVE_LREMOVEEA)
2016 return lremoveea(path, name);
2017 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2019 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2020 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2021 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2023 return extattr_delete_link(path, attrnamespace, attrname);
2024 #elif defined(HAVE_ATTR_REMOVE)
2025 int flags = ATTR_DONTFOLLOW;
2026 char *attrname = strchr(name,'.') + 1;
2028 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2030 return attr_remove(path, attrname, flags);
2031 #elif defined(HAVE_ATTROPEN)
2033 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2034 if (attrdirfd >= 0) {
2035 ret = solaris_unlinkat(attrdirfd, name);
2045 int sys_fremovexattr (int filedes, const char *name)
2047 #if defined(HAVE_FREMOVEXATTR)
2048 #ifndef XATTR_ADD_OPT
2049 return fremovexattr(filedes, name);
2052 return fremovexattr(filedes, name, options);
2054 #elif defined(HAVE_FREMOVEEA)
2055 return fremoveea(filedes, name);
2056 #elif defined(HAVE_EXTATTR_DELETE_FD)
2058 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2059 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2060 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2062 return extattr_delete_fd(filedes, attrnamespace, attrname);
2063 #elif defined(HAVE_ATTR_REMOVEF)
2065 char *attrname = strchr(name,'.') + 1;
2067 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2069 return attr_removef(filedes, attrname, flags);
2070 #elif defined(HAVE_ATTROPEN)
2072 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2073 if (attrdirfd >= 0) {
2074 ret = solaris_unlinkat(attrdirfd, name);
2084 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2086 #if defined(HAVE_SETXATTR)
2087 #ifndef XATTR_ADD_OPT
2088 return setxattr(path, name, value, size, flags);
2091 return setxattr(path, name, value, size, 0, options);
2093 #elif defined(HAVE_SETEA)
2094 return setea(path, name, value, size, flags);
2095 #elif defined(HAVE_EXTATTR_SET_FILE)
2098 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2099 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2100 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2102 /* Check attribute existence */
2103 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2105 /* REPLACE attribute, that doesn't exist */
2106 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2110 /* Ignore other errors */
2113 /* CREATE attribute, that already exists */
2114 if (flags & XATTR_CREATE) {
2120 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2121 return (retval < 0) ? -1 : 0;
2122 #elif defined(HAVE_ATTR_SET)
2124 char *attrname = strchr(name,'.') + 1;
2126 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2127 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2128 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2130 return attr_set(path, attrname, (const char *)value, size, myflags);
2131 #elif defined(HAVE_ATTROPEN)
2133 int myflags = O_RDWR;
2135 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2136 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2137 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2139 ret = solaris_write_xattr(attrfd, value, size);
2149 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2151 #if defined(HAVE_LSETXATTR)
2152 return lsetxattr(path, name, value, size, flags);
2153 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2154 int options = XATTR_NOFOLLOW;
2155 return setxattr(path, name, value, size, 0, options);
2156 #elif defined(LSETEA)
2157 return lsetea(path, name, value, size, flags);
2158 #elif defined(HAVE_EXTATTR_SET_LINK)
2161 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2162 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2163 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2165 /* Check attribute existence */
2166 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2168 /* REPLACE attribute, that doesn't exist */
2169 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2173 /* Ignore other errors */
2176 /* CREATE attribute, that already exists */
2177 if (flags & XATTR_CREATE) {
2184 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2185 return (retval < 0) ? -1 : 0;
2186 #elif defined(HAVE_ATTR_SET)
2187 int myflags = ATTR_DONTFOLLOW;
2188 char *attrname = strchr(name,'.') + 1;
2190 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2191 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2192 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2194 return attr_set(path, attrname, (const char *)value, size, myflags);
2195 #elif defined(HAVE_ATTROPEN)
2197 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2199 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2200 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2201 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2203 ret = solaris_write_xattr(attrfd, value, size);
2213 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2215 #if defined(HAVE_FSETXATTR)
2216 #ifndef XATTR_ADD_OPT
2217 return fsetxattr(filedes, name, value, size, flags);
2220 return fsetxattr(filedes, name, value, size, 0, options);
2222 #elif defined(HAVE_FSETEA)
2223 return fsetea(filedes, name, value, size, flags);
2224 #elif defined(HAVE_EXTATTR_SET_FD)
2227 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2228 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2229 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2231 /* Check attribute existence */
2232 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2234 /* REPLACE attribute, that doesn't exist */
2235 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2239 /* Ignore other errors */
2242 /* CREATE attribute, that already exists */
2243 if (flags & XATTR_CREATE) {
2249 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2250 return (retval < 0) ? -1 : 0;
2251 #elif defined(HAVE_ATTR_SETF)
2253 char *attrname = strchr(name,'.') + 1;
2255 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2256 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2257 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2259 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2260 #elif defined(HAVE_ATTROPEN)
2262 int myflags = O_RDWR | O_XATTR;
2264 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2265 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2266 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2268 ret = solaris_write_xattr(attrfd, value, size);
2278 /**************************************************************************
2279 helper functions for Solaris' EA support
2280 ****************************************************************************/
2281 #ifdef HAVE_ATTROPEN
2282 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2286 if (fstat(attrfd, &sbuf) == -1) {
2291 /* This is to return the current size of the named extended attribute */
2293 return sbuf.st_size;
2296 /* check size and read xattr */
2297 if (sbuf.st_size > size) {
2302 return read(attrfd, value, sbuf.st_size);
2305 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2310 int newfd = dup(attrdirfd);
2311 /* CAUTION: The originating file descriptor should not be
2312 used again following the call to fdopendir().
2313 For that reason we dup() the file descriptor
2314 here to make things more clear. */
2315 dirp = fdopendir(newfd);
2317 while ((de = readdir(dirp))) {
2318 size_t listlen = strlen(de->d_name);
2319 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2320 /* we don't want "." and ".." here: */
2321 DEBUG(10,("skipped EA %s\n",de->d_name));
2326 /* return the current size of the list of extended attribute names*/
2329 /* check size and copy entrieѕ + nul into list. */
2330 if ((len + listlen + 1) > size) {
2335 safe_strcpy(list + len, de->d_name, listlen);
2343 if (closedir(dirp) == -1) {
2344 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2350 static int solaris_unlinkat(int attrdirfd, const char *name)
2352 if (unlinkat(attrdirfd, name, 0) == -1) {
2353 if (errno == ENOENT) {
2361 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2363 int filedes = attropen(path, attrpath, oflag, mode);
2364 if (filedes == -1) {
2365 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2366 if (errno == EINVAL) {
2375 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2377 int filedes = openat(fildes, path, oflag, mode);
2378 if (filedes == -1) {
2379 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2380 if (errno == EINVAL) {
2389 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2391 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2394 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2398 #endif /*HAVE_ATTROPEN*/
2401 /****************************************************************************
2402 Return the major devicenumber for UNIX extensions.
2403 ****************************************************************************/
2405 uint32 unix_dev_major(SMB_DEV_T dev)
2407 #if defined(HAVE_DEVICE_MAJOR_FN)
2408 return (uint32)major(dev);
2410 return (uint32)(dev >> 8);
2414 /****************************************************************************
2415 Return the minor devicenumber for UNIX extensions.
2416 ****************************************************************************/
2418 uint32 unix_dev_minor(SMB_DEV_T dev)
2420 #if defined(HAVE_DEVICE_MINOR_FN)
2421 return (uint32)minor(dev);
2423 return (uint32)(dev & 0xff);
2427 #if defined(WITH_AIO)
2429 /*******************************************************************
2430 An aio_read wrapper that will deal with 64-bit sizes.
2431 ********************************************************************/
2433 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2435 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2436 return aio_read64(aiocb);
2437 #elif defined(HAVE_AIO_READ)
2438 return aio_read(aiocb);
2445 /*******************************************************************
2446 An aio_write wrapper that will deal with 64-bit sizes.
2447 ********************************************************************/
2449 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2451 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2452 return aio_write64(aiocb);
2453 #elif defined(HAVE_AIO_WRITE)
2454 return aio_write(aiocb);
2461 /*******************************************************************
2462 An aio_return wrapper that will deal with 64-bit sizes.
2463 ********************************************************************/
2465 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2467 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2468 return aio_return64(aiocb);
2469 #elif defined(HAVE_AIO_RETURN)
2470 return aio_return(aiocb);
2477 /*******************************************************************
2478 An aio_cancel wrapper that will deal with 64-bit sizes.
2479 ********************************************************************/
2481 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2483 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2484 return aio_cancel64(fd, aiocb);
2485 #elif defined(HAVE_AIO_CANCEL)
2486 return aio_cancel(fd, aiocb);
2493 /*******************************************************************
2494 An aio_error wrapper that will deal with 64-bit sizes.
2495 ********************************************************************/
2497 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2499 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2500 return aio_error64(aiocb);
2501 #elif defined(HAVE_AIO_ERROR)
2502 return aio_error(aiocb);
2509 /*******************************************************************
2510 An aio_fsync wrapper that will deal with 64-bit sizes.
2511 ********************************************************************/
2513 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2516 return aio_fsync64(op, aiocb);
2517 #elif defined(HAVE_AIO_FSYNC)
2518 return aio_fsync(op, aiocb);
2525 /*******************************************************************
2526 An aio_fsync wrapper that will deal with 64-bit sizes.
2527 ********************************************************************/
2529 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2531 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2532 return aio_suspend64(cblist, n, timeout);
2533 #elif defined(HAVE_AIO_FSYNC)
2534 return aio_suspend(cblist, n, timeout);
2540 #else /* !WITH_AIO */
2542 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2548 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2554 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2560 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2566 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2572 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2578 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2583 #endif /* WITH_AIO */
2585 int sys_getpeereid( int s, uid_t *uid)
2587 #if defined(HAVE_PEERCRED)
2589 socklen_t cred_len = sizeof(struct ucred);
2592 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2597 if (cred_len != sizeof(struct ucred)) {
2610 int sys_getnameinfo(const struct sockaddr *psa,
2619 * For Solaris we must make sure salen is the
2620 * correct length for the incoming sa_family.
2623 if (salen == sizeof(struct sockaddr_storage)) {
2624 salen = sizeof(struct sockaddr_in);
2625 #if defined(HAVE_IPV6)
2626 if (psa->sa_family == AF_INET6) {
2627 salen = sizeof(struct sockaddr_in6);
2631 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2634 int sys_connect(int fd, const struct sockaddr * addr)
2636 socklen_t salen = -1;
2638 if (addr->sa_family == AF_INET) {
2639 salen = sizeof(struct sockaddr_in);
2640 } else if (addr->sa_family == AF_UNIX) {
2641 salen = sizeof(struct sockaddr_un);
2643 #if defined(HAVE_IPV6)
2644 else if (addr->sa_family == AF_INET6) {
2645 salen = sizeof(struct sockaddr_in6);
2649 return connect(fd, addr, salen);