source: branches/samba-3.2.x/source/lib/system.c@ 447

Last change on this file since 447 was 247, checked in by Herwig Bauernfeind, 16 years ago

Fixes for Tickets #69 and #71 (by diver) in 3.2 branch

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