2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2005
6 Copyright (C) Timur Bakeyev 2005
7 Copyright (C) Bjoern Jacke 2006-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
39 - to support the philosophy of Samba to expose the features of
40 the OS within the SMB model. In general whatever file/printer/variable
41 expansions/etc make sense to the OS should be acceptable to Samba.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align
, size_t size
)
52 #if defined(HAVE_POSIX_MEMALIGN)
54 int ret
= posix_memalign( &p
, align
, size
);
59 #elif defined(HAVE_MEMALIGN)
60 return memalign( align
, size
);
62 /* On *BSD systems memaligns doesn't exist, but memory will
63 * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65 size_t pagesize
= (size_t)sysconf(_SC_PAGESIZE
);
66 #elif defined(HAVE_GETPAGESIZE)
67 size_t pagesize
= (size_t)getpagesize();
69 size_t pagesize
= (size_t)-1;
71 if (pagesize
== (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
75 if (size
< pagesize
) {
78 return SMB_MALLOC(size
);
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs
)
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs
< 0 || usecs
> 999999) {
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
110 tval
.tv_usec
= usecs
/1000;
111 select(0,NULL
,NULL
,NULL
,&tval
);
113 #endif /* HAVE_USLEEP */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t
sys_read(int fd
, void *buf
, size_t count
)
125 ret
= read(fd
, buf
, count
);
126 } while (ret
== -1 && errno
== EINTR
);
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
134 ssize_t
sys_write(int fd
, const void *buf
, size_t count
)
139 ret
= write(fd
, buf
, count
);
140 } while (ret
== -1 && errno
== EINTR
);
144 /*******************************************************************
145 A writev wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t
sys_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
153 /* Try to confuse write_data_iov a bit */
154 if ((random() % 5) == 0) {
155 return sys_write(fd
, iov
[0].iov_base
, iov
[0].iov_len
);
157 if (iov
[0].iov_len
> 1) {
158 return sys_write(fd
, iov
[0].iov_base
,
159 (random() % (iov
[0].iov_len
-1)) + 1);
164 ret
= writev(fd
, iov
, iovcnt
);
165 } while (ret
== -1 && errno
== EINTR
);
169 /*******************************************************************
170 A pread wrapper that will deal with EINTR and 64-bit file offsets.
171 ********************************************************************/
173 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174 ssize_t
sys_pread(int fd
, void *buf
, size_t count
, SMB_OFF_T off
)
179 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
180 ret
= pread64(fd
, buf
, count
, off
);
182 ret
= pread(fd
, buf
, count
, off
);
184 } while (ret
== -1 && errno
== EINTR
);
189 /*******************************************************************
190 A write wrapper that will deal with EINTR and 64-bit file offsets.
191 ********************************************************************/
193 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194 ssize_t
sys_pwrite(int fd
, const void *buf
, size_t count
, SMB_OFF_T off
)
199 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
200 ret
= pwrite64(fd
, buf
, count
, off
);
202 ret
= pwrite(fd
, buf
, count
, off
);
204 } while (ret
== -1 && errno
== EINTR
);
209 /*******************************************************************
210 A send wrapper that will deal with EINTR.
211 ********************************************************************/
213 ssize_t
sys_send(int s
, const void *msg
, size_t len
, int flags
)
218 ret
= send(s
, msg
, len
, flags
);
219 } while (ret
== -1 && errno
== EINTR
);
223 /*******************************************************************
224 A sendto wrapper that will deal with EINTR.
225 ********************************************************************/
227 ssize_t
sys_sendto(int s
, const void *msg
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
232 ret
= sendto(s
, msg
, len
, flags
, to
, tolen
);
233 } while (ret
== -1 && errno
== EINTR
);
237 /*******************************************************************
238 A recv wrapper that will deal with EINTR.
239 ********************************************************************/
241 ssize_t
sys_recv(int fd
, void *buf
, size_t count
, int flags
)
246 ret
= recv(fd
, buf
, count
, flags
);
247 } while (ret
== -1 && errno
== EINTR
);
251 /*******************************************************************
252 A recvfrom wrapper that will deal with EINTR.
253 ********************************************************************/
255 ssize_t
sys_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
260 ret
= recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
261 } while (ret
== -1 && errno
== EINTR
);
265 /*******************************************************************
266 A fcntl wrapper that will deal with EINTR.
267 ********************************************************************/
269 int sys_fcntl_ptr(int fd
, int cmd
, void *arg
)
274 ret
= fcntl(fd
, cmd
, arg
);
275 } while (ret
== -1 && errno
== EINTR
);
279 /*******************************************************************
280 A fcntl wrapper that will deal with EINTR.
281 ********************************************************************/
283 int sys_fcntl_long(int fd
, int cmd
, long arg
)
288 ret
= fcntl(fd
, cmd
, arg
);
289 } while (ret
== -1 && errno
== EINTR
);
293 /*******************************************************************
294 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 The wait() calls vary between systems
567 ********************************************************************/
569 int sys_waitpid(pid_t pid
,int *status
,int options
)
572 return waitpid(pid
,status
,options
);
573 #else /* HAVE_WAITPID */
574 return wait4(pid
, status
, options
, NULL
);
575 #endif /* HAVE_WAITPID */
578 /*******************************************************************
579 System wrapper for getwd
580 ********************************************************************/
582 char *sys_getwd(char *s
)
586 wd
= (char *)getcwd(s
, PATH_MAX
);
588 wd
= (char *)getwd(s
);
593 #if defined(HAVE_POSIX_CAPABILITIES)
595 /* This define hasn't made it into the glibc capabilities header yet. */
596 #ifndef SECURE_NO_SETUID_FIXUP
597 #define SECURE_NO_SETUID_FIXUP 2
600 /**************************************************************************
601 Try and abstract process capabilities (for systems that have them).
602 ****************************************************************************/
604 /* Set the POSIX capabilities needed for the given purpose into the effective
605 * capability set of the current process. Make sure they are always removed
606 * from the inheritable set, because there is no circumstance in which our
607 * children should inherit our elevated privileges.
609 static bool set_process_capability(enum smbd_capability capability
,
612 cap_value_t cap_vals
[2] = {0};
613 int num_cap_vals
= 0;
617 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
618 /* On Linux, make sure that any capabilities we grab are sticky
619 * across UID changes. We expect that this would allow us to keep both
620 * the effective and permitted capability sets, but as of circa 2.6.16,
621 * only the permitted set is kept. It is a bug (which we work around)
622 * that the effective set is lost, but we still require the effective
625 if (!prctl(PR_GET_KEEPCAPS
)) {
626 prctl(PR_SET_KEEPCAPS
, 1);
630 #if defined(HAVE_PRCTL) && defined(PR_SET_SECUREBITS) && defined(SECURE_NO_SETUID_FIXUP)
631 /* New way of setting capabilities as "sticky". */
634 * Use PR_SET_SECUREBITS to prevent setresuid()
635 * atomically dropping effective capabilities on
636 * uid change. Only available in Linux kernels
640 * http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html
643 * Specifically the CAP_KILL capability we need
644 * to allow Linux threads under different euids
645 * to send signals to each other.
648 if (prctl(PR_SET_SECUREBITS
, 1 << SECURE_NO_SETUID_FIXUP
)) {
649 DEBUG(0,("set_process_capability: "
650 "prctl PR_SET_SECUREBITS failed with error %s\n",
656 cap
= cap_get_proc();
658 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
663 switch (capability
) {
664 case KERNEL_OPLOCK_CAPABILITY
:
665 #ifdef CAP_NETWORK_MGT
666 /* IRIX has CAP_NETWORK_MGT for oplocks. */
667 cap_vals
[num_cap_vals
++] = CAP_NETWORK_MGT
;
670 case DMAPI_ACCESS_CAPABILITY
:
671 #ifdef CAP_DEVICE_MGT
672 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
673 cap_vals
[num_cap_vals
++] = CAP_DEVICE_MGT
;
675 /* Linux has CAP_MKNOD for DMAPI access. */
676 cap_vals
[num_cap_vals
++] = CAP_MKNOD
;
679 case LEASE_CAPABILITY
:
681 cap_vals
[num_cap_vals
++] = CAP_LEASE
;
684 case KILL_CAPABILITY
:
686 cap_vals
[num_cap_vals
++] = CAP_KILL
;
691 SMB_ASSERT(num_cap_vals
<= ARRAY_SIZE(cap_vals
));
693 if (num_cap_vals
== 0) {
699 * Ensure the capability is effective. We assume that as a root
700 * process it's always permitted.
703 if (cap_set_flag(cap
, CAP_EFFECTIVE
, num_cap_vals
, cap_vals
,
704 enable
? CAP_SET
: CAP_CLEAR
) == -1) {
705 DEBUG(0, ("set_process_capability: cap_set_flag effective "
713 /* We never want to pass capabilities down to our children, so make
714 * sure they are not inherited.
716 if (cap_set_flag(cap
, CAP_INHERITABLE
, num_cap_vals
,
717 cap_vals
, CAP_CLEAR
) == -1) {
718 DEBUG(0, ("set_process_capability: cap_set_flag inheritable "
726 if (cap_set_proc(cap
) == -1) {
727 DEBUG(0, ("set_process_capability: cap_set_flag (%d) failed: %s\n",
738 #endif /* HAVE_POSIX_CAPABILITIES */
740 /****************************************************************************
741 Gain the oplock capability from the kernel if possible.
742 ****************************************************************************/
744 void set_effective_capability(enum smbd_capability capability
)
746 #if defined(HAVE_POSIX_CAPABILITIES)
747 set_process_capability(capability
, True
);
748 #endif /* HAVE_POSIX_CAPABILITIES */
751 void drop_effective_capability(enum smbd_capability capability
)
753 #if defined(HAVE_POSIX_CAPABILITIES)
754 set_process_capability(capability
, False
);
755 #endif /* HAVE_POSIX_CAPABILITIES */
758 /**************************************************************************
759 Wrapper for random().
760 ****************************************************************************/
762 long sys_random(void)
764 #if defined(HAVE_RANDOM)
765 return (long)random();
766 #elif defined(HAVE_RAND)
769 DEBUG(0,("Error - no random function available !\n"));
774 /**************************************************************************
775 Wrapper for srandom().
776 ****************************************************************************/
778 void sys_srandom(unsigned int seed
)
780 #if defined(HAVE_SRANDOM)
782 #elif defined(HAVE_SRAND)
785 DEBUG(0,("Error - no srandom function available !\n"));
790 /**************************************************************************
791 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
792 ****************************************************************************/
796 #if defined(SYSCONF_SC_NGROUPS_MAX)
797 int ret
= sysconf(_SC_NGROUPS_MAX
);
798 return (ret
== -1) ? NGROUPS_MAX
: ret
;
804 /**************************************************************************
805 Wrap setgroups and getgroups for systems that declare getgroups() as
806 returning an array of gid_t, but actuall return an array of int.
807 ****************************************************************************/
809 #if defined(HAVE_BROKEN_GETGROUPS)
810 static int sys_broken_getgroups(int setlen
, gid_t
*gidset
)
817 return getgroups(setlen
, &gid
);
821 * Broken case. We need to allocate a
822 * GID_T array of size setlen.
831 setlen
= groups_max();
833 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
834 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
838 if((ngroups
= getgroups(setlen
, group_list
)) < 0) {
839 int saved_errno
= errno
;
840 SAFE_FREE(group_list
);
845 for(i
= 0; i
< ngroups
; i
++)
846 gidset
[i
] = (gid_t
)group_list
[i
];
848 SAFE_FREE(group_list
);
852 static int sys_broken_setgroups(int setlen
, gid_t
*gidset
)
860 if (setlen
< 0 || setlen
> groups_max()) {
866 * Broken case. We need to allocate a
867 * GID_T array of size setlen.
870 if((group_list
= SMB_MALLOC_ARRAY(GID_T
, setlen
)) == NULL
) {
871 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
875 for(i
= 0; i
< setlen
; i
++)
876 group_list
[i
] = (GID_T
) gidset
[i
];
878 if(setgroups(setlen
, group_list
) != 0) {
879 int saved_errno
= errno
;
880 SAFE_FREE(group_list
);
885 SAFE_FREE(group_list
);
889 #endif /* HAVE_BROKEN_GETGROUPS */
891 /* This is a list of systems that require the first GID passed to setgroups(2)
892 * to be the effective GID. If your system is one of these, add it here.
894 #if defined (FREEBSD) || defined (DARWINOS)
895 #define USE_BSD_SETGROUPS
898 #if defined(USE_BSD_SETGROUPS)
899 /* Depending on the particular BSD implementation, the first GID that is
900 * passed to setgroups(2) will either be ignored or will set the credential's
901 * effective GID. In either case, the right thing to do is to guarantee that
902 * gidset[0] is the effective GID.
904 static int sys_bsd_setgroups(gid_t primary_gid
, int setlen
, const gid_t
*gidset
)
906 gid_t
*new_gidset
= NULL
;
910 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
913 /* No group list, just make sure we are setting the efective GID. */
915 return setgroups(1, &primary_gid
);
918 /* If the primary gid is not the first array element, grow the array
919 * and insert it at the front.
921 if (gidset
[0] != primary_gid
) {
922 new_gidset
= SMB_MALLOC_ARRAY(gid_t
, setlen
+ 1);
923 if (new_gidset
== NULL
) {
927 memcpy(new_gidset
+ 1, gidset
, (setlen
* sizeof(gid_t
)));
928 new_gidset
[0] = primary_gid
;
933 DEBUG(3, ("forced to truncate group list from %d to %d\n",
938 #if defined(HAVE_BROKEN_GETGROUPS)
939 ret
= sys_broken_setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
941 ret
= setgroups(setlen
, new_gidset
? new_gidset
: gidset
);
946 SAFE_FREE(new_gidset
);
953 #endif /* USE_BSD_SETGROUPS */
955 /**************************************************************************
956 Wrapper for getgroups. Deals with broken (int) case.
957 ****************************************************************************/
959 int sys_getgroups(int setlen
, gid_t
*gidset
)
961 #if defined(HAVE_BROKEN_GETGROUPS)
962 return sys_broken_getgroups(setlen
, gidset
);
964 return getgroups(setlen
, gidset
);
968 /**************************************************************************
969 Wrapper for setgroups. Deals with broken (int) case and BSD case.
970 ****************************************************************************/
972 int sys_setgroups(gid_t
UNUSED(primary_gid
), int setlen
, gid_t
*gidset
)
974 #if !defined(HAVE_SETGROUPS)
977 #endif /* HAVE_SETGROUPS */
979 #if defined(USE_BSD_SETGROUPS)
980 return sys_bsd_setgroups(primary_gid
, setlen
, gidset
);
981 #elif defined(HAVE_BROKEN_GETGROUPS)
982 return sys_broken_setgroups(setlen
, gidset
);
984 return setgroups(setlen
, gidset
);
988 /**************************************************************************
989 Wrappers for setpwent(), getpwent() and endpwent()
990 ****************************************************************************/
992 void sys_setpwent(void)
997 struct passwd
*sys_getpwent(void)
1002 void sys_endpwent(void)
1007 /**************************************************************************
1008 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1009 ****************************************************************************/
1012 struct passwd
*sys_getpwnam(const char *name
)
1014 return getpwnam(name
);
1017 struct passwd
*sys_getpwuid(uid_t uid
)
1019 return getpwuid(uid
);
1022 struct group
*sys_getgrnam(const char *name
)
1024 return getgrnam(name
);
1027 struct group
*sys_getgrgid(gid_t gid
)
1029 return getgrgid(gid
);
1032 /**************************************************************************
1033 Extract a command into an arg list.
1034 ****************************************************************************/
1036 static char **extract_args(TALLOC_CTX
*mem_ctx
, const char *command
)
1045 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1046 DEBUG(0, ("talloc failed\n"));
1050 if(!(ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
))) {
1051 TALLOC_FREE(trunc_cmd
);
1060 for( argcl
= 1; ptr
; ptr
= strtok_r(NULL
, " \t", &saveptr
))
1063 TALLOC_FREE(trunc_cmd
);
1065 if (!(argl
= TALLOC_ARRAY(mem_ctx
, char *, argcl
+ 1))) {
1070 * Now do the extraction.
1073 if (!(trunc_cmd
= talloc_strdup(mem_ctx
, command
))) {
1077 ptr
= strtok_r(trunc_cmd
, " \t", &saveptr
);
1080 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1084 while((ptr
= strtok_r(NULL
, " \t", &saveptr
)) != NULL
) {
1086 if (!(argl
[i
++] = talloc_strdup(argl
, ptr
))) {
1095 DEBUG(0, ("talloc failed\n"));
1096 TALLOC_FREE(trunc_cmd
);
1102 /**************************************************************************
1103 Wrapper for popen. Safer as it doesn't search a path.
1104 Modified from the glibc sources.
1105 modified by tridge to return a file descriptor. We must kick our FILE* habit
1106 ****************************************************************************/
1108 typedef struct _popen_list
1112 struct _popen_list
*next
;
1115 static popen_list
*popen_chain
;
1117 int sys_popen(const char *command
)
1119 int parent_end
, child_end
;
1121 popen_list
*entry
= NULL
;
1124 if (pipe(pipe_fds
) < 0)
1127 parent_end
= pipe_fds
[0];
1128 child_end
= pipe_fds
[1];
1135 if((entry
= SMB_MALLOC_P(popen_list
)) == NULL
)
1138 ZERO_STRUCTP(entry
);
1141 * Extract the command and args into a NULL terminated array.
1144 if(!(argl
= extract_args(NULL
, command
)))
1147 entry
->child_pid
= sys_fork();
1149 if (entry
->child_pid
== -1) {
1153 if (entry
->child_pid
== 0) {
1159 int child_std_end
= STDOUT_FILENO
;
1163 if (child_end
!= child_std_end
) {
1164 dup2 (child_end
, child_std_end
);
1169 * POSIX.2: "popen() shall ensure that any streams from previous
1170 * popen() calls that remain open in the parent process are closed
1171 * in the new child process."
1174 for (p
= popen_chain
; p
; p
= p
->next
)
1177 execv(argl
[0], argl
);
1188 /* Link into popen_chain. */
1189 entry
->next
= popen_chain
;
1190 popen_chain
= entry
;
1191 entry
->fd
= parent_end
;
1204 /**************************************************************************
1205 Wrapper for pclose. Modified from the glibc sources.
1206 ****************************************************************************/
1208 int sys_pclose(int fd
)
1211 popen_list
**ptr
= &popen_chain
;
1212 popen_list
*entry
= NULL
;
1216 /* Unlink from popen_chain. */
1217 for ( ; *ptr
!= NULL
; ptr
= &(*ptr
)->next
) {
1218 if ((*ptr
)->fd
== fd
) {
1220 *ptr
= (*ptr
)->next
;
1226 if (status
< 0 || close(entry
->fd
) < 0)
1230 * As Samba is catching and eating child process
1231 * exits we don't really care about the child exit
1232 * code, a -1 with errno = ECHILD will do fine for us.
1236 wait_pid
= sys_waitpid (entry
->child_pid
, &wstatus
, 0);
1237 } while (wait_pid
== -1 && errno
== EINTR
);
1246 /**************************************************************************
1247 Wrapper for Admin Logs.
1248 ****************************************************************************/
1250 void sys_adminlog(int priority
, const char *format_str
, ...)
1254 char *msgbuf
= NULL
;
1256 va_start( ap
, format_str
);
1257 ret
= vasprintf( &msgbuf
, format_str
, ap
);
1263 #if defined(HAVE_SYSLOG)
1264 syslog( priority
, "%s", msgbuf
);
1266 DEBUG(0,("%s", msgbuf
));
1271 /******** Solaris EA helper function prototypes ********/
1272 #ifdef HAVE_ATTROPEN
1273 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1274 static int solaris_write_xattr(int attrfd
, const char *value
, size_t size
);
1275 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
);
1276 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
);
1277 static int solaris_unlinkat(int attrdirfd
, const char *name
);
1278 static int solaris_attropen(const char *path
, const char *attrpath
, int oflag
, mode_t mode
);
1279 static int solaris_openat(int fildes
, const char *path
, int oflag
, mode_t mode
);
1282 /**************************************************************************
1283 Wrappers for extented attribute calls. Based on the Linux package with
1284 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1285 ****************************************************************************/
1287 ssize_t
sys_getxattr (const char *path
, const char *name
, void *value
, size_t size
)
1289 #if defined(HAVE_GETXATTR)
1290 #ifndef XATTR_ADD_OPT
1291 return getxattr(path
, name
, value
, size
);
1294 return getxattr(path
, name
, value
, size
, 0, options
);
1296 #elif defined(HAVE_GETEA)
1297 return getea(path
, name
, value
, size
);
1298 #elif defined(HAVE_EXTATTR_GET_FILE)
1301 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1302 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1303 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1305 * The BSD implementation has a nasty habit of silently truncating
1306 * the returned value to the size of the buffer, so we have to check
1307 * that the buffer is large enough to fit the returned value.
1309 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1314 if((retval
=extattr_get_file(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1318 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno
)));
1320 #elif defined(HAVE_ATTR_GET)
1321 int retval
, flags
= 0;
1322 int valuelength
= (int)size
;
1323 char *attrname
= strchr(name
,'.') + 1;
1325 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1327 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1329 return retval
? retval
: valuelength
;
1330 #elif defined(HAVE_ATTROPEN)
1332 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
, 0);
1334 ret
= solaris_read_xattr(attrfd
, value
, size
);
1344 ssize_t
sys_lgetxattr (const char *path
, const char *name
, void *value
, size_t size
)
1346 #if defined(HAVE_LGETXATTR)
1347 return lgetxattr(path
, name
, value
, size
);
1348 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1349 int options
= XATTR_NOFOLLOW
;
1350 return getxattr(path
, name
, value
, size
, 0, options
);
1351 #elif defined(HAVE_LGETEA)
1352 return lgetea(path
, name
, value
, size
);
1353 #elif defined(HAVE_EXTATTR_GET_LINK)
1356 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1357 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1358 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1360 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1365 if((retval
=extattr_get_link(path
, attrnamespace
, attrname
, value
, size
)) >= 0)
1369 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno
)));
1371 #elif defined(HAVE_ATTR_GET)
1372 int retval
, flags
= ATTR_DONTFOLLOW
;
1373 int valuelength
= (int)size
;
1374 char *attrname
= strchr(name
,'.') + 1;
1376 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1378 retval
= attr_get(path
, attrname
, (char *)value
, &valuelength
, flags
);
1380 return retval
? retval
: valuelength
;
1381 #elif defined(HAVE_ATTROPEN)
1383 int attrfd
= solaris_attropen(path
, name
, O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1385 ret
= solaris_read_xattr(attrfd
, value
, size
);
1395 ssize_t
sys_fgetxattr (int filedes
, const char *name
, void *value
, size_t size
)
1397 #if defined(HAVE_FGETXATTR)
1398 #ifndef XATTR_ADD_OPT
1399 return fgetxattr(filedes
, name
, value
, size
);
1402 return fgetxattr(filedes
, name
, value
, size
, 0, options
);
1404 #elif defined(HAVE_FGETEA)
1405 return fgetea(filedes
, name
, value
, size
);
1406 #elif defined(HAVE_EXTATTR_GET_FD)
1409 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1410 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1411 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1413 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0)) >= 0) {
1418 if((retval
=extattr_get_fd(filedes
, attrnamespace
, attrname
, value
, size
)) >= 0)
1422 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno
)));
1424 #elif defined(HAVE_ATTR_GETF)
1425 int retval
, flags
= 0;
1426 int valuelength
= (int)size
;
1427 char *attrname
= strchr(name
,'.') + 1;
1429 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1431 retval
= attr_getf(filedes
, attrname
, (char *)value
, &valuelength
, flags
);
1433 return retval
? retval
: valuelength
;
1434 #elif defined(HAVE_ATTROPEN)
1436 int attrfd
= solaris_openat(filedes
, name
, O_RDONLY
|O_XATTR
, 0);
1438 ret
= solaris_read_xattr(attrfd
, value
, size
);
1448 #if defined(HAVE_EXTATTR_LIST_FILE)
1450 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1458 { EXTATTR_NAMESPACE_SYSTEM
, EXTATTR_PREFIX("system.") },
1459 { EXTATTR_NAMESPACE_USER
, EXTATTR_PREFIX("user.") },
1467 static ssize_t
bsd_attr_list (int type
, extattr_arg arg
, char *list
, size_t size
)
1469 ssize_t list_size
, total_size
= 0;
1472 /* Iterate through extattr(2) namespaces */
1473 for(t
= 0; t
< (sizeof(extattr
)/sizeof(extattr
[0])); t
++) {
1475 #if defined(HAVE_EXTATTR_LIST_FILE)
1477 list_size
= extattr_list_file(arg
.path
, extattr
[t
].space
, list
, size
);
1480 #if defined(HAVE_EXTATTR_LIST_LINK)
1482 list_size
= extattr_list_link(arg
.path
, extattr
[t
].space
, list
, size
);
1485 #if defined(HAVE_EXTATTR_LIST_FD)
1487 list_size
= extattr_list_fd(arg
.filedes
, extattr
[t
].space
, list
, size
);
1494 /* Some error happend. Errno should be set by the previous call */
1500 /* XXX: Call with an empty buffer may be used to calculate
1501 necessary buffer size. Unfortunately, we can't say, how
1502 many attributes were returned, so here is the potential
1503 problem with the emulation.
1506 /* Take the worse case of one char attribute names -
1507 two bytes per name plus one more for sanity.
1509 total_size
+= list_size
+ (list_size
/2 + 1)*extattr
[t
].len
;
1512 /* Count necessary offset to fit namespace prefixes */
1514 for(i
= 0; i
< list_size
; i
+= list
[i
] + 1)
1515 len
+= extattr
[t
].len
;
1517 total_size
+= list_size
+ len
;
1518 /* Buffer is too small to fit the results */
1519 if(total_size
> size
) {
1523 /* Shift results back, so we can prepend prefixes */
1524 buf
= memmove(list
+ len
, list
, list_size
);
1526 for(i
= 0; i
< list_size
; i
+= len
+ 1) {
1528 strncpy(list
, extattr
[t
].name
, extattr
[t
].len
+ 1);
1529 list
+= extattr
[t
].len
;
1530 strncpy(list
, buf
+ i
+ 1, len
);
1541 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1542 static char attr_buffer
[ATTR_MAX_VALUELEN
];
1544 static ssize_t
irix_attr_list(const char *path
, int filedes
, char *list
, size_t size
, int flags
)
1546 int retval
= 0, index
;
1547 attrlist_cursor_t
*cursor
= 0;
1549 attrlist_t
* al
= (attrlist_t
*)attr_buffer
;
1551 size_t ent_size
, left
= size
;
1556 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1558 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1560 for (index
= 0; index
< al
->al_count
; index
++) {
1561 ae
= ATTR_ENTRY(attr_buffer
, index
);
1562 ent_size
= strlen(ae
->a_name
) + sizeof("user.");
1563 if (left
>= ent_size
) {
1564 strncpy(bp
, "user.", sizeof("user."));
1565 strncat(bp
, ae
->a_name
, ent_size
- sizeof("user."));
1573 total_size
+= ent_size
;
1575 if (al
->al_more
== 0) break;
1582 retval
= attr_listf(filedes
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1584 retval
= attr_list(path
, attr_buffer
, ATTR_MAX_VALUELEN
, flags
, cursor
);
1586 for (index
= 0; index
< al
->al_count
; index
++) {
1587 ae
= ATTR_ENTRY(attr_buffer
, index
);
1588 ent_size
= strlen(ae
->a_name
) + sizeof("system.");
1589 if (left
>= ent_size
) {
1590 strncpy(bp
, "system.", sizeof("system."));
1591 strncat(bp
, ae
->a_name
, ent_size
- sizeof("system."));
1599 total_size
+= ent_size
;
1601 if (al
->al_more
== 0) break;
1604 return (ssize_t
)(retval
? retval
: total_size
);
1609 ssize_t
sys_listxattr (const char *path
, char *list
, size_t size
)
1611 #if defined(HAVE_LISTXATTR)
1612 #ifndef XATTR_ADD_OPT
1613 return listxattr(path
, list
, size
);
1616 return listxattr(path
, list
, size
, options
);
1618 #elif defined(HAVE_LISTEA)
1619 return listea(path
, list
, size
);
1620 #elif defined(HAVE_EXTATTR_LIST_FILE)
1623 return bsd_attr_list(0, arg
, list
, size
);
1624 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1625 return irix_attr_list(path
, 0, list
, size
, 0);
1626 #elif defined(HAVE_ATTROPEN)
1628 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
1629 if (attrdirfd
>= 0) {
1630 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1640 ssize_t
sys_llistxattr (const char *path
, char *list
, size_t size
)
1642 #if defined(HAVE_LLISTXATTR)
1643 return llistxattr(path
, list
, size
);
1644 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1645 int options
= XATTR_NOFOLLOW
;
1646 return listxattr(path
, list
, size
, options
);
1647 #elif defined(HAVE_LLISTEA)
1648 return llistea(path
, list
, size
);
1649 #elif defined(HAVE_EXTATTR_LIST_LINK)
1652 return bsd_attr_list(1, arg
, list
, size
);
1653 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1654 return irix_attr_list(path
, 0, list
, size
, ATTR_DONTFOLLOW
);
1655 #elif defined(HAVE_ATTROPEN)
1657 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1658 if (attrdirfd
>= 0) {
1659 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1669 ssize_t
sys_flistxattr (int filedes
, char *list
, size_t size
)
1671 #if defined(HAVE_FLISTXATTR)
1672 #ifndef XATTR_ADD_OPT
1673 return flistxattr(filedes
, list
, size
);
1676 return flistxattr(filedes
, list
, size
, options
);
1678 #elif defined(HAVE_FLISTEA)
1679 return flistea(filedes
, list
, size
);
1680 #elif defined(HAVE_EXTATTR_LIST_FD)
1682 arg
.filedes
= filedes
;
1683 return bsd_attr_list(2, arg
, list
, size
);
1684 #elif defined(HAVE_ATTR_LISTF)
1685 return irix_attr_list(NULL
, filedes
, list
, size
, 0);
1686 #elif defined(HAVE_ATTROPEN)
1688 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
1689 if (attrdirfd
>= 0) {
1690 ret
= solaris_list_xattr(attrdirfd
, list
, size
);
1700 int sys_removexattr (const char *path
, const char *name
)
1702 #if defined(HAVE_REMOVEXATTR)
1703 #ifndef XATTR_ADD_OPT
1704 return removexattr(path
, name
);
1707 return removexattr(path
, name
, options
);
1709 #elif defined(HAVE_REMOVEEA)
1710 return removeea(path
, name
);
1711 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1713 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1714 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1715 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1717 return extattr_delete_file(path
, attrnamespace
, attrname
);
1718 #elif defined(HAVE_ATTR_REMOVE)
1720 char *attrname
= strchr(name
,'.') + 1;
1722 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1724 return attr_remove(path
, attrname
, flags
);
1725 #elif defined(HAVE_ATTROPEN)
1727 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
, 0);
1728 if (attrdirfd
>= 0) {
1729 ret
= solaris_unlinkat(attrdirfd
, name
);
1739 int sys_lremovexattr (const char *path
, const char *name
)
1741 #if defined(HAVE_LREMOVEXATTR)
1742 return lremovexattr(path
, name
);
1743 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1744 int options
= XATTR_NOFOLLOW
;
1745 return removexattr(path
, name
, options
);
1746 #elif defined(HAVE_LREMOVEEA)
1747 return lremoveea(path
, name
);
1748 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1750 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1751 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1752 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1754 return extattr_delete_link(path
, attrnamespace
, attrname
);
1755 #elif defined(HAVE_ATTR_REMOVE)
1756 int flags
= ATTR_DONTFOLLOW
;
1757 char *attrname
= strchr(name
,'.') + 1;
1759 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1761 return attr_remove(path
, attrname
, flags
);
1762 #elif defined(HAVE_ATTROPEN)
1764 int attrdirfd
= solaris_attropen(path
, ".", O_RDONLY
|AT_SYMLINK_NOFOLLOW
, 0);
1765 if (attrdirfd
>= 0) {
1766 ret
= solaris_unlinkat(attrdirfd
, name
);
1776 int sys_fremovexattr (int filedes
, const char *name
)
1778 #if defined(HAVE_FREMOVEXATTR)
1779 #ifndef XATTR_ADD_OPT
1780 return fremovexattr(filedes
, name
);
1783 return fremovexattr(filedes
, name
, options
);
1785 #elif defined(HAVE_FREMOVEEA)
1786 return fremoveea(filedes
, name
);
1787 #elif defined(HAVE_EXTATTR_DELETE_FD)
1789 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1790 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1791 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1793 return extattr_delete_fd(filedes
, attrnamespace
, attrname
);
1794 #elif defined(HAVE_ATTR_REMOVEF)
1796 char *attrname
= strchr(name
,'.') + 1;
1798 if (strncmp(name
, "system", 6) == 0) flags
|= ATTR_ROOT
;
1800 return attr_removef(filedes
, attrname
, flags
);
1801 #elif defined(HAVE_ATTROPEN)
1803 int attrdirfd
= solaris_openat(filedes
, ".", O_RDONLY
|O_XATTR
, 0);
1804 if (attrdirfd
>= 0) {
1805 ret
= solaris_unlinkat(attrdirfd
, name
);
1815 int sys_setxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
1817 #if defined(HAVE_SETXATTR)
1818 #ifndef XATTR_ADD_OPT
1819 return setxattr(path
, name
, value
, size
, flags
);
1822 return setxattr(path
, name
, value
, size
, 0, options
);
1824 #elif defined(HAVE_SETEA)
1825 return setea(path
, name
, value
, size
, flags
);
1826 #elif defined(HAVE_EXTATTR_SET_FILE)
1829 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1830 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1831 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1833 /* Check attribute existence */
1834 retval
= extattr_get_file(path
, attrnamespace
, attrname
, NULL
, 0);
1836 /* REPLACE attribute, that doesn't exist */
1837 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
1841 /* Ignore other errors */
1844 /* CREATE attribute, that already exists */
1845 if (flags
& XATTR_CREATE
) {
1851 retval
= extattr_set_file(path
, attrnamespace
, attrname
, value
, size
);
1852 return (retval
< 0) ? -1 : 0;
1853 #elif defined(HAVE_ATTR_SET)
1855 char *attrname
= strchr(name
,'.') + 1;
1857 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
1858 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
1859 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
1861 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
1862 #elif defined(HAVE_ATTROPEN)
1864 int myflags
= O_RDWR
;
1866 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
1867 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
1868 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
1870 ret
= solaris_write_xattr(attrfd
, value
, size
);
1880 int sys_lsetxattr (const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
1882 #if defined(HAVE_LSETXATTR)
1883 return lsetxattr(path
, name
, value
, size
, flags
);
1884 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1885 int options
= XATTR_NOFOLLOW
;
1886 return setxattr(path
, name
, value
, size
, 0, options
);
1887 #elif defined(LSETEA)
1888 return lsetea(path
, name
, value
, size
, flags
);
1889 #elif defined(HAVE_EXTATTR_SET_LINK)
1892 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1893 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1894 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1896 /* Check attribute existence */
1897 retval
= extattr_get_link(path
, attrnamespace
, attrname
, NULL
, 0);
1899 /* REPLACE attribute, that doesn't exist */
1900 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
1904 /* Ignore other errors */
1907 /* CREATE attribute, that already exists */
1908 if (flags
& XATTR_CREATE
) {
1915 retval
= extattr_set_link(path
, attrnamespace
, attrname
, value
, size
);
1916 return (retval
< 0) ? -1 : 0;
1917 #elif defined(HAVE_ATTR_SET)
1918 int myflags
= ATTR_DONTFOLLOW
;
1919 char *attrname
= strchr(name
,'.') + 1;
1921 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
1922 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
1923 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
1925 return attr_set(path
, attrname
, (const char *)value
, size
, myflags
);
1926 #elif defined(HAVE_ATTROPEN)
1928 int myflags
= O_RDWR
| AT_SYMLINK_NOFOLLOW
;
1930 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
1931 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
1932 attrfd
= solaris_attropen(path
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
1934 ret
= solaris_write_xattr(attrfd
, value
, size
);
1944 int sys_fsetxattr (int filedes
, const char *name
, const void *value
, size_t size
, int flags
)
1946 #if defined(HAVE_FSETXATTR)
1947 #ifndef XATTR_ADD_OPT
1948 return fsetxattr(filedes
, name
, value
, size
, flags
);
1951 return fsetxattr(filedes
, name
, value
, size
, 0, options
);
1953 #elif defined(HAVE_FSETEA)
1954 return fsetea(filedes
, name
, value
, size
, flags
);
1955 #elif defined(HAVE_EXTATTR_SET_FD)
1958 int attrnamespace
= (strncmp(name
, "system", 6) == 0) ?
1959 EXTATTR_NAMESPACE_SYSTEM
: EXTATTR_NAMESPACE_USER
;
1960 const char *attrname
= ((s
=strchr_m(name
, '.')) == NULL
) ? name
: s
+ 1;
1962 /* Check attribute existence */
1963 retval
= extattr_get_fd(filedes
, attrnamespace
, attrname
, NULL
, 0);
1965 /* REPLACE attribute, that doesn't exist */
1966 if (flags
& XATTR_REPLACE
&& errno
== ENOATTR
) {
1970 /* Ignore other errors */
1973 /* CREATE attribute, that already exists */
1974 if (flags
& XATTR_CREATE
) {
1980 retval
= extattr_set_fd(filedes
, attrnamespace
, attrname
, value
, size
);
1981 return (retval
< 0) ? -1 : 0;
1982 #elif defined(HAVE_ATTR_SETF)
1984 char *attrname
= strchr(name
,'.') + 1;
1986 if (strncmp(name
, "system", 6) == 0) myflags
|= ATTR_ROOT
;
1987 if (flags
& XATTR_CREATE
) myflags
|= ATTR_CREATE
;
1988 if (flags
& XATTR_REPLACE
) myflags
|= ATTR_REPLACE
;
1990 return attr_setf(filedes
, attrname
, (const char *)value
, size
, myflags
);
1991 #elif defined(HAVE_ATTROPEN)
1993 int myflags
= O_RDWR
| O_XATTR
;
1995 if (flags
& XATTR_CREATE
) myflags
|= O_EXCL
;
1996 if (!(flags
& XATTR_REPLACE
)) myflags
|= O_CREAT
;
1997 attrfd
= solaris_openat(filedes
, name
, myflags
, (mode_t
) SOLARIS_ATTRMODE
);
1999 ret
= solaris_write_xattr(attrfd
, value
, size
);
2009 /**************************************************************************
2010 helper functions for Solaris' EA support
2011 ****************************************************************************/
2012 #ifdef HAVE_ATTROPEN
2013 static ssize_t
solaris_read_xattr(int attrfd
, void *value
, size_t size
)
2017 if (fstat(attrfd
, &sbuf
) == -1) {
2022 /* This is to return the current size of the named extended attribute */
2024 return sbuf
.st_size
;
2027 /* check size and read xattr */
2028 if (sbuf
.st_size
> size
) {
2033 return read(attrfd
, value
, sbuf
.st_size
);
2036 static ssize_t
solaris_list_xattr(int attrdirfd
, char *list
, size_t size
)
2041 int newfd
= dup(attrdirfd
);
2042 /* CAUTION: The originating file descriptor should not be
2043 used again following the call to fdopendir().
2044 For that reason we dup() the file descriptor
2045 here to make things more clear. */
2046 dirp
= fdopendir(newfd
);
2048 while ((de
= readdir(dirp
))) {
2049 size_t listlen
= strlen(de
->d_name
);
2050 if (!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, "..")) {
2051 /* we don't want "." and ".." here: */
2052 DEBUG(10,("skipped EA %s\n",de
->d_name
));
2057 /* return the current size of the list of extended attribute names*/
2060 /* check size and copy entrieѕ + nul into list. */
2061 if ((len
+ listlen
+ 1) > size
) {
2066 safe_strcpy(list
+ len
, de
->d_name
, listlen
);
2074 if (closedir(dirp
) == -1) {
2075 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno
)));
2081 static int solaris_unlinkat(int attrdirfd
, const char *name
)
2083 if (unlinkat(attrdirfd
, name
, 0) == -1) {
2084 if (errno
== ENOENT
) {
2092 static int solaris_attropen(const char *path
, const char *attrpath
, int oflag
, mode_t mode
)
2094 int filedes
= attropen(path
, attrpath
, oflag
, mode
);
2095 if (filedes
== -1) {
2096 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path
,attrpath
,strerror(errno
)));
2097 if (errno
== EINVAL
) {
2106 static int solaris_openat(int fildes
, const char *path
, int oflag
, mode_t mode
)
2108 int filedes
= openat(fildes
, path
, oflag
, mode
);
2109 if (filedes
== -1) {
2110 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes
,path
,strerror(errno
)));
2111 if (errno
== EINVAL
) {
2120 static int solaris_write_xattr(int attrfd
, const char *value
, size_t size
)
2122 if ((ftruncate(attrfd
, 0) == 0) && (write(attrfd
, value
, size
) == size
)) {
2125 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2129 #endif /*HAVE_ATTROPEN*/
2132 /****************************************************************************
2133 Return the major devicenumber for UNIX extensions.
2134 ****************************************************************************/
2136 uint32
unix_dev_major(SMB_DEV_T dev
)
2138 #if defined(HAVE_DEVICE_MAJOR_FN)
2139 return (uint32
)major(dev
);
2141 return (uint32
)(dev
>> 8);
2145 /****************************************************************************
2146 Return the minor devicenumber for UNIX extensions.
2147 ****************************************************************************/
2149 uint32
unix_dev_minor(SMB_DEV_T dev
)
2151 #if defined(HAVE_DEVICE_MINOR_FN)
2152 return (uint32
)minor(dev
);
2154 return (uint32
)(dev
& 0xff);
2158 #if defined(WITH_AIO)
2160 /*******************************************************************
2161 An aio_read wrapper that will deal with 64-bit sizes.
2162 ********************************************************************/
2164 int sys_aio_read(SMB_STRUCT_AIOCB
*aiocb
)
2166 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2167 return aio_read64(aiocb
);
2168 #elif defined(HAVE_AIO_READ)
2169 return aio_read(aiocb
);
2176 /*******************************************************************
2177 An aio_write wrapper that will deal with 64-bit sizes.
2178 ********************************************************************/
2180 int sys_aio_write(SMB_STRUCT_AIOCB
*aiocb
)
2182 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2183 return aio_write64(aiocb
);
2184 #elif defined(HAVE_AIO_WRITE)
2185 return aio_write(aiocb
);
2192 /*******************************************************************
2193 An aio_return wrapper that will deal with 64-bit sizes.
2194 ********************************************************************/
2196 ssize_t
sys_aio_return(SMB_STRUCT_AIOCB
*aiocb
)
2198 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2199 return aio_return64(aiocb
);
2200 #elif defined(HAVE_AIO_RETURN)
2201 return aio_return(aiocb
);
2208 /*******************************************************************
2209 An aio_cancel wrapper that will deal with 64-bit sizes.
2210 ********************************************************************/
2212 int sys_aio_cancel(int fd
, SMB_STRUCT_AIOCB
*aiocb
)
2214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2215 return aio_cancel64(fd
, aiocb
);
2216 #elif defined(HAVE_AIO_CANCEL)
2217 return aio_cancel(fd
, aiocb
);
2224 /*******************************************************************
2225 An aio_error wrapper that will deal with 64-bit sizes.
2226 ********************************************************************/
2228 int sys_aio_error(const SMB_STRUCT_AIOCB
*aiocb
)
2230 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2231 return aio_error64(aiocb
);
2232 #elif defined(HAVE_AIO_ERROR)
2233 return aio_error(aiocb
);
2240 /*******************************************************************
2241 An aio_fsync wrapper that will deal with 64-bit sizes.
2242 ********************************************************************/
2244 int sys_aio_fsync(int op
, SMB_STRUCT_AIOCB
*aiocb
)
2246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2247 return aio_fsync64(op
, aiocb
);
2248 #elif defined(HAVE_AIO_FSYNC)
2249 return aio_fsync(op
, aiocb
);
2256 /*******************************************************************
2257 An aio_fsync wrapper that will deal with 64-bit sizes.
2258 ********************************************************************/
2260 int sys_aio_suspend(const SMB_STRUCT_AIOCB
* const cblist
[], int n
, const struct timespec
*timeout
)
2262 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2263 return aio_suspend64(cblist
, n
, timeout
);
2264 #elif defined(HAVE_AIO_FSYNC)
2265 return aio_suspend(cblist
, n
, timeout
);
2271 #else /* !WITH_AIO */
2273 int sys_aio_read(SMB_STRUCT_AIOCB
*aiocb
)
2279 int sys_aio_write(SMB_STRUCT_AIOCB
*aiocb
)
2285 ssize_t
sys_aio_return(SMB_STRUCT_AIOCB
*aiocb
)
2291 int sys_aio_cancel(int fd
, SMB_STRUCT_AIOCB
*aiocb
)
2297 int sys_aio_error(const SMB_STRUCT_AIOCB
*aiocb
)
2303 int sys_aio_fsync(int op
, SMB_STRUCT_AIOCB
*aiocb
)
2309 int sys_aio_suspend(const SMB_STRUCT_AIOCB
* const cblist
[], int n
, const struct timespec
*timeout
)
2314 #endif /* WITH_AIO */
2316 int sys_getpeereid( int s
, uid_t
*uid
)
2318 #if defined(HAVE_PEERCRED)
2320 socklen_t cred_len
= sizeof(struct ucred
);
2323 ret
= getsockopt(s
, SOL_SOCKET
, SO_PEERCRED
, (void *)&cred
, &cred_len
);
2328 if (cred_len
!= sizeof(struct ucred
)) {
2341 int sys_getnameinfo(const struct sockaddr
*psa
,
2350 * For Solaris we must make sure salen is the
2351 * correct length for the incoming sa_family.
2354 if (salen
== sizeof(struct sockaddr_storage
)) {
2355 salen
= sizeof(struct sockaddr_in
);
2356 #if defined(HAVE_IPV6)
2357 if (psa
->sa_family
== AF_INET6
) {
2358 salen
= sizeof(struct sockaddr_in6
);
2362 return getnameinfo(psa
, salen
, host
, hostlen
, service
, servlen
, flags
);
2365 int sys_connect(int fd
, const struct sockaddr
* addr
)
2367 socklen_t salen
= -1;
2369 if (addr
->sa_family
== AF_INET
) {
2370 salen
= sizeof(struct sockaddr_in
);
2371 } else if (addr
->sa_family
== AF_UNIX
) {
2372 salen
= sizeof(struct sockaddr_un
);
2374 #if defined(HAVE_IPV6)
2375 else if (addr
->sa_family
== AF_INET6
) {
2376 salen
= sizeof(struct sockaddr_in6
);
2380 return connect(fd
, addr
, salen
);