source: branches/samba-3.3.x/source/lib/system.c@ 411

Last change on this file since 411 was 411, checked in by Herwig Bauernfeind, 15 years ago

Update Samba 3.3.x to 3.3.11

File size: 69.7 KB
Line 
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
8
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.
13
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.
18
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/>.
21*/
22
23#include "includes.h"
24
25#ifdef HAVE_SYS_PRCTL_H
26#include <sys/prctl.h>
27#endif
28
29/*
30 The idea is that this file will eventually have wrappers around all
31 important system calls in samba. The aims are:
32
33 - to enable easier porting by putting OS dependent stuff in here
34
35 - to allow for hooks into other "pseudo-filesystems"
36
37 - to allow easier integration of things like the japanese extensions
38
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.
42*/
43
44
45
46/*******************************************************************
47 A wrapper for memalign
48********************************************************************/
49
50void *sys_memalign( size_t align, size_t size )
51{
52#if defined(HAVE_POSIX_MEMALIGN)
53 void *p = NULL;
54 int ret = posix_memalign( &p, align, size );
55 if ( ret == 0 )
56 return p;
57
58 return NULL;
59#elif defined(HAVE_MEMALIGN)
60 return memalign( align, size );
61#else
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();
68#else
69 size_t pagesize = (size_t)-1;
70#endif
71 if (pagesize == (size_t)-1) {
72 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
73 return NULL;
74 }
75 if (size < pagesize) {
76 size = pagesize;
77 }
78 return SMB_MALLOC(size);
79#endif
80}
81
82/*******************************************************************
83 A wrapper for usleep in case we don't have one.
84********************************************************************/
85
86int sys_usleep(long usecs)
87{
88#ifndef HAVE_USLEEP
89 struct timeval tval;
90#endif
91
92 /*
93 * We need this braindamage as the glibc usleep
94 * is not SPEC1170 complient... grumble... JRA.
95 */
96
97 if(usecs < 0 || usecs > 1000000) {
98 errno = EINVAL;
99 return -1;
100 }
101
102#if HAVE_USLEEP
103 usleep(usecs);
104 return 0;
105#else /* HAVE_USLEEP */
106 /*
107 * Fake it with select...
108 */
109 tval.tv_sec = 0;
110 tval.tv_usec = usecs/1000;
111 select(0,NULL,NULL,NULL,&tval);
112 return 0;
113#endif /* HAVE_USLEEP */
114}
115
116/*******************************************************************
117A read wrapper that will deal with EINTR.
118********************************************************************/
119
120ssize_t sys_read(int fd, void *buf, size_t count)
121{
122 ssize_t ret;
123
124 do {
125 ret = read(fd, buf, count);
126 } while (ret == -1 && errno == EINTR);
127 return ret;
128}
129
130/*******************************************************************
131A write wrapper that will deal with EINTR.
132********************************************************************/
133
134ssize_t sys_write(int fd, const void *buf, size_t count)
135{
136 ssize_t ret;
137
138 do {
139 ret = write(fd, buf, count);
140 } while (ret == -1 && errno == EINTR);
141 return ret;
142}
143
144/*******************************************************************
145A writev wrapper that will deal with EINTR.
146********************************************************************/
147
148ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
149{
150 ssize_t ret;
151
152#if 0
153 /* Try to confuse write_data_iov a bit */
154 if ((random() % 5) == 0) {
155 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
156 }
157 if (iov[0].iov_len > 1) {
158 return sys_write(fd, iov[0].iov_base,
159 (random() % (iov[0].iov_len-1)) + 1);
160 }
161#endif
162
163 do {
164 ret = writev(fd, iov, iovcnt);
165 } while (ret == -1 && errno == EINTR);
166 return ret;
167}
168
169/*******************************************************************
170A pread wrapper that will deal with EINTR and 64-bit file offsets.
171********************************************************************/
172
173#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
174ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
175{
176 ssize_t ret;
177
178 do {
179#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
180 ret = pread64(fd, buf, count, off);
181#else
182 ret = pread(fd, buf, count, off);
183#endif
184 } while (ret == -1 && errno == EINTR);
185 return ret;
186}
187#endif
188
189/*******************************************************************
190A write wrapper that will deal with EINTR and 64-bit file offsets.
191********************************************************************/
192
193#if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
194ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
195{
196 ssize_t ret;
197
198 do {
199#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
200 ret = pwrite64(fd, buf, count, off);
201#else
202 ret = pwrite(fd, buf, count, off);
203#endif
204 } while (ret == -1 && errno == EINTR);
205 return ret;
206}
207#endif
208
209/*******************************************************************
210A send wrapper that will deal with EINTR.
211********************************************************************/
212
213ssize_t sys_send(int s, const void *msg, size_t len, int flags)
214{
215 ssize_t ret;
216
217 do {
218 ret = send(s, msg, len, flags);
219 } while (ret == -1 && errno == EINTR);
220 return ret;
221}
222
223/*******************************************************************
224A sendto wrapper that will deal with EINTR.
225********************************************************************/
226
227ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
228{
229 ssize_t ret;
230
231 do {
232 ret = sendto(s, msg, len, flags, to, tolen);
233 } while (ret == -1 && errno == EINTR);
234 return ret;
235}
236
237/*******************************************************************
238A recv wrapper that will deal with EINTR.
239********************************************************************/
240
241ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
242{
243 ssize_t ret;
244
245 do {
246 ret = recv(fd, buf, count, flags);
247 } while (ret == -1 && errno == EINTR);
248 return ret;
249}
250
251/*******************************************************************
252A recvfrom wrapper that will deal with EINTR.
253********************************************************************/
254
255ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
256{
257 ssize_t ret;
258
259 do {
260 ret = recvfrom(s, buf, len, flags, from, fromlen);
261 } while (ret == -1 && errno == EINTR);
262 return ret;
263}
264
265/*******************************************************************
266A fcntl wrapper that will deal with EINTR.
267********************************************************************/
268
269int sys_fcntl_ptr(int fd, int cmd, void *arg)
270{
271 int ret;
272
273 do {
274 ret = fcntl(fd, cmd, arg);
275 } while (ret == -1 && errno == EINTR);
276 return ret;
277}
278
279/*******************************************************************
280A fcntl wrapper that will deal with EINTR.
281********************************************************************/
282
283int sys_fcntl_long(int fd, int cmd, long arg)
284{
285 int ret;
286
287 do {
288 ret = fcntl(fd, cmd, arg);
289 } while (ret == -1 && errno == EINTR);
290 return ret;
291}
292
293/*******************************************************************
294A stat() wrapper that will deal with 64 bit filesizes.
295********************************************************************/
296
297int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
298{
299 int ret;
300#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
301 ret = stat64(fname, sbuf);
302#else
303 ret = stat(fname, sbuf);
304#endif
305 /* we always want directories to appear zero size */
306 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
307 return ret;
308}
309
310/*******************************************************************
311 An fstat() wrapper that will deal with 64 bit filesizes.
312********************************************************************/
313
314int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
315{
316 int ret;
317#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
318 ret = fstat64(fd, sbuf);
319#else
320 ret = fstat(fd, sbuf);
321#endif
322 /* we always want directories to appear zero size */
323 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
324 return ret;
325}
326
327/*******************************************************************
328 An lstat() wrapper that will deal with 64 bit filesizes.
329********************************************************************/
330
331int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
332{
333 int ret;
334#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
335 ret = lstat64(fname, sbuf);
336#else
337 ret = lstat(fname, sbuf);
338#endif
339 /* we always want directories to appear zero size */
340 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
341 return ret;
342}
343
344/*******************************************************************
345 An ftruncate() wrapper that will deal with 64 bit filesizes.
346********************************************************************/
347
348int sys_ftruncate(int fd, SMB_OFF_T offset)
349{
350#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
351 return ftruncate64(fd, offset);
352#elif defined(__OS2__)
353 return os2_ftruncate(fd, offset);
354#else
355 return ftruncate(fd, offset);
356#endif
357}
358
359/*******************************************************************
360 An lseek() wrapper that will deal with 64 bit filesizes.
361********************************************************************/
362
363SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
364{
365#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
366 return lseek64(fd, offset, whence);
367#else
368 return lseek(fd, offset, whence);
369#endif
370}
371
372/*******************************************************************
373 An fseek() wrapper that will deal with 64 bit filesizes.
374********************************************************************/
375
376int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
377{
378#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
379 return fseek64(fp, offset, whence);
380#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
381 return fseeko64(fp, offset, whence);
382#else
383 return fseek(fp, offset, whence);
384#endif
385}
386
387/*******************************************************************
388 An ftell() wrapper that will deal with 64 bit filesizes.
389********************************************************************/
390
391SMB_OFF_T sys_ftell(FILE *fp)
392{
393#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
394 return (SMB_OFF_T)ftell64(fp);
395#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
396 return (SMB_OFF_T)ftello64(fp);
397#else
398 return (SMB_OFF_T)ftell(fp);
399#endif
400}
401
402/*******************************************************************
403 A creat() wrapper that will deal with 64 bit filesizes.
404********************************************************************/
405
406int sys_creat(const char *path, mode_t mode)
407{
408#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
409 return creat64(path, mode);
410#else
411 /*
412 * If creat64 isn't defined then ensure we call a potential open64.
413 * JRA.
414 */
415 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
416#endif
417}
418
419/*******************************************************************
420 An open() wrapper that will deal with 64 bit filesizes.
421********************************************************************/
422
423int sys_open(const char *path, int oflag, mode_t mode)
424{
425#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
426 return open64(path, oflag, mode);
427#else
428 return open(path, oflag, mode);
429#endif
430}
431
432/*******************************************************************
433 An fopen() wrapper that will deal with 64 bit filesizes.
434********************************************************************/
435
436FILE *sys_fopen(const char *path, const char *type)
437{
438#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
439 return fopen64(path, type);
440#else
441 return fopen(path, type);
442#endif
443}
444
445
446/*******************************************************************
447 A flock() wrapper that will perform the kernel flock.
448********************************************************************/
449
450void kernel_flock(int fd, uint32 share_mode)
451{
452#if HAVE_KERNEL_SHARE_MODES
453 int kernel_mode = 0;
454 if (share_mode == FILE_SHARE_WRITE) {
455 kernel_mode = LOCK_MAND|LOCK_WRITE;
456 } else if (share_mode == FILE_SHARE_READ) {
457 kernel_mode = LOCK_MAND|LOCK_READ;
458 } else if (share_mode == FILE_SHARE_NONE) {
459 kernel_mode = LOCK_MAND;
460 }
461 if (kernel_mode) {
462 flock(fd, kernel_mode);
463 }
464#endif
465 ;
466}
467
468
469
470/*******************************************************************
471 An opendir wrapper that will deal with 64 bit filesizes.
472********************************************************************/
473
474SMB_STRUCT_DIR *sys_opendir(const char *name)
475{
476#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
477 return opendir64(name);
478#else
479 return opendir(name);
480#endif
481}
482
483/*******************************************************************
484 A readdir wrapper that will deal with 64 bit filesizes.
485********************************************************************/
486
487SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
488{
489#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
490 return readdir64(dirp);
491#else
492 return readdir(dirp);
493#endif
494}
495
496/*******************************************************************
497 A seekdir wrapper that will deal with 64 bit filesizes.
498********************************************************************/
499
500void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
501{
502#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
503 seekdir64(dirp, offset);
504#else
505 seekdir(dirp, offset);
506#endif
507}
508
509/*******************************************************************
510 A telldir wrapper that will deal with 64 bit filesizes.
511********************************************************************/
512
513long sys_telldir(SMB_STRUCT_DIR *dirp)
514{
515#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
516 return (long)telldir64(dirp);
517#else
518 return (long)telldir(dirp);
519#endif
520}
521
522/*******************************************************************
523 A rewinddir wrapper that will deal with 64 bit filesizes.
524********************************************************************/
525
526void sys_rewinddir(SMB_STRUCT_DIR *dirp)
527{
528#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
529 rewinddir64(dirp);
530#else
531 rewinddir(dirp);
532#endif
533}
534
535/*******************************************************************
536 A close wrapper that will deal with 64 bit filesizes.
537********************************************************************/
538
539int sys_closedir(SMB_STRUCT_DIR *dirp)
540{
541#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
542 return closedir64(dirp);
543#else
544 return closedir(dirp);
545#endif
546}
547
548/*******************************************************************
549 An mknod() wrapper that will deal with 64 bit filesizes.
550********************************************************************/
551
552int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
553{
554#if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
555#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
556 return mknod64(path, mode, dev);
557#else
558 return mknod(path, mode, dev);
559#endif
560#else
561 /* No mknod system call. */
562 errno = ENOSYS;
563 return -1;
564#endif
565}
566
567/*******************************************************************
568 Wrapper for realpath.
569********************************************************************/
570
571char *sys_realpath(const char *path, char *resolved_path)
572{
573#if defined(HAVE_REALPATH)
574 return realpath(path, resolved_path);
575#else
576 /* As realpath is not a system call we can't return ENOSYS. */
577 errno = EINVAL;
578 return NULL;
579#endif
580}
581
582/*******************************************************************
583The wait() calls vary between systems
584********************************************************************/
585
586int sys_waitpid(pid_t pid,int *status,int options)
587{
588#ifdef HAVE_WAITPID
589 return waitpid(pid,status,options);
590#else /* HAVE_WAITPID */
591 return wait4(pid, status, options, NULL);
592#endif /* HAVE_WAITPID */
593}
594
595/*******************************************************************
596 System wrapper for getwd
597********************************************************************/
598
599char *sys_getwd(char *s)
600{
601 char *wd;
602#ifdef HAVE_GETCWD
603 wd = (char *)getcwd(s, PATH_MAX);
604#else
605 wd = (char *)getwd(s);
606#endif
607 return wd;
608}
609
610/*******************************************************************
611system wrapper for symlink
612********************************************************************/
613
614int sys_symlink(const char *oldpath, const char *newpath)
615{
616#ifndef HAVE_SYMLINK
617 errno = ENOSYS;
618 return -1;
619#else
620 return symlink(oldpath, newpath);
621#endif
622}
623
624/*******************************************************************
625system wrapper for readlink
626********************************************************************/
627
628int sys_readlink(const char *path, char *buf, size_t bufsiz)
629{
630#ifndef HAVE_READLINK
631 errno = ENOSYS;
632 return -1;
633#else
634 return readlink(path, buf, bufsiz);
635#endif
636}
637
638/*******************************************************************
639system wrapper for link
640********************************************************************/
641
642int sys_link(const char *oldpath, const char *newpath)
643{
644#ifndef HAVE_LINK
645 errno = ENOSYS;
646 return -1;
647#else
648 return link(oldpath, newpath);
649#endif
650}
651
652/*******************************************************************
653chown isn't used much but OS/2 doesn't have it
654********************************************************************/
655
656int sys_chown(const char *fname,uid_t uid,gid_t gid)
657{
658#ifndef HAVE_CHOWN
659 static int done;
660 if (!done) {
661 DEBUG(1,("WARNING: no chown!\n"));
662 done=1;
663 }
664 errno = ENOSYS;
665 return -1;
666#else
667 return(chown(fname,uid,gid));
668#endif
669}
670
671/*******************************************************************
672 Wrapper for lchown.
673********************************************************************/
674
675int sys_lchown(const char *fname,uid_t uid,gid_t gid)
676{
677#ifndef HAVE_LCHOWN
678 static int done;
679 if (!done) {
680 DEBUG(1,("WARNING: no lchown!\n"));
681 done=1;
682 }
683 errno = ENOSYS;
684 return -1;
685#else
686 return(lchown(fname,uid,gid));
687#endif
688}
689
690/*******************************************************************
691os/2 also doesn't have chroot
692********************************************************************/
693int sys_chroot(const char *dname)
694{
695#ifndef HAVE_CHROOT
696 static int done;
697 if (!done) {
698 DEBUG(1,("WARNING: no chroot!\n"));
699 done=1;
700 }
701 errno = ENOSYS;
702 return -1;
703#else
704 return(chroot(dname));
705#endif
706}
707
708#if defined(HAVE_POSIX_CAPABILITIES)
709
710/* This define hasn't made it into the glibc capabilities header yet. */
711#ifndef SECURE_NO_SETUID_FIXUP
712#define SECURE_NO_SETUID_FIXUP 2
713#endif
714
715/**************************************************************************
716 Try and abstract process capabilities (for systems that have them).
717****************************************************************************/
718
719/* Set the POSIX capabilities needed for the given purpose into the effective
720 * capability set of the current process. Make sure they are always removed
721 * from the inheritable set, because there is no circumstance in which our
722 * children should inherit our elevated privileges.
723 */
724static bool set_process_capability(enum smbd_capability capability,
725 bool enable)
726{
727 cap_value_t cap_vals[2] = {0};
728 int num_cap_vals = 0;
729
730 cap_t cap;
731
732#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
733 /* On Linux, make sure that any capabilities we grab are sticky
734 * across UID changes. We expect that this would allow us to keep both
735 * the effective and permitted capability sets, but as of circa 2.6.16,
736 * only the permitted set is kept. It is a bug (which we work around)
737 * that the effective set is lost, but we still require the effective
738 * set to be kept.
739 */
740 if (!prctl(PR_GET_KEEPCAPS)) {
741 prctl(PR_SET_KEEPCAPS, 1);
742 }
743#endif
744
745#if defined(HAVE_PRCTL) && defined(PR_SET_SECUREBITS) && defined(SECURE_NO_SETUID_FIXUP)
746 /* New way of setting capabilities as "sticky". */
747
748 /*
749 * Use PR_SET_SECUREBITS to prevent setresuid()
750 * atomically dropping effective capabilities on
751 * uid change. Only available in Linux kernels
752 * 2.6.26 and above.
753 *
754 * See here:
755 * http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html
756 * for details.
757 *
758 * Specifically the CAP_KILL capability we need
759 * to allow Linux threads under different euids
760 * to send signals to each other.
761 */
762
763 if (prctl(PR_SET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP)) {
764 DEBUG(0,("set_process_capability: "
765 "prctl PR_SET_SECUREBITS failed with error %s\n",
766 strerror(errno) ));
767 return false;
768 }
769#endif
770
771 cap = cap_get_proc();
772 if (cap == NULL) {
773 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
774 strerror(errno)));
775 return False;
776 }
777
778 switch (capability) {
779 case KERNEL_OPLOCK_CAPABILITY:
780#ifdef CAP_NETWORK_MGT
781 /* IRIX has CAP_NETWORK_MGT for oplocks. */
782 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
783#endif
784 break;
785 case DMAPI_ACCESS_CAPABILITY:
786#ifdef CAP_DEVICE_MGT
787 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
788 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
789#elif CAP_MKNOD
790 /* Linux has CAP_MKNOD for DMAPI access. */
791 cap_vals[num_cap_vals++] = CAP_MKNOD;
792#endif
793 break;
794 case LEASE_CAPABILITY:
795#ifdef CAP_LEASE
796 cap_vals[num_cap_vals++] = CAP_LEASE;
797#endif
798 break;
799 case KILL_CAPABILITY:
800#ifdef CAP_KILL
801 cap_vals[num_cap_vals++] = CAP_KILL;
802#endif
803 break;
804 }
805
806 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
807
808 if (num_cap_vals == 0) {
809 cap_free(cap);
810 return True;
811 }
812
813 /*
814 * Ensure the capability is effective. We assume that as a root
815 * process it's always permitted.
816 */
817
818 if (cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
819 enable ? CAP_SET : CAP_CLEAR) == -1) {
820 DEBUG(0, ("set_process_capability: cap_set_flag effective "
821 "failed (%d): %s\n",
822 (int)capability,
823 strerror(errno)));
824 cap_free(cap);
825 return false;
826 }
827
828 /* We never want to pass capabilities down to our children, so make
829 * sure they are not inherited.
830 */
831 if (cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals,
832 cap_vals, CAP_CLEAR) == -1) {
833 DEBUG(0, ("set_process_capability: cap_set_flag inheritable "
834 "failed (%d): %s\n",
835 (int)capability,
836 strerror(errno)));
837 cap_free(cap);
838 return false;
839 }
840
841 if (cap_set_proc(cap) == -1) {
842 DEBUG(0, ("set_process_capability: cap_set_flag (%d) failed: %s\n",
843 (int)capability,
844 strerror(errno)));
845 cap_free(cap);
846 return False;
847 }
848
849 cap_free(cap);
850 return True;
851}
852
853#endif /* HAVE_POSIX_CAPABILITIES */
854
855/****************************************************************************
856 Gain the oplock capability from the kernel if possible.
857****************************************************************************/
858
859void set_effective_capability(enum smbd_capability capability)
860{
861#if defined(HAVE_POSIX_CAPABILITIES)
862 set_process_capability(capability, True);
863#endif /* HAVE_POSIX_CAPABILITIES */
864}
865
866void drop_effective_capability(enum smbd_capability capability)
867{
868#if defined(HAVE_POSIX_CAPABILITIES)
869 set_process_capability(capability, False);
870#endif /* HAVE_POSIX_CAPABILITIES */
871}
872
873/**************************************************************************
874 Wrapper for random().
875****************************************************************************/
876
877long sys_random(void)
878{
879#if defined(HAVE_RANDOM)
880 return (long)random();
881#elif defined(HAVE_RAND)
882 return (long)rand();
883#else
884 DEBUG(0,("Error - no random function available !\n"));
885 exit(1);
886#endif
887}
888
889/**************************************************************************
890 Wrapper for srandom().
891****************************************************************************/
892
893void sys_srandom(unsigned int seed)
894{
895#if defined(HAVE_SRANDOM)
896 srandom(seed);
897#elif defined(HAVE_SRAND)
898 srand(seed);
899#else
900 DEBUG(0,("Error - no srandom function available !\n"));
901 exit(1);
902#endif
903}
904
905/**************************************************************************
906 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
907****************************************************************************/
908
909int groups_max(void)
910{
911#if defined(SYSCONF_SC_NGROUPS_MAX)
912 int ret = sysconf(_SC_NGROUPS_MAX);
913 return (ret == -1) ? NGROUPS_MAX : ret;
914#else
915 return NGROUPS_MAX;
916#endif
917}
918
919/**************************************************************************
920 Wrap setgroups and getgroups for systems that declare getgroups() as
921 returning an array of gid_t, but actuall return an array of int.
922****************************************************************************/
923
924#if defined(HAVE_BROKEN_GETGROUPS)
925static int sys_broken_getgroups(int setlen, gid_t *gidset)
926{
927 GID_T gid;
928 GID_T *group_list;
929 int i, ngroups;
930
931 if(setlen == 0) {
932 return getgroups(setlen, &gid);
933 }
934
935 /*
936 * Broken case. We need to allocate a
937 * GID_T array of size setlen.
938 */
939
940 if(setlen < 0) {
941 errno = EINVAL;
942 return -1;
943 }
944
945 if (setlen == 0)
946 setlen = groups_max();
947
948 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
949 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
950 return -1;
951 }
952
953 if((ngroups = getgroups(setlen, group_list)) < 0) {
954 int saved_errno = errno;
955 SAFE_FREE(group_list);
956 errno = saved_errno;
957 return -1;
958 }
959
960 for(i = 0; i < ngroups; i++)
961 gidset[i] = (gid_t)group_list[i];
962
963 SAFE_FREE(group_list);
964 return ngroups;
965}
966
967static int sys_broken_setgroups(int setlen, gid_t *gidset)
968{
969 GID_T *group_list;
970 int i ;
971
972 if (setlen == 0)
973 return 0 ;
974
975 if (setlen < 0 || setlen > groups_max()) {
976 errno = EINVAL;
977 return -1;
978 }
979
980 /*
981 * Broken case. We need to allocate a
982 * GID_T array of size setlen.
983 */
984
985 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
986 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
987 return -1;
988 }
989
990 for(i = 0; i < setlen; i++)
991 group_list[i] = (GID_T) gidset[i];
992
993 if(setgroups(setlen, group_list) != 0) {
994 int saved_errno = errno;
995 SAFE_FREE(group_list);
996 errno = saved_errno;
997 return -1;
998 }
999
1000 SAFE_FREE(group_list);
1001 return 0 ;
1002}
1003
1004#endif /* HAVE_BROKEN_GETGROUPS */
1005
1006/* This is a list of systems that require the first GID passed to setgroups(2)
1007 * to be the effective GID. If your system is one of these, add it here.
1008 */
1009#if defined (FREEBSD) || defined (DARWINOS)
1010#define USE_BSD_SETGROUPS
1011#endif
1012
1013#if defined(USE_BSD_SETGROUPS)
1014/* Depending on the particular BSD implementation, the first GID that is
1015 * passed to setgroups(2) will either be ignored or will set the credential's
1016 * effective GID. In either case, the right thing to do is to guarantee that
1017 * gidset[0] is the effective GID.
1018 */
1019static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
1020{
1021 gid_t *new_gidset = NULL;
1022 int max;
1023 int ret;
1024
1025 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1026 max = groups_max();
1027
1028 /* No group list, just make sure we are setting the efective GID. */
1029 if (setlen == 0) {
1030 return setgroups(1, &primary_gid);
1031 }
1032
1033 /* If the primary gid is not the first array element, grow the array
1034 * and insert it at the front.
1035 */
1036 if (gidset[0] != primary_gid) {
1037 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1038 if (new_gidset == NULL) {
1039 return -1;
1040 }
1041
1042 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1043 new_gidset[0] = primary_gid;
1044 setlen++;
1045 }
1046
1047 if (setlen > max) {
1048 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1049 setlen, max));
1050 setlen = max;
1051 }
1052
1053#if defined(HAVE_BROKEN_GETGROUPS)
1054 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1055#else
1056 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1057#endif
1058
1059 if (new_gidset) {
1060 int errsav = errno;
1061 SAFE_FREE(new_gidset);
1062 errno = errsav;
1063 }
1064
1065 return ret;
1066}
1067
1068#endif /* USE_BSD_SETGROUPS */
1069
1070/**************************************************************************
1071 Wrapper for getgroups. Deals with broken (int) case.
1072****************************************************************************/
1073
1074int sys_getgroups(int setlen, gid_t *gidset)
1075{
1076#if defined(HAVE_BROKEN_GETGROUPS)
1077 return sys_broken_getgroups(setlen, gidset);
1078#else
1079 return getgroups(setlen, gidset);
1080#endif
1081}
1082
1083/**************************************************************************
1084 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1085****************************************************************************/
1086
1087int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1088{
1089#ifdef __OS2__x
1090 return 0;
1091#endif
1092#if !defined(HAVE_SETGROUPS)
1093 errno = ENOSYS;
1094 return -1;
1095#endif /* HAVE_SETGROUPS */
1096
1097#if defined(USE_BSD_SETGROUPS)
1098 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1099#elif defined(HAVE_BROKEN_GETGROUPS)
1100 return sys_broken_setgroups(setlen, gidset);
1101#else
1102 return setgroups(setlen, gidset);
1103#endif
1104}
1105
1106/**************************************************************************
1107 Wrappers for setpwent(), getpwent() and endpwent()
1108****************************************************************************/
1109
1110void sys_setpwent(void)
1111{
1112 setpwent();
1113}
1114
1115struct passwd *sys_getpwent(void)
1116{
1117 return getpwent();
1118}
1119
1120void sys_endpwent(void)
1121{
1122 endpwent();
1123}
1124
1125/**************************************************************************
1126 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1127****************************************************************************/
1128
1129
1130struct passwd *sys_getpwnam(const char *name)
1131{
1132 return getpwnam(name);
1133}
1134
1135struct passwd *sys_getpwuid(uid_t uid)
1136{
1137 return getpwuid(uid);
1138}
1139
1140struct group *sys_getgrnam(const char *name)
1141{
1142 return getgrnam(name);
1143}
1144
1145struct group *sys_getgrgid(gid_t gid)
1146{
1147 return getgrgid(gid);
1148}
1149
1150/**************************************************************************
1151 Extract a command into an arg list.
1152****************************************************************************/
1153
1154static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1155{
1156 char *trunc_cmd;
1157 char *saveptr;
1158 char *ptr;
1159 int argcl;
1160 char **argl = NULL;
1161 int i;
1162
1163 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1164 DEBUG(0, ("talloc failed\n"));
1165 goto nomem;
1166 }
1167
1168 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1169 TALLOC_FREE(trunc_cmd);
1170 errno = EINVAL;
1171 return NULL;
1172 }
1173
1174 /*
1175 * Count the args.
1176 */
1177
1178 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1179 argcl++;
1180
1181 TALLOC_FREE(trunc_cmd);
1182
1183 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1184 goto nomem;
1185 }
1186
1187 /*
1188 * Now do the extraction.
1189 */
1190
1191 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1192 goto nomem;
1193 }
1194
1195 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1196 i = 0;
1197
1198 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1199 goto nomem;
1200 }
1201
1202 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1203
1204 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1205 goto nomem;
1206 }
1207 }
1208
1209 argl[i++] = NULL;
1210 return argl;
1211
1212 nomem:
1213 DEBUG(0, ("talloc failed\n"));
1214 TALLOC_FREE(trunc_cmd);
1215 TALLOC_FREE(argl);
1216 errno = ENOMEM;
1217 return NULL;
1218}
1219
1220/**************************************************************************
1221 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1222 a sys_getpid() that only does a system call *once*.
1223****************************************************************************/
1224
1225static pid_t mypid = (pid_t)-1;
1226
1227pid_t sys_fork(void)
1228{
1229 pid_t forkret = fork();
1230
1231 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1232 mypid = (pid_t) -1;
1233
1234 return forkret;
1235}
1236
1237/**************************************************************************
1238 Wrapper for getpid. Ensures we only do a system call *once*.
1239****************************************************************************/
1240
1241pid_t sys_getpid(void)
1242{
1243 if (mypid == (pid_t)-1)
1244 mypid = getpid();
1245
1246 return mypid;
1247}
1248
1249/**************************************************************************
1250 Wrapper for popen. Safer as it doesn't search a path.
1251 Modified from the glibc sources.
1252 modified by tridge to return a file descriptor. We must kick our FILE* habit
1253****************************************************************************/
1254
1255typedef struct _popen_list
1256{
1257 int fd;
1258 pid_t child_pid;
1259 struct _popen_list *next;
1260} popen_list;
1261
1262static popen_list *popen_chain;
1263
1264int sys_popen(const char *command)
1265{
1266 int parent_end, child_end;
1267 int pipe_fds[2];
1268 popen_list *entry = NULL;
1269 char **argl = NULL;
1270
1271 if (pipe(pipe_fds) < 0)
1272 return -1;
1273
1274 parent_end = pipe_fds[0];
1275 child_end = pipe_fds[1];
1276
1277 if (!*command) {
1278 errno = EINVAL;
1279 goto err_exit;
1280 }
1281
1282 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1283 goto err_exit;
1284
1285 ZERO_STRUCTP(entry);
1286
1287 /*
1288 * Extract the command and args into a NULL terminated array.
1289 */
1290
1291 if(!(argl = extract_args(NULL, command)))
1292 goto err_exit;
1293
1294 entry->child_pid = sys_fork();
1295
1296 if (entry->child_pid == -1) {
1297 goto err_exit;
1298 }
1299
1300 if (entry->child_pid == 0) {
1301
1302 /*
1303 * Child !
1304 */
1305
1306 int child_std_end = STDOUT_FILENO;
1307 popen_list *p;
1308
1309 close(parent_end);
1310 if (child_end != child_std_end) {
1311 dup2 (child_end, child_std_end);
1312 close (child_end);
1313 }
1314
1315 /*
1316 * POSIX.2: "popen() shall ensure that any streams from previous
1317 * popen() calls that remain open in the parent process are closed
1318 * in the new child process."
1319 */
1320
1321 for (p = popen_chain; p; p = p->next)
1322 close(p->fd);
1323
1324 execv(argl[0], argl);
1325 _exit (127);
1326 }
1327
1328 /*
1329 * Parent.
1330 */
1331
1332 close (child_end);
1333 TALLOC_FREE(argl);
1334
1335 /* Link into popen_chain. */
1336 entry->next = popen_chain;
1337 popen_chain = entry;
1338 entry->fd = parent_end;
1339
1340 return entry->fd;
1341
1342err_exit:
1343
1344 SAFE_FREE(entry);
1345 SAFE_FREE(argl);
1346 close(pipe_fds[0]);
1347 close(pipe_fds[1]);
1348 return -1;
1349}
1350
1351/**************************************************************************
1352 Wrapper for pclose. Modified from the glibc sources.
1353****************************************************************************/
1354
1355int sys_pclose(int fd)
1356{
1357 int wstatus;
1358 popen_list **ptr = &popen_chain;
1359 popen_list *entry = NULL;
1360 pid_t wait_pid;
1361 int status = -1;
1362
1363 /* Unlink from popen_chain. */
1364 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1365 if ((*ptr)->fd == fd) {
1366 entry = *ptr;
1367 *ptr = (*ptr)->next;
1368 status = 0;
1369 break;
1370 }
1371 }
1372
1373 if (status < 0 || close(entry->fd) < 0)
1374 return -1;
1375
1376 /*
1377 * As Samba is catching and eating child process
1378 * exits we don't really care about the child exit
1379 * code, a -1 with errno = ECHILD will do fine for us.
1380 */
1381
1382 do {
1383 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1384 } while (wait_pid == -1 && errno == EINTR);
1385
1386 SAFE_FREE(entry);
1387
1388 if (wait_pid == -1)
1389 return -1;
1390 return wstatus;
1391}
1392
1393/**************************************************************************
1394 Wrappers for dlopen, dlsym, dlclose.
1395****************************************************************************/
1396
1397void *sys_dlopen(const char *name, int flags)
1398{
1399#if defined(HAVE_DLOPEN)
1400 return dlopen(name, flags);
1401#else
1402 return NULL;
1403#endif
1404}
1405
1406void *sys_dlsym(void *handle, const char *symbol)
1407{
1408#if defined(HAVE_DLSYM)
1409 return dlsym(handle, symbol);
1410#else
1411 return NULL;
1412#endif
1413}
1414
1415int sys_dlclose (void *handle)
1416{
1417#if defined(HAVE_DLCLOSE)
1418 return dlclose(handle);
1419#else
1420 return 0;
1421#endif
1422}
1423
1424const char *sys_dlerror(void)
1425{
1426#if defined(HAVE_DLERROR)
1427 return dlerror();
1428#else
1429 return NULL;
1430#endif
1431}
1432
1433int sys_dup2(int oldfd, int newfd)
1434{
1435#if defined(HAVE_DUP2)
1436 return dup2(oldfd, newfd);
1437#else
1438 errno = ENOSYS;
1439 return -1;
1440#endif
1441}
1442
1443/**************************************************************************
1444 Wrapper for Admin Logs.
1445****************************************************************************/
1446
1447 void sys_adminlog(int priority, const char *format_str, ...)
1448{
1449 va_list ap;
1450 int ret;
1451 char *msgbuf = NULL;
1452
1453 va_start( ap, format_str );
1454 ret = vasprintf( &msgbuf, format_str, ap );
1455 va_end( ap );
1456
1457 if (ret == -1)
1458 return;
1459
1460#if defined(HAVE_SYSLOG)
1461 syslog( priority, "%s", msgbuf );
1462#else
1463 DEBUG(0,("%s", msgbuf ));
1464#endif
1465 SAFE_FREE(msgbuf);
1466}
1467
1468/******** Solaris EA helper function prototypes ********/
1469#ifdef HAVE_ATTROPEN
1470#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1471static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1472static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1473static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1474static int solaris_unlinkat(int attrdirfd, const char *name);
1475static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1476static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1477#endif
1478
1479/**************************************************************************
1480 Wrappers for extented attribute calls. Based on the Linux package with
1481 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1482****************************************************************************/
1483
1484ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1485{
1486#if defined(HAVE_GETXATTR)
1487#ifndef XATTR_ADD_OPT
1488 return getxattr(path, name, value, size);
1489#else
1490 int options = 0;
1491 return getxattr(path, name, value, size, 0, options);
1492#endif
1493#elif defined(HAVE_GETEA)
1494 return getea(path, name, value, size);
1495#elif defined(HAVE_EXTATTR_GET_FILE)
1496 char *s;
1497 ssize_t retval;
1498 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1499 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1500 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1501 /*
1502 * The BSD implementation has a nasty habit of silently truncating
1503 * the returned value to the size of the buffer, so we have to check
1504 * that the buffer is large enough to fit the returned value.
1505 */
1506 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1507 if(retval > size) {
1508 errno = ERANGE;
1509 return -1;
1510 }
1511 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1512 return retval;
1513 }
1514
1515 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1516 return -1;
1517#elif defined(HAVE_ATTR_GET)
1518 int retval, flags = 0;
1519 int valuelength = (int)size;
1520 char *attrname = strchr(name,'.') + 1;
1521
1522 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1523
1524 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1525
1526 return retval ? retval : valuelength;
1527#elif defined(HAVE_ATTROPEN)
1528 ssize_t ret = -1;
1529 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1530 if (attrfd >= 0) {
1531 ret = solaris_read_xattr(attrfd, value, size);
1532 close(attrfd);
1533 }
1534 return ret;
1535#elif defined(__OS2__)
1536 return unigetxattr(path, 0, name, value, size);
1537#else
1538 errno = ENOSYS;
1539 return -1;
1540#endif
1541}
1542
1543ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1544{
1545#if defined(HAVE_LGETXATTR)
1546 return lgetxattr(path, name, value, size);
1547#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1548 int options = XATTR_NOFOLLOW;
1549 return getxattr(path, name, value, size, 0, options);
1550#elif defined(HAVE_LGETEA)
1551 return lgetea(path, name, value, size);
1552#elif defined(HAVE_EXTATTR_GET_LINK)
1553 char *s;
1554 ssize_t retval;
1555 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1556 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1557 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1558
1559 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1560 if(retval > size) {
1561 errno = ERANGE;
1562 return -1;
1563 }
1564 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1565 return retval;
1566 }
1567
1568 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1569 return -1;
1570#elif defined(HAVE_ATTR_GET)
1571 int retval, flags = ATTR_DONTFOLLOW;
1572 int valuelength = (int)size;
1573 char *attrname = strchr(name,'.') + 1;
1574
1575 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1576
1577 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1578
1579 return retval ? retval : valuelength;
1580#elif defined(HAVE_ATTROPEN)
1581 ssize_t ret = -1;
1582 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1583 if (attrfd >= 0) {
1584 ret = solaris_read_xattr(attrfd, value, size);
1585 close(attrfd);
1586 }
1587 return ret;
1588#else
1589 errno = ENOSYS;
1590 return -1;
1591#endif
1592}
1593
1594ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1595{
1596#if defined(HAVE_FGETXATTR)
1597#ifndef XATTR_ADD_OPT
1598 return fgetxattr(filedes, name, value, size);
1599#else
1600 int options = 0;
1601 return fgetxattr(filedes, name, value, size, 0, options);
1602#endif
1603#elif defined(HAVE_FGETEA)
1604 return fgetea(filedes, name, value, size);
1605#elif defined(HAVE_EXTATTR_GET_FD)
1606 char *s;
1607 ssize_t retval;
1608 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1609 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1610 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1611
1612 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1613 if(retval > size) {
1614 errno = ERANGE;
1615 return -1;
1616 }
1617 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1618 return retval;
1619 }
1620
1621 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1622 return -1;
1623#elif defined(HAVE_ATTR_GETF)
1624 int retval, flags = 0;
1625 int valuelength = (int)size;
1626 char *attrname = strchr(name,'.') + 1;
1627
1628 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1629
1630 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1631
1632 return retval ? retval : valuelength;
1633#elif defined(HAVE_ATTROPEN)
1634 ssize_t ret = -1;
1635 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1636 if (attrfd >= 0) {
1637 ret = solaris_read_xattr(attrfd, value, size);
1638 close(attrfd);
1639 }
1640 return ret;
1641#elif defined(__OS2__)
1642 return unigetxattr(0, filedes, name, value, size);
1643#else
1644 errno = ENOSYS;
1645 return -1;
1646#endif
1647}
1648
1649#if defined(HAVE_EXTATTR_LIST_FILE)
1650
1651#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1652
1653static struct {
1654 int space;
1655 const char *name;
1656 size_t len;
1657}
1658extattr[] = {
1659 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1660 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1661};
1662
1663typedef union {
1664 const char *path;
1665 int filedes;
1666} extattr_arg;
1667
1668static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1669{
1670 ssize_t list_size, total_size = 0;
1671 int i, t, len;
1672 char *buf;
1673 /* Iterate through extattr(2) namespaces */
1674 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1675 switch(type) {
1676#if defined(HAVE_EXTATTR_LIST_FILE)
1677 case 0:
1678 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1679 break;
1680#endif
1681#if defined(HAVE_EXTATTR_LIST_LINK)
1682 case 1:
1683 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1684 break;
1685#endif
1686#if defined(HAVE_EXTATTR_LIST_FD)
1687 case 2:
1688 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1689 break;
1690#endif
1691 default:
1692 errno = ENOSYS;
1693 return -1;
1694 }
1695 /* Some error happend. Errno should be set by the previous call */
1696 if(list_size < 0)
1697 return -1;
1698 /* No attributes */
1699 if(list_size == 0)
1700 continue;
1701 /* XXX: Call with an empty buffer may be used to calculate
1702 necessary buffer size. Unfortunately, we can't say, how
1703 many attributes were returned, so here is the potential
1704 problem with the emulation.
1705 */
1706 if(list == NULL) {
1707 /* Take the worse case of one char attribute names -
1708 two bytes per name plus one more for sanity.
1709 */
1710 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1711 continue;
1712 }
1713 /* Count necessary offset to fit namespace prefixes */
1714 len = 0;
1715 for(i = 0; i < list_size; i += list[i] + 1)
1716 len += extattr[t].len;
1717
1718 total_size += list_size + len;
1719 /* Buffer is too small to fit the results */
1720 if(total_size > size) {
1721 errno = ERANGE;
1722 return -1;
1723 }
1724 /* Shift results back, so we can prepend prefixes */
1725 buf = memmove(list + len, list, list_size);
1726
1727 for(i = 0; i < list_size; i += len + 1) {
1728 len = buf[i];
1729 strncpy(list, extattr[t].name, extattr[t].len + 1);
1730 list += extattr[t].len;
1731 strncpy(list, buf + i + 1, len);
1732 list[len] = '\0';
1733 list += len + 1;
1734 }
1735 size -= total_size;
1736 }
1737 return total_size;
1738}
1739
1740#endif
1741
1742#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1743static char attr_buffer[ATTR_MAX_VALUELEN];
1744
1745static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1746{
1747 int retval = 0, index;
1748 attrlist_cursor_t *cursor = 0;
1749 int total_size = 0;
1750 attrlist_t * al = (attrlist_t *)attr_buffer;
1751 attrlist_ent_t *ae;
1752 size_t ent_size, left = size;
1753 char *bp = list;
1754
1755 while (True) {
1756 if (filedes)
1757 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1758 else
1759 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1760 if (retval) break;
1761 for (index = 0; index < al->al_count; index++) {
1762 ae = ATTR_ENTRY(attr_buffer, index);
1763 ent_size = strlen(ae->a_name) + sizeof("user.");
1764 if (left >= ent_size) {
1765 strncpy(bp, "user.", sizeof("user."));
1766 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1767 bp += ent_size;
1768 left -= ent_size;
1769 } else if (size) {
1770 errno = ERANGE;
1771 retval = -1;
1772 break;
1773 }
1774 total_size += ent_size;
1775 }
1776 if (al->al_more == 0) break;
1777 }
1778 if (retval == 0) {
1779 flags |= ATTR_ROOT;
1780 cursor = 0;
1781 while (True) {
1782 if (filedes)
1783 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1784 else
1785 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1786 if (retval) break;
1787 for (index = 0; index < al->al_count; index++) {
1788 ae = ATTR_ENTRY(attr_buffer, index);
1789 ent_size = strlen(ae->a_name) + sizeof("system.");
1790 if (left >= ent_size) {
1791 strncpy(bp, "system.", sizeof("system."));
1792 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1793 bp += ent_size;
1794 left -= ent_size;
1795 } else if (size) {
1796 errno = ERANGE;
1797 retval = -1;
1798 break;
1799 }
1800 total_size += ent_size;
1801 }
1802 if (al->al_more == 0) break;
1803 }
1804 }
1805 return (ssize_t)(retval ? retval : total_size);
1806}
1807
1808#endif
1809
1810ssize_t sys_listxattr (const char *path, char *list, size_t size)
1811{
1812#if defined(HAVE_LISTXATTR)
1813#ifndef XATTR_ADD_OPT
1814 return listxattr(path, list, size);
1815#else
1816 int options = 0;
1817 return listxattr(path, list, size, options);
1818#endif
1819#elif defined(HAVE_LISTEA)
1820 return listea(path, list, size);
1821#elif defined(HAVE_EXTATTR_LIST_FILE)
1822 extattr_arg arg;
1823 arg.path = path;
1824 return bsd_attr_list(0, arg, list, size);
1825#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1826 return irix_attr_list(path, 0, list, size, 0);
1827#elif defined(HAVE_ATTROPEN)
1828 ssize_t ret = -1;
1829 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1830 if (attrdirfd >= 0) {
1831 ret = solaris_list_xattr(attrdirfd, list, size);
1832 close(attrdirfd);
1833 }
1834 return ret;
1835#elif defined(__OS2__)
1836 return unilistxattr(path, 0, list, size);
1837#else
1838 errno = ENOSYS;
1839 return -1;
1840#endif
1841}
1842
1843ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1844{
1845#if defined(HAVE_LLISTXATTR)
1846 return llistxattr(path, list, size);
1847#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1848 int options = XATTR_NOFOLLOW;
1849 return listxattr(path, list, size, options);
1850#elif defined(HAVE_LLISTEA)
1851 return llistea(path, list, size);
1852#elif defined(HAVE_EXTATTR_LIST_LINK)
1853 extattr_arg arg;
1854 arg.path = path;
1855 return bsd_attr_list(1, arg, list, size);
1856#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1857 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1858#elif defined(HAVE_ATTROPEN)
1859 ssize_t ret = -1;
1860 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1861 if (attrdirfd >= 0) {
1862 ret = solaris_list_xattr(attrdirfd, list, size);
1863 close(attrdirfd);
1864 }
1865 return ret;
1866#elif defined(__OS2__)
1867 return unilistxattr(path, 0, list, size);
1868#else
1869 errno = ENOSYS;
1870 return -1;
1871#endif
1872}
1873
1874ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1875{
1876#if defined(HAVE_FLISTXATTR)
1877#ifndef XATTR_ADD_OPT
1878 return flistxattr(filedes, list, size);
1879#else
1880 int options = 0;
1881 return flistxattr(filedes, list, size, options);
1882#endif
1883#elif defined(HAVE_FLISTEA)
1884 return flistea(filedes, list, size);
1885#elif defined(HAVE_EXTATTR_LIST_FD)
1886 extattr_arg arg;
1887 arg.filedes = filedes;
1888 return bsd_attr_list(2, arg, list, size);
1889#elif defined(HAVE_ATTR_LISTF)
1890 return irix_attr_list(NULL, filedes, list, size, 0);
1891#elif defined(HAVE_ATTROPEN)
1892 ssize_t ret = -1;
1893 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1894 if (attrdirfd >= 0) {
1895 ret = solaris_list_xattr(attrdirfd, list, size);
1896 close(attrdirfd);
1897 }
1898 return ret;
1899#elif defined(__OS2__)
1900 return unilistxattr(0, filedes, list, size);
1901#else
1902 errno = ENOSYS;
1903 return -1;
1904#endif
1905}
1906
1907int sys_removexattr (const char *path, const char *name)
1908{
1909#if defined(HAVE_REMOVEXATTR)
1910#ifndef XATTR_ADD_OPT
1911 return removexattr(path, name);
1912#else
1913 int options = 0;
1914 return removexattr(path, name, options);
1915#endif
1916#elif defined(HAVE_REMOVEEA)
1917 return removeea(path, name);
1918#elif defined(HAVE_EXTATTR_DELETE_FILE)
1919 char *s;
1920 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1921 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1922 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1923
1924 return extattr_delete_file(path, attrnamespace, attrname);
1925#elif defined(HAVE_ATTR_REMOVE)
1926 int flags = 0;
1927 char *attrname = strchr(name,'.') + 1;
1928
1929 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1930
1931 return attr_remove(path, attrname, flags);
1932#elif defined(HAVE_ATTROPEN)
1933 int ret = -1;
1934 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1935 if (attrdirfd >= 0) {
1936 ret = solaris_unlinkat(attrdirfd, name);
1937 close(attrdirfd);
1938 }
1939 return ret;
1940#elif defined(__OS2__)
1941 return uniremovexattr (path, 0, name);
1942#else
1943 errno = ENOSYS;
1944 return -1;
1945#endif
1946}
1947
1948int sys_lremovexattr (const char *path, const char *name)
1949{
1950#if defined(HAVE_LREMOVEXATTR)
1951 return lremovexattr(path, name);
1952#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1953 int options = XATTR_NOFOLLOW;
1954 return removexattr(path, name, options);
1955#elif defined(HAVE_LREMOVEEA)
1956 return lremoveea(path, name);
1957#elif defined(HAVE_EXTATTR_DELETE_LINK)
1958 char *s;
1959 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1960 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1961 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1962
1963 return extattr_delete_link(path, attrnamespace, attrname);
1964#elif defined(HAVE_ATTR_REMOVE)
1965 int flags = ATTR_DONTFOLLOW;
1966 char *attrname = strchr(name,'.') + 1;
1967
1968 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1969
1970 return attr_remove(path, attrname, flags);
1971#elif defined(HAVE_ATTROPEN)
1972 int ret = -1;
1973 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1974 if (attrdirfd >= 0) {
1975 ret = solaris_unlinkat(attrdirfd, name);
1976 close(attrdirfd);
1977 }
1978 return ret;
1979#elif defined(__OS2__)
1980 return uniremovexattr (path, 0, name);
1981#else
1982 errno = ENOSYS;
1983 return -1;
1984#endif
1985}
1986
1987int sys_fremovexattr (int filedes, const char *name)
1988{
1989#if defined(HAVE_FREMOVEXATTR)
1990#ifndef XATTR_ADD_OPT
1991 return fremovexattr(filedes, name);
1992#else
1993 int options = 0;
1994 return fremovexattr(filedes, name, options);
1995#endif
1996#elif defined(HAVE_FREMOVEEA)
1997 return fremoveea(filedes, name);
1998#elif defined(HAVE_EXTATTR_DELETE_FD)
1999 char *s;
2000 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2001 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2002 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2003
2004 return extattr_delete_fd(filedes, attrnamespace, attrname);
2005#elif defined(HAVE_ATTR_REMOVEF)
2006 int flags = 0;
2007 char *attrname = strchr(name,'.') + 1;
2008
2009 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
2010
2011 return attr_removef(filedes, attrname, flags);
2012#elif defined(HAVE_ATTROPEN)
2013 int ret = -1;
2014 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
2015 if (attrdirfd >= 0) {
2016 ret = solaris_unlinkat(attrdirfd, name);
2017 close(attrdirfd);
2018 }
2019 return ret;
2020#elif defined(__OS2__)
2021 return uniremovexattr (0, filedes, name);
2022#else
2023 errno = ENOSYS;
2024 return -1;
2025#endif
2026}
2027
2028int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2029{
2030#if defined(HAVE_SETXATTR)
2031#ifndef XATTR_ADD_OPT
2032 return setxattr(path, name, value, size, flags);
2033#else
2034 int options = 0;
2035 return setxattr(path, name, value, size, 0, options);
2036#endif
2037#elif defined(HAVE_SETEA)
2038 return setea(path, name, value, size, flags);
2039#elif defined(HAVE_EXTATTR_SET_FILE)
2040 char *s;
2041 int retval = 0;
2042 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2043 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2044 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2045 if (flags) {
2046 /* Check attribute existence */
2047 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
2048 if (retval < 0) {
2049 /* REPLACE attribute, that doesn't exist */
2050 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2051 errno = ENOATTR;
2052 return -1;
2053 }
2054 /* Ignore other errors */
2055 }
2056 else {
2057 /* CREATE attribute, that already exists */
2058 if (flags & XATTR_CREATE) {
2059 errno = EEXIST;
2060 return -1;
2061 }
2062 }
2063 }
2064 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2065 return (retval < 0) ? -1 : 0;
2066#elif defined(HAVE_ATTR_SET)
2067 int myflags = 0;
2068 char *attrname = strchr(name,'.') + 1;
2069
2070 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2071 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2072 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2073
2074 return attr_set(path, attrname, (const char *)value, size, myflags);
2075#elif defined(HAVE_ATTROPEN)
2076 int ret = -1;
2077 int myflags = O_RDWR;
2078 int attrfd;
2079 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2080 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2081 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2082 if (attrfd >= 0) {
2083 ret = solaris_write_xattr(attrfd, value, size);
2084 close(attrfd);
2085 }
2086 return ret;
2087#elif defined(__OS2__)
2088 return unisetxattr (path, 0, name, value, size, flags);
2089#else
2090 errno = ENOSYS;
2091 return -1;
2092#endif
2093}
2094
2095int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2096{
2097#if defined(HAVE_LSETXATTR)
2098 return lsetxattr(path, name, value, size, flags);
2099#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2100 int options = XATTR_NOFOLLOW;
2101 return setxattr(path, name, value, size, 0, options);
2102#elif defined(LSETEA)
2103 return lsetea(path, name, value, size, flags);
2104#elif defined(HAVE_EXTATTR_SET_LINK)
2105 char *s;
2106 int retval = 0;
2107 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2108 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2109 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2110 if (flags) {
2111 /* Check attribute existence */
2112 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2113 if (retval < 0) {
2114 /* REPLACE attribute, that doesn't exist */
2115 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2116 errno = ENOATTR;
2117 return -1;
2118 }
2119 /* Ignore other errors */
2120 }
2121 else {
2122 /* CREATE attribute, that already exists */
2123 if (flags & XATTR_CREATE) {
2124 errno = EEXIST;
2125 return -1;
2126 }
2127 }
2128 }
2129
2130 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2131 return (retval < 0) ? -1 : 0;
2132#elif defined(HAVE_ATTR_SET)
2133 int myflags = ATTR_DONTFOLLOW;
2134 char *attrname = strchr(name,'.') + 1;
2135
2136 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2137 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2138 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2139
2140 return attr_set(path, attrname, (const char *)value, size, myflags);
2141#elif defined(HAVE_ATTROPEN)
2142 int ret = -1;
2143 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2144 int attrfd;
2145 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2146 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2147 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2148 if (attrfd >= 0) {
2149 ret = solaris_write_xattr(attrfd, value, size);
2150 close(attrfd);
2151 }
2152 return ret;
2153#elif defined(__OS2__)
2154 return unisetxattr (path, 0, name, value, size, flags);
2155#else
2156 errno = ENOSYS;
2157 return -1;
2158#endif
2159}
2160
2161int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2162{
2163#if defined(HAVE_FSETXATTR)
2164#ifndef XATTR_ADD_OPT
2165 return fsetxattr(filedes, name, value, size, flags);
2166#else
2167 int options = 0;
2168 return fsetxattr(filedes, name, value, size, 0, options);
2169#endif
2170#elif defined(HAVE_FSETEA)
2171 return fsetea(filedes, name, value, size, flags);
2172#elif defined(HAVE_EXTATTR_SET_FD)
2173 char *s;
2174 int retval = 0;
2175 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2176 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2177 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2178 if (flags) {
2179 /* Check attribute existence */
2180 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2181 if (retval < 0) {
2182 /* REPLACE attribute, that doesn't exist */
2183 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2184 errno = ENOATTR;
2185 return -1;
2186 }
2187 /* Ignore other errors */
2188 }
2189 else {
2190 /* CREATE attribute, that already exists */
2191 if (flags & XATTR_CREATE) {
2192 errno = EEXIST;
2193 return -1;
2194 }
2195 }
2196 }
2197 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2198 return (retval < 0) ? -1 : 0;
2199#elif defined(HAVE_ATTR_SETF)
2200 int myflags = 0;
2201 char *attrname = strchr(name,'.') + 1;
2202
2203 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2204 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2205 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2206
2207 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2208#elif defined(HAVE_ATTROPEN)
2209 int ret = -1;
2210 int myflags = O_RDWR | O_XATTR;
2211 int attrfd;
2212 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2213 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2214 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2215 if (attrfd >= 0) {
2216 ret = solaris_write_xattr(attrfd, value, size);
2217 close(attrfd);
2218 }
2219 return ret;
2220#elif defined(__OS2__)
2221 return unisetxattr (0, filedes, name, value, size, flags);
2222#else
2223 errno = ENOSYS;
2224 return -1;
2225#endif
2226}
2227
2228/**************************************************************************
2229 helper functions for Solaris' EA support
2230****************************************************************************/
2231#ifdef HAVE_ATTROPEN
2232static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2233{
2234 struct stat sbuf;
2235
2236 if (fstat(attrfd, &sbuf) == -1) {
2237 errno = ENOATTR;
2238 return -1;
2239 }
2240
2241 /* This is to return the current size of the named extended attribute */
2242 if (size == 0) {
2243 return sbuf.st_size;
2244 }
2245
2246 /* check size and read xattr */
2247 if (sbuf.st_size > size) {
2248 errno = ERANGE;
2249 return -1;
2250 }
2251
2252 return read(attrfd, value, sbuf.st_size);
2253}
2254
2255static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2256{
2257 ssize_t len = 0;
2258 DIR *dirp;
2259 struct dirent *de;
2260 int newfd = dup(attrdirfd);
2261 /* CAUTION: The originating file descriptor should not be
2262 used again following the call to fdopendir().
2263 For that reason we dup() the file descriptor
2264 here to make things more clear. */
2265 dirp = fdopendir(newfd);
2266
2267 while ((de = readdir(dirp))) {
2268 size_t listlen = strlen(de->d_name);
2269 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2270 /* we don't want "." and ".." here: */
2271 DEBUG(10,("skipped EA %s\n",de->d_name));
2272 continue;
2273 }
2274
2275 if (size == 0) {
2276 /* return the current size of the list of extended attribute names*/
2277 len += listlen + 1;
2278 } else {
2279 /* check size and copy entrieѕ + nul into list. */
2280 if ((len + listlen + 1) > size) {
2281 errno = ERANGE;
2282 len = -1;
2283 break;
2284 } else {
2285 safe_strcpy(list + len, de->d_name, listlen);
2286 len += listlen;
2287 list[len] = '\0';
2288 ++len;
2289 }
2290 }
2291 }
2292
2293 if (closedir(dirp) == -1) {
2294 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2295 return -1;
2296 }
2297 return len;
2298}
2299
2300static int solaris_unlinkat(int attrdirfd, const char *name)
2301{
2302 if (unlinkat(attrdirfd, name, 0) == -1) {
2303 if (errno == ENOENT) {
2304 errno = ENOATTR;
2305 }
2306 return -1;
2307 }
2308 return 0;
2309}
2310
2311static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2312{
2313 int filedes = attropen(path, attrpath, oflag, mode);
2314 if (filedes == -1) {
2315 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2316 if (errno == EINVAL) {
2317 errno = ENOTSUP;
2318 } else {
2319 errno = ENOATTR;
2320 }
2321 }
2322 return filedes;
2323}
2324
2325static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2326{
2327 int filedes = openat(fildes, path, oflag, mode);
2328 if (filedes == -1) {
2329 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2330 if (errno == EINVAL) {
2331 errno = ENOTSUP;
2332 } else {
2333 errno = ENOATTR;
2334 }
2335 }
2336 return filedes;
2337}
2338
2339static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2340{
2341 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2342 return 0;
2343 } else {
2344 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2345 return -1;
2346 }
2347}
2348#endif /*HAVE_ATTROPEN*/
2349
2350
2351/****************************************************************************
2352 Return the major devicenumber for UNIX extensions.
2353****************************************************************************/
2354
2355uint32 unix_dev_major(SMB_DEV_T dev)
2356{
2357#if defined(HAVE_DEVICE_MAJOR_FN)
2358 return (uint32)major(dev);
2359#else
2360 return (uint32)(dev >> 8);
2361#endif
2362}
2363
2364/****************************************************************************
2365 Return the minor devicenumber for UNIX extensions.
2366****************************************************************************/
2367
2368uint32 unix_dev_minor(SMB_DEV_T dev)
2369{
2370#if defined(HAVE_DEVICE_MINOR_FN)
2371 return (uint32)minor(dev);
2372#else
2373 return (uint32)(dev & 0xff);
2374#endif
2375}
2376
2377#if defined(WITH_AIO)
2378
2379/*******************************************************************
2380 An aio_read wrapper that will deal with 64-bit sizes.
2381********************************************************************/
2382
2383int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2384{
2385#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2386 return aio_read64(aiocb);
2387#elif defined(HAVE_AIO_READ)
2388 return aio_read(aiocb);
2389#else
2390 errno = ENOSYS;
2391 return -1;
2392#endif
2393}
2394
2395/*******************************************************************
2396 An aio_write wrapper that will deal with 64-bit sizes.
2397********************************************************************/
2398
2399int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2400{
2401#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2402 return aio_write64(aiocb);
2403#elif defined(HAVE_AIO_WRITE)
2404 return aio_write(aiocb);
2405#else
2406 errno = ENOSYS;
2407 return -1;
2408#endif
2409}
2410
2411/*******************************************************************
2412 An aio_return wrapper that will deal with 64-bit sizes.
2413********************************************************************/
2414
2415ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2416{
2417#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2418 return aio_return64(aiocb);
2419#elif defined(HAVE_AIO_RETURN)
2420 return aio_return(aiocb);
2421#else
2422 errno = ENOSYS;
2423 return -1;
2424#endif
2425}
2426
2427/*******************************************************************
2428 An aio_cancel wrapper that will deal with 64-bit sizes.
2429********************************************************************/
2430
2431int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2432{
2433#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2434 return aio_cancel64(fd, aiocb);
2435#elif defined(HAVE_AIO_CANCEL)
2436 return aio_cancel(fd, aiocb);
2437#else
2438 errno = ENOSYS;
2439 return -1;
2440#endif
2441}
2442
2443/*******************************************************************
2444 An aio_error wrapper that will deal with 64-bit sizes.
2445********************************************************************/
2446
2447int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2448{
2449#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2450 return aio_error64(aiocb);
2451#elif defined(HAVE_AIO_ERROR)
2452 return aio_error(aiocb);
2453#else
2454 errno = ENOSYS;
2455 return -1;
2456#endif
2457}
2458
2459/*******************************************************************
2460 An aio_fsync wrapper that will deal with 64-bit sizes.
2461********************************************************************/
2462
2463int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2464{
2465#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2466 return aio_fsync64(op, aiocb);
2467#elif defined(HAVE_AIO_FSYNC)
2468 return aio_fsync(op, aiocb);
2469#else
2470 errno = ENOSYS;
2471 return -1;
2472#endif
2473}
2474
2475/*******************************************************************
2476 An aio_fsync wrapper that will deal with 64-bit sizes.
2477********************************************************************/
2478
2479int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2480{
2481#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2482 return aio_suspend64(cblist, n, timeout);
2483#elif defined(HAVE_AIO_FSYNC)
2484 return aio_suspend(cblist, n, timeout);
2485#else
2486 errno = ENOSYS;
2487 return -1;
2488#endif
2489}
2490#else /* !WITH_AIO */
2491
2492int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2493{
2494 errno = ENOSYS;
2495 return -1;
2496}
2497
2498int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2499{
2500 errno = ENOSYS;
2501 return -1;
2502}
2503
2504ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2505{
2506 errno = ENOSYS;
2507 return -1;
2508}
2509
2510int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2511{
2512 errno = ENOSYS;
2513 return -1;
2514}
2515
2516int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2517{
2518 errno = ENOSYS;
2519 return -1;
2520}
2521
2522int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2523{
2524 errno = ENOSYS;
2525 return -1;
2526}
2527
2528int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2529{
2530 errno = ENOSYS;
2531 return -1;
2532}
2533#endif /* WITH_AIO */
2534
2535int sys_getpeereid( int s, uid_t *uid)
2536{
2537#if defined(HAVE_PEERCRED)
2538 struct ucred cred;
2539 socklen_t cred_len = sizeof(struct ucred);
2540 int ret;
2541
2542 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2543 if (ret != 0) {
2544 return -1;
2545 }
2546
2547 if (cred_len != sizeof(struct ucred)) {
2548 errno = EINVAL;
2549 return -1;
2550 }
2551
2552 *uid = cred.uid;
2553 return 0;
2554#else
2555 errno = ENOSYS;
2556 return -1;
2557#endif
2558}
2559
2560int sys_getnameinfo(const struct sockaddr *psa,
2561 socklen_t salen,
2562 char *host,
2563 size_t hostlen,
2564 char *service,
2565 size_t servlen,
2566 int flags)
2567{
2568 /*
2569 * For Solaris we must make sure salen is the
2570 * correct length for the incoming sa_family.
2571 */
2572
2573 if (salen == sizeof(struct sockaddr_storage)) {
2574 salen = sizeof(struct sockaddr_in);
2575#if defined(HAVE_IPV6)
2576 if (psa->sa_family == AF_INET6) {
2577 salen = sizeof(struct sockaddr_in6);
2578 }
2579#endif
2580 }
2581 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2582}
2583
2584int sys_connect(int fd, const struct sockaddr * addr)
2585{
2586 socklen_t salen = -1;
2587
2588 if (addr->sa_family == AF_INET) {
2589 salen = sizeof(struct sockaddr_in);
2590 } else if (addr->sa_family == AF_UNIX) {
2591 salen = sizeof(struct sockaddr_un);
2592 }
2593#if defined(HAVE_IPV6)
2594 else if (addr->sa_family == AF_INET6) {
2595 salen = sizeof(struct sockaddr_in6);
2596 }
2597#endif
2598
2599 return connect(fd, addr, salen);
2600}
Note: See TracBrowser for help on using the repository browser.