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 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 A stat() wrapper that will deal with 64 bit filesizes.
295 ********************************************************************/
297 int sys_stat(const char *fname
,SMB_STRUCT_STAT
*sbuf
)
300 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
301 ret
= stat64(fname
, sbuf
);
303 ret
= stat(fname
, sbuf
);
305 /* we always want directories to appear zero size */
306 if (ret
== 0 && S_ISDIR(sbuf
->st_mode
)) sbuf
->st_size
= 0;
310 /*******************************************************************
311 An fstat() wrapper that will deal with 64 bit filesizes.
312 ********************************************************************/
314 int sys_fstat(int fd
,SMB_STRUCT_STAT
*sbuf
)
317 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
318 ret
= fstat64(fd
, sbuf
);
320 ret
= fstat(fd
, sbuf
);
322 /* we always want directories to appear zero size */
323 if (ret
== 0 && S_ISDIR(sbuf
->st_mode
)) sbuf
->st_size
= 0;
327 /*******************************************************************
328 An lstat() wrapper that will deal with 64 bit filesizes.
329 ********************************************************************/
331 int sys_lstat(const char *fname
,SMB_STRUCT_STAT
*sbuf
)
334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
335 ret
= lstat64(fname
, sbuf
);
337 ret
= lstat(fname
, sbuf
);
339 /* we always want directories to appear zero size */
340 if (ret
== 0 && S_ISDIR(sbuf
->st_mode
)) sbuf
->st_size
= 0;
344 /*******************************************************************
345 An ftruncate() wrapper that will deal with 64 bit filesizes.
346 ********************************************************************/
348 int sys_ftruncate(int fd
, SMB_OFF_T offset
)
350 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
351 return ftruncate64(fd
, offset
);
353 return ftruncate(fd
, offset
);
357 /*******************************************************************
358 An lseek() wrapper that will deal with 64 bit filesizes.
359 ********************************************************************/
361 SMB_OFF_T
sys_lseek(int fd
, SMB_OFF_T offset
, int whence
)
363 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
364 return lseek64(fd
, offset
, whence
);
366 return lseek(fd
, offset
, whence
);
370 /*******************************************************************
371 An fseek() wrapper that will deal with 64 bit filesizes.
372 ********************************************************************/
374 int sys_fseek(FILE *fp
, SMB_OFF_T offset
, int whence
)
376 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
377 return fseek64(fp
, offset
, whence
);
378 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
379 return fseeko64(fp
, offset
, whence
);
381 return fseek(fp
, offset
, whence
);
385 /*******************************************************************
386 An ftell() wrapper that will deal with 64 bit filesizes.
387 ********************************************************************/
389 SMB_OFF_T
sys_ftell(FILE *fp
)
391 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
392 return (SMB_OFF_T
)ftell64(fp
);
393 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
394 return (SMB_OFF_T
)ftello64(fp
);
396 return (SMB_OFF_T
)ftell(fp
);
400 /*******************************************************************
401 A creat() wrapper that will deal with 64 bit filesizes.
402 ********************************************************************/
404 int sys_creat(const char *path
, mode_t mode
)
406 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
407 return creat64(path
, mode
);
410 * If creat64 isn't defined then ensure we call a potential open64.
413 return sys_open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, mode
);
417 /*******************************************************************
418 An open() wrapper that will deal with 64 bit filesizes.
419 ********************************************************************/
421 int sys_open(const char *path
, int oflag
, mode_t mode
)
423 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
424 return open64(path
, oflag
, mode
);
426 return open(path
, oflag
, mode
);
430 /*******************************************************************
431 An fopen() wrapper that will deal with 64 bit filesizes.
432 ********************************************************************/
434 FILE *sys_fopen(const char *path
, const char *type
)
436 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
437 return fopen64(path
, type
);
439 return fopen(path
, type
);
444 /*******************************************************************
445 A flock() wrapper that will perform the kernel flock.
446 ********************************************************************/
448 void kernel_flock(int fd
, uint32 share_mode
)
450 #if HAVE_KERNEL_SHARE_MODES
452 if (share_mode
== FILE_SHARE_WRITE
) {
453 kernel_mode
= LOCK_MAND
|LOCK_WRITE
;
454 } else if (share_mode
== FILE_SHARE_READ
) {
455 kernel_mode
= LOCK_MAND
|LOCK_READ
;
456 } else if (share_mode
== FILE_SHARE_NONE
) {
457 kernel_mode
= LOCK_MAND
;
460 flock(fd
, kernel_mode
);
468 /*******************************************************************
469 An opendir wrapper that will deal with 64 bit filesizes.
470 ********************************************************************/
472 SMB_STRUCT_DIR
*sys_opendir(const char *name
)
474 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
475 return opendir64(name
);
477 return opendir(name
);
481 /*******************************************************************
482 A readdir wrapper that will deal with 64 bit filesizes.
483 ********************************************************************/
485 SMB_STRUCT_DIRENT
*sys_readdir(SMB_STRUCT_DIR
*dirp
)
487 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
488 return readdir64(dirp
);
490 return readdir(dirp
);
494 /*******************************************************************
495 A seekdir wrapper that will deal with 64 bit filesizes.
496 ********************************************************************/
498 void sys_seekdir(SMB_STRUCT_DIR
*dirp
, long offset
)
500 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
501 seekdir64(dirp
, offset
);
503 seekdir(dirp
, offset
);
507 /*******************************************************************
508 A telldir wrapper that will deal with 64 bit filesizes.
509 ********************************************************************/
511 long sys_telldir(SMB_STRUCT_DIR
*dirp
)
513 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
514 return (long)telldir64(dirp
);
516 return (long)telldir(dirp
);
520 /*******************************************************************
521 A rewinddir wrapper that will deal with 64 bit filesizes.
522 ********************************************************************/
524 void sys_rewinddir(SMB_STRUCT_DIR
*dirp
)
526 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
533 /*******************************************************************
534 A close wrapper that will deal with 64 bit filesizes.
535 ********************************************************************/
537 int sys_closedir(SMB_STRUCT_DIR
*dirp
)
539 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
540 return closedir64(dirp
);
542 return closedir(dirp
);
546 /*******************************************************************
547 An mknod() wrapper that will deal with 64 bit filesizes.
548 ********************************************************************/
550 int sys_mknod(const char *path
, mode_t mode
, SMB_DEV_T dev
)
552 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
553 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
554 return mknod64(path
, mode
, dev
);
556 return mknod(path
, mode
, dev
);
559 /* No mknod system call. */
565 /*******************************************************************
566 Wrapper for realpath.
567 ********************************************************************/
569 char *sys_realpath(const char *path
, char *resolved_path
)
571 #if defined(HAVE_REALPATH)
572 return realpath(path
, resolved_path
);
574 /* As realpath is not a system call we can't return ENOSYS. */
580 /*******************************************************************
581 The wait() calls vary between systems
582 ********************************************************************/
584 int sys_waitpid(pid_t pid
,int *status
,int options
)
587 return waitpid(pid
,status
,options
);
588 #else /* HAVE_WAITPID */
589 return wait4(pid
, status
, options
, NULL
);
590 #endif /* HAVE_WAITPID */
593 /*******************************************************************
594 System wrapper for getwd
595 ********************************************************************/
597 char *sys_getwd(char *s
)
601 wd
= (char *)getcwd(s
, PATH_MAX
);
603 wd
= (char *)getwd(s
);
608 /*******************************************************************
609 system wrapper for symlink
610 ********************************************************************/
612 int sys_symlink(const char *oldpath
, const char *newpath
)
618 return symlink(oldpath
, newpath
);
622 /*******************************************************************
623 system wrapper for readlink
624 ********************************************************************/
626 int sys_readlink(const char *path
, char *buf
, size_t bufsiz
)
628 #ifndef HAVE_READLINK
632 return readlink(path
, buf
, bufsiz
);
636 /*******************************************************************
637 system wrapper for link
638 ********************************************************************/
640 int sys_link(const char *oldpath
, const char *newpath
)
646 return link(oldpath
, newpath
);
650 /*******************************************************************
651 chown isn't used much but OS/2 doesn't have it
652 ********************************************************************/
654 int sys_chown(const char *fname
,uid_t uid
,gid_t gid
)
659 DEBUG(1,("WARNING: no chown!\n"));
665 return(chown(fname
,uid
,gid
));
669 /*******************************************************************
671 ********************************************************************/
673 int sys_lchown(const char *fname
,uid_t uid
,gid_t gid
)
678 DEBUG(1,("WARNING: no lchown!\n"));
684 return(lchown(fname
,uid
,gid
));
688 /*******************************************************************
689 os/2 also doesn't have chroot
690 ********************************************************************/
691 int sys_chroot(const char *dname
)
696 DEBUG(1,("WARNING: no chroot!\n"));
702 return(chroot(dname
));
706 #if defined(HAVE_POSIX_CAPABILITIES)
708 /**************************************************************************
709 Try and abstract process capabilities (for systems that have them).
710 ****************************************************************************/
712 /* Set the POSIX capabilities needed for the given purpose into the effective
713 * capability set of the current process. Make sure they are always removed
714 * from the inheritable set, because there is no circumstance in which our
715 * children should inherit our elevated privileges.
717 static bool set_process_capability(enum smbd_capability capability
,
720 cap_value_t cap_vals
[2] = {0};
721 int num_cap_vals
= 0;
725 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
726 /* On Linux, make sure that any capabilities we grab are sticky
727 * across UID changes. We expect that this would allow us to keep both
728 * the effective and permitted capability sets, but as of circa 2.6.16,
729 * only the permitted set is kept. It is a bug (which we work around)
730 * that the effective set is lost, but we still require the effective
733 if (!prctl(PR_GET_KEEPCAPS
)) {
734 prctl(PR_SET_KEEPCAPS
, 1);
738 cap
= cap_get_proc();
740 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
745 switch (capability
) {
746 case KERNEL_OPLOCK_CAPABILITY
:
747 #ifdef CAP_NETWORK_MGT
748 /* IRIX has CAP_NETWORK_MGT for oplocks. */
749 cap_vals
[num_cap_vals
++] = CAP_NETWORK_MGT
;
752 case DMAPI_ACCESS_CAPABILITY
:
753 #ifdef CAP_DEVICE_MGT
754 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
755 cap_vals
[num_cap_vals
++] = CAP_DEVICE_MGT
;
757 /* Linux has CAP_MKNOD for DMAPI access. */
758 cap_vals
[num_cap_vals
++] = CAP_MKNOD
;
761 case LEASE_CAPABILITY
:
763 cap_vals
[num_cap_vals
++] = CAP_LEASE
;
768 SMB_ASSERT(num_cap_vals
<= ARRAY_SIZE(cap_vals
));
770 if (num_cap_vals
== 0) {
775 cap_set_flag(cap
, CAP_EFFECTIVE
, num_cap_vals
, cap_vals
,
776 enable
? CAP_SET
: CAP_CLEAR
);
778 /* We never want to pass capabilities down to our children, so make
779 * sure they are not inherited.
781 cap_set_flag(cap
, CAP_INHERITABLE
, num_cap_vals
, cap_vals
, CAP_CLEAR
);
783 if (cap_set_proc(cap
) == -1) {
784 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
794 #endif /* HAVE_POSIX_CAPABILITIES */
796 /****************************************************************************
797 Gain the oplock capability from the kernel if possible.
798 ****************************************************************************/
800 void set_effective_capability(enum smbd_capability capability
)
802 #if defined(HAVE_POSIX_CAPABILITIES)
803 set_process_capability(capability
, True
);
804 #endif /* HAVE_POSIX_CAPABILITIES */
807 void drop_effective_capability(enum smbd_capability capability
)
809 #if defined(HAVE_POSIX_CAPABILITIES)
810 set_process_capability(capability
, False
);
811 #endif /* HAVE_POSIX_CAPABILITIES */
814 /**************************************************************************
815 Wrapper for random().
816 ****************************************************************************/
818 long sys_random(void)
820 #if defined(HAVE_RANDOM)
821 return (long)random();
822 #elif defined(HAVE_RAND)
825 DEBUG(0,("Error - no random function available !\n"));
830 /**************************************************************************
831 Wrapper for srandom().
832 ****************************************************************************/
834 void sys_srandom(unsigned int seed
)
836 #if defined(HAVE_SRANDOM)
838 #elif defined(HAVE_SRAND)
841 DEBUG(0,("Error - no srandom function available !\n"));
846 /**************************************************************************
847 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
848 ****************************************************************************/
852 #if defined(SYSCONF_SC_NGROUPS_MAX)
853 int ret
= sysconf(_SC_NGROUPS_MAX
);
854 return (ret
== -1) ? NGROUPS_MAX
: ret
;
860 /**************************************************************************
861 Wrap setgroups and getgroups for systems that declare getgroups() as
862 returning an array of gid_t, but actuall return an array of int.
863 ****************************************************************************/
865 #if defined(HAVE_BROKEN_GETGROUPS)
866 static int sys_broken_getgroups(int setlen
, gid_t
*gidset
)
873 return getgroups(setlen
, &gid
);
877 * Broken case. We need to allocate a
878 * GID_T array of size setlen.
887 setlen
= groups_max();
889 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
890 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
894 if((ngroups
= getgroups(setlen
, group_list
)) < 0) {
895 int saved_errno
= errno
;
896 SAFE_FREE(group_list
);
901 for(i
= 0; i
< ngroups
; i
++)
902 gidset
[i
] = (gid_t
)group_list
[i
];
904 SAFE_FREE(group_list
);
908 static int sys_broken_setgroups(int setlen
, gid_t
*gidset
)
916 if (setlen
< 0 || setlen
> groups_max()) {
922 * Broken case. We need to allocate a
923 * GID_T array of size setlen.
926 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
927 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
931 for(i
= 0; i
< setlen
; i
++)
932 group_list
[i
] = (GID_T
) gidset
[i
];
934 if(setgroups(setlen
, group_list
) != 0) {
935 int saved_errno
= errno
;
936 SAFE_FREE(group_list
);
941 SAFE_FREE(group_list
);
945 #endif /* HAVE_BROKEN_GETGROUPS */
947 /* This is a list of systems that require the first GID passed to setgroups(2)
948 * to be the effective GID. If your system is one of these, add it here.
950 #if defined (FREEBSD) || defined (DARWINOS)
951 #define USE_BSD_SETGROUPS
954 #if defined(USE_BSD_SETGROUPS)
955 /* Depending on the particular BSD implementation, the first GID that is
956 * passed to setgroups(2) will either be ignored or will set the credential's
957 * effective GID. In either case, the right thing to do is to guarantee that
958 * gidset[0] is the effective GID.
960 static int sys_bsd_setgroups(gid_t primary_gid
, int setlen
, const gid_t
*gidset
)
962 gid_t
*new_gidset
= NULL
;
966 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
969 /* No group list, just make sure we are setting the efective GID. */
971 return setgroups(1, &primary_gid
);
974 /* If the primary gid is not the first array element, grow the array
975 * and insert it at the front.
977 if (gidset
[0] != primary_gid
) {
978 new_gidset
= SMB_MALLOC_ARRAY(gid_t
, setlen
+ 1);
979 if (new_gidset
== NULL
) {
983 memcpy(new_gidset
+ 1, gidset
, (setlen
* sizeof(gid_t
)));
984 new_gidset
[0] = primary_gid
;
989 DEBUG(3, ("forced to truncate group list from %d to %d\n",
994 #if defined(HAVE_BROKEN_GETGROUPS)
995 ret
= sys_broken_setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
997 ret
= setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
1002 SAFE_FREE(new_gidset
);
1009 #endif /* USE_BSD_SETGROUPS */
1011 /**************************************************************************
1012 Wrapper for getgroups. Deals with broken (int) case.
1013 ****************************************************************************/
1015 int sys_getgroups(int setlen
, gid_t
*gidset
)
1017 #if defined(HAVE_BROKEN_GETGROUPS)
1018 return sys_broken_getgroups(setlen
, gidset
);
1020 return getgroups(setlen
, gidset
);
1024 /**************************************************************************
1025 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1026 ****************************************************************************/
1028 int sys_setgroups(gid_t
UNUSED(primary_gid
), int setlen
, gid_t
*gidset
)
1030 #if !defined(HAVE_SETGROUPS)
1033 #endif /* HAVE_SETGROUPS */
1035 #if defined(USE_BSD_SETGROUPS)
1036 return sys_bsd_setgroups(primary_gid
, setlen
, gidset
);
1037 #elif defined(HAVE_BROKEN_GETGROUPS)
1038 return sys_broken_setgroups(setlen
, gidset
);
1040 return setgroups(setlen
, gidset
);
1044 /**************************************************************************
1045 Wrappers for setpwent(), getpwent() and endpwent()
1046 ****************************************************************************/
1048 void sys_setpwent(void)
1053 struct passwd
*sys_getpwent(void)
1058 void sys_endpwent(void)
1063 /**************************************************************************
1064 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1065 ****************************************************************************/
1068 struct passwd
*sys_getpwnam(const char *name
)
1070 return getpwnam(name
);
1073 struct passwd
*sys_getpwuid(uid_t uid
)
1075 return getpwuid(uid
);
1078 struct group
*sys_getgrnam(const char *name
)
1080 return getgrnam(name
);
1083 struct group
*sys_getgrgid(gid_t gid
)
1085 return getgrgid(gid
);
1088 /**************************************************************************
1089 Extract a command into an arg list.
1090 ****************************************************************************/
1092 static char **extract_args(TALLOC_CTX
*mem_ctx
, const char *command
)
1101 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1102 DEBUG(0, ("talloc failed\n"));
1106 if(!(ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
))) {
1107 TALLOC_FREE(trunc_cmd
);
1116 for( argcl
= 1; ptr
; ptr
= strtok_r(NULL
, " \t", &saveptr
))
1119 TALLOC_FREE(trunc_cmd
);
1121 if (!(argl
= TALLOC_ARRAY(mem_ctx
, char *, argcl
+ 1))) {
1126 * Now do the extraction.
1129 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1133 ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
);
1136 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1140 while((ptr
= strtok_r(NULL
, " \t", &saveptr
)) != NULL
) {
1142 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1151 DEBUG(0, ("talloc failed\n"));
1152 TALLOC_FREE(trunc_cmd
);
1158 /**************************************************************************
1159 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1160 a sys_getpid() that only does a system call *once*.
1161 ****************************************************************************/
1163 static pid_t mypid
= (pid_t
)-1;
1165 pid_t
sys_fork(void)
1167 pid_t forkret
= fork();
1169 if (forkret
== (pid_t
)0) /* Child - reset mypid so sys_getpid does a system call. */
1175 /**************************************************************************
1176 Wrapper for getpid. Ensures we only do a system call *once*.
1177 ****************************************************************************/
1179 pid_t
sys_getpid(void)
1181 if (mypid
== (pid_t
)-1)
1187 /**************************************************************************
1188 Wrapper for popen. Safer as it doesn't search a path.
1189 Modified from the glibc sources.
1190 modified by tridge to return a file descriptor. We must kick our FILE* habit
1191 ****************************************************************************/
1193 typedef struct _popen_list
1197 struct _popen_list
*next
;
1200 static popen_list
*popen_chain
;
1202 int sys_popen(const char *command
)
1204 int parent_end
, child_end
;
1206 popen_list
*entry
= NULL
;
1209 if (pipe(pipe_fds
) < 0)
1212 parent_end
= pipe_fds
[0];
1213 child_end
= pipe_fds
[1];
1220 if((entry
= SMB_MALLOC_P(popen_list
)) == NULL
)
1223 ZERO_STRUCTP(entry
);
1226 * Extract the command and args into a NULL terminated array.
1229 if(!(argl
= extract_args(NULL
, command
)))
1232 entry
->child_pid
= sys_fork();
1234 if (entry
->child_pid
== -1) {
1238 if (entry
->child_pid
== 0) {
1244 int child_std_end
= STDOUT_FILENO
;
1248 if (child_end
!= child_std_end
) {
1249 dup2 (child_end
, child_std_end
);
1254 * POSIX.2: "popen() shall ensure that any streams from previous
1255 * popen() calls that remain open in the parent process are closed
1256 * in the new child process."
1259 for (p
= popen_chain
; p
; p
= p
->next
)
1262 execv(argl
[0], argl
);
1273 /* Link into popen_chain. */
1274 entry
->next
= popen_chain
;
1275 popen_chain
= entry
;
1276 entry
->fd
= parent_end
;
1289 /**************************************************************************
1290 Wrapper for pclose. Modified from the glibc sources.
1291 ****************************************************************************/
1293 int sys_pclose(int fd
)
1296 popen_list
**ptr
= &popen_chain
;
1297 popen_list
*entry
= NULL
;
1301 /* Unlink from popen_chain. */
1302 for ( ; *ptr
!= NULL
; ptr
= &(*ptr
)->next
) {
1303 if ((*ptr
)->fd
== fd
) {
1305 *ptr
= (*ptr
)->next
;
1311 if (status
< 0 || close(entry
->fd
) < 0)
1315 * As Samba is catching and eating child process
1316 * exits we don't really care about the child exit
1317 * code, a -1 with errno = ECHILD will do fine for us.
1321 wait_pid
= sys_waitpid (entry
->child_pid
, &wstatus
, 0);
1322 } while (wait_pid
== -1 && errno
== EINTR
);
1331 /**************************************************************************
1332 Wrappers for dlopen, dlsym, dlclose.
1333 ****************************************************************************/
1335 void *sys_dlopen(const char *name
, int flags
)
1337 #if defined(HAVE_DLOPEN)
1338 return dlopen(name
, flags
);
1344 void *sys_dlsym(void *handle
, const char *symbol
)
1346 #if defined(HAVE_DLSYM)
1347 return dlsym(handle
, symbol
);
1353 int sys_dlclose (void *handle
)
1355 #if defined(HAVE_DLCLOSE)
1356 return dlclose(handle
);
1362 const char *sys_dlerror(void)
1364 #if defined(HAVE_DLERROR)
1371 int sys_dup2(int oldfd
, int newfd
)
1373 #if defined(HAVE_DUP2)
1374 return dup2(oldfd
, newfd
);
1381 /**************************************************************************
1382 Wrapper for Admin Logs.
1383 ****************************************************************************/
1385 void sys_adminlog(int priority
, const char *format_str
, ...)
1389 char *msgbuf
= NULL
;
1391 va_start( ap
, format_str
);
1392 ret
= vasprintf( &msgbuf
, format_str
, ap
);
1398 #if defined(HAVE_SYSLOG)
1399 syslog( priority
, "%s", msgbuf
);
1401 DEBUG(0,("%s", msgbuf
));
1406 /******** Solaris EA helper function prototypes ********/
1407 #ifdef HAVE_ATTROPEN
1408 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1409 static int solaris_write_xattr(int attrfd
, const char *value
, size_t size
);
1410 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
);
1411 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
);
1412 static int solaris_unlinkat(int attrdirfd
, const char *name
);
1413 static int solaris_attropen(const char *path
, const char *attrpath
, int oflag
, mode_t mode
);
1414 static int solaris_openat(int fildes
, const char *path
, int oflag
, mode_t mode
);
1417 /**************************************************************************
1418 Wrappers for extented attribute calls. Based on the Linux package with
1419 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1420 ****************************************************************************/
1422 ssize_t
sys_getxattr (const char *path
, const char *name
, void *value
, size_t size
)
1424 #if defined(HAVE_GETXATTR)
1425 #ifndef XATTR_ADD_OPT
1426 return getxattr(path
, name
, value
, size
);
1429 return getxattr(path
, name
, value
, size
, 0, options
);
1431 #elif defined(HAVE_GETEA)
1432 return getea(path
, name
, value
, size
);
1433 #elif defined(HAVE_EXTATTR_GET_FILE)
1436 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1437 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1438 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1440 * The BSD implementation has a nasty habit of silently truncating
1441 * the returned value to the size of the buffer, so we have to check
1442 * that the buffer is large enough to fit the returned value.
1444 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1449 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1453 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno
)));
1455 #elif defined(HAVE_ATTR_GET)
1456 int retval
, flags
= 0;
1457 int valuelength
= (int)size
;
1458 char *attrname
= strchr(name
,'.') + 1;
1460 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1462 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1464 return retval
? retval
: valuelength
;
1465 #elif defined(HAVE_ATTROPEN)
1467 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
, 0);
1469 ret
= solaris_read_xattr(attrfd
, value
, size
);
1479 ssize_t
sys_lgetxattr (const char *path
, const char *name
, void *value
, size_t size
)
1481 #if defined(HAVE_LGETXATTR)
1482 return lgetxattr(path
, name
, value
, size
);
1483 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1484 int options
= XATTR_NOFOLLOW
;
1485 return getxattr(path
, name
, value
, size
, 0, options
);
1486 #elif defined(HAVE_LGETEA)
1487 return lgetea(path
, name
, value
, size
);
1488 #elif defined(HAVE_EXTATTR_GET_LINK)
1491 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1492 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1493 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1495 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1500 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1504 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno
)));
1506 #elif defined(HAVE_ATTR_GET)
1507 int retval
, flags
= ATTR_DONTFOLLOW
;
1508 int valuelength
= (int)size
;
1509 char *attrname
= strchr(name
,'.') + 1;
1511 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1513 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1515 return retval
? retval
: valuelength
;
1516 #elif defined(HAVE_ATTROPEN)
1518 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1520 ret
= solaris_read_xattr(attrfd
, value
, size
);
1530 ssize_t
sys_fgetxattr (int filedes
, const char *name
, void *value
, size_t size
)
1532 #if defined(HAVE_FGETXATTR)
1533 #ifndef XATTR_ADD_OPT
1534 return fgetxattr(filedes
, name
, value
, size
);
1537 return fgetxattr(filedes
, name
, value
, size
, 0, options
);
1539 #elif defined(HAVE_FGETEA)
1540 return fgetea(filedes
, name
, value
, size
);
1541 #elif defined(HAVE_EXTATTR_GET_FD)
1544 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1545 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1546 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1548 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1553 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, value
, size
)) >= 0)
1557 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno
)));
1559 #elif defined(HAVE_ATTR_GETF)
1560 int retval
, flags
= 0;
1561 int valuelength
= (int)size
;
1562 char *attrname
= strchr(name
,'.') + 1;
1564 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1566 retval
= attr_getf(filedes
, attrname
, (char *)value
, &valuelength
, flags
);
1568 return retval
? retval
: valuelength
;
1569 #elif defined(HAVE_ATTROPEN)
1571 int attrfd
= solaris_openat(filedes
, name
, O_RDONLY
|O_XATTR
, 0);
1573 ret
= solaris_read_xattr(attrfd
, value
, size
);
1583 #if defined(HAVE_EXTATTR_LIST_FILE)
1585 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1593 { EXTATTR_NAMESPACE_SYSTEM
, EXTATTR_PREFIX("system.") },
1594 { EXTATTR_NAMESPACE_USER
, EXTATTR_PREFIX("user.") },
1602 static ssize_t
bsd_attr_list (int type
, extattr_arg arg
, char *list
, size_t size
)
1604 ssize_t list_size
, total_size
= 0;
1607 /* Iterate through extattr(2) namespaces */
1608 for(t
= 0; t
< (sizeof(extattr
)/sizeof(extattr
[0])); t
++) {
1610 #if defined(HAVE_EXTATTR_LIST_FILE)
1612 list_size
= extattr_list_file(arg
.path
, extattr
[t
].space
, list
, size
);
1615 #if defined(HAVE_EXTATTR_LIST_LINK)
1617 list_size
= extattr_list_link(arg
.path
, extattr
[t
].space
, list
, size
);
1620 #if defined(HAVE_EXTATTR_LIST_FD)
1622 list_size
= extattr_list_fd(arg
.filedes
, extattr
[t
].space
, list
, size
);
1629 /* Some error happend. Errno should be set by the previous call */
1635 /* XXX: Call with an empty buffer may be used to calculate
1636 necessary buffer size. Unfortunately, we can't say, how
1637 many attributes were returned, so here is the potential
1638 problem with the emulation.
1641 /* Take the worse case of one char attribute names -
1642 two bytes per name plus one more for sanity.
1644 total_size
+= list_size
+ (list_size
/2 + 1)*extattr
[t
].len
;
1647 /* Count necessary offset to fit namespace prefixes */
1649 for(i
= 0; i
< list_size
; i
+= list
[i
] + 1)
1650 len
+= extattr
[t
].len
;
1652 total_size
+= list_size
+ len
;
1653 /* Buffer is too small to fit the results */
1654 if(total_size
> size
) {
1658 /* Shift results back, so we can prepend prefixes */
1659 buf
= memmove(list
+ len
, list
, list_size
);
1661 for(i
= 0; i
< list_size
; i
+= len
+ 1) {
1663 strncpy(list
, extattr
[t
].name
, extattr
[t
].len
+ 1);
1664 list
+= extattr
[t
].len
;
1665 strncpy(list
, buf
+ i
+ 1, len
);
1676 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1677 static char attr_buffer
[ATTR_MAX_VALUELEN
];
1679 static ssize_t
irix_attr_list(const char *path
, int filedes
, char *list
, size_t size
, int flags
)
1681 int retval
= 0, index
;
1682 attrlist_cursor_t
*cursor
= 0;
1684 attrlist_t
* al
= (attrlist_t
*)attr_buffer
;
1686 size_t ent_size
, left
= size
;
1691 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1693 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1695 for (index
= 0; index
< al
->al_count
; index
++) {
1696 ae
= ATTR_ENTRY(attr_buffer
, index
);
1697 ent_size
= strlen(ae
->a_name
) + sizeof("user.");
1698 if (left
>= ent_size
) {
1699 strncpy(bp
, "user.", sizeof("user."));
1700 strncat(bp
, ae
->a_name
, ent_size
- sizeof("user."));
1708 total_size
+= ent_size
;
1710 if (al
->al_more
== 0) break;
1717 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1719 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1721 for (index
= 0; index
< al
->al_count
; index
++) {
1722 ae
= ATTR_ENTRY(attr_buffer
, index
);
1723 ent_size
= strlen(ae
->a_name
) + sizeof("system.");
1724 if (left
>= ent_size
) {
1725 strncpy(bp
, "system.", sizeof("system."));
1726 strncat(bp
, ae
->a_name
, ent_size
- sizeof("system."));
1734 total_size
+= ent_size
;
1736 if (al
->al_more
== 0) break;
1739 return (ssize_t
)(retval
? retval
: total_size
);
1744 ssize_t
sys_listxattr (const char *path
, char *list
, size_t size
)
1746 #if defined(HAVE_LISTXATTR)
1747 #ifndef XATTR_ADD_OPT
1748 return listxattr(path
, list
, size
);
1751 return listxattr(path
, list
, size
, options
);
1753 #elif defined(HAVE_LISTEA)
1754 return listea(path
, list
, size
);
1755 #elif defined(HAVE_EXTATTR_LIST_FILE)
1758 return bsd_attr_list(0, arg
, list
, size
);
1759 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1760 return irix_attr_list(path
, 0, list
, size
, 0);
1761 #elif defined(HAVE_ATTROPEN)
1763 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
1764 if (attrdirfd
>= 0) {
1765 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1775 ssize_t
sys_llistxattr (const char *path
, char *list
, size_t size
)
1777 #if defined(HAVE_LLISTXATTR)
1778 return llistxattr(path
, list
, size
);
1779 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1780 int options
= XATTR_NOFOLLOW
;
1781 return listxattr(path
, list
, size
, options
);
1782 #elif defined(HAVE_LLISTEA)
1783 return llistea(path
, list
, size
);
1784 #elif defined(HAVE_EXTATTR_LIST_LINK)
1787 return bsd_attr_list(1, arg
, list
, size
);
1788 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1789 return irix_attr_list(path
, 0, list
, size
, ATTR_DONTFOLLOW
);
1790 #elif defined(HAVE_ATTROPEN)
1792 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1793 if (attrdirfd
>= 0) {
1794 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1804 ssize_t
sys_flistxattr (int filedes
, char *list
, size_t size
)
1806 #if defined(HAVE_FLISTXATTR)
1807 #ifndef XATTR_ADD_OPT
1808 return flistxattr(filedes
, list
, size
);
1811 return flistxattr(filedes
, list
, size
, options
);
1813 #elif defined(HAVE_FLISTEA)
1814 return flistea(filedes
, list
, size
);
1815 #elif defined(HAVE_EXTATTR_LIST_FD)
1817 arg
.filedes
= filedes
;
1818 return bsd_attr_list(2, arg
, list
, size
);
1819 #elif defined(HAVE_ATTR_LISTF)
1820 return irix_attr_list(NULL
, filedes
, list
, size
, 0);
1821 #elif defined(HAVE_ATTROPEN)
1823 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
1824 if (attrdirfd
>= 0) {
1825 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1835 int sys_removexattr (const char *path
, const char *name
)
1837 #if defined(HAVE_REMOVEXATTR)
1838 #ifndef XATTR_ADD_OPT
1839 return removexattr(path
, name
);
1842 return removexattr(path
, name
, options
);
1844 #elif defined(HAVE_REMOVEEA)
1845 return removeea(path
, name
);
1846 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1848 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1849 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1850 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1852 return extattr_delete_file(path
, attrnamespace
, attrname
);
1853 #elif defined(HAVE_ATTR_REMOVE)
1855 char *attrname
= strchr(name
,'.') + 1;
1857 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1859 return attr_remove(path
, attrname
, flags
);
1860 #elif defined(HAVE_ATTROPEN)
1862 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
1863 if (attrdirfd
>= 0) {
1864 ret
= solaris_unlinkat(attrdirfd
, name
);
1874 int sys_lremovexattr (const char *path
, const char *name
)
1876 #if defined(HAVE_LREMOVEXATTR)
1877 return lremovexattr(path
, name
);
1878 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1879 int options
= XATTR_NOFOLLOW
;
1880 return removexattr(path
, name
, options
);
1881 #elif defined(HAVE_LREMOVEEA)
1882 return lremoveea(path
, name
);
1883 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1885 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1886 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1887 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1889 return extattr_delete_link(path
, attrnamespace
, attrname
);
1890 #elif defined(HAVE_ATTR_REMOVE)
1891 int flags
= ATTR_DONTFOLLOW
;
1892 char *attrname
= strchr(name
,'.') + 1;
1894 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1896 return attr_remove(path
, attrname
, flags
);
1897 #elif defined(HAVE_ATTROPEN)
1899 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1900 if (attrdirfd
>= 0) {
1901 ret
= solaris_unlinkat(attrdirfd
, name
);
1911 int sys_fremovexattr (int filedes
, const char *name
)
1913 #if defined(HAVE_FREMOVEXATTR)
1914 #ifndef XATTR_ADD_OPT
1915 return fremovexattr(filedes
, name
);
1918 return fremovexattr(filedes
, name
, options
);
1920 #elif defined(HAVE_FREMOVEEA)
1921 return fremoveea(filedes
, name
);
1922 #elif defined(HAVE_EXTATTR_DELETE_FD)
1924 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1925 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1926 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1928 return extattr_delete_fd(filedes
, attrnamespace
, attrname
);
1929 #elif defined(HAVE_ATTR_REMOVEF)
1931 char *attrname
= strchr(name
,'.') + 1;
1933 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1935 return attr_removef(filedes
, attrname
, flags
);
1936 #elif defined(HAVE_ATTROPEN)
1938 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
1939 if (attrdirfd
>= 0) {
1940 ret
= solaris_unlinkat(attrdirfd
, name
);
1950 int sys_setxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
1952 #if defined(HAVE_SETXATTR)
1953 #ifndef XATTR_ADD_OPT
1954 return setxattr(path
, name
, value
, size
, flags
);
1957 return setxattr(path
, name
, value
, size
, 0, options
);
1959 #elif defined(HAVE_SETEA)
1960 return setea(path
, name
, value
, size
, flags
);
1961 #elif defined(HAVE_EXTATTR_SET_FILE)
1964 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1965 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1966 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1968 /* Check attribute existence */
1969 retval
= extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0);
1971 /* REPLACE attribute, that doesn't exist */
1972 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
1976 /* Ignore other errors */
1979 /* CREATE attribute, that already exists */
1980 if (flags
& XATTR_CREATE
) {
1986 retval
= extattr_set_file(path
, attrnamespace
, attrname
, value
, size
);
1987 return (retval
< 0) ? -1 : 0;
1988 #elif defined(HAVE_ATTR_SET)
1990 char *attrname
= strchr(name
,'.') + 1;
1992 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
1993 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
1994 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
1996 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
1997 #elif defined(HAVE_ATTROPEN)
1999 int myflags
= O_RDWR
;
2001 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2002 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2003 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2005 ret
= solaris_write_xattr(attrfd
, value
, size
);
2015 int sys_lsetxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2017 #if defined(HAVE_LSETXATTR)
2018 return lsetxattr(path
, name
, value
, size
, flags
);
2019 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2020 int options
= XATTR_NOFOLLOW
;
2021 return setxattr(path
, name
, value
, size
, 0, options
);
2022 #elif defined(LSETEA)
2023 return lsetea(path
, name
, value
, size
, flags
);
2024 #elif defined(HAVE_EXTATTR_SET_LINK)
2027 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2028 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2029 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2031 /* Check attribute existence */
2032 retval
= extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0);
2034 /* REPLACE attribute, that doesn't exist */
2035 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
2039 /* Ignore other errors */
2042 /* CREATE attribute, that already exists */
2043 if (flags
& XATTR_CREATE
) {
2050 retval
= extattr_set_link(path
, attrnamespace
, attrname
, value
, size
);
2051 return (retval
< 0) ? -1 : 0;
2052 #elif defined(HAVE_ATTR_SET)
2053 int myflags
= ATTR_DONTFOLLOW
;
2054 char *attrname
= strchr(name
,'.') + 1;
2056 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
2057 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
2058 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
2060 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
2061 #elif defined(HAVE_ATTROPEN)
2063 int myflags
= O_RDWR
| AT_SYMLINK_NOFOLLOW
;
2065 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2066 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2067 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2069 ret
= solaris_write_xattr(attrfd
, value
, size
);
2079 int sys_fsetxattr (int filedes
, const char *name
, const void *value
, size_t size
, int flags
)
2081 #if defined(HAVE_FSETXATTR)
2082 #ifndef XATTR_ADD_OPT
2083 return fsetxattr(filedes
, name
, value
, size
, flags
);
2086 return fsetxattr(filedes
, name
, value
, size
, 0, options
);
2088 #elif defined(HAVE_FSETEA)
2089 return fsetea(filedes
, name
, value
, size
, flags
);
2090 #elif defined(HAVE_EXTATTR_SET_FD)
2093 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
2094 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
2095 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
2097 /* Check attribute existence */
2098 retval
= extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0);
2100 /* REPLACE attribute, that doesn't exist */
2101 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
2105 /* Ignore other errors */
2108 /* CREATE attribute, that already exists */
2109 if (flags
& XATTR_CREATE
) {
2115 retval
= extattr_set_fd(filedes
, attrnamespace
, attrname
, value
, size
);
2116 return (retval
< 0) ? -1 : 0;
2117 #elif defined(HAVE_ATTR_SETF)
2119 char *attrname
= strchr(name
,'.') + 1;
2121 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
2122 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
2123 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
2125 return attr_setf(filedes
, attrname
, (const char *)value
, size
, myflags
);
2126 #elif defined(HAVE_ATTROPEN)
2128 int myflags
= O_RDWR
| O_XATTR
;
2130 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
2131 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
2132 attrfd
= solaris_openat(filedes
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
2134 ret
= solaris_write_xattr(attrfd
, value
, size
);
2144 /**************************************************************************
2145 helper functions for Solaris' EA support
2146 ****************************************************************************/
2147 #ifdef HAVE_ATTROPEN
2148 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
)
2152 if (fstat(attrfd
, &sbuf
) == -1) {
2157 /* This is to return the current size of the named extended attribute */
2159 return sbuf
.st_size
;
2162 /* check size and read xattr */
2163 if (sbuf
.st_size
> size
) {
2168 return read(attrfd
, value
, sbuf
.st_size
);
2171 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
)
2177 int newfd
= dup(attrdirfd
);
2178 /* CAUTION: The originating file descriptor should not be
2179 used again following the call to fdopendir().
2180 For that reason we dup() the file descriptor
2181 here to make things more clear. */
2182 dirp
= fdopendir(newfd
);
2184 while ((de
= readdir(dirp
))) {
2185 size_t listlen
= strlen(de
->d_name
);
2186 if (!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, "..")) {
2187 /* we don't want "." and ".." here: */
2188 DEBUG(10,("skipped EA %s\n",de
->d_name
));
2193 /* return the current size of the list of extended attribute names*/
2196 /* check size and copy entrieѕ + nul into list. */
2197 if ((len
+ listlen
+ 1) > size
) {
2202 safe_strcpy(list
+ len
, de
->d_name
, listlen
);
2210 if (closedir(dirp
) == -1) {
2211 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno
)));
2217 static int solaris_unlinkat(int attrdirfd
, const char *name
)
2219 if (unlinkat(attrdirfd
, name
, 0) == -1) {
2220 if (errno
== ENOENT
) {
2228 static int solaris_attropen(const char *path
, const char *attrpath
, int oflag
, mode_t mode
)
2230 int filedes
= attropen(path
, attrpath
, oflag
, mode
);
2231 if (filedes
== -1) {
2232 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path
,attrpath
,strerror(errno
)));
2233 if (errno
== EINVAL
) {
2242 static int solaris_openat(int fildes
, const char *path
, int oflag
, mode_t mode
)
2244 int filedes
= openat(fildes
, path
, oflag
, mode
);
2245 if (filedes
== -1) {
2246 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes
,path
,strerror(errno
)));
2247 if (errno
== EINVAL
) {
2256 static int solaris_write_xattr(int attrfd
, const char *value
, size_t size
)
2258 if ((ftruncate(attrfd
, 0) == 0) && (write(attrfd
, value
, size
) == size
)) {
2261 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2265 #endif /*HAVE_ATTROPEN*/
2268 /****************************************************************************
2269 Return the major devicenumber for UNIX extensions.
2270 ****************************************************************************/
2272 uint32
unix_dev_major(SMB_DEV_T dev
)
2274 #if defined(HAVE_DEVICE_MAJOR_FN)
2275 return (uint32
)major(dev
);
2277 return (uint32
)(dev
>> 8);
2281 /****************************************************************************
2282 Return the minor devicenumber for UNIX extensions.
2283 ****************************************************************************/
2285 uint32
unix_dev_minor(SMB_DEV_T dev
)
2287 #if defined(HAVE_DEVICE_MINOR_FN)
2288 return (uint32
)minor(dev
);
2290 return (uint32
)(dev
& 0xff);
2294 #if defined(WITH_AIO)
2296 /*******************************************************************
2297 An aio_read wrapper that will deal with 64-bit sizes.
2298 ********************************************************************/
2300 int sys_aio_read(SMB_STRUCT_AIOCB
*aiocb
)
2302 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2303 return aio_read64(aiocb
);
2304 #elif defined(HAVE_AIO_READ)
2305 return aio_read(aiocb
);
2312 /*******************************************************************
2313 An aio_write wrapper that will deal with 64-bit sizes.
2314 ********************************************************************/
2316 int sys_aio_write(SMB_STRUCT_AIOCB
*aiocb
)
2318 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2319 return aio_write64(aiocb
);
2320 #elif defined(HAVE_AIO_WRITE)
2321 return aio_write(aiocb
);
2328 /*******************************************************************
2329 An aio_return wrapper that will deal with 64-bit sizes.
2330 ********************************************************************/
2332 ssize_t
sys_aio_return(SMB_STRUCT_AIOCB
*aiocb
)
2334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2335 return aio_return64(aiocb
);
2336 #elif defined(HAVE_AIO_RETURN)
2337 return aio_return(aiocb
);
2344 /*******************************************************************
2345 An aio_cancel wrapper that will deal with 64-bit sizes.
2346 ********************************************************************/
2348 int sys_aio_cancel(int fd
, SMB_STRUCT_AIOCB
*aiocb
)
2350 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2351 return aio_cancel64(fd
, aiocb
);
2352 #elif defined(HAVE_AIO_CANCEL)
2353 return aio_cancel(fd
, aiocb
);
2360 /*******************************************************************
2361 An aio_error wrapper that will deal with 64-bit sizes.
2362 ********************************************************************/
2364 int sys_aio_error(const SMB_STRUCT_AIOCB
*aiocb
)
2366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2367 return aio_error64(aiocb
);
2368 #elif defined(HAVE_AIO_ERROR)
2369 return aio_error(aiocb
);
2376 /*******************************************************************
2377 An aio_fsync wrapper that will deal with 64-bit sizes.
2378 ********************************************************************/
2380 int sys_aio_fsync(int op
, SMB_STRUCT_AIOCB
*aiocb
)
2382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2383 return aio_fsync64(op
, aiocb
);
2384 #elif defined(HAVE_AIO_FSYNC)
2385 return aio_fsync(op
, aiocb
);
2392 /*******************************************************************
2393 An aio_fsync wrapper that will deal with 64-bit sizes.
2394 ********************************************************************/
2396 int sys_aio_suspend(const SMB_STRUCT_AIOCB
* const cblist
[], int n
, const struct timespec
*timeout
)
2398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2399 return aio_suspend64(cblist
, n
, timeout
);
2400 #elif defined(HAVE_AIO_FSYNC)
2401 return aio_suspend(cblist
, n
, timeout
);
2407 #else /* !WITH_AIO */
2409 int sys_aio_read(SMB_STRUCT_AIOCB
*aiocb
)
2415 int sys_aio_write(SMB_STRUCT_AIOCB
*aiocb
)
2421 ssize_t
sys_aio_return(SMB_STRUCT_AIOCB
*aiocb
)
2427 int sys_aio_cancel(int fd
, SMB_STRUCT_AIOCB
*aiocb
)
2433 int sys_aio_error(const SMB_STRUCT_AIOCB
*aiocb
)
2439 int sys_aio_fsync(int op
, SMB_STRUCT_AIOCB
*aiocb
)
2445 int sys_aio_suspend(const SMB_STRUCT_AIOCB
* const cblist
[], int n
, const struct timespec
*timeout
)
2450 #endif /* WITH_AIO */
2452 int sys_getpeereid( int s
, uid_t
*uid
)
2454 #if defined(HAVE_PEERCRED)
2456 socklen_t cred_len
= sizeof(struct ucred
);
2459 ret
= getsockopt(s
, SOL_SOCKET
, SO_PEERCRED
, (void *)&cred
, &cred_len
);
2464 if (cred_len
!= sizeof(struct ucred
)) {
2477 int sys_getnameinfo(const struct sockaddr
*psa
,
2486 * For Solaris we must make sure salen is the
2487 * correct length for the incoming sa_family.
2490 if (salen
== sizeof(struct sockaddr_storage
)) {
2491 salen
= sizeof(struct sockaddr_in
);
2492 #if defined(HAVE_IPV6)
2493 if (psa
->sa_family
== AF_INET6
) {
2494 salen
= sizeof(struct sockaddr_in6
);
2498 return getnameinfo(psa
, salen
, host
, hostlen
, service
, servlen
, flags
);
2501 int sys_connect(int fd
, const struct sockaddr
* addr
)
2503 socklen_t salen
= -1;
2505 if (addr
->sa_family
== AF_INET
) {
2506 salen
= sizeof(struct sockaddr_in
);
2507 } else if (addr
->sa_family
== AF_UNIX
) {
2508 salen
= sizeof(struct sockaddr_un
);
2510 #if defined(HAVE_IPV6)
2511 else if (addr
->sa_family
== AF_INET6
) {
2512 salen
= sizeof(struct sockaddr_in6
);
2516 return connect(fd
, addr
, salen
);