man pages: Fix synonyms.
[Samba.git] / source / lib / system.c
blobde5f55276e6257dcbaec13822b1fc2b0e6c21be2
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #ifdef HAVE_SYS_PRCTL_H
27 #include <sys/prctl.h>
28 #endif
31 The idea is that this file will eventually have wrappers around all
32 important system calls in samba. The aims are:
34 - to enable easier porting by putting OS dependent stuff in here
36 - to allow for hooks into other "pseudo-filesystems"
38 - to allow easier integration of things like the japanese extensions
40 - to support the philosophy of Samba to expose the features of
41 the OS within the SMB model. In general whatever file/printer/variable
42 expansions/etc make sense to the OS should be acceptable to Samba.
47 /*******************************************************************
48 A wrapper for memalign
49 ********************************************************************/
51 void *sys_memalign( size_t align, size_t size )
53 #if defined(HAVE_POSIX_MEMALIGN)
54 void *p = NULL;
55 int ret = posix_memalign( &p, align, size );
56 if ( ret == 0 )
57 return p;
59 return NULL;
60 #elif defined(HAVE_MEMALIGN)
61 return memalign( align, size );
62 #else
63 /* On *BSD systems memaligns doesn't exist, but memory will
64 * be aligned on allocations of > pagesize. */
65 #if defined(SYSCONF_SC_PAGESIZE)
66 size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
67 #elif defined(HAVE_GETPAGESIZE)
68 size_t pagesize = (size_t)getpagesize();
69 #else
70 size_t pagesize = (size_t)-1;
71 #endif
72 if (pagesize == (size_t)-1) {
73 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
74 return NULL;
76 if (size < pagesize) {
77 size = pagesize;
79 return SMB_MALLOC(size);
80 #endif
83 /*******************************************************************
84 A wrapper for usleep in case we don't have one.
85 ********************************************************************/
87 int sys_usleep(long usecs)
89 #ifndef HAVE_USLEEP
90 struct timeval tval;
91 #endif
94 * We need this braindamage as the glibc usleep
95 * is not SPEC1170 complient... grumble... JRA.
98 if(usecs < 0 || usecs > 1000000) {
99 errno = EINVAL;
100 return -1;
103 #if HAVE_USLEEP
104 usleep(usecs);
105 return 0;
106 #else /* HAVE_USLEEP */
108 * Fake it with select...
110 tval.tv_sec = 0;
111 tval.tv_usec = usecs/1000;
112 select(0,NULL,NULL,NULL,&tval);
113 return 0;
114 #endif /* HAVE_USLEEP */
117 /*******************************************************************
118 A read wrapper that will deal with EINTR.
119 ********************************************************************/
121 ssize_t sys_read(int fd, void *buf, size_t count)
123 ssize_t ret;
125 do {
126 ret = read(fd, buf, count);
127 } while (ret == -1 && errno == EINTR);
128 return ret;
131 /*******************************************************************
132 A write wrapper that will deal with EINTR.
133 ********************************************************************/
135 ssize_t sys_write(int fd, const void *buf, size_t count)
137 ssize_t ret;
139 do {
140 ret = write(fd, buf, count);
141 } while (ret == -1 && errno == EINTR);
142 return ret;
145 /*******************************************************************
146 A pread wrapper that will deal with EINTR and 64-bit file offsets.
147 ********************************************************************/
149 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
150 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
152 ssize_t ret;
154 do {
155 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
156 ret = pread64(fd, buf, count, off);
157 #else
158 ret = pread(fd, buf, count, off);
159 #endif
160 } while (ret == -1 && errno == EINTR);
161 return ret;
163 #endif
165 /*******************************************************************
166 A write wrapper that will deal with EINTR and 64-bit file offsets.
167 ********************************************************************/
169 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
170 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
172 ssize_t ret;
174 do {
175 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
176 ret = pwrite64(fd, buf, count, off);
177 #else
178 ret = pwrite(fd, buf, count, off);
179 #endif
180 } while (ret == -1 && errno == EINTR);
181 return ret;
183 #endif
185 /*******************************************************************
186 A send wrapper that will deal with EINTR.
187 ********************************************************************/
189 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
191 ssize_t ret;
193 do {
194 ret = send(s, msg, len, flags);
195 } while (ret == -1 && errno == EINTR);
196 return ret;
199 /*******************************************************************
200 A sendto wrapper that will deal with EINTR.
201 ********************************************************************/
203 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
205 ssize_t ret;
207 do {
208 ret = sendto(s, msg, len, flags, to, tolen);
209 } while (ret == -1 && errno == EINTR);
210 return ret;
213 /*******************************************************************
214 A recv wrapper that will deal with EINTR.
215 ********************************************************************/
217 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
219 ssize_t ret;
221 do {
222 ret = recv(fd, buf, count, flags);
223 } while (ret == -1 && errno == EINTR);
224 return ret;
227 /*******************************************************************
228 A recvfrom wrapper that will deal with EINTR.
229 ********************************************************************/
231 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
233 ssize_t ret;
235 do {
236 ret = recvfrom(s, buf, len, flags, from, fromlen);
237 } while (ret == -1 && errno == EINTR);
238 return ret;
241 /*******************************************************************
242 A fcntl wrapper that will deal with EINTR.
243 ********************************************************************/
245 int sys_fcntl_ptr(int fd, int cmd, void *arg)
247 int ret;
249 do {
250 ret = fcntl(fd, cmd, arg);
251 } while (ret == -1 && errno == EINTR);
252 return ret;
255 /*******************************************************************
256 A fcntl wrapper that will deal with EINTR.
257 ********************************************************************/
259 int sys_fcntl_long(int fd, int cmd, long arg)
261 int ret;
263 do {
264 ret = fcntl(fd, cmd, arg);
265 } while (ret == -1 && errno == EINTR);
266 return ret;
269 /*******************************************************************
270 A stat() wrapper that will deal with 64 bit filesizes.
271 ********************************************************************/
273 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
275 int ret;
276 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
277 ret = stat64(fname, sbuf);
278 #else
279 ret = stat(fname, sbuf);
280 #endif
281 /* we always want directories to appear zero size */
282 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
283 return ret;
286 /*******************************************************************
287 An fstat() wrapper that will deal with 64 bit filesizes.
288 ********************************************************************/
290 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
292 int ret;
293 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
294 ret = fstat64(fd, sbuf);
295 #else
296 ret = fstat(fd, sbuf);
297 #endif
298 /* we always want directories to appear zero size */
299 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
300 return ret;
303 /*******************************************************************
304 An lstat() wrapper that will deal with 64 bit filesizes.
305 ********************************************************************/
307 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
309 int ret;
310 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
311 ret = lstat64(fname, sbuf);
312 #else
313 ret = lstat(fname, sbuf);
314 #endif
315 /* we always want directories to appear zero size */
316 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
317 return ret;
320 /*******************************************************************
321 An ftruncate() wrapper that will deal with 64 bit filesizes.
322 ********************************************************************/
324 int sys_ftruncate(int fd, SMB_OFF_T offset)
326 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
327 return ftruncate64(fd, offset);
328 #else
329 return ftruncate(fd, offset);
330 #endif
333 /*******************************************************************
334 An lseek() wrapper that will deal with 64 bit filesizes.
335 ********************************************************************/
337 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
339 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
340 return lseek64(fd, offset, whence);
341 #else
342 return lseek(fd, offset, whence);
343 #endif
346 /*******************************************************************
347 An fseek() wrapper that will deal with 64 bit filesizes.
348 ********************************************************************/
350 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
352 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
353 return fseek64(fp, offset, whence);
354 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
355 return fseeko64(fp, offset, whence);
356 #else
357 return fseek(fp, offset, whence);
358 #endif
361 /*******************************************************************
362 An ftell() wrapper that will deal with 64 bit filesizes.
363 ********************************************************************/
365 SMB_OFF_T sys_ftell(FILE *fp)
367 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
368 return (SMB_OFF_T)ftell64(fp);
369 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
370 return (SMB_OFF_T)ftello64(fp);
371 #else
372 return (SMB_OFF_T)ftell(fp);
373 #endif
376 /*******************************************************************
377 A creat() wrapper that will deal with 64 bit filesizes.
378 ********************************************************************/
380 int sys_creat(const char *path, mode_t mode)
382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
383 return creat64(path, mode);
384 #else
386 * If creat64 isn't defined then ensure we call a potential open64.
387 * JRA.
389 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
390 #endif
393 /*******************************************************************
394 An open() wrapper that will deal with 64 bit filesizes.
395 ********************************************************************/
397 int sys_open(const char *path, int oflag, mode_t mode)
399 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
400 return open64(path, oflag, mode);
401 #else
402 return open(path, oflag, mode);
403 #endif
406 /*******************************************************************
407 An fopen() wrapper that will deal with 64 bit filesizes.
408 ********************************************************************/
410 FILE *sys_fopen(const char *path, const char *type)
412 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
413 return fopen64(path, type);
414 #else
415 return fopen(path, type);
416 #endif
420 /*******************************************************************
421 A flock() wrapper that will perform the kernel flock.
422 ********************************************************************/
424 void kernel_flock(int fd, uint32 share_mode)
426 #if HAVE_KERNEL_SHARE_MODES
427 int kernel_mode = 0;
428 if (share_mode == FILE_SHARE_WRITE) {
429 kernel_mode = LOCK_MAND|LOCK_WRITE;
430 } else if (share_mode == FILE_SHARE_READ) {
431 kernel_mode = LOCK_MAND|LOCK_READ;
432 } else if (share_mode == FILE_SHARE_NONE) {
433 kernel_mode = LOCK_MAND;
435 if (kernel_mode) {
436 flock(fd, kernel_mode);
438 #endif
444 /*******************************************************************
445 An opendir wrapper that will deal with 64 bit filesizes.
446 ********************************************************************/
448 SMB_STRUCT_DIR *sys_opendir(const char *name)
450 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
451 return opendir64(name);
452 #else
453 return opendir(name);
454 #endif
457 /*******************************************************************
458 A readdir wrapper that will deal with 64 bit filesizes.
459 ********************************************************************/
461 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
463 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
464 return readdir64(dirp);
465 #else
466 return readdir(dirp);
467 #endif
470 /*******************************************************************
471 A seekdir wrapper that will deal with 64 bit filesizes.
472 ********************************************************************/
474 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
476 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
477 seekdir64(dirp, offset);
478 #else
479 seekdir(dirp, offset);
480 #endif
483 /*******************************************************************
484 A telldir wrapper that will deal with 64 bit filesizes.
485 ********************************************************************/
487 long sys_telldir(SMB_STRUCT_DIR *dirp)
489 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
490 return (long)telldir64(dirp);
491 #else
492 return (long)telldir(dirp);
493 #endif
496 /*******************************************************************
497 A rewinddir wrapper that will deal with 64 bit filesizes.
498 ********************************************************************/
500 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
502 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
503 rewinddir64(dirp);
504 #else
505 rewinddir(dirp);
506 #endif
509 /*******************************************************************
510 A close wrapper that will deal with 64 bit filesizes.
511 ********************************************************************/
513 int sys_closedir(SMB_STRUCT_DIR *dirp)
515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
516 return closedir64(dirp);
517 #else
518 return closedir(dirp);
519 #endif
522 /*******************************************************************
523 An mknod() wrapper that will deal with 64 bit filesizes.
524 ********************************************************************/
526 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
528 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
529 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
530 return mknod64(path, mode, dev);
531 #else
532 return mknod(path, mode, dev);
533 #endif
534 #else
535 /* No mknod system call. */
536 errno = ENOSYS;
537 return -1;
538 #endif
541 /*******************************************************************
542 Wrapper for realpath.
543 ********************************************************************/
545 char *sys_realpath(const char *path, char *resolved_path)
547 #if defined(HAVE_REALPATH)
548 return realpath(path, resolved_path);
549 #else
550 /* As realpath is not a system call we can't return ENOSYS. */
551 errno = EINVAL;
552 return NULL;
553 #endif
556 /*******************************************************************
557 The wait() calls vary between systems
558 ********************************************************************/
560 int sys_waitpid(pid_t pid,int *status,int options)
562 #ifdef HAVE_WAITPID
563 return waitpid(pid,status,options);
564 #else /* HAVE_WAITPID */
565 return wait4(pid, status, options, NULL);
566 #endif /* HAVE_WAITPID */
569 /*******************************************************************
570 System wrapper for getwd
571 ********************************************************************/
573 char *sys_getwd(char *s)
575 char *wd;
576 #ifdef HAVE_GETCWD
577 wd = (char *)getcwd(s, sizeof (pstring));
578 #else
579 wd = (char *)getwd(s);
580 #endif
581 return wd;
584 /*******************************************************************
585 system wrapper for symlink
586 ********************************************************************/
588 int sys_symlink(const char *oldpath, const char *newpath)
590 #ifndef HAVE_SYMLINK
591 errno = ENOSYS;
592 return -1;
593 #else
594 return symlink(oldpath, newpath);
595 #endif
598 /*******************************************************************
599 system wrapper for readlink
600 ********************************************************************/
602 int sys_readlink(const char *path, char *buf, size_t bufsiz)
604 #ifndef HAVE_READLINK
605 errno = ENOSYS;
606 return -1;
607 #else
608 return readlink(path, buf, bufsiz);
609 #endif
612 /*******************************************************************
613 system wrapper for link
614 ********************************************************************/
616 int sys_link(const char *oldpath, const char *newpath)
618 #ifndef HAVE_LINK
619 errno = ENOSYS;
620 return -1;
621 #else
622 return link(oldpath, newpath);
623 #endif
626 /*******************************************************************
627 chown isn't used much but OS/2 doesn't have it
628 ********************************************************************/
630 int sys_chown(const char *fname,uid_t uid,gid_t gid)
632 #ifndef HAVE_CHOWN
633 static int done;
634 if (!done) {
635 DEBUG(1,("WARNING: no chown!\n"));
636 done=1;
638 errno = ENOSYS;
639 return -1;
640 #else
641 return(chown(fname,uid,gid));
642 #endif
645 /*******************************************************************
646 os/2 also doesn't have chroot
647 ********************************************************************/
648 int sys_chroot(const char *dname)
650 #ifndef HAVE_CHROOT
651 static int done;
652 if (!done) {
653 DEBUG(1,("WARNING: no chroot!\n"));
654 done=1;
656 errno = ENOSYS;
657 return -1;
658 #else
659 return(chroot(dname));
660 #endif
663 /**************************************************************************
664 A wrapper for gethostbyname() that tries avoids looking up hostnames
665 in the root domain, which can cause dial-on-demand links to come up for no
666 apparent reason.
667 ****************************************************************************/
669 struct hostent *sys_gethostbyname(const char *name)
671 #ifdef REDUCE_ROOT_DNS_LOOKUPS
672 char query[256], hostname[256];
673 char *domain;
675 /* Does this name have any dots in it? If so, make no change */
677 if (strchr_m(name, '.'))
678 return(gethostbyname(name));
680 /* Get my hostname, which should have domain name
681 attached. If not, just do the gethostname on the
682 original string.
685 gethostname(hostname, sizeof(hostname) - 1);
686 hostname[sizeof(hostname) - 1] = 0;
687 if ((domain = strchr_m(hostname, '.')) == NULL)
688 return(gethostbyname(name));
690 /* Attach domain name to query and do modified query.
691 If names too large, just do gethostname on the
692 original string.
695 if((strlen(name) + strlen(domain)) >= sizeof(query))
696 return(gethostbyname(name));
698 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
699 return(gethostbyname(query));
700 #else /* REDUCE_ROOT_DNS_LOOKUPS */
701 return(gethostbyname(name));
702 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
706 #if defined(HAVE_POSIX_CAPABILITIES)
708 #ifdef HAVE_SYS_CAPABILITY_H
710 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
711 #define _I386_STATFS_H
712 #define _PPC_STATFS_H
713 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
714 #endif
716 #include <sys/capability.h>
718 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
719 #undef _I386_STATFS_H
720 #undef _PPC_STATFS_H
721 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
722 #endif
724 #endif /* HAVE_SYS_CAPABILITY_H */
726 /**************************************************************************
727 Try and abstract process capabilities (for systems that have them).
728 ****************************************************************************/
730 /* Set the POSIX capabilities needed for the given purpose into the effective
731 * capability set of the current process. Make sure they are always removed
732 * from the inheritable set, because there is no circumstance in which our
733 * children should inherit our elevated privileges.
735 static BOOL set_process_capability(enum smbd_capability capability,
736 BOOL enable)
738 cap_value_t cap_vals[2] = {0};
739 int num_cap_vals = 0;
741 cap_t cap;
743 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
744 /* On Linux, make sure that any capabilities we grab are sticky
745 * across UID changes. We expect that this would allow us to keep both
746 * the effective and permitted capability sets, but as of circa 2.6.16,
747 * only the permitted set is kept. It is a bug (which we work around)
748 * that the effective set is lost, but we still require the effective
749 * set to be kept.
751 if (!prctl(PR_GET_KEEPCAPS)) {
752 prctl(PR_SET_KEEPCAPS, 1);
754 #endif
756 cap = cap_get_proc();
757 if (cap == NULL) {
758 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
759 strerror(errno)));
760 return False;
763 switch (capability) {
764 case KERNEL_OPLOCK_CAPABILITY:
765 #ifdef CAP_NETWORK_MGT
766 /* IRIX has CAP_NETWORK_MGT for oplocks. */
767 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
768 #endif
769 break;
770 case DMAPI_ACCESS_CAPABILITY:
771 #ifdef CAP_DEVICE_MGT
772 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
773 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
774 #elif CAP_MKNOD
775 /* Linux has CAP_MKNOD for DMAPI access. */
776 cap_vals[num_cap_vals++] = CAP_MKNOD;
777 #endif
778 break;
779 case LEASE_CAPABILITY:
780 #ifdef CAP_LEASE
781 cap_vals[num_cap_vals++] = CAP_LEASE;
782 #endif
783 break;
786 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
788 if (num_cap_vals == 0) {
789 cap_free(cap);
790 return True;
793 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
794 enable ? CAP_SET : CAP_CLEAR);
796 /* We never want to pass capabilities down to our children, so make
797 * sure they are not inherited.
799 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
801 if (cap_set_proc(cap) == -1) {
802 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
803 strerror(errno)));
804 cap_free(cap);
805 return False;
808 cap_free(cap);
809 return True;
812 #endif /* HAVE_POSIX_CAPABILITIES */
814 /****************************************************************************
815 Gain the oplock capability from the kernel if possible.
816 ****************************************************************************/
818 void set_effective_capability(enum smbd_capability capability)
820 #if defined(HAVE_POSIX_CAPABILITIES)
821 set_process_capability(capability, True);
822 #endif /* HAVE_POSIX_CAPABILITIES */
825 void drop_effective_capability(enum smbd_capability capability)
827 #if defined(HAVE_POSIX_CAPABILITIES)
828 set_process_capability(capability, False);
829 #endif /* HAVE_POSIX_CAPABILITIES */
832 /**************************************************************************
833 Wrapper for random().
834 ****************************************************************************/
836 long sys_random(void)
838 #if defined(HAVE_RANDOM)
839 return (long)random();
840 #elif defined(HAVE_RAND)
841 return (long)rand();
842 #else
843 DEBUG(0,("Error - no random function available !\n"));
844 exit(1);
845 #endif
848 /**************************************************************************
849 Wrapper for srandom().
850 ****************************************************************************/
852 void sys_srandom(unsigned int seed)
854 #if defined(HAVE_SRANDOM)
855 srandom(seed);
856 #elif defined(HAVE_SRAND)
857 srand(seed);
858 #else
859 DEBUG(0,("Error - no srandom function available !\n"));
860 exit(1);
861 #endif
864 /**************************************************************************
865 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
866 ****************************************************************************/
868 int groups_max(void)
870 #if defined(SYSCONF_SC_NGROUPS_MAX)
871 int ret = sysconf(_SC_NGROUPS_MAX);
872 return (ret == -1) ? NGROUPS_MAX : ret;
873 #else
874 return NGROUPS_MAX;
875 #endif
878 /**************************************************************************
879 Wrapper for getgroups. Deals with broken (int) case.
880 ****************************************************************************/
882 int sys_getgroups(int setlen, gid_t *gidset)
884 #if !defined(HAVE_BROKEN_GETGROUPS)
885 return getgroups(setlen, gidset);
886 #else
888 GID_T gid;
889 GID_T *group_list;
890 int i, ngroups;
892 if(setlen == 0) {
893 return getgroups(setlen, &gid);
897 * Broken case. We need to allocate a
898 * GID_T array of size setlen.
901 if(setlen < 0) {
902 errno = EINVAL;
903 return -1;
906 if (setlen == 0)
907 setlen = groups_max();
909 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
910 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
911 return -1;
914 if((ngroups = getgroups(setlen, group_list)) < 0) {
915 int saved_errno = errno;
916 SAFE_FREE(group_list);
917 errno = saved_errno;
918 return -1;
921 for(i = 0; i < ngroups; i++)
922 gidset[i] = (gid_t)group_list[i];
924 SAFE_FREE(group_list);
925 return ngroups;
926 #endif /* HAVE_BROKEN_GETGROUPS */
930 /**************************************************************************
931 Wrapper for setgroups. Deals with broken (int) case. Automatically used
932 if we have broken getgroups.
933 ****************************************************************************/
935 int sys_setgroups(int setlen, gid_t *gidset)
937 #if !defined(HAVE_SETGROUPS)
938 errno = ENOSYS;
939 return -1;
940 #endif /* HAVE_SETGROUPS */
942 #if !defined(HAVE_BROKEN_GETGROUPS)
943 return setgroups(setlen, gidset);
944 #else
946 GID_T *group_list;
947 int i ;
949 if (setlen == 0)
950 return 0 ;
952 if (setlen < 0 || setlen > groups_max()) {
953 errno = EINVAL;
954 return -1;
958 * Broken case. We need to allocate a
959 * GID_T array of size setlen.
962 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
963 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
964 return -1;
967 for(i = 0; i < setlen; i++)
968 group_list[i] = (GID_T) gidset[i];
970 if(setgroups(setlen, group_list) != 0) {
971 int saved_errno = errno;
972 SAFE_FREE(group_list);
973 errno = saved_errno;
974 return -1;
977 SAFE_FREE(group_list);
978 return 0 ;
979 #endif /* HAVE_BROKEN_GETGROUPS */
982 /**************************************************************************
983 Wrappers for setpwent(), getpwent() and endpwent()
984 ****************************************************************************/
986 void sys_setpwent(void)
988 setpwent();
991 struct passwd *sys_getpwent(void)
993 return getpwent();
996 void sys_endpwent(void)
998 endpwent();
1001 /**************************************************************************
1002 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1003 ****************************************************************************/
1005 #ifdef ENABLE_BUILD_FARM_HACKS
1008 * In the build farm we want to be able to join machines to the domain. As we
1009 * don't have root access, we need to bypass direct access to /etc/passwd
1010 * after a user has been created via samr. Fake those users.
1013 static struct passwd *fake_pwd;
1014 static int num_fake_pwd;
1016 struct passwd *sys_getpwnam(const char *name)
1018 int i;
1020 for (i=0; i<num_fake_pwd; i++) {
1021 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
1022 DEBUG(10, ("Returning fake user %s\n", name));
1023 return &fake_pwd[i];
1027 return getpwnam(name);
1030 struct passwd *sys_getpwuid(uid_t uid)
1032 int i;
1034 for (i=0; i<num_fake_pwd; i++) {
1035 if (fake_pwd[i].pw_uid == uid) {
1036 DEBUG(10, ("Returning fake user %s\n",
1037 fake_pwd[i].pw_name));
1038 return &fake_pwd[i];
1042 return getpwuid(uid);
1045 void faked_create_user(const char *name)
1047 int i;
1048 uid_t uid;
1049 struct passwd new_pwd;
1051 for (i=0; i<10; i++) {
1052 generate_random_buffer((unsigned char *)&uid,
1053 sizeof(uid));
1054 if (getpwuid(uid) == NULL) {
1055 break;
1059 if (i==10) {
1060 /* Weird. No free uid found... */
1061 return;
1064 new_pwd.pw_name = SMB_STRDUP(name);
1065 new_pwd.pw_passwd = SMB_STRDUP("x");
1066 new_pwd.pw_uid = uid;
1067 new_pwd.pw_gid = 100;
1068 new_pwd.pw_gecos = SMB_STRDUP("faked user");
1069 new_pwd.pw_dir = SMB_STRDUP("/nodir");
1070 new_pwd.pw_shell = SMB_STRDUP("/bin/false");
1072 ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
1073 &num_fake_pwd);
1075 DEBUG(10, ("Added fake user %s, have %d fake users\n",
1076 name, num_fake_pwd));
1079 #else
1081 struct passwd *sys_getpwnam(const char *name)
1083 return getpwnam(name);
1086 struct passwd *sys_getpwuid(uid_t uid)
1088 return getpwuid(uid);
1091 #endif
1093 struct group *sys_getgrnam(const char *name)
1095 return getgrnam(name);
1098 struct group *sys_getgrgid(gid_t gid)
1100 return getgrgid(gid);
1103 #if 0 /* NOT CURRENTLY USED - JRA */
1104 /**************************************************************************
1105 The following are the UNICODE versions of *all* system interface functions
1106 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
1107 which currently are left as ascii as they are not used other than in name
1108 resolution.
1109 ****************************************************************************/
1111 /**************************************************************************
1112 Wide stat. Just narrow and call sys_xxx.
1113 ****************************************************************************/
1115 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1117 pstring fname;
1118 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1121 /**************************************************************************
1122 Wide lstat. Just narrow and call sys_xxx.
1123 ****************************************************************************/
1125 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
1127 pstring fname;
1128 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
1131 /**************************************************************************
1132 Wide creat. Just narrow and call sys_xxx.
1133 ****************************************************************************/
1135 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
1137 pstring fname;
1138 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
1141 /**************************************************************************
1142 Wide open. Just narrow and call sys_xxx.
1143 ****************************************************************************/
1145 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
1147 pstring fname;
1148 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
1151 /**************************************************************************
1152 Wide fopen. Just narrow and call sys_xxx.
1153 ****************************************************************************/
1155 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
1157 pstring fname;
1158 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
1161 /**************************************************************************
1162 Wide opendir. Just narrow and call sys_xxx.
1163 ****************************************************************************/
1165 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
1167 pstring fname;
1168 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
1171 /**************************************************************************
1172 Wide readdir. Return a structure pointer containing a wide filename.
1173 ****************************************************************************/
1175 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
1177 static SMB_STRUCT_WDIRENT retval;
1178 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
1180 if(!dirval)
1181 return NULL;
1184 * The only POSIX defined member of this struct is d_name.
1187 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
1189 return &retval;
1192 /**************************************************************************
1193 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
1194 ****************************************************************************/
1196 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
1198 pstring fname;
1199 char *p = sys_getwd(fname);
1201 if(!p)
1202 return NULL;
1204 return unix_to_unicode(s, p, sizeof(wpstring));
1207 /**************************************************************************
1208 Wide chown. Just narrow and call sys_xxx.
1209 ****************************************************************************/
1211 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1213 pstring fname;
1214 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1217 /**************************************************************************
1218 Wide chroot. Just narrow and call sys_xxx.
1219 ****************************************************************************/
1221 int wsys_chroot(const smb_ucs2_t *wfname)
1223 pstring fname;
1224 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1227 /**************************************************************************
1228 Wide getpwnam. Return a structure pointer containing wide names.
1229 ****************************************************************************/
1231 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1233 static SMB_STRUCT_WPASSWD retval;
1234 fstring name;
1235 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1237 if(!pwret)
1238 return NULL;
1240 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1241 retval.pw_passwd = pwret->pw_passwd;
1242 retval.pw_uid = pwret->pw_uid;
1243 retval.pw_gid = pwret->pw_gid;
1244 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1245 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1246 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1248 return &retval;
1251 /**************************************************************************
1252 Wide getpwuid. Return a structure pointer containing wide names.
1253 ****************************************************************************/
1255 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1257 static SMB_STRUCT_WPASSWD retval;
1258 struct passwd *pwret = sys_getpwuid(uid);
1260 if(!pwret)
1261 return NULL;
1263 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1264 retval.pw_passwd = pwret->pw_passwd;
1265 retval.pw_uid = pwret->pw_uid;
1266 retval.pw_gid = pwret->pw_gid;
1267 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1268 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1269 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1271 return &retval;
1273 #endif /* NOT CURRENTLY USED - JRA */
1275 /**************************************************************************
1276 Extract a command into an arg list. Uses a static pstring for storage.
1277 Caller frees returned arg list (which contains pointers into the static pstring).
1278 ****************************************************************************/
1280 static char **extract_args(const char *command)
1282 static pstring trunc_cmd;
1283 char *ptr;
1284 int argcl;
1285 char **argl = NULL;
1286 int i;
1288 pstrcpy(trunc_cmd, command);
1290 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1291 errno = EINVAL;
1292 return NULL;
1296 * Count the args.
1299 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1300 argcl++;
1302 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1303 return NULL;
1306 * Now do the extraction.
1309 pstrcpy(trunc_cmd, command);
1311 ptr = strtok(trunc_cmd, " \t");
1312 i = 0;
1313 argl[i++] = ptr;
1315 while((ptr = strtok(NULL, " \t")) != NULL)
1316 argl[i++] = ptr;
1318 argl[i++] = NULL;
1319 return argl;
1322 /**************************************************************************
1323 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1324 a sys_getpid() that only does a system call *once*.
1325 ****************************************************************************/
1327 static pid_t mypid = (pid_t)-1;
1329 pid_t sys_fork(void)
1331 pid_t forkret = fork();
1333 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1334 mypid = (pid_t) -1;
1336 return forkret;
1339 /**************************************************************************
1340 Wrapper for getpid. Ensures we only do a system call *once*.
1341 ****************************************************************************/
1343 pid_t sys_getpid(void)
1345 if (mypid == (pid_t)-1)
1346 mypid = getpid();
1348 return mypid;
1351 /**************************************************************************
1352 Wrapper for popen. Safer as it doesn't search a path.
1353 Modified from the glibc sources.
1354 modified by tridge to return a file descriptor. We must kick our FILE* habit
1355 ****************************************************************************/
1357 typedef struct _popen_list
1359 int fd;
1360 pid_t child_pid;
1361 struct _popen_list *next;
1362 } popen_list;
1364 static popen_list *popen_chain;
1366 int sys_popen(const char *command)
1368 int parent_end, child_end;
1369 int pipe_fds[2];
1370 popen_list *entry = NULL;
1371 char **argl = NULL;
1373 if (pipe(pipe_fds) < 0)
1374 return -1;
1376 parent_end = pipe_fds[0];
1377 child_end = pipe_fds[1];
1379 if (!*command) {
1380 errno = EINVAL;
1381 goto err_exit;
1384 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1385 goto err_exit;
1387 ZERO_STRUCTP(entry);
1390 * Extract the command and args into a NULL terminated array.
1393 if(!(argl = extract_args(command)))
1394 goto err_exit;
1396 entry->child_pid = sys_fork();
1398 if (entry->child_pid == -1) {
1399 goto err_exit;
1402 if (entry->child_pid == 0) {
1405 * Child !
1408 int child_std_end = STDOUT_FILENO;
1409 popen_list *p;
1411 close(parent_end);
1412 if (child_end != child_std_end) {
1413 dup2 (child_end, child_std_end);
1414 close (child_end);
1418 * POSIX.2: "popen() shall ensure that any streams from previous
1419 * popen() calls that remain open in the parent process are closed
1420 * in the new child process."
1423 for (p = popen_chain; p; p = p->next)
1424 close(p->fd);
1426 execv(argl[0], argl);
1427 _exit (127);
1431 * Parent.
1434 close (child_end);
1435 SAFE_FREE(argl);
1437 /* Link into popen_chain. */
1438 entry->next = popen_chain;
1439 popen_chain = entry;
1440 entry->fd = parent_end;
1442 return entry->fd;
1444 err_exit:
1446 SAFE_FREE(entry);
1447 SAFE_FREE(argl);
1448 close(pipe_fds[0]);
1449 close(pipe_fds[1]);
1450 return -1;
1453 /**************************************************************************
1454 Wrapper for pclose. Modified from the glibc sources.
1455 ****************************************************************************/
1457 int sys_pclose(int fd)
1459 int wstatus;
1460 popen_list **ptr = &popen_chain;
1461 popen_list *entry = NULL;
1462 pid_t wait_pid;
1463 int status = -1;
1465 /* Unlink from popen_chain. */
1466 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1467 if ((*ptr)->fd == fd) {
1468 entry = *ptr;
1469 *ptr = (*ptr)->next;
1470 status = 0;
1471 break;
1475 if (status < 0 || close(entry->fd) < 0)
1476 return -1;
1479 * As Samba is catching and eating child process
1480 * exits we don't really care about the child exit
1481 * code, a -1 with errno = ECHILD will do fine for us.
1484 do {
1485 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1486 } while (wait_pid == -1 && errno == EINTR);
1488 SAFE_FREE(entry);
1490 if (wait_pid == -1)
1491 return -1;
1492 return wstatus;
1495 /**************************************************************************
1496 Wrappers for dlopen, dlsym, dlclose.
1497 ****************************************************************************/
1499 void *sys_dlopen(const char *name, int flags)
1501 #if defined(HAVE_DLOPEN)
1502 return dlopen(name, flags);
1503 #else
1504 return NULL;
1505 #endif
1508 void *sys_dlsym(void *handle, const char *symbol)
1510 #if defined(HAVE_DLSYM)
1511 return dlsym(handle, symbol);
1512 #else
1513 return NULL;
1514 #endif
1517 int sys_dlclose (void *handle)
1519 #if defined(HAVE_DLCLOSE)
1520 return dlclose(handle);
1521 #else
1522 return 0;
1523 #endif
1526 const char *sys_dlerror(void)
1528 #if defined(HAVE_DLERROR)
1529 return dlerror();
1530 #else
1531 return NULL;
1532 #endif
1535 int sys_dup2(int oldfd, int newfd)
1537 #if defined(HAVE_DUP2)
1538 return dup2(oldfd, newfd);
1539 #else
1540 errno = ENOSYS;
1541 return -1;
1542 #endif
1545 /**************************************************************************
1546 Wrapper for Admin Logs.
1547 ****************************************************************************/
1549 void sys_adminlog(int priority, const char *format_str, ...)
1551 va_list ap;
1552 int ret;
1553 char *msgbuf = NULL;
1555 va_start( ap, format_str );
1556 ret = vasprintf( &msgbuf, format_str, ap );
1557 va_end( ap );
1559 if (ret == -1)
1560 return;
1562 #if defined(HAVE_SYSLOG)
1563 syslog( priority, "%s", msgbuf );
1564 #else
1565 DEBUG(0,("%s", msgbuf ));
1566 #endif
1567 SAFE_FREE(msgbuf);
1570 /******** Solaris EA helper function prototypes ********/
1571 #ifdef HAVE_ATTROPEN
1572 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1573 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1574 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1575 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1576 static int solaris_unlinkat(int attrdirfd, const char *name);
1577 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1578 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1579 #endif
1581 /**************************************************************************
1582 Wrappers for extented attribute calls. Based on the Linux package with
1583 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1584 ****************************************************************************/
1586 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1588 #if defined(HAVE_GETXATTR)
1589 #ifndef XATTR_ADD_OPT
1590 return getxattr(path, name, value, size);
1591 #else
1592 int options = 0;
1593 return getxattr(path, name, value, size, 0, options);
1594 #endif
1595 #elif defined(HAVE_GETEA)
1596 return getea(path, name, value, size);
1597 #elif defined(HAVE_EXTATTR_GET_FILE)
1598 char *s;
1599 ssize_t retval;
1600 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1601 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1602 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1604 * The BSD implementation has a nasty habit of silently truncating
1605 * the returned value to the size of the buffer, so we have to check
1606 * that the buffer is large enough to fit the returned value.
1608 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1609 if(retval > size) {
1610 errno = ERANGE;
1611 return -1;
1613 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1614 return retval;
1617 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1618 return -1;
1619 #elif defined(HAVE_ATTR_GET)
1620 int retval, flags = 0;
1621 int valuelength = (int)size;
1622 char *attrname = strchr(name,'.') + 1;
1624 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1626 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1628 return retval ? retval : valuelength;
1629 #elif defined(HAVE_ATTROPEN)
1630 ssize_t ret = -1;
1631 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1632 if (attrfd >= 0) {
1633 ret = solaris_read_xattr(attrfd, value, size);
1634 close(attrfd);
1636 return ret;
1637 #else
1638 errno = ENOSYS;
1639 return -1;
1640 #endif
1643 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1645 #if defined(HAVE_LGETXATTR)
1646 return lgetxattr(path, name, value, size);
1647 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1648 int options = XATTR_NOFOLLOW;
1649 return getxattr(path, name, value, size, 0, options);
1650 #elif defined(HAVE_LGETEA)
1651 return lgetea(path, name, value, size);
1652 #elif defined(HAVE_EXTATTR_GET_LINK)
1653 char *s;
1654 ssize_t retval;
1655 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1656 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1657 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1659 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1660 if(retval > size) {
1661 errno = ERANGE;
1662 return -1;
1664 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1665 return retval;
1668 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1669 return -1;
1670 #elif defined(HAVE_ATTR_GET)
1671 int retval, flags = ATTR_DONTFOLLOW;
1672 int valuelength = (int)size;
1673 char *attrname = strchr(name,'.') + 1;
1675 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1677 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1679 return retval ? retval : valuelength;
1680 #elif defined(HAVE_ATTROPEN)
1681 ssize_t ret = -1;
1682 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1683 if (attrfd >= 0) {
1684 ret = solaris_read_xattr(attrfd, value, size);
1685 close(attrfd);
1687 return ret;
1688 #else
1689 errno = ENOSYS;
1690 return -1;
1691 #endif
1694 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1696 #if defined(HAVE_FGETXATTR)
1697 #ifndef XATTR_ADD_OPT
1698 return fgetxattr(filedes, name, value, size);
1699 #else
1700 int options = 0;
1701 return fgetxattr(filedes, name, value, size, 0, options);
1702 #endif
1703 #elif defined(HAVE_FGETEA)
1704 return fgetea(filedes, name, value, size);
1705 #elif defined(HAVE_EXTATTR_GET_FD)
1706 char *s;
1707 ssize_t retval;
1708 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1709 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1710 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1712 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1713 if(retval > size) {
1714 errno = ERANGE;
1715 return -1;
1717 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1718 return retval;
1721 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1722 return -1;
1723 #elif defined(HAVE_ATTR_GETF)
1724 int retval, flags = 0;
1725 int valuelength = (int)size;
1726 char *attrname = strchr(name,'.') + 1;
1728 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1730 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1732 return retval ? retval : valuelength;
1733 #elif defined(HAVE_ATTROPEN)
1734 ssize_t ret = -1;
1735 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1736 if (attrfd >= 0) {
1737 ret = solaris_read_xattr(attrfd, value, size);
1738 close(attrfd);
1740 return ret;
1741 #else
1742 errno = ENOSYS;
1743 return -1;
1744 #endif
1747 #if defined(HAVE_EXTATTR_LIST_FILE)
1749 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1751 static struct {
1752 int space;
1753 const char *name;
1754 size_t len;
1756 extattr[] = {
1757 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1758 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1761 typedef union {
1762 const char *path;
1763 int filedes;
1764 } extattr_arg;
1766 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1768 ssize_t list_size, total_size = 0;
1769 int i, t, len;
1770 char *buf;
1771 /* Iterate through extattr(2) namespaces */
1772 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1773 switch(type) {
1774 #if defined(HAVE_EXTATTR_LIST_FILE)
1775 case 0:
1776 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1777 break;
1778 #endif
1779 #if defined(HAVE_EXTATTR_LIST_LINK)
1780 case 1:
1781 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1782 break;
1783 #endif
1784 #if defined(HAVE_EXTATTR_LIST_FD)
1785 case 2:
1786 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1787 break;
1788 #endif
1789 default:
1790 errno = ENOSYS;
1791 return -1;
1793 /* Some error happend. Errno should be set by the previous call */
1794 if(list_size < 0)
1795 return -1;
1796 /* No attributes */
1797 if(list_size == 0)
1798 continue;
1799 /* XXX: Call with an empty buffer may be used to calculate
1800 necessary buffer size. Unfortunately, we can't say, how
1801 many attributes were returned, so here is the potential
1802 problem with the emulation.
1804 if(list == NULL) {
1805 /* Take the worse case of one char attribute names -
1806 two bytes per name plus one more for sanity.
1808 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1809 continue;
1811 /* Count necessary offset to fit namespace prefixes */
1812 len = 0;
1813 for(i = 0; i < list_size; i += list[i] + 1)
1814 len += extattr[t].len;
1816 total_size += list_size + len;
1817 /* Buffer is too small to fit the results */
1818 if(total_size > size) {
1819 errno = ERANGE;
1820 return -1;
1822 /* Shift results back, so we can prepend prefixes */
1823 buf = memmove(list + len, list, list_size);
1825 for(i = 0; i < list_size; i += len + 1) {
1826 len = buf[i];
1827 strncpy(list, extattr[t].name, extattr[t].len + 1);
1828 list += extattr[t].len;
1829 strncpy(list, buf + i + 1, len);
1830 list[len] = '\0';
1831 list += len + 1;
1833 size -= total_size;
1835 return total_size;
1838 #endif
1840 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1841 static char attr_buffer[ATTR_MAX_VALUELEN];
1843 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1845 int retval = 0, index;
1846 attrlist_cursor_t *cursor = 0;
1847 int total_size = 0;
1848 attrlist_t * al = (attrlist_t *)attr_buffer;
1849 attrlist_ent_t *ae;
1850 size_t ent_size, left = size;
1851 char *bp = list;
1853 while (True) {
1854 if (filedes)
1855 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1856 else
1857 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1858 if (retval) break;
1859 for (index = 0; index < al->al_count; index++) {
1860 ae = ATTR_ENTRY(attr_buffer, index);
1861 ent_size = strlen(ae->a_name) + sizeof("user.");
1862 if (left >= ent_size) {
1863 strncpy(bp, "user.", sizeof("user."));
1864 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1865 bp += ent_size;
1866 left -= ent_size;
1867 } else if (size) {
1868 errno = ERANGE;
1869 retval = -1;
1870 break;
1872 total_size += ent_size;
1874 if (al->al_more == 0) break;
1876 if (retval == 0) {
1877 flags |= ATTR_ROOT;
1878 cursor = 0;
1879 while (True) {
1880 if (filedes)
1881 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1882 else
1883 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1884 if (retval) break;
1885 for (index = 0; index < al->al_count; index++) {
1886 ae = ATTR_ENTRY(attr_buffer, index);
1887 ent_size = strlen(ae->a_name) + sizeof("system.");
1888 if (left >= ent_size) {
1889 strncpy(bp, "system.", sizeof("system."));
1890 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1891 bp += ent_size;
1892 left -= ent_size;
1893 } else if (size) {
1894 errno = ERANGE;
1895 retval = -1;
1896 break;
1898 total_size += ent_size;
1900 if (al->al_more == 0) break;
1903 return (ssize_t)(retval ? retval : total_size);
1906 #endif
1908 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1910 #if defined(HAVE_LISTXATTR)
1911 #ifndef XATTR_ADD_OPT
1912 return listxattr(path, list, size);
1913 #else
1914 int options = 0;
1915 return listxattr(path, list, size, options);
1916 #endif
1917 #elif defined(HAVE_LISTEA)
1918 return listea(path, list, size);
1919 #elif defined(HAVE_EXTATTR_LIST_FILE)
1920 extattr_arg arg;
1921 arg.path = path;
1922 return bsd_attr_list(0, arg, list, size);
1923 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1924 return irix_attr_list(path, 0, list, size, 0);
1925 #elif defined(HAVE_ATTROPEN)
1926 ssize_t ret = -1;
1927 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1928 if (attrdirfd >= 0) {
1929 ret = solaris_list_xattr(attrdirfd, list, size);
1930 close(attrdirfd);
1932 return ret;
1933 #else
1934 errno = ENOSYS;
1935 return -1;
1936 #endif
1939 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1941 #if defined(HAVE_LLISTXATTR)
1942 return llistxattr(path, list, size);
1943 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1944 int options = XATTR_NOFOLLOW;
1945 return listxattr(path, list, size, options);
1946 #elif defined(HAVE_LLISTEA)
1947 return llistea(path, list, size);
1948 #elif defined(HAVE_EXTATTR_LIST_LINK)
1949 extattr_arg arg;
1950 arg.path = path;
1951 return bsd_attr_list(1, arg, list, size);
1952 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1953 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1954 #elif defined(HAVE_ATTROPEN)
1955 ssize_t ret = -1;
1956 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1957 if (attrdirfd >= 0) {
1958 ret = solaris_list_xattr(attrdirfd, list, size);
1959 close(attrdirfd);
1961 return ret;
1962 #else
1963 errno = ENOSYS;
1964 return -1;
1965 #endif
1968 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1970 #if defined(HAVE_FLISTXATTR)
1971 #ifndef XATTR_ADD_OPT
1972 return flistxattr(filedes, list, size);
1973 #else
1974 int options = 0;
1975 return flistxattr(filedes, list, size, options);
1976 #endif
1977 #elif defined(HAVE_FLISTEA)
1978 return flistea(filedes, list, size);
1979 #elif defined(HAVE_EXTATTR_LIST_FD)
1980 extattr_arg arg;
1981 arg.filedes = filedes;
1982 return bsd_attr_list(2, arg, list, size);
1983 #elif defined(HAVE_ATTR_LISTF)
1984 return irix_attr_list(NULL, filedes, list, size, 0);
1985 #elif defined(HAVE_ATTROPEN)
1986 ssize_t ret = -1;
1987 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1988 if (attrdirfd >= 0) {
1989 ret = solaris_list_xattr(attrdirfd, list, size);
1990 close(attrdirfd);
1992 return ret;
1993 #else
1994 errno = ENOSYS;
1995 return -1;
1996 #endif
1999 int sys_removexattr (const char *path, const char *name)
2001 #if defined(HAVE_REMOVEXATTR)
2002 #ifndef XATTR_ADD_OPT
2003 return removexattr(path, name);
2004 #else
2005 int options = 0;
2006 return removexattr(path, name, options);
2007 #endif
2008 #elif defined(HAVE_REMOVEEA)
2009 return removeea(path, name);
2010 #elif defined(HAVE_EXTATTR_DELETE_FILE)
2011 char *s;
2012 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2013 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2014 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2016 return extattr_delete_file(path, attrnamespace, attrname);
2017 #elif defined(HAVE_ATTR_REMOVE)
2018 int flags = 0;
2019 char *attrname = strchr(name,'.') + 1;
2021 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2023 return attr_remove(path, attrname, flags);
2024 #elif defined(HAVE_ATTROPEN)
2025 int ret = -1;
2026 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
2027 if (attrdirfd >= 0) {
2028 ret = solaris_unlinkat(attrdirfd, name);
2029 close(attrdirfd);
2031 return ret;
2032 #else
2033 errno = ENOSYS;
2034 return -1;
2035 #endif
2038 int sys_lremovexattr (const char *path, const char *name)
2040 #if defined(HAVE_LREMOVEXATTR)
2041 return lremovexattr(path, name);
2042 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
2043 int options = XATTR_NOFOLLOW;
2044 return removexattr(path, name, options);
2045 #elif defined(HAVE_LREMOVEEA)
2046 return lremoveea(path, name);
2047 #elif defined(HAVE_EXTATTR_DELETE_LINK)
2048 char *s;
2049 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2050 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2051 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2053 return extattr_delete_link(path, attrnamespace, attrname);
2054 #elif defined(HAVE_ATTR_REMOVE)
2055 int flags = ATTR_DONTFOLLOW;
2056 char *attrname = strchr(name,'.') + 1;
2058 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2060 return attr_remove(path, attrname, flags);
2061 #elif defined(HAVE_ATTROPEN)
2062 int ret = -1;
2063 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
2064 if (attrdirfd >= 0) {
2065 ret = solaris_unlinkat(attrdirfd, name);
2066 close(attrdirfd);
2068 return ret;
2069 #else
2070 errno = ENOSYS;
2071 return -1;
2072 #endif
2075 int sys_fremovexattr (int filedes, const char *name)
2077 #if defined(HAVE_FREMOVEXATTR)
2078 #ifndef XATTR_ADD_OPT
2079 return fremovexattr(filedes, name);
2080 #else
2081 int options = 0;
2082 return fremovexattr(filedes, name, options);
2083 #endif
2084 #elif defined(HAVE_FREMOVEEA)
2085 return fremoveea(filedes, name);
2086 #elif defined(HAVE_EXTATTR_DELETE_FD)
2087 char *s;
2088 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2089 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2090 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2092 return extattr_delete_fd(filedes, attrnamespace, attrname);
2093 #elif defined(HAVE_ATTR_REMOVEF)
2094 int flags = 0;
2095 char *attrname = strchr(name,'.') + 1;
2097 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2099 return attr_removef(filedes, attrname, flags);
2100 #elif defined(HAVE_ATTROPEN)
2101 int ret = -1;
2102 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2103 if (attrdirfd >= 0) {
2104 ret = solaris_unlinkat(attrdirfd, name);
2105 close(attrdirfd);
2107 return ret;
2108 #else
2109 errno = ENOSYS;
2110 return -1;
2111 #endif
2114 #if !defined(HAVE_SETXATTR)
2115 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
2116 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
2117 #endif
2119 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2121 #if defined(HAVE_SETXATTR)
2122 #ifndef XATTR_ADD_OPT
2123 return setxattr(path, name, value, size, flags);
2124 #else
2125 int options = 0;
2126 return setxattr(path, name, value, size, 0, options);
2127 #endif
2128 #elif defined(HAVE_SETEA)
2129 return setea(path, name, value, size, flags);
2130 #elif defined(HAVE_EXTATTR_SET_FILE)
2131 char *s;
2132 int retval = 0;
2133 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2134 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2135 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2136 if (flags) {
2137 /* Check attribute existence */
2138 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2139 if (retval < 0) {
2140 /* REPLACE attribute, that doesn't exist */
2141 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2142 errno = ENOATTR;
2143 return -1;
2145 /* Ignore other errors */
2147 else {
2148 /* CREATE attribute, that already exists */
2149 if (flags & XATTR_CREATE) {
2150 errno = EEXIST;
2151 return -1;
2155 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2156 return (retval < 0) ? -1 : 0;
2157 #elif defined(HAVE_ATTR_SET)
2158 int myflags = 0;
2159 char *attrname = strchr(name,'.') + 1;
2161 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2162 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2163 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2165 return attr_set(path, attrname, (const char *)value, size, myflags);
2166 #elif defined(HAVE_ATTROPEN)
2167 int ret = -1;
2168 int myflags = O_RDWR;
2169 int attrfd;
2170 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2171 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2172 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2173 if (attrfd >= 0) {
2174 ret = solaris_write_xattr(attrfd, value, size);
2175 close(attrfd);
2177 return ret;
2178 #else
2179 errno = ENOSYS;
2180 return -1;
2181 #endif
2184 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2186 #if defined(HAVE_LSETXATTR)
2187 return lsetxattr(path, name, value, size, flags);
2188 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2189 int options = XATTR_NOFOLLOW;
2190 return setxattr(path, name, value, size, 0, options);
2191 #elif defined(LSETEA)
2192 return lsetea(path, name, value, size, flags);
2193 #elif defined(HAVE_EXTATTR_SET_LINK)
2194 char *s;
2195 int retval = 0;
2196 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2197 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2198 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2199 if (flags) {
2200 /* Check attribute existence */
2201 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2202 if (retval < 0) {
2203 /* REPLACE attribute, that doesn't exist */
2204 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2205 errno = ENOATTR;
2206 return -1;
2208 /* Ignore other errors */
2210 else {
2211 /* CREATE attribute, that already exists */
2212 if (flags & XATTR_CREATE) {
2213 errno = EEXIST;
2214 return -1;
2219 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2220 return (retval < 0) ? -1 : 0;
2221 #elif defined(HAVE_ATTR_SET)
2222 int myflags = ATTR_DONTFOLLOW;
2223 char *attrname = strchr(name,'.') + 1;
2225 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2226 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2227 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2229 return attr_set(path, attrname, (const char *)value, size, myflags);
2230 #elif defined(HAVE_ATTROPEN)
2231 int ret = -1;
2232 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2233 int attrfd;
2234 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2235 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2236 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2237 if (attrfd >= 0) {
2238 ret = solaris_write_xattr(attrfd, value, size);
2239 close(attrfd);
2241 return ret;
2242 #else
2243 errno = ENOSYS;
2244 return -1;
2245 #endif
2248 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2250 #if defined(HAVE_FSETXATTR)
2251 #ifndef XATTR_ADD_OPT
2252 return fsetxattr(filedes, name, value, size, flags);
2253 #else
2254 int options = 0;
2255 return fsetxattr(filedes, name, value, size, 0, options);
2256 #endif
2257 #elif defined(HAVE_FSETEA)
2258 return fsetea(filedes, name, value, size, flags);
2259 #elif defined(HAVE_EXTATTR_SET_FD)
2260 char *s;
2261 int retval = 0;
2262 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2263 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2264 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2265 if (flags) {
2266 /* Check attribute existence */
2267 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2268 if (retval < 0) {
2269 /* REPLACE attribute, that doesn't exist */
2270 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2271 errno = ENOATTR;
2272 return -1;
2274 /* Ignore other errors */
2276 else {
2277 /* CREATE attribute, that already exists */
2278 if (flags & XATTR_CREATE) {
2279 errno = EEXIST;
2280 return -1;
2284 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2285 return (retval < 0) ? -1 : 0;
2286 #elif defined(HAVE_ATTR_SETF)
2287 int myflags = 0;
2288 char *attrname = strchr(name,'.') + 1;
2290 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2291 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2292 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2294 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2295 #elif defined(HAVE_ATTROPEN)
2296 int ret = -1;
2297 int myflags = O_RDWR | O_XATTR;
2298 int attrfd;
2299 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2300 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2301 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2302 if (attrfd >= 0) {
2303 ret = solaris_write_xattr(attrfd, value, size);
2304 close(attrfd);
2306 return ret;
2307 #else
2308 errno = ENOSYS;
2309 return -1;
2310 #endif
2313 /**************************************************************************
2314 helper functions for Solaris' EA support
2315 ****************************************************************************/
2316 #ifdef HAVE_ATTROPEN
2317 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2319 struct stat sbuf;
2321 if (fstat(attrfd, &sbuf) == -1) {
2322 errno = ENOATTR;
2323 return -1;
2326 /* This is to return the current size of the named extended attribute */
2327 if (size == 0) {
2328 return sbuf.st_size;
2331 /* check size and read xattr */
2332 if (sbuf.st_size > size) {
2333 errno = ERANGE;
2334 return -1;
2337 return read(attrfd, value, sbuf.st_size);
2340 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2342 ssize_t len = 0;
2343 int stop = 0;
2344 DIR *dirp;
2345 struct dirent *de;
2346 int newfd = dup(attrdirfd);
2347 /* CAUTION: The originating file descriptor should not be
2348 used again following the call to fdopendir().
2349 For that reason we dup() the file descriptor
2350 here to make things more clear. */
2351 dirp = fdopendir(newfd);
2353 while ((de = readdir(dirp))) {
2354 size_t listlen = strlen(de->d_name);
2355 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2356 /* we don't want "." and ".." here: */
2357 DEBUG(10,("skipped EA %s\n",de->d_name));
2358 continue;
2361 if (size == 0) {
2362 /* return the current size of the list of extended attribute names*/
2363 len += listlen + 1;
2364 } else {
2365 /* check size and copy entrieѕ + nul into list. */
2366 if ((len + listlen + 1) > size) {
2367 errno = ERANGE;
2368 len = -1;
2369 break;
2370 } else {
2371 safe_strcpy(list + len, de->d_name, listlen);
2372 pstrcpy(list + len, de->d_name);
2373 len += listlen;
2374 list[len] = '\0';
2375 ++len;
2380 if (closedir(dirp) == -1) {
2381 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2382 return -1;
2384 return len;
2387 static int solaris_unlinkat(int attrdirfd, const char *name)
2389 if (unlinkat(attrdirfd, name, 0) == -1) {
2390 if (errno == ENOENT) {
2391 errno = ENOATTR;
2393 return -1;
2395 return 0;
2398 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2400 int filedes = attropen(path, attrpath, oflag, mode);
2401 if (filedes == -1) {
2402 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2403 if (errno == EINVAL) {
2404 errno = ENOTSUP;
2405 } else {
2406 errno = ENOATTR;
2409 return filedes;
2412 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2414 int filedes = openat(fildes, path, oflag, mode);
2415 if (filedes == -1) {
2416 DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2417 if (errno == EINVAL) {
2418 errno = ENOTSUP;
2419 } else {
2420 errno = ENOATTR;
2423 return filedes;
2426 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2428 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2429 return 0;
2430 } else {
2431 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2432 return -1;
2435 #endif /*HAVE_ATTROPEN*/
2437 /****************************************************************************
2438 Return the major devicenumber for UNIX extensions.
2439 ****************************************************************************/
2441 uint32 unix_dev_major(SMB_DEV_T dev)
2443 #if defined(HAVE_DEVICE_MAJOR_FN)
2444 return (uint32)major(dev);
2445 #else
2446 return (uint32)(dev >> 8);
2447 #endif
2450 /****************************************************************************
2451 Return the minor devicenumber for UNIX extensions.
2452 ****************************************************************************/
2454 uint32 unix_dev_minor(SMB_DEV_T dev)
2456 #if defined(HAVE_DEVICE_MINOR_FN)
2457 return (uint32)minor(dev);
2458 #else
2459 return (uint32)(dev & 0xff);
2460 #endif
2463 #if defined(WITH_AIO)
2465 /*******************************************************************
2466 An aio_read wrapper that will deal with 64-bit sizes.
2467 ********************************************************************/
2469 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2471 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2472 return aio_read64(aiocb);
2473 #elif defined(HAVE_AIO_READ)
2474 return aio_read(aiocb);
2475 #else
2476 errno = ENOSYS;
2477 return -1;
2478 #endif
2481 /*******************************************************************
2482 An aio_write wrapper that will deal with 64-bit sizes.
2483 ********************************************************************/
2485 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2487 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2488 return aio_write64(aiocb);
2489 #elif defined(HAVE_AIO_WRITE)
2490 return aio_write(aiocb);
2491 #else
2492 errno = ENOSYS;
2493 return -1;
2494 #endif
2497 /*******************************************************************
2498 An aio_return wrapper that will deal with 64-bit sizes.
2499 ********************************************************************/
2501 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2503 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2504 return aio_return64(aiocb);
2505 #elif defined(HAVE_AIO_RETURN)
2506 return aio_return(aiocb);
2507 #else
2508 errno = ENOSYS;
2509 return -1;
2510 #endif
2513 /*******************************************************************
2514 An aio_cancel wrapper that will deal with 64-bit sizes.
2515 ********************************************************************/
2517 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2519 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2520 return aio_cancel64(fd, aiocb);
2521 #elif defined(HAVE_AIO_CANCEL)
2522 return aio_cancel(fd, aiocb);
2523 #else
2524 errno = ENOSYS;
2525 return -1;
2526 #endif
2529 /*******************************************************************
2530 An aio_error wrapper that will deal with 64-bit sizes.
2531 ********************************************************************/
2533 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2535 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2536 return aio_error64(aiocb);
2537 #elif defined(HAVE_AIO_ERROR)
2538 return aio_error(aiocb);
2539 #else
2540 errno = ENOSYS;
2541 return -1;
2542 #endif
2545 /*******************************************************************
2546 An aio_fsync wrapper that will deal with 64-bit sizes.
2547 ********************************************************************/
2549 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2551 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2552 return aio_fsync64(op, aiocb);
2553 #elif defined(HAVE_AIO_FSYNC)
2554 return aio_fsync(op, aiocb);
2555 #else
2556 errno = ENOSYS;
2557 return -1;
2558 #endif
2561 /*******************************************************************
2562 An aio_fsync wrapper that will deal with 64-bit sizes.
2563 ********************************************************************/
2565 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2567 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2568 return aio_suspend64(cblist, n, timeout);
2569 #elif defined(HAVE_AIO_FSYNC)
2570 return aio_suspend(cblist, n, timeout);
2571 #else
2572 errno = ENOSYS;
2573 return -1;
2574 #endif
2576 #else /* !WITH_AIO */
2578 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2580 errno = ENOSYS;
2581 return -1;
2584 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2586 errno = ENOSYS;
2587 return -1;
2590 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2592 errno = ENOSYS;
2593 return -1;
2596 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2598 errno = ENOSYS;
2599 return -1;
2602 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2604 errno = ENOSYS;
2605 return -1;
2608 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2610 errno = ENOSYS;
2611 return -1;
2614 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2616 errno = ENOSYS;
2617 return -1;
2619 #endif /* WITH_AIO */
2621 int sys_getpeereid( int s, uid_t *uid)
2623 #if defined(HAVE_PEERCRED)
2624 struct ucred cred;
2625 socklen_t cred_len = sizeof(struct ucred);
2626 int ret;
2628 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2629 if (ret != 0) {
2630 return -1;
2633 if (cred_len != sizeof(struct ucred)) {
2634 errno = EINVAL;
2635 return -1;
2638 *uid = cred.uid;
2639 return 0;
2640 #else
2641 errno = ENOSYS;
2642 return -1;
2643 #endif