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 ret = writev(fd, iov, iovcnt);
154 } while (ret == -1 && errno == EINTR);
158 /*******************************************************************
159 A pread wrapper that will deal with EINTR and 64-bit file offsets.
160 ********************************************************************/
162 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
163 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
168 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
169 ret = pread64(fd, buf, count, off);
171 ret = pread(fd, buf, count, off);
173 } while (ret == -1 && errno == EINTR);
178 /*******************************************************************
179 A write wrapper that will deal with EINTR and 64-bit file offsets.
180 ********************************************************************/
182 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
183 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
188 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
189 ret = pwrite64(fd, buf, count, off);
191 ret = pwrite(fd, buf, count, off);
193 } while (ret == -1 && errno == EINTR);
198 /*******************************************************************
199 A send wrapper that will deal with EINTR.
200 ********************************************************************/
202 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
207 ret = send(s, msg, len, flags);
208 } while (ret == -1 && errno == EINTR);
212 /*******************************************************************
213 A sendto wrapper that will deal with EINTR.
214 ********************************************************************/
216 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
221 ret = sendto(s, msg, len, flags, to, tolen);
222 } while (ret == -1 && errno == EINTR);
226 /*******************************************************************
227 A recv wrapper that will deal with EINTR.
228 ********************************************************************/
230 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
235 ret = recv(fd, buf, count, flags);
236 } while (ret == -1 && errno == EINTR);
240 /*******************************************************************
241 A recvfrom wrapper that will deal with EINTR.
242 ********************************************************************/
244 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
249 ret = recvfrom(s, buf, len, flags, from, fromlen);
250 } while (ret == -1 && errno == EINTR);
254 /*******************************************************************
255 A fcntl wrapper that will deal with EINTR.
256 ********************************************************************/
258 int sys_fcntl_ptr(int fd, int cmd, void *arg)
263 ret = fcntl(fd, cmd, arg);
264 } while (ret == -1 && errno == EINTR);
268 /*******************************************************************
269 A fcntl wrapper that will deal with EINTR.
270 ********************************************************************/
272 int sys_fcntl_long(int fd, int cmd, long arg)
277 ret = fcntl(fd, cmd, arg);
278 } while (ret == -1 && errno == EINTR);
282 /*******************************************************************
283 A stat() wrapper that will deal with 64 bit filesizes.
284 ********************************************************************/
286 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
289 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
290 ret = stat64(fname, sbuf);
292 ret = stat(fname, sbuf);
294 /* we always want directories to appear zero size */
295 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
299 /*******************************************************************
300 An fstat() wrapper that will deal with 64 bit filesizes.
301 ********************************************************************/
303 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
306 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
307 ret = fstat64(fd, sbuf);
309 ret = fstat(fd, sbuf);
311 /* we always want directories to appear zero size */
312 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
316 /*******************************************************************
317 An lstat() wrapper that will deal with 64 bit filesizes.
318 ********************************************************************/
320 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
323 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
324 ret = lstat64(fname, sbuf);
326 ret = lstat(fname, sbuf);
328 /* we always want directories to appear zero size */
329 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
333 /*******************************************************************
334 An ftruncate() wrapper that will deal with 64 bit filesizes.
335 ********************************************************************/
337 int sys_ftruncate(int fd, SMB_OFF_T offset)
339 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
340 return ftruncate64(fd, offset);
342 return ftruncate(fd, offset);
346 /*******************************************************************
347 An lseek() wrapper that will deal with 64 bit filesizes.
348 ********************************************************************/
350 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
352 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
353 return lseek64(fd, offset, whence);
355 return lseek(fd, offset, whence);
359 /*******************************************************************
360 An fseek() wrapper that will deal with 64 bit filesizes.
361 ********************************************************************/
363 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
365 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
366 return fseek64(fp, offset, whence);
367 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
368 return fseeko64(fp, offset, whence);
370 return fseek(fp, offset, whence);
374 /*******************************************************************
375 An ftell() wrapper that will deal with 64 bit filesizes.
376 ********************************************************************/
378 SMB_OFF_T sys_ftell(FILE *fp)
380 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
381 return (SMB_OFF_T)ftell64(fp);
382 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
383 return (SMB_OFF_T)ftello64(fp);
385 return (SMB_OFF_T)ftell(fp);
389 /*******************************************************************
390 A creat() wrapper that will deal with 64 bit filesizes.
391 ********************************************************************/
393 int sys_creat(const char *path, mode_t mode)
395 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
396 return creat64(path, mode);
399 * If creat64 isn't defined then ensure we call a potential open64.
402 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
406 /*******************************************************************
407 An open() wrapper that will deal with 64 bit filesizes.
408 ********************************************************************/
410 int sys_open(const char *path, int oflag, mode_t mode)
412 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
413 return open64(path, oflag, mode);
415 return open(path, oflag, mode);
419 /*******************************************************************
420 An fopen() wrapper that will deal with 64 bit filesizes.
421 ********************************************************************/
423 FILE *sys_fopen(const char *path, const char *type)
425 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
426 return fopen64(path, type);
428 return fopen(path, type);
433 /*******************************************************************
434 A flock() wrapper that will perform the kernel flock.
435 ********************************************************************/
437 void kernel_flock(int fd, uint32 share_mode)
439 #if HAVE_KERNEL_SHARE_MODES
441 if (share_mode == FILE_SHARE_WRITE) {
442 kernel_mode = LOCK_MAND|LOCK_WRITE;
443 } else if (share_mode == FILE_SHARE_READ) {
444 kernel_mode = LOCK_MAND|LOCK_READ;
445 } else if (share_mode == FILE_SHARE_NONE) {
446 kernel_mode = LOCK_MAND;
449 flock(fd, kernel_mode);
457 /*******************************************************************
458 An opendir wrapper that will deal with 64 bit filesizes.
459 ********************************************************************/
461 SMB_STRUCT_DIR *sys_opendir(const char *name)
463 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
464 return opendir64(name);
466 return opendir(name);
470 /*******************************************************************
471 A readdir wrapper that will deal with 64 bit filesizes.
472 ********************************************************************/
474 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
476 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
477 return readdir64(dirp);
479 return readdir(dirp);
483 /*******************************************************************
484 A seekdir wrapper that will deal with 64 bit filesizes.
485 ********************************************************************/
487 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
489 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
490 seekdir64(dirp, offset);
492 seekdir(dirp, offset);
496 /*******************************************************************
497 A telldir wrapper that will deal with 64 bit filesizes.
498 ********************************************************************/
500 long sys_telldir(SMB_STRUCT_DIR *dirp)
502 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
503 return (long)telldir64(dirp);
505 return (long)telldir(dirp);
509 /*******************************************************************
510 A rewinddir wrapper that will deal with 64 bit filesizes.
511 ********************************************************************/
513 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
522 /*******************************************************************
523 A close wrapper that will deal with 64 bit filesizes.
524 ********************************************************************/
526 int sys_closedir(SMB_STRUCT_DIR *dirp)
528 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
529 return closedir64(dirp);
531 return closedir(dirp);
535 /*******************************************************************
536 An mknod() wrapper that will deal with 64 bit filesizes.
537 ********************************************************************/
539 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
541 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
542 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
543 return mknod64(path, mode, dev);
545 return mknod(path, mode, dev);
548 /* No mknod system call. */
554 /*******************************************************************
555 The wait() calls vary between systems
556 ********************************************************************/
558 int sys_waitpid(pid_t pid,int *status,int options)
561 return waitpid(pid,status,options);
562 #else /* HAVE_WAITPID */
563 return wait4(pid, status, options, NULL);
564 #endif /* HAVE_WAITPID */
567 /*******************************************************************
568 System wrapper for getwd
569 ********************************************************************/
571 char *sys_getwd(char *s)
575 wd = (char *)getcwd(s, PATH_MAX);
577 wd = (char *)getwd(s);
582 #if defined(HAVE_POSIX_CAPABILITIES)
584 /**************************************************************************
585 Try and abstract process capabilities (for systems that have them).
586 ****************************************************************************/
588 /* Set the POSIX capabilities needed for the given purpose into the effective
589 * capability set of the current process. Make sure they are always removed
590 * from the inheritable set, because there is no circumstance in which our
591 * children should inherit our elevated privileges.
593 static bool set_process_capability(enum smbd_capability capability,
596 cap_value_t cap_vals[2] = {0};
597 int num_cap_vals = 0;
601 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
602 /* On Linux, make sure that any capabilities we grab are sticky
603 * across UID changes. We expect that this would allow us to keep both
604 * the effective and permitted capability sets, but as of circa 2.6.16,
605 * only the permitted set is kept. It is a bug (which we work around)
606 * that the effective set is lost, but we still require the effective
609 if (!prctl(PR_GET_KEEPCAPS)) {
610 prctl(PR_SET_KEEPCAPS, 1);
614 cap = cap_get_proc();
616 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
621 switch (capability) {
622 case KERNEL_OPLOCK_CAPABILITY:
623 #ifdef CAP_NETWORK_MGT
624 /* IRIX has CAP_NETWORK_MGT for oplocks. */
625 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
628 case DMAPI_ACCESS_CAPABILITY:
629 #ifdef CAP_DEVICE_MGT
630 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
631 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
633 /* Linux has CAP_MKNOD for DMAPI access. */
634 cap_vals[num_cap_vals++] = CAP_MKNOD;
637 case LEASE_CAPABILITY:
639 cap_vals[num_cap_vals++] = CAP_LEASE;
644 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
646 if (num_cap_vals == 0) {
651 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
652 enable ? CAP_SET : CAP_CLEAR);
654 /* We never want to pass capabilities down to our children, so make
655 * sure they are not inherited.
657 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
659 if (cap_set_proc(cap) == -1) {
660 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
670 #endif /* HAVE_POSIX_CAPABILITIES */
672 /****************************************************************************
673 Gain the oplock capability from the kernel if possible.
674 ****************************************************************************/
676 void set_effective_capability(enum smbd_capability capability)
678 #if defined(HAVE_POSIX_CAPABILITIES)
679 set_process_capability(capability, True);
680 #endif /* HAVE_POSIX_CAPABILITIES */
683 void drop_effective_capability(enum smbd_capability capability)
685 #if defined(HAVE_POSIX_CAPABILITIES)
686 set_process_capability(capability, False);
687 #endif /* HAVE_POSIX_CAPABILITIES */
690 /**************************************************************************
691 Wrapper for random().
692 ****************************************************************************/
694 long sys_random(void)
696 #if defined(HAVE_RANDOM)
697 return (long)random();
698 #elif defined(HAVE_RAND)
701 DEBUG(0,("Error - no random function available !\n"));
706 /**************************************************************************
707 Wrapper for srandom().
708 ****************************************************************************/
710 void sys_srandom(unsigned int seed)
712 #if defined(HAVE_SRANDOM)
714 #elif defined(HAVE_SRAND)
717 DEBUG(0,("Error - no srandom function available !\n"));
722 /**************************************************************************
723 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
724 ****************************************************************************/
728 #if defined(SYSCONF_SC_NGROUPS_MAX)
729 int ret = sysconf(_SC_NGROUPS_MAX);
730 return (ret == -1) ? NGROUPS_MAX : ret;
736 /**************************************************************************
737 Wrap setgroups and getgroups for systems that declare getgroups() as
738 returning an array of gid_t, but actuall return an array of int.
739 ****************************************************************************/
741 #if defined(HAVE_BROKEN_GETGROUPS)
742 static int sys_broken_getgroups(int setlen, gid_t *gidset)
749 return getgroups(setlen, &gid);
753 * Broken case. We need to allocate a
754 * GID_T array of size setlen.
763 setlen = groups_max();
765 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
766 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
770 if((ngroups = getgroups(setlen, group_list)) < 0) {
771 int saved_errno = errno;
772 SAFE_FREE(group_list);
777 for(i = 0; i < ngroups; i++)
778 gidset[i] = (gid_t)group_list[i];
780 SAFE_FREE(group_list);
784 static int sys_broken_setgroups(int setlen, gid_t *gidset)
792 if (setlen < 0 || setlen > groups_max()) {
798 * Broken case. We need to allocate a
799 * GID_T array of size setlen.
802 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
803 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
807 for(i = 0; i < setlen; i++)
808 group_list[i] = (GID_T) gidset[i];
810 if(setgroups(setlen, group_list) != 0) {
811 int saved_errno = errno;
812 SAFE_FREE(group_list);
817 SAFE_FREE(group_list);
821 #endif /* HAVE_BROKEN_GETGROUPS */
823 /* This is a list of systems that require the first GID passed to setgroups(2)
824 * to be the effective GID. If your system is one of these, add it here.
826 #if defined (FREEBSD) || defined (DARWINOS)
827 #define USE_BSD_SETGROUPS
830 #if defined(USE_BSD_SETGROUPS)
831 /* Depending on the particular BSD implementation, the first GID that is
832 * passed to setgroups(2) will either be ignored or will set the credential's
833 * effective GID. In either case, the right thing to do is to guarantee that
834 * gidset[0] is the effective GID.
836 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
838 gid_t *new_gidset = NULL;
842 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
845 /* No group list, just make sure we are setting the efective GID. */
847 return setgroups(1, &primary_gid);
850 /* If the primary gid is not the first array element, grow the array
851 * and insert it at the front.
853 if (gidset[0] != primary_gid) {
854 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
855 if (new_gidset == NULL) {
859 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
860 new_gidset[0] = primary_gid;
865 DEBUG(3, ("forced to truncate group list from %d to %d\n",
870 #if defined(HAVE_BROKEN_GETGROUPS)
871 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
873 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
878 SAFE_FREE(new_gidset);
885 #endif /* USE_BSD_SETGROUPS */
887 /**************************************************************************
888 Wrapper for getgroups. Deals with broken (int) case.
889 ****************************************************************************/
891 int sys_getgroups(int setlen, gid_t *gidset)
893 #if defined(HAVE_BROKEN_GETGROUPS)
894 return sys_broken_getgroups(setlen, gidset);
896 return getgroups(setlen, gidset);
900 /**************************************************************************
901 Wrapper for setgroups. Deals with broken (int) case and BSD case.
902 ****************************************************************************/
904 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
906 #if !defined(HAVE_SETGROUPS)
909 #endif /* HAVE_SETGROUPS */
911 #if defined(USE_BSD_SETGROUPS)
912 return sys_bsd_setgroups(primary_gid, setlen, gidset);
913 #elif defined(HAVE_BROKEN_GETGROUPS)
914 return sys_broken_setgroups(setlen, gidset);
916 return setgroups(setlen, gidset);
920 /**************************************************************************
921 Wrappers for setpwent(), getpwent() and endpwent()
922 ****************************************************************************/
924 void sys_setpwent(void)
929 struct passwd *sys_getpwent(void)
934 void sys_endpwent(void)
939 /**************************************************************************
940 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
941 ****************************************************************************/
944 struct passwd *sys_getpwnam(const char *name)
946 return getpwnam(name);
949 struct passwd *sys_getpwuid(uid_t uid)
951 return getpwuid(uid);
954 struct group *sys_getgrnam(const char *name)
956 return getgrnam(name);
959 struct group *sys_getgrgid(gid_t gid)
961 return getgrgid(gid);
964 /**************************************************************************
965 Extract a command into an arg list.
966 ****************************************************************************/
968 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
977 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
978 DEBUG(0, ("talloc failed\n"));
982 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
983 TALLOC_FREE(trunc_cmd);
992 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
995 TALLOC_FREE(trunc_cmd);
997 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1002 * Now do the extraction.
1005 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1009 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1012 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1016 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1018 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1027 DEBUG(0, ("talloc failed\n"));
1028 TALLOC_FREE(trunc_cmd);
1034 /**************************************************************************
1035 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1036 a sys_getpid() that only does a system call *once*.
1037 ****************************************************************************/
1039 static pid_t mypid = (pid_t)-1;
1041 pid_t sys_fork(void)
1043 pid_t forkret = fork();
1045 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1051 /**************************************************************************
1052 Wrapper for getpid. Ensures we only do a system call *once*.
1053 ****************************************************************************/
1055 pid_t sys_getpid(void)
1057 if (mypid == (pid_t)-1)
1063 /**************************************************************************
1064 Wrapper for popen. Safer as it doesn't search a path.
1065 Modified from the glibc sources.
1066 modified by tridge to return a file descriptor. We must kick our FILE* habit
1067 ****************************************************************************/
1069 typedef struct _popen_list
1073 struct _popen_list *next;
1076 static popen_list *popen_chain;
1078 int sys_popen(const char *command)
1080 int parent_end, child_end;
1082 popen_list *entry = NULL;
1085 if (pipe(pipe_fds) < 0)
1088 parent_end = pipe_fds[0];
1089 child_end = pipe_fds[1];
1096 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1099 ZERO_STRUCTP(entry);
1102 * Extract the command and args into a NULL terminated array.
1105 if(!(argl = extract_args(NULL, command)))
1108 entry->child_pid = sys_fork();
1110 if (entry->child_pid == -1) {
1114 if (entry->child_pid == 0) {
1120 int child_std_end = STDOUT_FILENO;
1124 if (child_end != child_std_end) {
1125 dup2 (child_end, child_std_end);
1130 * POSIX.2: "popen() shall ensure that any streams from previous
1131 * popen() calls that remain open in the parent process are closed
1132 * in the new child process."
1135 for (p = popen_chain; p; p = p->next)
1138 execv(argl[0], argl);
1149 /* Link into popen_chain. */
1150 entry->next = popen_chain;
1151 popen_chain = entry;
1152 entry->fd = parent_end;
1165 /**************************************************************************
1166 Wrapper for pclose. Modified from the glibc sources.
1167 ****************************************************************************/
1169 int sys_pclose(int fd)
1172 popen_list **ptr = &popen_chain;
1173 popen_list *entry = NULL;
1177 /* Unlink from popen_chain. */
1178 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1179 if ((*ptr)->fd == fd) {
1181 *ptr = (*ptr)->next;
1187 if (status < 0 || close(entry->fd) < 0)
1191 * As Samba is catching and eating child process
1192 * exits we don't really care about the child exit
1193 * code, a -1 with errno = ECHILD will do fine for us.
1197 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1198 } while (wait_pid == -1 && errno == EINTR);
1207 /**************************************************************************
1208 Wrapper for Admin Logs.
1209 ****************************************************************************/
1211 void sys_adminlog(int priority, const char *format_str, ...)
1215 char *msgbuf = NULL;
1217 va_start( ap, format_str );
1218 ret = vasprintf( &msgbuf, format_str, ap );
1224 #if defined(HAVE_SYSLOG)
1225 syslog( priority, "%s", msgbuf );
1227 DEBUG(0,("%s", msgbuf ));
1232 /******** Solaris EA helper function prototypes ********/
1233 #ifdef HAVE_ATTROPEN
1234 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1235 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1236 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1237 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1238 static int solaris_unlinkat(int attrdirfd, const char *name);
1239 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1240 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1243 /**************************************************************************
1244 Wrappers for extented attribute calls. Based on the Linux package with
1245 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1246 ****************************************************************************/
1248 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1250 #if defined(HAVE_GETXATTR)
1251 #ifndef XATTR_ADD_OPT
1252 return getxattr(path, name, value, size);
1255 return getxattr(path, name, value, size, 0, options);
1257 #elif defined(HAVE_GETEA)
1258 return getea(path, name, value, size);
1259 #elif defined(HAVE_EXTATTR_GET_FILE)
1262 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1263 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1264 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1266 * The BSD implementation has a nasty habit of silently truncating
1267 * the returned value to the size of the buffer, so we have to check
1268 * that the buffer is large enough to fit the returned value.
1270 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1275 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1279 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1281 #elif defined(HAVE_ATTR_GET)
1282 int retval, flags = 0;
1283 int valuelength = (int)size;
1284 char *attrname = strchr(name,'.') + 1;
1286 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1288 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1290 return retval ? retval : valuelength;
1291 #elif defined(HAVE_ATTROPEN)
1293 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1295 ret = solaris_read_xattr(attrfd, value, size);
1305 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1307 #if defined(HAVE_LGETXATTR)
1308 return lgetxattr(path, name, value, size);
1309 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1310 int options = XATTR_NOFOLLOW;
1311 return getxattr(path, name, value, size, 0, options);
1312 #elif defined(HAVE_LGETEA)
1313 return lgetea(path, name, value, size);
1314 #elif defined(HAVE_EXTATTR_GET_LINK)
1317 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1318 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1319 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1321 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1326 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1330 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1332 #elif defined(HAVE_ATTR_GET)
1333 int retval, flags = ATTR_DONTFOLLOW;
1334 int valuelength = (int)size;
1335 char *attrname = strchr(name,'.') + 1;
1337 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1339 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1341 return retval ? retval : valuelength;
1342 #elif defined(HAVE_ATTROPEN)
1344 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1346 ret = solaris_read_xattr(attrfd, value, size);
1356 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1358 #if defined(HAVE_FGETXATTR)
1359 #ifndef XATTR_ADD_OPT
1360 return fgetxattr(filedes, name, value, size);
1363 return fgetxattr(filedes, name, value, size, 0, options);
1365 #elif defined(HAVE_FGETEA)
1366 return fgetea(filedes, name, value, size);
1367 #elif defined(HAVE_EXTATTR_GET_FD)
1370 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1371 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1372 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1374 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1379 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1383 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1385 #elif defined(HAVE_ATTR_GETF)
1386 int retval, flags = 0;
1387 int valuelength = (int)size;
1388 char *attrname = strchr(name,'.') + 1;
1390 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1392 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1394 return retval ? retval : valuelength;
1395 #elif defined(HAVE_ATTROPEN)
1397 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1399 ret = solaris_read_xattr(attrfd, value, size);
1409 #if defined(HAVE_EXTATTR_LIST_FILE)
1411 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1419 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1420 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1428 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1430 ssize_t list_size, total_size = 0;
1433 /* Iterate through extattr(2) namespaces */
1434 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1436 #if defined(HAVE_EXTATTR_LIST_FILE)
1438 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1441 #if defined(HAVE_EXTATTR_LIST_LINK)
1443 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1446 #if defined(HAVE_EXTATTR_LIST_FD)
1448 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1455 /* Some error happend. Errno should be set by the previous call */
1461 /* XXX: Call with an empty buffer may be used to calculate
1462 necessary buffer size. Unfortunately, we can't say, how
1463 many attributes were returned, so here is the potential
1464 problem with the emulation.
1467 /* Take the worse case of one char attribute names -
1468 two bytes per name plus one more for sanity.
1470 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1473 /* Count necessary offset to fit namespace prefixes */
1475 for(i = 0; i < list_size; i += list[i] + 1)
1476 len += extattr[t].len;
1478 total_size += list_size + len;
1479 /* Buffer is too small to fit the results */
1480 if(total_size > size) {
1484 /* Shift results back, so we can prepend prefixes */
1485 buf = memmove(list + len, list, list_size);
1487 for(i = 0; i < list_size; i += len + 1) {
1489 strncpy(list, extattr[t].name, extattr[t].len + 1);
1490 list += extattr[t].len;
1491 strncpy(list, buf + i + 1, len);
1502 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1503 static char attr_buffer[ATTR_MAX_VALUELEN];
1505 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1507 int retval = 0, index;
1508 attrlist_cursor_t *cursor = 0;
1510 attrlist_t * al = (attrlist_t *)attr_buffer;
1512 size_t ent_size, left = size;
1517 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1519 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1521 for (index = 0; index < al->al_count; index++) {
1522 ae = ATTR_ENTRY(attr_buffer, index);
1523 ent_size = strlen(ae->a_name) + sizeof("user.");
1524 if (left >= ent_size) {
1525 strncpy(bp, "user.", sizeof("user."));
1526 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1534 total_size += ent_size;
1536 if (al->al_more == 0) break;
1543 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1545 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1547 for (index = 0; index < al->al_count; index++) {
1548 ae = ATTR_ENTRY(attr_buffer, index);
1549 ent_size = strlen(ae->a_name) + sizeof("system.");
1550 if (left >= ent_size) {
1551 strncpy(bp, "system.", sizeof("system."));
1552 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1560 total_size += ent_size;
1562 if (al->al_more == 0) break;
1565 return (ssize_t)(retval ? retval : total_size);
1570 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1572 #if defined(HAVE_LISTXATTR)
1573 #ifndef XATTR_ADD_OPT
1574 return listxattr(path, list, size);
1577 return listxattr(path, list, size, options);
1579 #elif defined(HAVE_LISTEA)
1580 return listea(path, list, size);
1581 #elif defined(HAVE_EXTATTR_LIST_FILE)
1584 return bsd_attr_list(0, arg, list, size);
1585 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1586 return irix_attr_list(path, 0, list, size, 0);
1587 #elif defined(HAVE_ATTROPEN)
1589 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1590 if (attrdirfd >= 0) {
1591 ret = solaris_list_xattr(attrdirfd, list, size);
1601 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1603 #if defined(HAVE_LLISTXATTR)
1604 return llistxattr(path, list, size);
1605 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1606 int options = XATTR_NOFOLLOW;
1607 return listxattr(path, list, size, options);
1608 #elif defined(HAVE_LLISTEA)
1609 return llistea(path, list, size);
1610 #elif defined(HAVE_EXTATTR_LIST_LINK)
1613 return bsd_attr_list(1, arg, list, size);
1614 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1615 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1616 #elif defined(HAVE_ATTROPEN)
1618 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1619 if (attrdirfd >= 0) {
1620 ret = solaris_list_xattr(attrdirfd, list, size);
1630 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1632 #if defined(HAVE_FLISTXATTR)
1633 #ifndef XATTR_ADD_OPT
1634 return flistxattr(filedes, list, size);
1637 return flistxattr(filedes, list, size, options);
1639 #elif defined(HAVE_FLISTEA)
1640 return flistea(filedes, list, size);
1641 #elif defined(HAVE_EXTATTR_LIST_FD)
1643 arg.filedes = filedes;
1644 return bsd_attr_list(2, arg, list, size);
1645 #elif defined(HAVE_ATTR_LISTF)
1646 return irix_attr_list(NULL, filedes, list, size, 0);
1647 #elif defined(HAVE_ATTROPEN)
1649 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1650 if (attrdirfd >= 0) {
1651 ret = solaris_list_xattr(attrdirfd, list, size);
1661 int sys_removexattr (const char *path, const char *name)
1663 #if defined(HAVE_REMOVEXATTR)
1664 #ifndef XATTR_ADD_OPT
1665 return removexattr(path, name);
1668 return removexattr(path, name, options);
1670 #elif defined(HAVE_REMOVEEA)
1671 return removeea(path, name);
1672 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1674 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1675 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1676 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1678 return extattr_delete_file(path, attrnamespace, attrname);
1679 #elif defined(HAVE_ATTR_REMOVE)
1681 char *attrname = strchr(name,'.') + 1;
1683 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1685 return attr_remove(path, attrname, flags);
1686 #elif defined(HAVE_ATTROPEN)
1688 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1689 if (attrdirfd >= 0) {
1690 ret = solaris_unlinkat(attrdirfd, name);
1700 int sys_lremovexattr (const char *path, const char *name)
1702 #if defined(HAVE_LREMOVEXATTR)
1703 return lremovexattr(path, name);
1704 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1705 int options = XATTR_NOFOLLOW;
1706 return removexattr(path, name, options);
1707 #elif defined(HAVE_LREMOVEEA)
1708 return lremoveea(path, name);
1709 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1711 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1712 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1713 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1715 return extattr_delete_link(path, attrnamespace, attrname);
1716 #elif defined(HAVE_ATTR_REMOVE)
1717 int flags = ATTR_DONTFOLLOW;
1718 char *attrname = strchr(name,'.') + 1;
1720 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1722 return attr_remove(path, attrname, flags);
1723 #elif defined(HAVE_ATTROPEN)
1725 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1726 if (attrdirfd >= 0) {
1727 ret = solaris_unlinkat(attrdirfd, name);
1737 int sys_fremovexattr (int filedes, const char *name)
1739 #if defined(HAVE_FREMOVEXATTR)
1740 #ifndef XATTR_ADD_OPT
1741 return fremovexattr(filedes, name);
1744 return fremovexattr(filedes, name, options);
1746 #elif defined(HAVE_FREMOVEEA)
1747 return fremoveea(filedes, name);
1748 #elif defined(HAVE_EXTATTR_DELETE_FD)
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_fd(filedes, attrnamespace, attrname);
1755 #elif defined(HAVE_ATTR_REMOVEF)
1757 char *attrname = strchr(name,'.') + 1;
1759 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1761 return attr_removef(filedes, attrname, flags);
1762 #elif defined(HAVE_ATTROPEN)
1764 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1765 if (attrdirfd >= 0) {
1766 ret = solaris_unlinkat(attrdirfd, name);
1776 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1778 #if defined(HAVE_SETXATTR)
1779 #ifndef XATTR_ADD_OPT
1780 return setxattr(path, name, value, size, flags);
1783 return setxattr(path, name, value, size, 0, options);
1785 #elif defined(HAVE_SETEA)
1786 return setea(path, name, value, size, flags);
1787 #elif defined(HAVE_EXTATTR_SET_FILE)
1790 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1791 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1792 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1794 /* Check attribute existence */
1795 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1797 /* REPLACE attribute, that doesn't exist */
1798 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1802 /* Ignore other errors */
1805 /* CREATE attribute, that already exists */
1806 if (flags & XATTR_CREATE) {
1812 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1813 return (retval < 0) ? -1 : 0;
1814 #elif defined(HAVE_ATTR_SET)
1816 char *attrname = strchr(name,'.') + 1;
1818 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1819 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1820 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1822 return attr_set(path, attrname, (const char *)value, size, myflags);
1823 #elif defined(HAVE_ATTROPEN)
1825 int myflags = O_RDWR;
1827 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1828 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1829 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1831 ret = solaris_write_xattr(attrfd, value, size);
1841 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1843 #if defined(HAVE_LSETXATTR)
1844 return lsetxattr(path, name, value, size, flags);
1845 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1846 int options = XATTR_NOFOLLOW;
1847 return setxattr(path, name, value, size, 0, options);
1848 #elif defined(LSETEA)
1849 return lsetea(path, name, value, size, flags);
1850 #elif defined(HAVE_EXTATTR_SET_LINK)
1853 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1854 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1855 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1857 /* Check attribute existence */
1858 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1860 /* REPLACE attribute, that doesn't exist */
1861 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1865 /* Ignore other errors */
1868 /* CREATE attribute, that already exists */
1869 if (flags & XATTR_CREATE) {
1876 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1877 return (retval < 0) ? -1 : 0;
1878 #elif defined(HAVE_ATTR_SET)
1879 int myflags = ATTR_DONTFOLLOW;
1880 char *attrname = strchr(name,'.') + 1;
1882 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1883 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1884 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1886 return attr_set(path, attrname, (const char *)value, size, myflags);
1887 #elif defined(HAVE_ATTROPEN)
1889 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1891 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1892 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1893 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1895 ret = solaris_write_xattr(attrfd, value, size);
1905 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1907 #if defined(HAVE_FSETXATTR)
1908 #ifndef XATTR_ADD_OPT
1909 return fsetxattr(filedes, name, value, size, flags);
1912 return fsetxattr(filedes, name, value, size, 0, options);
1914 #elif defined(HAVE_FSETEA)
1915 return fsetea(filedes, name, value, size, flags);
1916 #elif defined(HAVE_EXTATTR_SET_FD)
1919 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1920 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1921 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1923 /* Check attribute existence */
1924 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1926 /* REPLACE attribute, that doesn't exist */
1927 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1931 /* Ignore other errors */
1934 /* CREATE attribute, that already exists */
1935 if (flags & XATTR_CREATE) {
1941 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1942 return (retval < 0) ? -1 : 0;
1943 #elif defined(HAVE_ATTR_SETF)
1945 char *attrname = strchr(name,'.') + 1;
1947 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1948 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1949 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1951 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1952 #elif defined(HAVE_ATTROPEN)
1954 int myflags = O_RDWR | O_XATTR;
1956 if (flags & XATTR_CREATE) myflags |= O_EXCL;
1957 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1958 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1960 ret = solaris_write_xattr(attrfd, value, size);
1970 /**************************************************************************
1971 helper functions for Solaris' EA support
1972 ****************************************************************************/
1973 #ifdef HAVE_ATTROPEN
1974 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
1978 if (fstat(attrfd, &sbuf) == -1) {
1983 /* This is to return the current size of the named extended attribute */
1985 return sbuf.st_size;
1988 /* check size and read xattr */
1989 if (sbuf.st_size > size) {
1994 return read(attrfd, value, sbuf.st_size);
1997 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2003 int newfd = dup(attrdirfd);
2004 /* CAUTION: The originating file descriptor should not be
2005 used again following the call to fdopendir().
2006 For that reason we dup() the file descriptor
2007 here to make things more clear. */
2008 dirp = fdopendir(newfd);
2010 while ((de = readdir(dirp))) {
2011 size_t listlen = strlen(de->d_name);
2012 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2013 /* we don't want "." and ".." here: */
2014 DEBUG(10,("skipped EA %s\n",de->d_name));
2019 /* return the current size of the list of extended attribute names*/
2022 /* check size and copy entrieѕ + nul into list. */
2023 if ((len + listlen + 1) > size) {
2028 safe_strcpy(list + len, de->d_name, listlen);
2036 if (closedir(dirp) == -1) {
2037 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2043 static int solaris_unlinkat(int attrdirfd, const char *name)
2045 if (unlinkat(attrdirfd, name, 0) == -1) {
2046 if (errno == ENOENT) {
2054 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2056 int filedes = attropen(path, attrpath, oflag, mode);
2057 if (filedes == -1) {
2058 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2059 if (errno == EINVAL) {
2068 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2070 int filedes = openat(fildes, path, oflag, mode);
2071 if (filedes == -1) {
2072 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2073 if (errno == EINVAL) {
2082 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2084 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2087 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2091 #endif /*HAVE_ATTROPEN*/
2094 /****************************************************************************
2095 Return the major devicenumber for UNIX extensions.
2096 ****************************************************************************/
2098 uint32 unix_dev_major(SMB_DEV_T dev)
2100 #if defined(HAVE_DEVICE_MAJOR_FN)
2101 return (uint32)major(dev);
2103 return (uint32)(dev >> 8);
2107 /****************************************************************************
2108 Return the minor devicenumber for UNIX extensions.
2109 ****************************************************************************/
2111 uint32 unix_dev_minor(SMB_DEV_T dev)
2113 #if defined(HAVE_DEVICE_MINOR_FN)
2114 return (uint32)minor(dev);
2116 return (uint32)(dev & 0xff);
2120 #if defined(WITH_AIO)
2122 /*******************************************************************
2123 An aio_read wrapper that will deal with 64-bit sizes.
2124 ********************************************************************/
2126 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2128 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2129 return aio_read64(aiocb);
2130 #elif defined(HAVE_AIO_READ)
2131 return aio_read(aiocb);
2138 /*******************************************************************
2139 An aio_write wrapper that will deal with 64-bit sizes.
2140 ********************************************************************/
2142 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2144 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2145 return aio_write64(aiocb);
2146 #elif defined(HAVE_AIO_WRITE)
2147 return aio_write(aiocb);
2154 /*******************************************************************
2155 An aio_return wrapper that will deal with 64-bit sizes.
2156 ********************************************************************/
2158 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2160 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2161 return aio_return64(aiocb);
2162 #elif defined(HAVE_AIO_RETURN)
2163 return aio_return(aiocb);
2170 /*******************************************************************
2171 An aio_cancel wrapper that will deal with 64-bit sizes.
2172 ********************************************************************/
2174 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2176 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2177 return aio_cancel64(fd, aiocb);
2178 #elif defined(HAVE_AIO_CANCEL)
2179 return aio_cancel(fd, aiocb);
2186 /*******************************************************************
2187 An aio_error wrapper that will deal with 64-bit sizes.
2188 ********************************************************************/
2190 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2192 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2193 return aio_error64(aiocb);
2194 #elif defined(HAVE_AIO_ERROR)
2195 return aio_error(aiocb);
2202 /*******************************************************************
2203 An aio_fsync wrapper that will deal with 64-bit sizes.
2204 ********************************************************************/
2206 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2208 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2209 return aio_fsync64(op, aiocb);
2210 #elif defined(HAVE_AIO_FSYNC)
2211 return aio_fsync(op, aiocb);
2218 /*******************************************************************
2219 An aio_fsync wrapper that will deal with 64-bit sizes.
2220 ********************************************************************/
2222 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2224 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2225 return aio_suspend64(cblist, n, timeout);
2226 #elif defined(HAVE_AIO_FSYNC)
2227 return aio_suspend(cblist, n, timeout);
2233 #else /* !WITH_AIO */
2235 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2241 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2247 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2253 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2259 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2265 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2271 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2276 #endif /* WITH_AIO */
2278 int sys_getpeereid( int s, uid_t *uid)
2280 #if defined(HAVE_PEERCRED)
2282 socklen_t cred_len = sizeof(struct ucred);
2285 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2290 if (cred_len != sizeof(struct ucred)) {
2303 int sys_getnameinfo(const struct sockaddr *psa,
2312 * For Solaris we must make sure salen is the
2313 * correct length for the incoming sa_family.
2316 if (salen == sizeof(struct sockaddr_storage)) {
2317 salen = sizeof(struct sockaddr_in);
2318 #if defined(HAVE_IPV6)
2319 if (psa->sa_family == AF_INET6) {
2320 salen = sizeof(struct sockaddr_in6);
2324 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2327 int sys_connect(int fd, const struct sockaddr * addr)
2329 socklen_t salen = -1;
2331 if (addr->sa_family == AF_INET) {
2332 salen = sizeof(struct sockaddr_in);
2333 } else if (addr->sa_family == AF_UNIX) {
2334 salen = sizeof(struct sockaddr_un);
2336 #if defined(HAVE_IPV6)
2337 else if (addr->sa_family == AF_INET6) {
2338 salen = sizeof(struct sockaddr_in6);
2342 return connect(fd, addr, salen);