2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2005
6 Copyright (C) Timur Bakeyev 2005
7 Copyright (C) Bjoern Jacke 2006-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #ifdef HAVE_SYS_PRCTL_H
26 #include <sys/prctl.h>
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
33 - to enable easier porting by putting OS dependent stuff in here
35 - to allow for hooks into other "pseudo-filesystems"
37 - to allow easier integration of things like the japanese extensions
39 - to support the philosophy of Samba to expose the features of
40 the OS within the SMB model. In general whatever file/printer/variable
41 expansions/etc make sense to the OS should be acceptable to Samba.
46 /*******************************************************************
47 A wrapper for memalign
48 ********************************************************************/
50 void *sys_memalign( size_t align, size_t size )
52 #if defined(HAVE_POSIX_MEMALIGN)
54 int ret = posix_memalign( &p, align, size );
59 #elif defined(HAVE_MEMALIGN)
60 return memalign( align, size );
62 /* On *BSD systems memaligns doesn't exist, but memory will
63 * be aligned on allocations of > pagesize. */
64 #if defined(SYSCONF_SC_PAGESIZE)
65 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
66 #elif defined(HAVE_GETPAGESIZE)
67 size_t pagesize = (size_t)getpagesize();
69 size_t pagesize = (size_t)-1;
71 if (pagesize == (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
75 if (size < pagesize) {
78 return SMB_MALLOC(size);
82 /*******************************************************************
83 A wrapper for usleep in case we don't have one.
84 ********************************************************************/
86 int sys_usleep(long usecs)
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
97 if(usecs < 0 || usecs > 1000000) {
105 #else /* HAVE_USLEEP */
107 * Fake it with select...
110 tval.tv_usec = usecs/1000;
111 select(0,NULL,NULL,NULL,&tval);
113 #endif /* HAVE_USLEEP */
116 /*******************************************************************
117 A read wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_read(int fd, void *buf, size_t count)
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
130 /*******************************************************************
131 A write wrapper that will deal with EINTR.
132 ********************************************************************/
134 ssize_t sys_write(int fd, const void *buf, size_t count)
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
144 /*******************************************************************
145 A pread wrapper that will deal with EINTR and 64-bit file offsets.
146 ********************************************************************/
148 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
149 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
154 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
155 ret = pread64(fd, buf, count, off);
157 ret = pread(fd, buf, count, off);
159 } while (ret == -1 && errno == EINTR);
164 /*******************************************************************
165 A write wrapper that will deal with EINTR and 64-bit file offsets.
166 ********************************************************************/
168 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
169 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
174 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
175 ret = pwrite64(fd, buf, count, off);
177 ret = pwrite(fd, buf, count, off);
179 } while (ret == -1 && errno == EINTR);
184 /*******************************************************************
185 A send wrapper that will deal with EINTR.
186 ********************************************************************/
188 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
193 ret = send(s, msg, len, flags);
194 } while (ret == -1 && errno == EINTR);
198 /*******************************************************************
199 A sendto wrapper that will deal with EINTR.
200 ********************************************************************/
202 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
207 ret = sendto(s, msg, len, flags, to, tolen);
208 } while (ret == -1 && errno == EINTR);
212 /*******************************************************************
213 A recv wrapper that will deal with EINTR.
214 ********************************************************************/
216 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
221 ret = recv(fd, buf, count, flags);
222 } while (ret == -1 && errno == EINTR);
226 /*******************************************************************
227 A recvfrom wrapper that will deal with EINTR.
228 ********************************************************************/
230 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
235 ret = recvfrom(s, buf, len, flags, from, fromlen);
236 } while (ret == -1 && errno == EINTR);
240 /*******************************************************************
241 A fcntl wrapper that will deal with EINTR.
242 ********************************************************************/
244 int sys_fcntl_ptr(int fd, int cmd, void *arg)
249 ret = fcntl(fd, cmd, arg);
250 } while (ret == -1 && errno == EINTR);
254 /*******************************************************************
255 A fcntl wrapper that will deal with EINTR.
256 ********************************************************************/
258 int sys_fcntl_long(int fd, int cmd, long arg)
263 ret = fcntl(fd, cmd, arg);
264 } while (ret == -1 && errno == EINTR);
268 /*******************************************************************
269 A stat() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
272 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
275 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
276 ret = stat64(fname, sbuf);
278 ret = stat(fname, sbuf);
280 /* we always want directories to appear zero size */
281 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
285 /*******************************************************************
286 An fstat() wrapper that will deal with 64 bit filesizes.
287 ********************************************************************/
289 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
292 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
293 ret = fstat64(fd, sbuf);
295 ret = fstat(fd, sbuf);
297 /* we always want directories to appear zero size */
298 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
302 /*******************************************************************
303 An lstat() wrapper that will deal with 64 bit filesizes.
304 ********************************************************************/
306 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
309 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
310 ret = lstat64(fname, sbuf);
312 ret = lstat(fname, sbuf);
314 /* we always want directories to appear zero size */
315 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
319 /*******************************************************************
320 An ftruncate() wrapper that will deal with 64 bit filesizes.
321 ********************************************************************/
323 int sys_ftruncate(int fd, SMB_OFF_T offset)
325 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
326 return ftruncate64(fd, offset);
328 return ftruncate(fd, offset);
332 /*******************************************************************
333 An lseek() wrapper that will deal with 64 bit filesizes.
334 ********************************************************************/
336 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
338 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
339 return lseek64(fd, offset, whence);
341 return lseek(fd, offset, whence);
345 /*******************************************************************
346 An fseek() wrapper that will deal with 64 bit filesizes.
347 ********************************************************************/
349 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
351 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
352 return fseek64(fp, offset, whence);
353 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
354 return fseeko64(fp, offset, whence);
356 return fseek(fp, offset, whence);
360 /*******************************************************************
361 An ftell() wrapper that will deal with 64 bit filesizes.
362 ********************************************************************/
364 SMB_OFF_T sys_ftell(FILE *fp)
366 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
367 return (SMB_OFF_T)ftell64(fp);
368 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
369 return (SMB_OFF_T)ftello64(fp);
371 return (SMB_OFF_T)ftell(fp);
375 /*******************************************************************
376 A creat() wrapper that will deal with 64 bit filesizes.
377 ********************************************************************/
379 int sys_creat(const char *path, mode_t mode)
381 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
382 return creat64(path, mode);
385 * If creat64 isn't defined then ensure we call a potential open64.
388 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
392 /*******************************************************************
393 An open() wrapper that will deal with 64 bit filesizes.
394 ********************************************************************/
396 int sys_open(const char *path, int oflag, mode_t mode)
398 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
399 return open64(path, oflag, mode);
401 return open(path, oflag, mode);
405 /*******************************************************************
406 An fopen() wrapper that will deal with 64 bit filesizes.
407 ********************************************************************/
409 FILE *sys_fopen(const char *path, const char *type)
411 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
412 return fopen64(path, type);
414 return fopen(path, type);
419 /*******************************************************************
420 A flock() wrapper that will perform the kernel flock.
421 ********************************************************************/
423 void kernel_flock(int fd, uint32 share_mode)
425 #if HAVE_KERNEL_SHARE_MODES
427 if (share_mode == FILE_SHARE_WRITE) {
428 kernel_mode = LOCK_MAND|LOCK_WRITE;
429 } else if (share_mode == FILE_SHARE_READ) {
430 kernel_mode = LOCK_MAND|LOCK_READ;
431 } else if (share_mode == FILE_SHARE_NONE) {
432 kernel_mode = LOCK_MAND;
435 flock(fd, kernel_mode);
443 /*******************************************************************
444 An opendir wrapper that will deal with 64 bit filesizes.
445 ********************************************************************/
447 SMB_STRUCT_DIR *sys_opendir(const char *name)
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
450 return opendir64(name);
452 return opendir(name);
456 /*******************************************************************
457 A readdir wrapper that will deal with 64 bit filesizes.
458 ********************************************************************/
460 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
462 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
463 return readdir64(dirp);
465 return readdir(dirp);
469 /*******************************************************************
470 A seekdir wrapper that will deal with 64 bit filesizes.
471 ********************************************************************/
473 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
475 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
476 seekdir64(dirp, offset);
478 seekdir(dirp, offset);
482 /*******************************************************************
483 A telldir wrapper that will deal with 64 bit filesizes.
484 ********************************************************************/
486 long sys_telldir(SMB_STRUCT_DIR *dirp)
488 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
489 return (long)telldir64(dirp);
491 return (long)telldir(dirp);
495 /*******************************************************************
496 A rewinddir wrapper that will deal with 64 bit filesizes.
497 ********************************************************************/
499 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
501 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
508 /*******************************************************************
509 A close wrapper that will deal with 64 bit filesizes.
510 ********************************************************************/
512 int sys_closedir(SMB_STRUCT_DIR *dirp)
514 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
515 return closedir64(dirp);
517 return closedir(dirp);
521 /*******************************************************************
522 An mknod() wrapper that will deal with 64 bit filesizes.
523 ********************************************************************/
525 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
527 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
528 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
529 return mknod64(path, mode, dev);
531 return mknod(path, mode, dev);
534 /* No mknod system call. */
540 /*******************************************************************
541 Wrapper for realpath.
542 ********************************************************************/
544 char *sys_realpath(const char *path, char *resolved_path)
546 #if defined(HAVE_REALPATH)
547 return realpath(path, resolved_path);
549 /* As realpath is not a system call we can't return ENOSYS. */
555 /*******************************************************************
556 The wait() calls vary between systems
557 ********************************************************************/
559 int sys_waitpid(pid_t pid,int *status,int options)
562 return waitpid(pid,status,options);
563 #else /* HAVE_WAITPID */
564 return wait4(pid, status, options, NULL);
565 #endif /* HAVE_WAITPID */
568 /*******************************************************************
569 System wrapper for getwd
570 ********************************************************************/
572 char *sys_getwd(char *s)
577 wd = (char *)getcwd(s, PATH_MAX);
579 wd = (char *)getcwd(s, sizeof (pstring));
582 wd = (char *)getwd(s);
587 /*******************************************************************
588 system wrapper for symlink
589 ********************************************************************/
591 int sys_symlink(const char *oldpath, const char *newpath)
597 return symlink(oldpath, newpath);
601 /*******************************************************************
602 system wrapper for readlink
603 ********************************************************************/
605 int sys_readlink(const char *path, char *buf, size_t bufsiz)
607 #ifndef HAVE_READLINK
611 return readlink(path, buf, bufsiz);
615 /*******************************************************************
616 system wrapper for link
617 ********************************************************************/
619 int sys_link(const char *oldpath, const char *newpath)
625 return link(oldpath, newpath);
629 /*******************************************************************
630 chown isn't used much but OS/2 doesn't have it
631 ********************************************************************/
633 int sys_chown(const char *fname,uid_t uid,gid_t gid)
638 DEBUG(1,("WARNING: no chown!\n"));
644 return(chown(fname,uid,gid));
648 /*******************************************************************
650 ********************************************************************/
652 int sys_lchown(const char *fname,uid_t uid,gid_t gid)
657 DEBUG(1,("WARNING: no lchown!\n"));
663 return(lchown(fname,uid,gid));
667 /*******************************************************************
668 os/2 also doesn't have chroot
669 ********************************************************************/
670 int sys_chroot(const char *dname)
675 DEBUG(1,("WARNING: no chroot!\n"));
681 return(chroot(dname));
685 /**************************************************************************
686 A wrapper for gethostbyname() that tries avoids looking up hostnames
687 in the root domain, which can cause dial-on-demand links to come up for no
689 ****************************************************************************/
691 struct hostent *sys_gethostbyname(const char *name)
693 #ifdef REDUCE_ROOT_DNS_LOOKUPS
694 char query[256], hostname[256];
697 /* Does this name have any dots in it? If so, make no change */
699 if (strchr_m(name, '.'))
700 return(gethostbyname(name));
702 /* Get my hostname, which should have domain name
703 attached. If not, just do the gethostname on the
707 gethostname(hostname, sizeof(hostname) - 1);
708 hostname[sizeof(hostname) - 1] = 0;
709 if ((domain = strchr_m(hostname, '.')) == NULL)
710 return(gethostbyname(name));
712 /* Attach domain name to query and do modified query.
713 If names too large, just do gethostname on the
717 if((strlen(name) + strlen(domain)) >= sizeof(query))
718 return(gethostbyname(name));
720 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
721 return(gethostbyname(query));
722 #else /* REDUCE_ROOT_DNS_LOOKUPS */
723 return(gethostbyname(name));
724 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
728 #if defined(HAVE_POSIX_CAPABILITIES)
730 #ifdef HAVE_SYS_CAPABILITY_H
732 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
733 #define _I386_STATFS_H
734 #define _PPC_STATFS_H
735 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
738 #include <sys/capability.h>
740 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
741 #undef _I386_STATFS_H
743 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
746 #endif /* HAVE_SYS_CAPABILITY_H */
748 /**************************************************************************
749 Try and abstract process capabilities (for systems that have them).
750 ****************************************************************************/
752 /* Set the POSIX capabilities needed for the given purpose into the effective
753 * capability set of the current process. Make sure they are always removed
754 * from the inheritable set, because there is no circumstance in which our
755 * children should inherit our elevated privileges.
757 static BOOL set_process_capability(enum smbd_capability capability,
760 cap_value_t cap_vals[2] = {0};
761 int num_cap_vals = 0;
765 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
766 /* On Linux, make sure that any capabilities we grab are sticky
767 * across UID changes. We expect that this would allow us to keep both
768 * the effective and permitted capability sets, but as of circa 2.6.16,
769 * only the permitted set is kept. It is a bug (which we work around)
770 * that the effective set is lost, but we still require the effective
773 if (!prctl(PR_GET_KEEPCAPS)) {
774 prctl(PR_SET_KEEPCAPS, 1);
778 cap = cap_get_proc();
780 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
785 switch (capability) {
786 case KERNEL_OPLOCK_CAPABILITY:
787 #ifdef CAP_NETWORK_MGT
788 /* IRIX has CAP_NETWORK_MGT for oplocks. */
789 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
792 case DMAPI_ACCESS_CAPABILITY:
793 #ifdef CAP_DEVICE_MGT
794 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
795 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
797 /* Linux has CAP_MKNOD for DMAPI access. */
798 cap_vals[num_cap_vals++] = CAP_MKNOD;
803 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
805 if (num_cap_vals == 0) {
810 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
811 enable ? CAP_SET : CAP_CLEAR);
813 /* We never want to pass capabilities down to our children, so make
814 * sure they are not inherited.
816 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
818 if (cap_set_proc(cap) == -1) {
819 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
829 #endif /* HAVE_POSIX_CAPABILITIES */
831 /****************************************************************************
832 Gain the oplock capability from the kernel if possible.
833 ****************************************************************************/
835 void set_effective_capability(enum smbd_capability capability)
837 #if defined(HAVE_POSIX_CAPABILITIES)
838 set_process_capability(capability, True);
839 #endif /* HAVE_POSIX_CAPABILITIES */
842 void drop_effective_capability(enum smbd_capability capability)
844 #if defined(HAVE_POSIX_CAPABILITIES)
845 set_process_capability(capability, False);
846 #endif /* HAVE_POSIX_CAPABILITIES */
849 /**************************************************************************
850 Wrapper for random().
851 ****************************************************************************/
853 long sys_random(void)
855 #if defined(HAVE_RANDOM)
856 return (long)random();
857 #elif defined(HAVE_RAND)
860 DEBUG(0,("Error - no random function available !\n"));
865 /**************************************************************************
866 Wrapper for srandom().
867 ****************************************************************************/
869 void sys_srandom(unsigned int seed)
871 #if defined(HAVE_SRANDOM)
873 #elif defined(HAVE_SRAND)
876 DEBUG(0,("Error - no srandom function available !\n"));
881 /**************************************************************************
882 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
883 ****************************************************************************/
887 #if defined(SYSCONF_SC_NGROUPS_MAX)
888 int ret = sysconf(_SC_NGROUPS_MAX);
889 return (ret == -1) ? NGROUPS_MAX : ret;
895 /**************************************************************************
896 Wrap setgroups and getgroups for systems that declare getgroups() as
897 returning an array of gid_t, but actuall return an array of int.
898 ****************************************************************************/
900 #if defined(HAVE_BROKEN_GETGROUPS)
901 static int sys_broken_getgroups(int setlen, gid_t *gidset)
908 return getgroups(setlen, &gid);
912 * Broken case. We need to allocate a
913 * GID_T array of size setlen.
922 setlen = groups_max();
924 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
925 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
929 if((ngroups = getgroups(setlen, group_list)) < 0) {
930 int saved_errno = errno;
931 SAFE_FREE(group_list);
936 for(i = 0; i < ngroups; i++)
937 gidset[i] = (gid_t)group_list[i];
939 SAFE_FREE(group_list);
943 static int sys_broken_setgroups(int setlen, gid_t *gidset)
951 if (setlen < 0 || setlen > groups_max()) {
957 * Broken case. We need to allocate a
958 * GID_T array of size setlen.
961 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
962 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
966 for(i = 0; i < setlen; i++)
967 group_list[i] = (GID_T) gidset[i];
969 if(setgroups(setlen, group_list) != 0) {
970 int saved_errno = errno;
971 SAFE_FREE(group_list);
976 SAFE_FREE(group_list);
980 #endif /* HAVE_BROKEN_GETGROUPS */
982 /* This is a list of systems that require the first GID passed to setgroups(2)
983 * to be the effective GID. If your system is one of these, add it here.
985 #if defined (FREEBSD) || defined (DARWINOS)
986 #define USE_BSD_SETGROUPS
989 #if defined(USE_BSD_SETGROUPS)
990 /* Depending on the particular BSD implementation, the first GID that is
991 * passed to setgroups(2) will either be ignored or will set the credential's
992 * effective GID. In either case, the right thing to do is to guarantee that
993 * gidset[0] is the effective GID.
995 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
997 gid_t *new_gidset = NULL;
1001 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1004 /* No group list, just make sure we are setting the efective GID. */
1006 return setgroups(1, &primary_gid);
1009 /* If the primary gid is not the first array element, grow the array
1010 * and insert it at the front.
1012 if (gidset[0] != primary_gid) {
1013 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1014 if (new_gidset == NULL) {
1018 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1019 new_gidset[0] = primary_gid;
1024 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1029 #if defined(HAVE_BROKEN_GETGROUPS)
1030 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1032 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1037 SAFE_FREE(new_gidset);
1044 #endif /* USE_BSD_SETGROUPS */
1046 /**************************************************************************
1047 Wrapper for getgroups. Deals with broken (int) case.
1048 ****************************************************************************/
1050 int sys_getgroups(int setlen, gid_t *gidset)
1052 #if defined(HAVE_BROKEN_GETGROUPS)
1053 return sys_broken_getgroups(setlen, gidset);
1055 return getgroups(setlen, gidset);
1059 /**************************************************************************
1060 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1061 ****************************************************************************/
1063 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1065 #if !defined(HAVE_SETGROUPS)
1068 #endif /* HAVE_SETGROUPS */
1070 #if defined(USE_BSD_SETGROUPS)
1071 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1072 #elif defined(HAVE_BROKEN_GETGROUPS)
1073 return sys_broken_setgroups(setlen, gidset);
1075 return setgroups(setlen, gidset);
1079 /**************************************************************************
1080 Wrappers for setpwent(), getpwent() and endpwent()
1081 ****************************************************************************/
1083 void sys_setpwent(void)
1088 struct passwd *sys_getpwent(void)
1093 void sys_endpwent(void)
1098 /**************************************************************************
1099 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1100 ****************************************************************************/
1102 #ifdef ENABLE_BUILD_FARM_HACKS
1105 * In the build farm we want to be able to join machines to the domain. As we
1106 * don't have root access, we need to bypass direct access to /etc/passwd
1107 * after a user has been created via samr. Fake those users.
1110 static struct passwd *fake_pwd;
1111 static int num_fake_pwd;
1113 struct passwd *sys_getpwnam(const char *name)
1117 for (i=0; i<num_fake_pwd; i++) {
1118 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1119 DEBUG(10, ("Returning fake user %s\n", name));
1120 return &fake_pwd[i];
1124 return getpwnam(name);
1127 struct passwd *sys_getpwuid(uid_t uid)
1131 for (i=0; i<num_fake_pwd; i++) {
1132 if (fake_pwd[i].pw_uid == uid) {
1133 DEBUG(10, ("Returning fake user %s\n",
1134 fake_pwd[i].pw_name));
1135 return &fake_pwd[i];
1139 return getpwuid(uid);
1142 void faked_create_user(const char *name)
1146 struct passwd new_pwd;
1148 for (i=0; i<10; i++) {
1149 generate_random_buffer((unsigned char *)&uid,
1151 if (getpwuid(uid) == NULL) {
1157 /* Weird. No free uid found... */
1161 new_pwd.pw_name = SMB_STRDUP(name);
1162 new_pwd.pw_passwd = SMB_STRDUP("x");
1163 new_pwd.pw_uid = uid;
1164 new_pwd.pw_gid = 100;
1165 new_pwd.pw_gecos = SMB_STRDUP("faked user");
1166 new_pwd.pw_dir = SMB_STRDUP("/nodir");
1167 new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1169 ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1172 DEBUG(10, ("Added fake user %s, have %d fake users\n",
1173 name, num_fake_pwd));
1178 struct passwd *sys_getpwnam(const char *name)
1180 return getpwnam(name);
1183 struct passwd *sys_getpwuid(uid_t uid)
1185 return getpwuid(uid);
1190 struct group *sys_getgrnam(const char *name)
1192 return getgrnam(name);
1195 struct group *sys_getgrgid(gid_t gid)
1197 return getgrgid(gid);
1200 #if 0 /* NOT CURRENTLY USED - JRA */
1201 /**************************************************************************
1202 The following are the UNICODE versions of *all* system interface functions
1203 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1204 which currently are left as ascii as they are not used other than in name
1206 ****************************************************************************/
1208 /**************************************************************************
1209 Wide stat. Just narrow and call sys_xxx.
1210 ****************************************************************************/
1212 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1215 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1218 /**************************************************************************
1219 Wide lstat. Just narrow and call sys_xxx.
1220 ****************************************************************************/
1222 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1225 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1228 /**************************************************************************
1229 Wide creat. Just narrow and call sys_xxx.
1230 ****************************************************************************/
1232 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1235 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1238 /**************************************************************************
1239 Wide open. Just narrow and call sys_xxx.
1240 ****************************************************************************/
1242 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1245 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1248 /**************************************************************************
1249 Wide fopen. Just narrow and call sys_xxx.
1250 ****************************************************************************/
1252 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1255 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1258 /**************************************************************************
1259 Wide opendir. Just narrow and call sys_xxx.
1260 ****************************************************************************/
1262 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1265 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1268 /**************************************************************************
1269 Wide readdir. Return a structure pointer containing a wide filename.
1270 ****************************************************************************/
1272 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1274 static SMB_STRUCT_WDIRENT retval;
1275 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1281 * The only POSIX defined member of this struct is d_name.
1284 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1289 /**************************************************************************
1290 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1291 ****************************************************************************/
1293 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1296 char *p = sys_getwd(fname);
1301 return unix_to_unicode(s, p, sizeof(wpstring));
1304 /**************************************************************************
1305 Wide chown. Just narrow and call sys_xxx.
1306 ****************************************************************************/
1308 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1311 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1314 /**************************************************************************
1315 Wide chroot. Just narrow and call sys_xxx.
1316 ****************************************************************************/
1318 int wsys_chroot(const smb_ucs2_t *wfname)
1321 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1324 /**************************************************************************
1325 Wide getpwnam. Return a structure pointer containing wide names.
1326 ****************************************************************************/
1328 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1330 static SMB_STRUCT_WPASSWD retval;
1332 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1337 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1338 retval.pw_passwd = pwret->pw_passwd;
1339 retval.pw_uid = pwret->pw_uid;
1340 retval.pw_gid = pwret->pw_gid;
1341 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1342 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1343 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1348 /**************************************************************************
1349 Wide getpwuid. Return a structure pointer containing wide names.
1350 ****************************************************************************/
1352 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1354 static SMB_STRUCT_WPASSWD retval;
1355 struct passwd *pwret = sys_getpwuid(uid);
1360 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1361 retval.pw_passwd = pwret->pw_passwd;
1362 retval.pw_uid = pwret->pw_uid;
1363 retval.pw_gid = pwret->pw_gid;
1364 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1365 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1366 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1370 #endif /* NOT CURRENTLY USED - JRA */
1372 /**************************************************************************
1373 Extract a command into an arg list.
1374 ****************************************************************************/
1376 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1385 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1386 DEBUG(0, ("talloc failed\n"));
1390 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1391 TALLOC_FREE(trunc_cmd);
1400 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1403 TALLOC_FREE(trunc_cmd);
1405 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1410 * Now do the extraction.
1413 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1417 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1420 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1424 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1426 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1435 DEBUG(0, ("talloc failed\n"));
1436 TALLOC_FREE(trunc_cmd);
1442 /**************************************************************************
1443 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1444 a sys_getpid() that only does a system call *once*.
1445 ****************************************************************************/
1447 static pid_t mypid = (pid_t)-1;
1449 pid_t sys_fork(void)
1451 pid_t forkret = fork();
1453 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1459 /**************************************************************************
1460 Wrapper for getpid. Ensures we only do a system call *once*.
1461 ****************************************************************************/
1463 pid_t sys_getpid(void)
1465 if (mypid == (pid_t)-1)
1471 /**************************************************************************
1472 Wrapper for popen. Safer as it doesn't search a path.
1473 Modified from the glibc sources.
1474 modified by tridge to return a file descriptor. We must kick our FILE* habit
1475 ****************************************************************************/
1477 typedef struct _popen_list
1481 struct _popen_list *next;
1484 static popen_list *popen_chain;
1486 int sys_popen(const char *command)
1488 int parent_end, child_end;
1490 popen_list *entry = NULL;
1493 if (pipe(pipe_fds) < 0)
1496 parent_end = pipe_fds[0];
1497 child_end = pipe_fds[1];
1504 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1507 ZERO_STRUCTP(entry);
1510 * Extract the command and args into a NULL terminated array.
1513 if(!(argl = extract_args(NULL, command)))
1516 entry->child_pid = sys_fork();
1518 if (entry->child_pid == -1) {
1522 if (entry->child_pid == 0) {
1528 int child_std_end = STDOUT_FILENO;
1532 if (child_end != child_std_end) {
1533 dup2 (child_end, child_std_end);
1538 * POSIX.2: "popen() shall ensure that any streams from previous
1539 * popen() calls that remain open in the parent process are closed
1540 * in the new child process."
1543 for (p = popen_chain; p; p = p->next)
1546 execv(argl[0], argl);
1557 /* Link into popen_chain. */
1558 entry->next = popen_chain;
1559 popen_chain = entry;
1560 entry->fd = parent_end;
1573 /**************************************************************************
1574 Wrapper for pclose. Modified from the glibc sources.
1575 ****************************************************************************/
1577 int sys_pclose(int fd)
1580 popen_list **ptr = &popen_chain;
1581 popen_list *entry = NULL;
1585 /* Unlink from popen_chain. */
1586 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1587 if ((*ptr)->fd == fd) {
1589 *ptr = (*ptr)->next;
1595 if (status < 0 || close(entry->fd) < 0)
1599 * As Samba is catching and eating child process
1600 * exits we don't really care about the child exit
1601 * code, a -1 with errno = ECHILD will do fine for us.
1605 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1606 } while (wait_pid == -1 && errno == EINTR);
1615 /**************************************************************************
1616 Wrappers for dlopen, dlsym, dlclose.
1617 ****************************************************************************/
1619 void *sys_dlopen(const char *name, int flags)
1621 #if defined(HAVE_DLOPEN)
1622 return dlopen(name, flags);
1628 void *sys_dlsym(void *handle, const char *symbol)
1630 #if defined(HAVE_DLSYM)
1631 return dlsym(handle, symbol);
1637 int sys_dlclose (void *handle)
1639 #if defined(HAVE_DLCLOSE)
1640 return dlclose(handle);
1646 const char *sys_dlerror(void)
1648 #if defined(HAVE_DLERROR)
1655 int sys_dup2(int oldfd, int newfd)
1657 #if defined(HAVE_DUP2)
1658 return dup2(oldfd, newfd);
1665 /**************************************************************************
1666 Wrapper for Admin Logs.
1667 ****************************************************************************/
1669 void sys_adminlog(int priority, const char *format_str, ...)
1673 char *msgbuf = NULL;
1675 va_start( ap, format_str );
1676 ret = vasprintf( &msgbuf, format_str, ap );
1682 #if defined(HAVE_SYSLOG)
1683 syslog( priority, "%s", msgbuf );
1685 DEBUG(0,("%s", msgbuf ));
1690 /******** Solaris EA helper function prototypes ********/
1691 #ifdef HAVE_ATTROPEN
1692 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1693 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1694 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1695 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1696 static int solaris_unlinkat(int attrdirfd, const char *name);
1697 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1698 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1701 /**************************************************************************
1702 Wrappers for extented attribute calls. Based on the Linux package with
1703 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1704 ****************************************************************************/
1706 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1708 #if defined(HAVE_GETXATTR)
1709 #ifndef XATTR_ADD_OPT
1710 return getxattr(path, name, value, size);
1713 return getxattr(path, name, value, size, 0, options);
1715 #elif defined(HAVE_GETEA)
1716 return getea(path, name, value, size);
1717 #elif defined(HAVE_EXTATTR_GET_FILE)
1720 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1721 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1722 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1724 * The BSD implementation has a nasty habit of silently truncating
1725 * the returned value to the size of the buffer, so we have to check
1726 * that the buffer is large enough to fit the returned value.
1728 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1733 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1737 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1739 #elif defined(HAVE_ATTR_GET)
1740 int retval, flags = 0;
1741 int valuelength = (int)size;
1742 char *attrname = strchr(name,'.') + 1;
1744 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1746 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1748 return retval ? retval : valuelength;
1749 #elif defined(HAVE_ATTROPEN)
1751 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1753 ret = solaris_read_xattr(attrfd, value, size);
1763 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1765 #if defined(HAVE_LGETXATTR)
1766 return lgetxattr(path, name, value, size);
1767 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1768 int options = XATTR_NOFOLLOW;
1769 return getxattr(path, name, value, size, 0, options);
1770 #elif defined(HAVE_LGETEA)
1771 return lgetea(path, name, value, size);
1772 #elif defined(HAVE_EXTATTR_GET_LINK)
1775 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1776 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1777 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1779 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1784 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1788 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1790 #elif defined(HAVE_ATTR_GET)
1791 int retval, flags = ATTR_DONTFOLLOW;
1792 int valuelength = (int)size;
1793 char *attrname = strchr(name,'.') + 1;
1795 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1797 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1799 return retval ? retval : valuelength;
1800 #elif defined(HAVE_ATTROPEN)
1802 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1804 ret = solaris_read_xattr(attrfd, value, size);
1814 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1816 #if defined(HAVE_FGETXATTR)
1817 #ifndef XATTR_ADD_OPT
1818 return fgetxattr(filedes, name, value, size);
1821 return fgetxattr(filedes, name, value, size, 0, options);
1823 #elif defined(HAVE_FGETEA)
1824 return fgetea(filedes, name, value, size);
1825 #elif defined(HAVE_EXTATTR_GET_FD)
1828 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1829 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1830 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1832 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1837 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1841 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1843 #elif defined(HAVE_ATTR_GETF)
1844 int retval, flags = 0;
1845 int valuelength = (int)size;
1846 char *attrname = strchr(name,'.') + 1;
1848 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1850 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1852 return retval ? retval : valuelength;
1853 #elif defined(HAVE_ATTROPEN)
1855 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1857 ret = solaris_read_xattr(attrfd, value, size);
1867 #if defined(HAVE_EXTATTR_LIST_FILE)
1869 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1877 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1878 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1886 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1888 ssize_t list_size, total_size = 0;
1891 /* Iterate through extattr(2) namespaces */
1892 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1894 #if defined(HAVE_EXTATTR_LIST_FILE)
1896 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1899 #if defined(HAVE_EXTATTR_LIST_LINK)
1901 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1904 #if defined(HAVE_EXTATTR_LIST_FD)
1906 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1913 /* Some error happend. Errno should be set by the previous call */
1919 /* XXX: Call with an empty buffer may be used to calculate
1920 necessary buffer size. Unfortunately, we can't say, how
1921 many attributes were returned, so here is the potential
1922 problem with the emulation.
1925 /* Take the worse case of one char attribute names -
1926 two bytes per name plus one more for sanity.
1928 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1931 /* Count necessary offset to fit namespace prefixes */
1933 for(i = 0; i < list_size; i += list[i] + 1)
1934 len += extattr[t].len;
1936 total_size += list_size + len;
1937 /* Buffer is too small to fit the results */
1938 if(total_size > size) {
1942 /* Shift results back, so we can prepend prefixes */
1943 buf = memmove(list + len, list, list_size);
1945 for(i = 0; i < list_size; i += len + 1) {
1947 strncpy(list, extattr[t].name, extattr[t].len + 1);
1948 list += extattr[t].len;
1949 strncpy(list, buf + i + 1, len);
1960 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1961 static char attr_buffer[ATTR_MAX_VALUELEN];
1963 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1965 int retval = 0, index;
1966 attrlist_cursor_t *cursor = 0;
1968 attrlist_t * al = (attrlist_t *)attr_buffer;
1970 size_t ent_size, left = size;
1975 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1977 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1979 for (index = 0; index < al->al_count; index++) {
1980 ae = ATTR_ENTRY(attr_buffer, index);
1981 ent_size = strlen(ae->a_name) + sizeof("user.");
1982 if (left >= ent_size) {
1983 strncpy(bp, "user.", sizeof("user."));
1984 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1992 total_size += ent_size;
1994 if (al->al_more == 0) break;
2001 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
2003 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
2005 for (index = 0; index < al->al_count; index++) {
2006 ae = ATTR_ENTRY(attr_buffer, index);
2007 ent_size = strlen(ae->a_name) + sizeof("system.");
2008 if (left >= ent_size) {
2009 strncpy(bp, "system.", sizeof("system."));
2010 strncat(bp, ae->a_name, ent_size - sizeof("system."));
2018 total_size += ent_size;
2020 if (al->al_more == 0) break;
2023 return (ssize_t)(retval ? retval : total_size);
2028 ssize_t sys_listxattr (const char *path, char *list, size_t size)
2030 #if defined(HAVE_LISTXATTR)
2031 #ifndef XATTR_ADD_OPT
2032 return listxattr(path, list, size);
2035 return listxattr(path, list, size, options);
2037 #elif defined(HAVE_LISTEA)
2038 return listea(path, list, size);
2039 #elif defined(HAVE_EXTATTR_LIST_FILE)
2042 return bsd_attr_list(0, arg, list, size);
2043 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2044 return irix_attr_list(path, 0, list, size, 0);
2045 #elif defined(HAVE_ATTROPEN)
2047 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2048 if (attrdirfd >= 0) {
2049 ret = solaris_list_xattr(attrdirfd, list, size);
2059 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
2061 #if defined(HAVE_LLISTXATTR)
2062 return llistxattr(path, list, size);
2063 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
2064 int options = XATTR_NOFOLLOW;
2065 return listxattr(path, list, size, options);
2066 #elif defined(HAVE_LLISTEA)
2067 return llistea(path, list, size);
2068 #elif defined(HAVE_EXTATTR_LIST_LINK)
2071 return bsd_attr_list(1, arg, list, size);
2072 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2073 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
2074 #elif defined(HAVE_ATTROPEN)
2076 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2077 if (attrdirfd >= 0) {
2078 ret = solaris_list_xattr(attrdirfd, list, size);
2088 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
2090 #if defined(HAVE_FLISTXATTR)
2091 #ifndef XATTR_ADD_OPT
2092 return flistxattr(filedes, list, size);
2095 return flistxattr(filedes, list, size, options);
2097 #elif defined(HAVE_FLISTEA)
2098 return flistea(filedes, list, size);
2099 #elif defined(HAVE_EXTATTR_LIST_FD)
2101 arg.filedes = filedes;
2102 return bsd_attr_list(2, arg, list, size);
2103 #elif defined(HAVE_ATTR_LISTF)
2104 return irix_attr_list(NULL, filedes, list, size, 0);
2105 #elif defined(HAVE_ATTROPEN)
2107 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2108 if (attrdirfd >= 0) {
2109 ret = solaris_list_xattr(attrdirfd, list, size);
2119 int sys_removexattr (const char *path, const char *name)
2121 #if defined(HAVE_REMOVEXATTR)
2122 #ifndef XATTR_ADD_OPT
2123 return removexattr(path, name);
2126 return removexattr(path, name, options);
2128 #elif defined(HAVE_REMOVEEA)
2129 return removeea(path, name);
2130 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2132 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2133 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2134 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2136 return extattr_delete_file(path, attrnamespace, attrname);
2137 #elif defined(HAVE_ATTR_REMOVE)
2139 char *attrname = strchr(name,'.') + 1;
2141 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2143 return attr_remove(path, attrname, flags);
2144 #elif defined(HAVE_ATTROPEN)
2146 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2147 if (attrdirfd >= 0) {
2148 ret = solaris_unlinkat(attrdirfd, name);
2158 int sys_lremovexattr (const char *path, const char *name)
2160 #if defined(HAVE_LREMOVEXATTR)
2161 return lremovexattr(path, name);
2162 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2163 int options = XATTR_NOFOLLOW;
2164 return removexattr(path, name, options);
2165 #elif defined(HAVE_LREMOVEEA)
2166 return lremoveea(path, name);
2167 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2169 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2170 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2171 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2173 return extattr_delete_link(path, attrnamespace, attrname);
2174 #elif defined(HAVE_ATTR_REMOVE)
2175 int flags = ATTR_DONTFOLLOW;
2176 char *attrname = strchr(name,'.') + 1;
2178 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2180 return attr_remove(path, attrname, flags);
2181 #elif defined(HAVE_ATTROPEN)
2183 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2184 if (attrdirfd >= 0) {
2185 ret = solaris_unlinkat(attrdirfd, name);
2195 int sys_fremovexattr (int filedes, const char *name)
2197 #if defined(HAVE_FREMOVEXATTR)
2198 #ifndef XATTR_ADD_OPT
2199 return fremovexattr(filedes, name);
2202 return fremovexattr(filedes, name, options);
2204 #elif defined(HAVE_FREMOVEEA)
2205 return fremoveea(filedes, name);
2206 #elif defined(HAVE_EXTATTR_DELETE_FD)
2208 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2209 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2210 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2212 return extattr_delete_fd(filedes, attrnamespace, attrname);
2213 #elif defined(HAVE_ATTR_REMOVEF)
2215 char *attrname = strchr(name,'.') + 1;
2217 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2219 return attr_removef(filedes, attrname, flags);
2220 #elif defined(HAVE_ATTROPEN)
2222 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2223 if (attrdirfd >= 0) {
2224 ret = solaris_unlinkat(attrdirfd, name);
2234 #if !defined(HAVE_SETXATTR)
2235 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
2236 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
2239 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2241 #if defined(HAVE_SETXATTR)
2242 #ifndef XATTR_ADD_OPT
2243 return setxattr(path, name, value, size, flags);
2246 return setxattr(path, name, value, size, 0, options);
2248 #elif defined(HAVE_SETEA)
2249 return setea(path, name, value, size, flags);
2250 #elif defined(HAVE_EXTATTR_SET_FILE)
2253 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2254 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2255 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2257 /* Check attribute existence */
2258 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2260 /* REPLACE attribute, that doesn't exist */
2261 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2265 /* Ignore other errors */
2268 /* CREATE attribute, that already exists */
2269 if (flags & XATTR_CREATE) {
2275 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2276 return (retval < 0) ? -1 : 0;
2277 #elif defined(HAVE_ATTR_SET)
2279 char *attrname = strchr(name,'.') + 1;
2281 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2282 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2283 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2285 return attr_set(path, attrname, (const char *)value, size, myflags);
2286 #elif defined(HAVE_ATTROPEN)
2288 int myflags = O_RDWR;
2289 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2290 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2291 int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2293 ret = solaris_write_xattr(attrfd, value, size);
2303 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2305 #if defined(HAVE_LSETXATTR)
2306 return lsetxattr(path, name, value, size, flags);
2307 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2308 int options = XATTR_NOFOLLOW;
2309 return setxattr(path, name, value, size, 0, options);
2310 #elif defined(LSETEA)
2311 return lsetea(path, name, value, size, flags);
2312 #elif defined(HAVE_EXTATTR_SET_LINK)
2315 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2316 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2317 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2319 /* Check attribute existence */
2320 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2322 /* REPLACE attribute, that doesn't exist */
2323 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2327 /* Ignore other errors */
2330 /* CREATE attribute, that already exists */
2331 if (flags & XATTR_CREATE) {
2338 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2339 return (retval < 0) ? -1 : 0;
2340 #elif defined(HAVE_ATTR_SET)
2341 int myflags = ATTR_DONTFOLLOW;
2342 char *attrname = strchr(name,'.') + 1;
2344 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2345 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2346 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2348 return attr_set(path, attrname, (const char *)value, size, myflags);
2349 #elif defined(HAVE_ATTROPEN)
2351 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2352 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2353 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2354 int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2356 ret = solaris_write_xattr(attrfd, value, size);
2366 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2368 #if defined(HAVE_FSETXATTR)
2369 #ifndef XATTR_ADD_OPT
2370 return fsetxattr(filedes, name, value, size, flags);
2373 return fsetxattr(filedes, name, value, size, 0, options);
2375 #elif defined(HAVE_FSETEA)
2376 return fsetea(filedes, name, value, size, flags);
2377 #elif defined(HAVE_EXTATTR_SET_FD)
2380 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2381 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2382 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2384 /* Check attribute existence */
2385 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2387 /* REPLACE attribute, that doesn't exist */
2388 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2392 /* Ignore other errors */
2395 /* CREATE attribute, that already exists */
2396 if (flags & XATTR_CREATE) {
2402 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2403 return (retval < 0) ? -1 : 0;
2404 #elif defined(HAVE_ATTR_SETF)
2406 char *attrname = strchr(name,'.') + 1;
2408 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2409 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2410 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2412 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2413 #elif defined(HAVE_ATTROPEN)
2415 int myflags = O_RDWR | O_XATTR;
2416 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2417 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2418 int attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2420 ret = solaris_write_xattr(attrfd, value, size);
2430 /**************************************************************************
2431 helper functions for Solaris' EA support
2432 ****************************************************************************/
2433 #ifdef HAVE_ATTROPEN
2434 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2438 if (fstat(attrfd, &sbuf) == -1) {
2443 /* This is to return the current size of the named extended attribute */
2445 return sbuf.st_size;
2448 /* check size and read xattr */
2449 if (sbuf.st_size > size) {
2454 return read(attrfd, value, sbuf.st_size);
2457 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2463 int newfd = dup(attrdirfd);
2464 /* CAUTION: The originating file descriptor should not be
2465 used again following the call to fdopendir().
2466 For that reason we dup() the file descriptor
2467 here to make things more clear. */
2468 dirp = fdopendir(newfd);
2470 while ((de = readdir(dirp))) {
2471 size_t listlen = strlen(de->d_name);
2472 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2473 /* we don't want "." and ".." here: */
2474 DEBUG(10,("skipped EA %s\n",de->d_name));
2479 /* return the current size of the list of extended attribute names*/
2482 /* check size and copy entrieѕ + nul into list. */
2483 if ((len + listlen + 1) > size) {
2488 safe_strcpy(list + len, de->d_name, listlen);
2489 pstrcpy(list + len, de->d_name);
2497 if (closedir(dirp) == -1) {
2498 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2504 static int solaris_unlinkat(int attrdirfd, const char *name)
2506 if (unlinkat(attrdirfd, name, 0) == -1) {
2507 if (errno == ENOENT) {
2515 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2517 int filedes = attropen(path, attrpath, oflag, mode);
2518 if (filedes == -1) {
2519 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2520 if (errno == EINVAL) {
2529 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2531 int filedes = openat(fildes, path, oflag, mode);
2532 if (filedes == -1) {
2533 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2534 if (errno == EINVAL) {
2543 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2545 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2548 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2552 #endif /*HAVE_ATTROPEN*/
2555 /****************************************************************************
2556 Return the major devicenumber for UNIX extensions.
2557 ****************************************************************************/
2559 uint32 unix_dev_major(SMB_DEV_T dev)
2561 #if defined(HAVE_DEVICE_MAJOR_FN)
2562 return (uint32)major(dev);
2564 return (uint32)(dev >> 8);
2568 /****************************************************************************
2569 Return the minor devicenumber for UNIX extensions.
2570 ****************************************************************************/
2572 uint32 unix_dev_minor(SMB_DEV_T dev)
2574 #if defined(HAVE_DEVICE_MINOR_FN)
2575 return (uint32)minor(dev);
2577 return (uint32)(dev & 0xff);
2581 #if defined(WITH_AIO)
2583 /*******************************************************************
2584 An aio_read wrapper that will deal with 64-bit sizes.
2585 ********************************************************************/
2587 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2589 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2590 return aio_read64(aiocb);
2591 #elif defined(HAVE_AIO_READ)
2592 return aio_read(aiocb);
2599 /*******************************************************************
2600 An aio_write wrapper that will deal with 64-bit sizes.
2601 ********************************************************************/
2603 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2605 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2606 return aio_write64(aiocb);
2607 #elif defined(HAVE_AIO_WRITE)
2608 return aio_write(aiocb);
2615 /*******************************************************************
2616 An aio_return wrapper that will deal with 64-bit sizes.
2617 ********************************************************************/
2619 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2621 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2622 return aio_return64(aiocb);
2623 #elif defined(HAVE_AIO_RETURN)
2624 return aio_return(aiocb);
2631 /*******************************************************************
2632 An aio_cancel wrapper that will deal with 64-bit sizes.
2633 ********************************************************************/
2635 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2637 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2638 return aio_cancel64(fd, aiocb);
2639 #elif defined(HAVE_AIO_CANCEL)
2640 return aio_cancel(fd, aiocb);
2647 /*******************************************************************
2648 An aio_error wrapper that will deal with 64-bit sizes.
2649 ********************************************************************/
2651 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2653 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2654 return aio_error64(aiocb);
2655 #elif defined(HAVE_AIO_ERROR)
2656 return aio_error(aiocb);
2663 /*******************************************************************
2664 An aio_fsync wrapper that will deal with 64-bit sizes.
2665 ********************************************************************/
2667 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2669 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2670 return aio_fsync64(op, aiocb);
2671 #elif defined(HAVE_AIO_FSYNC)
2672 return aio_fsync(op, aiocb);
2679 /*******************************************************************
2680 An aio_fsync wrapper that will deal with 64-bit sizes.
2681 ********************************************************************/
2683 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2685 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2686 return aio_suspend64(cblist, n, timeout);
2687 #elif defined(HAVE_AIO_FSYNC)
2688 return aio_suspend(cblist, n, timeout);
2694 #else /* !WITH_AIO */
2696 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2702 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2708 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2714 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2720 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2726 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2732 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2737 #endif /* WITH_AIO */
2739 int sys_getpeereid( int s, uid_t *uid)
2741 #if defined(HAVE_PEERCRED)
2743 socklen_t cred_len = sizeof(struct ucred);
2746 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2751 if (cred_len != sizeof(struct ucred)) {