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 > 1000000) {
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 pread wrapper that will deal with EINTR and 64-bit file offsets.
146 ********************************************************************/
148 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
149 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
154 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
155 ret = pread64(fd, buf, count, off);
157 ret = pread(fd, buf, count, off);
159 } while (ret == -1 && errno == EINTR);
164 /*******************************************************************
165 A write wrapper that will deal with EINTR and 64-bit file offsets.
166 ********************************************************************/
168 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
169 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
174 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
175 ret = pwrite64(fd, buf, count, off);
177 ret = pwrite(fd, buf, count, off);
179 } while (ret == -1 && errno == EINTR);
184 /*******************************************************************
185 A send wrapper that will deal with EINTR.
186 ********************************************************************/
188 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
193 ret = send(s, msg, len, flags);
194 } while (ret == -1 && errno == EINTR);
198 /*******************************************************************
199 A sendto wrapper that will deal with EINTR.
200 ********************************************************************/
202 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
207 ret = sendto(s, msg, len, flags, to, tolen);
208 } while (ret == -1 && errno == EINTR);
212 /*******************************************************************
213 A recv wrapper that will deal with EINTR.
214 ********************************************************************/
216 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
221 ret = recv(fd, buf, count, flags);
222 } while (ret == -1 && errno == EINTR);
226 /*******************************************************************
227 A recvfrom wrapper that will deal with EINTR.
228 ********************************************************************/
230 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
235 ret = recvfrom(s, buf, len, flags, from, fromlen);
236 } while (ret == -1 && errno == EINTR);
240 /*******************************************************************
241 A fcntl wrapper that will deal with EINTR.
242 ********************************************************************/
244 int sys_fcntl_ptr(int fd, int cmd, void *arg)
249 ret = fcntl(fd, cmd, arg);
250 } while (ret == -1 && errno == EINTR);
254 /*******************************************************************
255 A fcntl wrapper that will deal with EINTR.
256 ********************************************************************/
258 int sys_fcntl_long(int fd, int cmd, long arg)
263 ret = fcntl(fd, cmd, arg);
264 } while (ret == -1 && errno == EINTR);
268 /*******************************************************************
269 A stat() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
272 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
275 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
276 ret = stat64(fname, sbuf);
278 ret = stat(fname, sbuf);
280 /* we always want directories to appear zero size */
281 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
285 /*******************************************************************
286 An fstat() wrapper that will deal with 64 bit filesizes.
287 ********************************************************************/
289 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
292 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
293 ret = fstat64(fd, sbuf);
295 ret = fstat(fd, sbuf);
297 /* we always want directories to appear zero size */
298 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
302 /*******************************************************************
303 An lstat() wrapper that will deal with 64 bit filesizes.
304 ********************************************************************/
306 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
309 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
310 ret = lstat64(fname, sbuf);
312 ret = lstat(fname, sbuf);
314 /* we always want directories to appear zero size */
315 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
319 /*******************************************************************
320 An ftruncate() wrapper that will deal with 64 bit filesizes.
321 ********************************************************************/
323 int sys_ftruncate(int fd, SMB_OFF_T offset)
325 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
326 return ftruncate64(fd, offset);
328 return ftruncate(fd, offset);
332 /*******************************************************************
333 An lseek() wrapper that will deal with 64 bit filesizes.
334 ********************************************************************/
336 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
338 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
339 return lseek64(fd, offset, whence);
341 return lseek(fd, offset, whence);
345 /*******************************************************************
346 An fseek() wrapper that will deal with 64 bit filesizes.
347 ********************************************************************/
349 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
351 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
352 return fseek64(fp, offset, whence);
353 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
354 return fseeko64(fp, offset, whence);
356 return fseek(fp, offset, whence);
360 /*******************************************************************
361 An ftell() wrapper that will deal with 64 bit filesizes.
362 ********************************************************************/
364 SMB_OFF_T sys_ftell(FILE *fp)
366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
367 return (SMB_OFF_T)ftell64(fp);
368 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
369 return (SMB_OFF_T)ftello64(fp);
371 return (SMB_OFF_T)ftell(fp);
375 /*******************************************************************
376 A creat() wrapper that will deal with 64 bit filesizes.
377 ********************************************************************/
379 int sys_creat(const char *path, mode_t mode)
381 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
382 return creat64(path, mode);
385 * If creat64 isn't defined then ensure we call a potential open64.
388 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
392 /*******************************************************************
393 An open() wrapper that will deal with 64 bit filesizes.
394 ********************************************************************/
396 int sys_open(const char *path, int oflag, mode_t mode)
398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
399 return open64(path, oflag, mode);
401 return open(path, oflag, mode);
405 /*******************************************************************
406 An fopen() wrapper that will deal with 64 bit filesizes.
407 ********************************************************************/
409 FILE *sys_fopen(const char *path, const char *type)
411 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
412 return fopen64(path, type);
414 return fopen(path, type);
419 /*******************************************************************
420 A flock() wrapper that will perform the kernel flock.
421 ********************************************************************/
423 void kernel_flock(int fd, uint32 share_mode)
425 #if HAVE_KERNEL_SHARE_MODES
427 if (share_mode == FILE_SHARE_WRITE) {
428 kernel_mode = LOCK_MAND|LOCK_WRITE;
429 } else if (share_mode == FILE_SHARE_READ) {
430 kernel_mode = LOCK_MAND|LOCK_READ;
431 } else if (share_mode == FILE_SHARE_NONE) {
432 kernel_mode = LOCK_MAND;
435 flock(fd, kernel_mode);
443 /*******************************************************************
444 An opendir wrapper that will deal with 64 bit filesizes.
445 ********************************************************************/
447 SMB_STRUCT_DIR *sys_opendir(const char *name)
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
450 return opendir64(name);
452 return opendir(name);
456 /*******************************************************************
457 A readdir wrapper that will deal with 64 bit filesizes.
458 ********************************************************************/
460 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
462 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
463 return readdir64(dirp);
465 return readdir(dirp);
469 /*******************************************************************
470 A seekdir wrapper that will deal with 64 bit filesizes.
471 ********************************************************************/
473 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
475 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
476 seekdir64(dirp, offset);
478 seekdir(dirp, offset);
482 /*******************************************************************
483 A telldir wrapper that will deal with 64 bit filesizes.
484 ********************************************************************/
486 long sys_telldir(SMB_STRUCT_DIR *dirp)
488 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
489 return (long)telldir64(dirp);
491 return (long)telldir(dirp);
495 /*******************************************************************
496 A rewinddir wrapper that will deal with 64 bit filesizes.
497 ********************************************************************/
499 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
501 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
508 /*******************************************************************
509 A close wrapper that will deal with 64 bit filesizes.
510 ********************************************************************/
512 int sys_closedir(SMB_STRUCT_DIR *dirp)
514 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
515 return closedir64(dirp);
517 return closedir(dirp);
521 /*******************************************************************
522 An mknod() wrapper that will deal with 64 bit filesizes.
523 ********************************************************************/
525 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
527 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
528 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
529 return mknod64(path, mode, dev);
531 return mknod(path, mode, dev);
534 /* No mknod system call. */
540 /*******************************************************************
541 Wrapper for realpath.
542 ********************************************************************/
544 char *sys_realpath(const char *path, char *resolved_path)
546 #if defined(HAVE_REALPATH)
547 return realpath(path, resolved_path);
549 /* As realpath is not a system call we can't return ENOSYS. */
555 /*******************************************************************
556 The wait() calls vary between systems
557 ********************************************************************/
559 int sys_waitpid(pid_t pid,int *status,int options)
562 return waitpid(pid,status,options);
563 #else /* HAVE_WAITPID */
564 return wait4(pid, status, options, NULL);
565 #endif /* HAVE_WAITPID */
568 /*******************************************************************
569 System wrapper for getwd
570 ********************************************************************/
572 char *sys_getwd(char *s)
576 wd = (char *)getcwd(s, PATH_MAX);
578 wd = (char *)getwd(s);
583 /*******************************************************************
584 system wrapper for symlink
585 ********************************************************************/
587 int sys_symlink(const char *oldpath, const char *newpath)
593 return symlink(oldpath, newpath);
597 /*******************************************************************
598 system wrapper for readlink
599 ********************************************************************/
601 int sys_readlink(const char *path, char *buf, size_t bufsiz)
603 #ifndef HAVE_READLINK
607 return readlink(path, buf, bufsiz);
611 /*******************************************************************
612 system wrapper for link
613 ********************************************************************/
615 int sys_link(const char *oldpath, const char *newpath)
621 return link(oldpath, newpath);
625 /*******************************************************************
626 chown isn't used much but OS/2 doesn't have it
627 ********************************************************************/
629 int sys_chown(const char *fname,uid_t uid,gid_t gid)
634 DEBUG(1,("WARNING: no chown!\n"));
640 return(chown(fname,uid,gid));
644 /*******************************************************************
646 ********************************************************************/
648 int sys_lchown(const char *fname,uid_t uid,gid_t gid)
653 DEBUG(1,("WARNING: no lchown!\n"));
659 return(lchown(fname,uid,gid));
663 /*******************************************************************
664 os/2 also doesn't have chroot
665 ********************************************************************/
666 int sys_chroot(const char *dname)
671 DEBUG(1,("WARNING: no chroot!\n"));
677 return(chroot(dname));
681 #if defined(HAVE_POSIX_CAPABILITIES)
683 /**************************************************************************
684 Try and abstract process capabilities (for systems that have them).
685 ****************************************************************************/
687 /* Set the POSIX capabilities needed for the given purpose into the effective
688 * capability set of the current process. Make sure they are always removed
689 * from the inheritable set, because there is no circumstance in which our
690 * children should inherit our elevated privileges.
692 static bool set_process_capability(enum smbd_capability capability,
695 cap_value_t cap_vals[2] = {0};
696 int num_cap_vals = 0;
700 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
701 /* On Linux, make sure that any capabilities we grab are sticky
702 * across UID changes. We expect that this would allow us to keep both
703 * the effective and permitted capability sets, but as of circa 2.6.16,
704 * only the permitted set is kept. It is a bug (which we work around)
705 * that the effective set is lost, but we still require the effective
708 if (!prctl(PR_GET_KEEPCAPS)) {
709 prctl(PR_SET_KEEPCAPS, 1);
713 cap = cap_get_proc();
715 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
720 switch (capability) {
721 case KERNEL_OPLOCK_CAPABILITY:
722 #ifdef CAP_NETWORK_MGT
723 /* IRIX has CAP_NETWORK_MGT for oplocks. */
724 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
727 case DMAPI_ACCESS_CAPABILITY:
728 #ifdef CAP_DEVICE_MGT
729 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
730 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
732 /* Linux has CAP_MKNOD for DMAPI access. */
733 cap_vals[num_cap_vals++] = CAP_MKNOD;
738 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
740 if (num_cap_vals == 0) {
745 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
746 enable ? CAP_SET : CAP_CLEAR);
748 /* We never want to pass capabilities down to our children, so make
749 * sure they are not inherited.
751 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
753 if (cap_set_proc(cap) == -1) {
754 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
764 #endif /* HAVE_POSIX_CAPABILITIES */
766 /****************************************************************************
767 Gain the oplock capability from the kernel if possible.
768 ****************************************************************************/
770 void set_effective_capability(enum smbd_capability capability)
772 #if defined(HAVE_POSIX_CAPABILITIES)
773 set_process_capability(capability, True);
774 #endif /* HAVE_POSIX_CAPABILITIES */
777 void drop_effective_capability(enum smbd_capability capability)
779 #if defined(HAVE_POSIX_CAPABILITIES)
780 set_process_capability(capability, False);
781 #endif /* HAVE_POSIX_CAPABILITIES */
784 /**************************************************************************
785 Wrapper for random().
786 ****************************************************************************/
788 long sys_random(void)
790 #if defined(HAVE_RANDOM)
791 return (long)random();
792 #elif defined(HAVE_RAND)
795 DEBUG(0,("Error - no random function available !\n"));
800 /**************************************************************************
801 Wrapper for srandom().
802 ****************************************************************************/
804 void sys_srandom(unsigned int seed)
806 #if defined(HAVE_SRANDOM)
808 #elif defined(HAVE_SRAND)
811 DEBUG(0,("Error - no srandom function available !\n"));
816 /**************************************************************************
817 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
818 ****************************************************************************/
822 #if defined(SYSCONF_SC_NGROUPS_MAX)
823 int ret = sysconf(_SC_NGROUPS_MAX);
824 return (ret == -1) ? NGROUPS_MAX : ret;
830 /**************************************************************************
831 Wrap setgroups and getgroups for systems that declare getgroups() as
832 returning an array of gid_t, but actuall return an array of int.
833 ****************************************************************************/
835 #if defined(HAVE_BROKEN_GETGROUPS)
836 static int sys_broken_getgroups(int setlen, gid_t *gidset)
843 return getgroups(setlen, &gid);
847 * Broken case. We need to allocate a
848 * GID_T array of size setlen.
857 setlen = groups_max();
859 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
860 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
864 if((ngroups = getgroups(setlen, group_list)) < 0) {
865 int saved_errno = errno;
866 SAFE_FREE(group_list);
871 for(i = 0; i < ngroups; i++)
872 gidset[i] = (gid_t)group_list[i];
874 SAFE_FREE(group_list);
878 static int sys_broken_setgroups(int setlen, gid_t *gidset)
886 if (setlen < 0 || setlen > groups_max()) {
892 * Broken case. We need to allocate a
893 * GID_T array of size setlen.
896 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
897 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
901 for(i = 0; i < setlen; i++)
902 group_list[i] = (GID_T) gidset[i];
904 if(setgroups(setlen, group_list) != 0) {
905 int saved_errno = errno;
906 SAFE_FREE(group_list);
911 SAFE_FREE(group_list);
915 #endif /* HAVE_BROKEN_GETGROUPS */
917 /* This is a list of systems that require the first GID passed to setgroups(2)
918 * to be the effective GID. If your system is one of these, add it here.
920 #if defined (FREEBSD) || defined (DARWINOS)
921 #define USE_BSD_SETGROUPS
924 #if defined(USE_BSD_SETGROUPS)
925 /* Depending on the particular BSD implementation, the first GID that is
926 * passed to setgroups(2) will either be ignored or will set the credential's
927 * effective GID. In either case, the right thing to do is to guarantee that
928 * gidset[0] is the effective GID.
930 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
932 gid_t *new_gidset = NULL;
936 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
939 /* No group list, just make sure we are setting the efective GID. */
941 return setgroups(1, &primary_gid);
944 /* If the primary gid is not the first array element, grow the array
945 * and insert it at the front.
947 if (gidset[0] != primary_gid) {
948 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
949 if (new_gidset == NULL) {
953 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
954 new_gidset[0] = primary_gid;
959 DEBUG(3, ("forced to truncate group list from %d to %d\n",
964 #if defined(HAVE_BROKEN_GETGROUPS)
965 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
967 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
972 SAFE_FREE(new_gidset);
979 #endif /* USE_BSD_SETGROUPS */
981 /**************************************************************************
982 Wrapper for getgroups. Deals with broken (int) case.
983 ****************************************************************************/
985 int sys_getgroups(int setlen, gid_t *gidset)
987 #if defined(HAVE_BROKEN_GETGROUPS)
988 return sys_broken_getgroups(setlen, gidset);
990 return getgroups(setlen, gidset);
994 /**************************************************************************
995 Wrapper for setgroups. Deals with broken (int) case and BSD case.
996 ****************************************************************************/
998 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1000 #if !defined(HAVE_SETGROUPS)
1003 #endif /* HAVE_SETGROUPS */
1005 #if defined(USE_BSD_SETGROUPS)
1006 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1007 #elif defined(HAVE_BROKEN_GETGROUPS)
1008 return sys_broken_setgroups(setlen, gidset);
1010 return setgroups(setlen, gidset);
1014 /**************************************************************************
1015 Wrappers for setpwent(), getpwent() and endpwent()
1016 ****************************************************************************/
1018 void sys_setpwent(void)
1023 struct passwd *sys_getpwent(void)
1028 void sys_endpwent(void)
1033 /**************************************************************************
1034 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1035 ****************************************************************************/
1038 struct passwd *sys_getpwnam(const char *name)
1040 return getpwnam(name);
1043 struct passwd *sys_getpwuid(uid_t uid)
1045 return getpwuid(uid);
1048 struct group *sys_getgrnam(const char *name)
1050 return getgrnam(name);
1053 struct group *sys_getgrgid(gid_t gid)
1055 return getgrgid(gid);
1058 /**************************************************************************
1059 Extract a command into an arg list.
1060 ****************************************************************************/
1062 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1071 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1072 DEBUG(0, ("talloc failed\n"));
1076 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1077 TALLOC_FREE(trunc_cmd);
1086 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1089 TALLOC_FREE(trunc_cmd);
1091 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1096 * Now do the extraction.
1099 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1103 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1106 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1110 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1112 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1121 DEBUG(0, ("talloc failed\n"));
1122 TALLOC_FREE(trunc_cmd);
1128 /**************************************************************************
1129 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1130 a sys_getpid() that only does a system call *once*.
1131 ****************************************************************************/
1133 static pid_t mypid = (pid_t)-1;
1135 pid_t sys_fork(void)
1137 pid_t forkret = fork();
1139 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1145 /**************************************************************************
1146 Wrapper for getpid. Ensures we only do a system call *once*.
1147 ****************************************************************************/
1149 pid_t sys_getpid(void)
1151 if (mypid == (pid_t)-1)
1157 /**************************************************************************
1158 Wrapper for popen. Safer as it doesn't search a path.
1159 Modified from the glibc sources.
1160 modified by tridge to return a file descriptor. We must kick our FILE* habit
1161 ****************************************************************************/
1163 typedef struct _popen_list
1167 struct _popen_list *next;
1170 static popen_list *popen_chain;
1172 int sys_popen(const char *command)
1174 int parent_end, child_end;
1176 popen_list *entry = NULL;
1179 if (pipe(pipe_fds) < 0)
1182 parent_end = pipe_fds[0];
1183 child_end = pipe_fds[1];
1190 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1193 ZERO_STRUCTP(entry);
1196 * Extract the command and args into a NULL terminated array.
1199 if(!(argl = extract_args(NULL, command)))
1202 entry->child_pid = sys_fork();
1204 if (entry->child_pid == -1) {
1208 if (entry->child_pid == 0) {
1214 int child_std_end = STDOUT_FILENO;
1218 if (child_end != child_std_end) {
1219 dup2 (child_end, child_std_end);
1224 * POSIX.2: "popen() shall ensure that any streams from previous
1225 * popen() calls that remain open in the parent process are closed
1226 * in the new child process."
1229 for (p = popen_chain; p; p = p->next)
1232 execv(argl[0], argl);
1243 /* Link into popen_chain. */
1244 entry->next = popen_chain;
1245 popen_chain = entry;
1246 entry->fd = parent_end;
1259 /**************************************************************************
1260 Wrapper for pclose. Modified from the glibc sources.
1261 ****************************************************************************/
1263 int sys_pclose(int fd)
1266 popen_list **ptr = &popen_chain;
1267 popen_list *entry = NULL;
1271 /* Unlink from popen_chain. */
1272 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1273 if ((*ptr)->fd == fd) {
1275 *ptr = (*ptr)->next;
1281 if (status < 0 || close(entry->fd) < 0)
1285 * As Samba is catching and eating child process
1286 * exits we don't really care about the child exit
1287 * code, a -1 with errno = ECHILD will do fine for us.
1291 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1292 } while (wait_pid == -1 && errno == EINTR);
1301 /**************************************************************************
1302 Wrappers for dlopen, dlsym, dlclose.
1303 ****************************************************************************/
1305 void *sys_dlopen(const char *name, int flags)
1307 #if defined(HAVE_DLOPEN)
1308 return dlopen(name, flags);
1314 void *sys_dlsym(void *handle, const char *symbol)
1316 #if defined(HAVE_DLSYM)
1317 return dlsym(handle, symbol);
1323 int sys_dlclose (void *handle)
1325 #if defined(HAVE_DLCLOSE)
1326 return dlclose(handle);
1332 const char *sys_dlerror(void)
1334 #if defined(HAVE_DLERROR)
1341 int sys_dup2(int oldfd, int newfd)
1343 #if defined(HAVE_DUP2)
1344 return dup2(oldfd, newfd);
1351 /**************************************************************************
1352 Wrapper for Admin Logs.
1353 ****************************************************************************/
1355 void sys_adminlog(int priority, const char *format_str, ...)
1359 char *msgbuf = NULL;
1361 va_start( ap, format_str );
1362 ret = vasprintf( &msgbuf, format_str, ap );
1368 #if defined(HAVE_SYSLOG)
1369 syslog( priority, "%s", msgbuf );
1371 DEBUG(0,("%s", msgbuf ));
1376 /******** Solaris EA helper function prototypes ********/
1377 #ifdef HAVE_ATTROPEN
1378 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1379 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1380 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1381 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1382 static int solaris_unlinkat(int attrdirfd, const char *name);
1383 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1384 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1387 /**************************************************************************
1388 Wrappers for extented attribute calls. Based on the Linux package with
1389 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1390 ****************************************************************************/
1392 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1394 #if defined(HAVE_GETXATTR)
1395 #ifndef XATTR_ADD_OPT
1396 return getxattr(path, name, value, size);
1399 return getxattr(path, name, value, size, 0, options);
1401 #elif defined(HAVE_GETEA)
1402 return getea(path, name, value, size);
1403 #elif defined(HAVE_EXTATTR_GET_FILE)
1406 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1407 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1408 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1410 * The BSD implementation has a nasty habit of silently truncating
1411 * the returned value to the size of the buffer, so we have to check
1412 * that the buffer is large enough to fit the returned value.
1414 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1419 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1423 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1425 #elif defined(HAVE_ATTR_GET)
1426 int retval, flags = 0;
1427 int valuelength = (int)size;
1428 char *attrname = strchr(name,'.') + 1;
1430 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1432 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1434 return retval ? retval : valuelength;
1435 #elif defined(HAVE_ATTROPEN)
1437 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1439 ret = solaris_read_xattr(attrfd, value, size);
1449 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1451 #if defined(HAVE_LGETXATTR)
1452 return lgetxattr(path, name, value, size);
1453 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1454 int options = XATTR_NOFOLLOW;
1455 return getxattr(path, name, value, size, 0, options);
1456 #elif defined(HAVE_LGETEA)
1457 return lgetea(path, name, value, size);
1458 #elif defined(HAVE_EXTATTR_GET_LINK)
1461 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1462 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1463 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1465 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1470 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1474 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1476 #elif defined(HAVE_ATTR_GET)
1477 int retval, flags = ATTR_DONTFOLLOW;
1478 int valuelength = (int)size;
1479 char *attrname = strchr(name,'.') + 1;
1481 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1483 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1485 return retval ? retval : valuelength;
1486 #elif defined(HAVE_ATTROPEN)
1488 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1490 ret = solaris_read_xattr(attrfd, value, size);
1500 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1502 #if defined(HAVE_FGETXATTR)
1503 #ifndef XATTR_ADD_OPT
1504 return fgetxattr(filedes, name, value, size);
1507 return fgetxattr(filedes, name, value, size, 0, options);
1509 #elif defined(HAVE_FGETEA)
1510 return fgetea(filedes, name, value, size);
1511 #elif defined(HAVE_EXTATTR_GET_FD)
1514 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1515 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1516 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1518 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1523 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1527 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1529 #elif defined(HAVE_ATTR_GETF)
1530 int retval, flags = 0;
1531 int valuelength = (int)size;
1532 char *attrname = strchr(name,'.') + 1;
1534 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1536 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1538 return retval ? retval : valuelength;
1539 #elif defined(HAVE_ATTROPEN)
1541 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1543 ret = solaris_read_xattr(attrfd, value, size);
1553 #if defined(HAVE_EXTATTR_LIST_FILE)
1555 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1563 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1564 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1572 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1574 ssize_t list_size, total_size = 0;
1577 /* Iterate through extattr(2) namespaces */
1578 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1580 #if defined(HAVE_EXTATTR_LIST_FILE)
1582 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1585 #if defined(HAVE_EXTATTR_LIST_LINK)
1587 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1590 #if defined(HAVE_EXTATTR_LIST_FD)
1592 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1599 /* Some error happend. Errno should be set by the previous call */
1605 /* XXX: Call with an empty buffer may be used to calculate
1606 necessary buffer size. Unfortunately, we can't say, how
1607 many attributes were returned, so here is the potential
1608 problem with the emulation.
1611 /* Take the worse case of one char attribute names -
1612 two bytes per name plus one more for sanity.
1614 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1617 /* Count necessary offset to fit namespace prefixes */
1619 for(i = 0; i < list_size; i += list[i] + 1)
1620 len += extattr[t].len;
1622 total_size += list_size + len;
1623 /* Buffer is too small to fit the results */
1624 if(total_size > size) {
1628 /* Shift results back, so we can prepend prefixes */
1629 buf = memmove(list + len, list, list_size);
1631 for(i = 0; i < list_size; i += len + 1) {
1633 strncpy(list, extattr[t].name, extattr[t].len + 1);
1634 list += extattr[t].len;
1635 strncpy(list, buf + i + 1, len);
1646 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1647 static char attr_buffer[ATTR_MAX_VALUELEN];
1649 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1651 int retval = 0, index;
1652 attrlist_cursor_t *cursor = 0;
1654 attrlist_t * al = (attrlist_t *)attr_buffer;
1656 size_t ent_size, left = size;
1661 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1663 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1665 for (index = 0; index < al->al_count; index++) {
1666 ae = ATTR_ENTRY(attr_buffer, index);
1667 ent_size = strlen(ae->a_name) + sizeof("user.");
1668 if (left >= ent_size) {
1669 strncpy(bp, "user.", sizeof("user."));
1670 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1678 total_size += ent_size;
1680 if (al->al_more == 0) break;
1687 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1689 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1691 for (index = 0; index < al->al_count; index++) {
1692 ae = ATTR_ENTRY(attr_buffer, index);
1693 ent_size = strlen(ae->a_name) + sizeof("system.");
1694 if (left >= ent_size) {
1695 strncpy(bp, "system.", sizeof("system."));
1696 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1704 total_size += ent_size;
1706 if (al->al_more == 0) break;
1709 return (ssize_t)(retval ? retval : total_size);
1714 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1716 #if defined(HAVE_LISTXATTR)
1717 #ifndef XATTR_ADD_OPT
1718 return listxattr(path, list, size);
1721 return listxattr(path, list, size, options);
1723 #elif defined(HAVE_LISTEA)
1724 return listea(path, list, size);
1725 #elif defined(HAVE_EXTATTR_LIST_FILE)
1728 return bsd_attr_list(0, arg, list, size);
1729 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1730 return irix_attr_list(path, 0, list, size, 0);
1731 #elif defined(HAVE_ATTROPEN)
1733 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1734 if (attrdirfd >= 0) {
1735 ret = solaris_list_xattr(attrdirfd, list, size);
1745 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1747 #if defined(HAVE_LLISTXATTR)
1748 return llistxattr(path, list, size);
1749 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1750 int options = XATTR_NOFOLLOW;
1751 return listxattr(path, list, size, options);
1752 #elif defined(HAVE_LLISTEA)
1753 return llistea(path, list, size);
1754 #elif defined(HAVE_EXTATTR_LIST_LINK)
1757 return bsd_attr_list(1, arg, list, size);
1758 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1759 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1760 #elif defined(HAVE_ATTROPEN)
1762 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1763 if (attrdirfd >= 0) {
1764 ret = solaris_list_xattr(attrdirfd, list, size);
1774 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1776 #if defined(HAVE_FLISTXATTR)
1777 #ifndef XATTR_ADD_OPT
1778 return flistxattr(filedes, list, size);
1781 return flistxattr(filedes, list, size, options);
1783 #elif defined(HAVE_FLISTEA)
1784 return flistea(filedes, list, size);
1785 #elif defined(HAVE_EXTATTR_LIST_FD)
1787 arg.filedes = filedes;
1788 return bsd_attr_list(2, arg, list, size);
1789 #elif defined(HAVE_ATTR_LISTF)
1790 return irix_attr_list(NULL, filedes, list, size, 0);
1791 #elif defined(HAVE_ATTROPEN)
1793 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1794 if (attrdirfd >= 0) {
1795 ret = solaris_list_xattr(attrdirfd, list, size);
1805 int sys_removexattr (const char *path, const char *name)
1807 #if defined(HAVE_REMOVEXATTR)
1808 #ifndef XATTR_ADD_OPT
1809 return removexattr(path, name);
1812 return removexattr(path, name, options);
1814 #elif defined(HAVE_REMOVEEA)
1815 return removeea(path, name);
1816 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1818 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1819 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1820 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1822 return extattr_delete_file(path, attrnamespace, attrname);
1823 #elif defined(HAVE_ATTR_REMOVE)
1825 char *attrname = strchr(name,'.') + 1;
1827 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1829 return attr_remove(path, attrname, flags);
1830 #elif defined(HAVE_ATTROPEN)
1832 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1833 if (attrdirfd >= 0) {
1834 ret = solaris_unlinkat(attrdirfd, name);
1844 int sys_lremovexattr (const char *path, const char *name)
1846 #if defined(HAVE_LREMOVEXATTR)
1847 return lremovexattr(path, name);
1848 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1849 int options = XATTR_NOFOLLOW;
1850 return removexattr(path, name, options);
1851 #elif defined(HAVE_LREMOVEEA)
1852 return lremoveea(path, name);
1853 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1855 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1856 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1857 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1859 return extattr_delete_link(path, attrnamespace, attrname);
1860 #elif defined(HAVE_ATTR_REMOVE)
1861 int flags = ATTR_DONTFOLLOW;
1862 char *attrname = strchr(name,'.') + 1;
1864 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1866 return attr_remove(path, attrname, flags);
1867 #elif defined(HAVE_ATTROPEN)
1869 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1870 if (attrdirfd >= 0) {
1871 ret = solaris_unlinkat(attrdirfd, name);
1881 int sys_fremovexattr (int filedes, const char *name)
1883 #if defined(HAVE_FREMOVEXATTR)
1884 #ifndef XATTR_ADD_OPT
1885 return fremovexattr(filedes, name);
1888 return fremovexattr(filedes, name, options);
1890 #elif defined(HAVE_FREMOVEEA)
1891 return fremoveea(filedes, name);
1892 #elif defined(HAVE_EXTATTR_DELETE_FD)
1894 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1895 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1896 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1898 return extattr_delete_fd(filedes, attrnamespace, attrname);
1899 #elif defined(HAVE_ATTR_REMOVEF)
1901 char *attrname = strchr(name,'.') + 1;
1903 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1905 return attr_removef(filedes, attrname, flags);
1906 #elif defined(HAVE_ATTROPEN)
1908 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1909 if (attrdirfd >= 0) {
1910 ret = solaris_unlinkat(attrdirfd, name);
1920 #if !defined(HAVE_SETXATTR)
1921 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1922 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1925 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1927 #if defined(HAVE_SETXATTR)
1928 #ifndef XATTR_ADD_OPT
1929 return setxattr(path, name, value, size, flags);
1932 return setxattr(path, name, value, size, 0, options);
1934 #elif defined(HAVE_SETEA)
1935 return setea(path, name, value, size, flags);
1936 #elif defined(HAVE_EXTATTR_SET_FILE)
1939 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1940 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1941 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1943 /* Check attribute existence */
1944 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1946 /* REPLACE attribute, that doesn't exist */
1947 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1951 /* Ignore other errors */
1954 /* CREATE attribute, that already exists */
1955 if (flags & XATTR_CREATE) {
1961 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1962 return (retval < 0) ? -1 : 0;
1963 #elif defined(HAVE_ATTR_SET)
1965 char *attrname = strchr(name,'.') + 1;
1967 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1968 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1969 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1971 return attr_set(path, attrname, (const char *)value, size, myflags);
1972 #elif defined(HAVE_ATTROPEN)
1974 int myflags = O_RDWR;
1976 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1977 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1978 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1980 ret = solaris_write_xattr(attrfd, value, size);
1990 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1992 #if defined(HAVE_LSETXATTR)
1993 return lsetxattr(path, name, value, size, flags);
1994 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1995 int options = XATTR_NOFOLLOW;
1996 return setxattr(path, name, value, size, 0, options);
1997 #elif defined(LSETEA)
1998 return lsetea(path, name, value, size, flags);
1999 #elif defined(HAVE_EXTATTR_SET_LINK)
2002 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2003 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2004 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2006 /* Check attribute existence */
2007 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2009 /* REPLACE attribute, that doesn't exist */
2010 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2014 /* Ignore other errors */
2017 /* CREATE attribute, that already exists */
2018 if (flags & XATTR_CREATE) {
2025 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2026 return (retval < 0) ? -1 : 0;
2027 #elif defined(HAVE_ATTR_SET)
2028 int myflags = ATTR_DONTFOLLOW;
2029 char *attrname = strchr(name,'.') + 1;
2031 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2032 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2033 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2035 return attr_set(path, attrname, (const char *)value, size, myflags);
2036 #elif defined(HAVE_ATTROPEN)
2038 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2040 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2041 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2042 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2044 ret = solaris_write_xattr(attrfd, value, size);
2054 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2056 #if defined(HAVE_FSETXATTR)
2057 #ifndef XATTR_ADD_OPT
2058 return fsetxattr(filedes, name, value, size, flags);
2061 return fsetxattr(filedes, name, value, size, 0, options);
2063 #elif defined(HAVE_FSETEA)
2064 return fsetea(filedes, name, value, size, flags);
2065 #elif defined(HAVE_EXTATTR_SET_FD)
2068 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2069 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2070 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2072 /* Check attribute existence */
2073 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2075 /* REPLACE attribute, that doesn't exist */
2076 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2080 /* Ignore other errors */
2083 /* CREATE attribute, that already exists */
2084 if (flags & XATTR_CREATE) {
2090 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2091 return (retval < 0) ? -1 : 0;
2092 #elif defined(HAVE_ATTR_SETF)
2094 char *attrname = strchr(name,'.') + 1;
2096 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2097 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2098 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2100 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2101 #elif defined(HAVE_ATTROPEN)
2103 int myflags = O_RDWR | O_XATTR;
2105 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2106 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2107 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2109 ret = solaris_write_xattr(attrfd, value, size);
2119 /**************************************************************************
2120 helper functions for Solaris' EA support
2121 ****************************************************************************/
2122 #ifdef HAVE_ATTROPEN
2123 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2127 if (fstat(attrfd, &sbuf) == -1) {
2132 /* This is to return the current size of the named extended attribute */
2134 return sbuf.st_size;
2137 /* check size and read xattr */
2138 if (sbuf.st_size > size) {
2143 return read(attrfd, value, sbuf.st_size);
2146 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2152 int newfd = dup(attrdirfd);
2153 /* CAUTION: The originating file descriptor should not be
2154 used again following the call to fdopendir().
2155 For that reason we dup() the file descriptor
2156 here to make things more clear. */
2157 dirp = fdopendir(newfd);
2159 while ((de = readdir(dirp))) {
2160 size_t listlen = strlen(de->d_name);
2161 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2162 /* we don't want "." and ".." here: */
2163 DEBUG(10,("skipped EA %s\n",de->d_name));
2168 /* return the current size of the list of extended attribute names*/
2171 /* check size and copy entrieѕ + nul into list. */
2172 if ((len + listlen + 1) > size) {
2177 safe_strcpy(list + len, de->d_name, listlen);
2185 if (closedir(dirp) == -1) {
2186 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2192 static int solaris_unlinkat(int attrdirfd, const char *name)
2194 if (unlinkat(attrdirfd, name, 0) == -1) {
2195 if (errno == ENOENT) {
2203 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2205 int filedes = attropen(path, attrpath, oflag, mode);
2206 if (filedes == -1) {
2207 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2208 if (errno == EINVAL) {
2217 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2219 int filedes = openat(fildes, path, oflag, mode);
2220 if (filedes == -1) {
2221 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2222 if (errno == EINVAL) {
2231 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2233 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2236 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2240 #endif /*HAVE_ATTROPEN*/
2243 /****************************************************************************
2244 Return the major devicenumber for UNIX extensions.
2245 ****************************************************************************/
2247 uint32 unix_dev_major(SMB_DEV_T dev)
2249 #if defined(HAVE_DEVICE_MAJOR_FN)
2250 return (uint32)major(dev);
2252 return (uint32)(dev >> 8);
2256 /****************************************************************************
2257 Return the minor devicenumber for UNIX extensions.
2258 ****************************************************************************/
2260 uint32 unix_dev_minor(SMB_DEV_T dev)
2262 #if defined(HAVE_DEVICE_MINOR_FN)
2263 return (uint32)minor(dev);
2265 return (uint32)(dev & 0xff);
2269 #if defined(WITH_AIO)
2271 /*******************************************************************
2272 An aio_read wrapper that will deal with 64-bit sizes.
2273 ********************************************************************/
2275 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2277 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2278 return aio_read64(aiocb);
2279 #elif defined(HAVE_AIO_READ)
2280 return aio_read(aiocb);
2287 /*******************************************************************
2288 An aio_write wrapper that will deal with 64-bit sizes.
2289 ********************************************************************/
2291 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2293 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2294 return aio_write64(aiocb);
2295 #elif defined(HAVE_AIO_WRITE)
2296 return aio_write(aiocb);
2303 /*******************************************************************
2304 An aio_return wrapper that will deal with 64-bit sizes.
2305 ********************************************************************/
2307 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2309 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2310 return aio_return64(aiocb);
2311 #elif defined(HAVE_AIO_RETURN)
2312 return aio_return(aiocb);
2319 /*******************************************************************
2320 An aio_cancel wrapper that will deal with 64-bit sizes.
2321 ********************************************************************/
2323 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2325 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2326 return aio_cancel64(fd, aiocb);
2327 #elif defined(HAVE_AIO_CANCEL)
2328 return aio_cancel(fd, aiocb);
2335 /*******************************************************************
2336 An aio_error wrapper that will deal with 64-bit sizes.
2337 ********************************************************************/
2339 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2341 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2342 return aio_error64(aiocb);
2343 #elif defined(HAVE_AIO_ERROR)
2344 return aio_error(aiocb);
2351 /*******************************************************************
2352 An aio_fsync wrapper that will deal with 64-bit sizes.
2353 ********************************************************************/
2355 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2357 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2358 return aio_fsync64(op, aiocb);
2359 #elif defined(HAVE_AIO_FSYNC)
2360 return aio_fsync(op, aiocb);
2367 /*******************************************************************
2368 An aio_fsync wrapper that will deal with 64-bit sizes.
2369 ********************************************************************/
2371 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2373 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2374 return aio_suspend64(cblist, n, timeout);
2375 #elif defined(HAVE_AIO_FSYNC)
2376 return aio_suspend(cblist, n, timeout);
2382 #else /* !WITH_AIO */
2384 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2390 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2396 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2402 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2408 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2414 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2420 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2425 #endif /* WITH_AIO */
2427 int sys_getpeereid( int s, uid_t *uid)
2429 #if defined(HAVE_PEERCRED)
2431 socklen_t cred_len = sizeof(struct ucred);
2434 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2439 if (cred_len != sizeof(struct ucred)) {
2452 int sys_getnameinfo(const struct sockaddr *psa,
2461 * For Solaris we must make sure salen is the
2462 * correct length for the incoming sa_family.
2465 if (salen == sizeof(struct sockaddr_storage)) {
2466 salen = sizeof(struct sockaddr_in);
2467 #if defined(HAVE_IPV6)
2468 if (psa->sa_family == AF_INET6) {
2469 salen = sizeof(struct sockaddr_in6);
2473 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2476 int sys_connect(int fd, const struct sockaddr * addr)
2478 socklen_t salen = -1;
2480 if (addr->sa_family == AF_INET) {
2481 salen = sizeof(struct sockaddr_in);
2482 } else if (addr->sa_family == AF_UNIX) {
2483 salen = sizeof(struct sockaddr_un);
2485 #if defined(HAVE_IPV6)
2486 else if (addr->sa_family == AF_INET6) {
2487 salen = sizeof(struct sockaddr_in6);
2491 return connect(fd, addr, salen);