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

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

Update 3.3 to 3.3.7

File size: 68.2 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/**************************************************************************
711 Try and abstract process capabilities (for systems that have them).
712****************************************************************************/
713
714/* Set the POSIX capabilities needed for the given purpose into the effective
715 * capability set of the current process. Make sure they are always removed
716 * from the inheritable set, because there is no circumstance in which our
717 * children should inherit our elevated privileges.
718 */
719static bool set_process_capability(enum smbd_capability capability,
720 bool enable)
721{
722 cap_value_t cap_vals[2] = {0};
723 int num_cap_vals = 0;
724
725 cap_t cap;
726
727#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
728 /* On Linux, make sure that any capabilities we grab are sticky
729 * across UID changes. We expect that this would allow us to keep both
730 * the effective and permitted capability sets, but as of circa 2.6.16,
731 * only the permitted set is kept. It is a bug (which we work around)
732 * that the effective set is lost, but we still require the effective
733 * set to be kept.
734 */
735 if (!prctl(PR_GET_KEEPCAPS)) {
736 prctl(PR_SET_KEEPCAPS, 1);
737 }
738#endif
739
740 cap = cap_get_proc();
741 if (cap == NULL) {
742 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
743 strerror(errno)));
744 return False;
745 }
746
747 switch (capability) {
748 case KERNEL_OPLOCK_CAPABILITY:
749#ifdef CAP_NETWORK_MGT
750 /* IRIX has CAP_NETWORK_MGT for oplocks. */
751 cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
752#endif
753 break;
754 case DMAPI_ACCESS_CAPABILITY:
755#ifdef CAP_DEVICE_MGT
756 /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
757 cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
758#elif CAP_MKNOD
759 /* Linux has CAP_MKNOD for DMAPI access. */
760 cap_vals[num_cap_vals++] = CAP_MKNOD;
761#endif
762 break;
763 case LEASE_CAPABILITY:
764#ifdef CAP_LEASE
765 cap_vals[num_cap_vals++] = CAP_LEASE;
766#endif
767 break;
768 }
769
770 SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
771
772 if (num_cap_vals == 0) {
773 cap_free(cap);
774 return True;
775 }
776
777 cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
778 enable ? CAP_SET : CAP_CLEAR);
779
780 /* We never want to pass capabilities down to our children, so make
781 * sure they are not inherited.
782 */
783 cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
784
785 if (cap_set_proc(cap) == -1) {
786 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
787 strerror(errno)));
788 cap_free(cap);
789 return False;
790 }
791
792 cap_free(cap);
793 return True;
794}
795
796#endif /* HAVE_POSIX_CAPABILITIES */
797
798/****************************************************************************
799 Gain the oplock capability from the kernel if possible.
800****************************************************************************/
801
802void set_effective_capability(enum smbd_capability capability)
803{
804#if defined(HAVE_POSIX_CAPABILITIES)
805 set_process_capability(capability, True);
806#endif /* HAVE_POSIX_CAPABILITIES */
807}
808
809void drop_effective_capability(enum smbd_capability capability)
810{
811#if defined(HAVE_POSIX_CAPABILITIES)
812 set_process_capability(capability, False);
813#endif /* HAVE_POSIX_CAPABILITIES */
814}
815
816/**************************************************************************
817 Wrapper for random().
818****************************************************************************/
819
820long sys_random(void)
821{
822#if defined(HAVE_RANDOM)
823 return (long)random();
824#elif defined(HAVE_RAND)
825 return (long)rand();
826#else
827 DEBUG(0,("Error - no random function available !\n"));
828 exit(1);
829#endif
830}
831
832/**************************************************************************
833 Wrapper for srandom().
834****************************************************************************/
835
836void sys_srandom(unsigned int seed)
837{
838#if defined(HAVE_SRANDOM)
839 srandom(seed);
840#elif defined(HAVE_SRAND)
841 srand(seed);
842#else
843 DEBUG(0,("Error - no srandom function available !\n"));
844 exit(1);
845#endif
846}
847
848/**************************************************************************
849 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
850****************************************************************************/
851
852int groups_max(void)
853{
854#if defined(SYSCONF_SC_NGROUPS_MAX)
855 int ret = sysconf(_SC_NGROUPS_MAX);
856 return (ret == -1) ? NGROUPS_MAX : ret;
857#else
858 return NGROUPS_MAX;
859#endif
860}
861
862/**************************************************************************
863 Wrap setgroups and getgroups for systems that declare getgroups() as
864 returning an array of gid_t, but actuall return an array of int.
865****************************************************************************/
866
867#if defined(HAVE_BROKEN_GETGROUPS)
868static int sys_broken_getgroups(int setlen, gid_t *gidset)
869{
870 GID_T gid;
871 GID_T *group_list;
872 int i, ngroups;
873
874 if(setlen == 0) {
875 return getgroups(setlen, &gid);
876 }
877
878 /*
879 * Broken case. We need to allocate a
880 * GID_T array of size setlen.
881 */
882
883 if(setlen < 0) {
884 errno = EINVAL;
885 return -1;
886 }
887
888 if (setlen == 0)
889 setlen = groups_max();
890
891 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
892 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
893 return -1;
894 }
895
896 if((ngroups = getgroups(setlen, group_list)) < 0) {
897 int saved_errno = errno;
898 SAFE_FREE(group_list);
899 errno = saved_errno;
900 return -1;
901 }
902
903 for(i = 0; i < ngroups; i++)
904 gidset[i] = (gid_t)group_list[i];
905
906 SAFE_FREE(group_list);
907 return ngroups;
908}
909
910static int sys_broken_setgroups(int setlen, gid_t *gidset)
911{
912 GID_T *group_list;
913 int i ;
914
915 if (setlen == 0)
916 return 0 ;
917
918 if (setlen < 0 || setlen > groups_max()) {
919 errno = EINVAL;
920 return -1;
921 }
922
923 /*
924 * Broken case. We need to allocate a
925 * GID_T array of size setlen.
926 */
927
928 if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
929 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
930 return -1;
931 }
932
933 for(i = 0; i < setlen; i++)
934 group_list[i] = (GID_T) gidset[i];
935
936 if(setgroups(setlen, group_list) != 0) {
937 int saved_errno = errno;
938 SAFE_FREE(group_list);
939 errno = saved_errno;
940 return -1;
941 }
942
943 SAFE_FREE(group_list);
944 return 0 ;
945}
946
947#endif /* HAVE_BROKEN_GETGROUPS */
948
949/* This is a list of systems that require the first GID passed to setgroups(2)
950 * to be the effective GID. If your system is one of these, add it here.
951 */
952#if defined (FREEBSD) || defined (DARWINOS)
953#define USE_BSD_SETGROUPS
954#endif
955
956#if defined(USE_BSD_SETGROUPS)
957/* Depending on the particular BSD implementation, the first GID that is
958 * passed to setgroups(2) will either be ignored or will set the credential's
959 * effective GID. In either case, the right thing to do is to guarantee that
960 * gidset[0] is the effective GID.
961 */
962static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
963{
964 gid_t *new_gidset = NULL;
965 int max;
966 int ret;
967
968 /* setgroups(2) will fail with EINVAL if we pass too many groups. */
969 max = groups_max();
970
971 /* No group list, just make sure we are setting the efective GID. */
972 if (setlen == 0) {
973 return setgroups(1, &primary_gid);
974 }
975
976 /* If the primary gid is not the first array element, grow the array
977 * and insert it at the front.
978 */
979 if (gidset[0] != primary_gid) {
980 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
981 if (new_gidset == NULL) {
982 return -1;
983 }
984
985 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
986 new_gidset[0] = primary_gid;
987 setlen++;
988 }
989
990 if (setlen > max) {
991 DEBUG(3, ("forced to truncate group list from %d to %d\n",
992 setlen, max));
993 setlen = max;
994 }
995
996#if defined(HAVE_BROKEN_GETGROUPS)
997 ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
998#else
999 ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
1000#endif
1001
1002 if (new_gidset) {
1003 int errsav = errno;
1004 SAFE_FREE(new_gidset);
1005 errno = errsav;
1006 }
1007
1008 return ret;
1009}
1010
1011#endif /* USE_BSD_SETGROUPS */
1012
1013/**************************************************************************
1014 Wrapper for getgroups. Deals with broken (int) case.
1015****************************************************************************/
1016
1017int sys_getgroups(int setlen, gid_t *gidset)
1018{
1019#if defined(HAVE_BROKEN_GETGROUPS)
1020 return sys_broken_getgroups(setlen, gidset);
1021#else
1022 return getgroups(setlen, gidset);
1023#endif
1024}
1025
1026/**************************************************************************
1027 Wrapper for setgroups. Deals with broken (int) case and BSD case.
1028****************************************************************************/
1029
1030int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1031{
1032#ifdef __OS2__x
1033 return 0;
1034#endif
1035#if !defined(HAVE_SETGROUPS)
1036 errno = ENOSYS;
1037 return -1;
1038#endif /* HAVE_SETGROUPS */
1039
1040#if defined(USE_BSD_SETGROUPS)
1041 return sys_bsd_setgroups(primary_gid, setlen, gidset);
1042#elif defined(HAVE_BROKEN_GETGROUPS)
1043 return sys_broken_setgroups(setlen, gidset);
1044#else
1045 return setgroups(setlen, gidset);
1046#endif
1047}
1048
1049/**************************************************************************
1050 Wrappers for setpwent(), getpwent() and endpwent()
1051****************************************************************************/
1052
1053void sys_setpwent(void)
1054{
1055 setpwent();
1056}
1057
1058struct passwd *sys_getpwent(void)
1059{
1060 return getpwent();
1061}
1062
1063void sys_endpwent(void)
1064{
1065 endpwent();
1066}
1067
1068/**************************************************************************
1069 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
1070****************************************************************************/
1071
1072
1073struct passwd *sys_getpwnam(const char *name)
1074{
1075 return getpwnam(name);
1076}
1077
1078struct passwd *sys_getpwuid(uid_t uid)
1079{
1080 return getpwuid(uid);
1081}
1082
1083struct group *sys_getgrnam(const char *name)
1084{
1085 return getgrnam(name);
1086}
1087
1088struct group *sys_getgrgid(gid_t gid)
1089{
1090 return getgrgid(gid);
1091}
1092
1093/**************************************************************************
1094 Extract a command into an arg list.
1095****************************************************************************/
1096
1097static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1098{
1099 char *trunc_cmd;
1100 char *saveptr;
1101 char *ptr;
1102 int argcl;
1103 char **argl = NULL;
1104 int i;
1105
1106 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1107 DEBUG(0, ("talloc failed\n"));
1108 goto nomem;
1109 }
1110
1111 if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1112 TALLOC_FREE(trunc_cmd);
1113 errno = EINVAL;
1114 return NULL;
1115 }
1116
1117 /*
1118 * Count the args.
1119 */
1120
1121 for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1122 argcl++;
1123
1124 TALLOC_FREE(trunc_cmd);
1125
1126 if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1127 goto nomem;
1128 }
1129
1130 /*
1131 * Now do the extraction.
1132 */
1133
1134 if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1135 goto nomem;
1136 }
1137
1138 ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1139 i = 0;
1140
1141 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1142 goto nomem;
1143 }
1144
1145 while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1146
1147 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1148 goto nomem;
1149 }
1150 }
1151
1152 argl[i++] = NULL;
1153 return argl;
1154
1155 nomem:
1156 DEBUG(0, ("talloc failed\n"));
1157 TALLOC_FREE(trunc_cmd);
1158 TALLOC_FREE(argl);
1159 errno = ENOMEM;
1160 return NULL;
1161}
1162
1163/**************************************************************************
1164 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1165 a sys_getpid() that only does a system call *once*.
1166****************************************************************************/
1167
1168static pid_t mypid = (pid_t)-1;
1169
1170pid_t sys_fork(void)
1171{
1172 pid_t forkret = fork();
1173
1174 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1175 mypid = (pid_t) -1;
1176
1177 return forkret;
1178}
1179
1180/**************************************************************************
1181 Wrapper for getpid. Ensures we only do a system call *once*.
1182****************************************************************************/
1183
1184pid_t sys_getpid(void)
1185{
1186 if (mypid == (pid_t)-1)
1187 mypid = getpid();
1188
1189 return mypid;
1190}
1191
1192/**************************************************************************
1193 Wrapper for popen. Safer as it doesn't search a path.
1194 Modified from the glibc sources.
1195 modified by tridge to return a file descriptor. We must kick our FILE* habit
1196****************************************************************************/
1197
1198typedef struct _popen_list
1199{
1200 int fd;
1201 pid_t child_pid;
1202 struct _popen_list *next;
1203} popen_list;
1204
1205static popen_list *popen_chain;
1206
1207int sys_popen(const char *command)
1208{
1209 int parent_end, child_end;
1210 int pipe_fds[2];
1211 popen_list *entry = NULL;
1212 char **argl = NULL;
1213
1214 if (pipe(pipe_fds) < 0)
1215 return -1;
1216
1217 parent_end = pipe_fds[0];
1218 child_end = pipe_fds[1];
1219
1220 if (!*command) {
1221 errno = EINVAL;
1222 goto err_exit;
1223 }
1224
1225 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1226 goto err_exit;
1227
1228 ZERO_STRUCTP(entry);
1229
1230 /*
1231 * Extract the command and args into a NULL terminated array.
1232 */
1233
1234 if(!(argl = extract_args(NULL, command)))
1235 goto err_exit;
1236
1237 entry->child_pid = sys_fork();
1238
1239 if (entry->child_pid == -1) {
1240 goto err_exit;
1241 }
1242
1243 if (entry->child_pid == 0) {
1244
1245 /*
1246 * Child !
1247 */
1248
1249 int child_std_end = STDOUT_FILENO;
1250 popen_list *p;
1251
1252 close(parent_end);
1253 if (child_end != child_std_end) {
1254 dup2 (child_end, child_std_end);
1255 close (child_end);
1256 }
1257
1258 /*
1259 * POSIX.2: "popen() shall ensure that any streams from previous
1260 * popen() calls that remain open in the parent process are closed
1261 * in the new child process."
1262 */
1263
1264 for (p = popen_chain; p; p = p->next)
1265 close(p->fd);
1266
1267 execv(argl[0], argl);
1268 _exit (127);
1269 }
1270
1271 /*
1272 * Parent.
1273 */
1274
1275 close (child_end);
1276 TALLOC_FREE(argl);
1277
1278 /* Link into popen_chain. */
1279 entry->next = popen_chain;
1280 popen_chain = entry;
1281 entry->fd = parent_end;
1282
1283 return entry->fd;
1284
1285err_exit:
1286
1287 SAFE_FREE(entry);
1288 SAFE_FREE(argl);
1289 close(pipe_fds[0]);
1290 close(pipe_fds[1]);
1291 return -1;
1292}
1293
1294/**************************************************************************
1295 Wrapper for pclose. Modified from the glibc sources.
1296****************************************************************************/
1297
1298int sys_pclose(int fd)
1299{
1300 int wstatus;
1301 popen_list **ptr = &popen_chain;
1302 popen_list *entry = NULL;
1303 pid_t wait_pid;
1304 int status = -1;
1305
1306 /* Unlink from popen_chain. */
1307 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1308 if ((*ptr)->fd == fd) {
1309 entry = *ptr;
1310 *ptr = (*ptr)->next;
1311 status = 0;
1312 break;
1313 }
1314 }
1315
1316 if (status < 0 || close(entry->fd) < 0)
1317 return -1;
1318
1319 /*
1320 * As Samba is catching and eating child process
1321 * exits we don't really care about the child exit
1322 * code, a -1 with errno = ECHILD will do fine for us.
1323 */
1324
1325 do {
1326 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1327 } while (wait_pid == -1 && errno == EINTR);
1328
1329 SAFE_FREE(entry);
1330
1331 if (wait_pid == -1)
1332 return -1;
1333 return wstatus;
1334}
1335
1336/**************************************************************************
1337 Wrappers for dlopen, dlsym, dlclose.
1338****************************************************************************/
1339
1340void *sys_dlopen(const char *name, int flags)
1341{
1342#if defined(HAVE_DLOPEN)
1343 return dlopen(name, flags);
1344#else
1345 return NULL;
1346#endif
1347}
1348
1349void *sys_dlsym(void *handle, const char *symbol)
1350{
1351#if defined(HAVE_DLSYM)
1352 return dlsym(handle, symbol);
1353#else
1354 return NULL;
1355#endif
1356}
1357
1358int sys_dlclose (void *handle)
1359{
1360#if defined(HAVE_DLCLOSE)
1361 return dlclose(handle);
1362#else
1363 return 0;
1364#endif
1365}
1366
1367const char *sys_dlerror(void)
1368{
1369#if defined(HAVE_DLERROR)
1370 return dlerror();
1371#else
1372 return NULL;
1373#endif
1374}
1375
1376int sys_dup2(int oldfd, int newfd)
1377{
1378#if defined(HAVE_DUP2)
1379 return dup2(oldfd, newfd);
1380#else
1381 errno = ENOSYS;
1382 return -1;
1383#endif
1384}
1385
1386/**************************************************************************
1387 Wrapper for Admin Logs.
1388****************************************************************************/
1389
1390 void sys_adminlog(int priority, const char *format_str, ...)
1391{
1392 va_list ap;
1393 int ret;
1394 char *msgbuf = NULL;
1395
1396 va_start( ap, format_str );
1397 ret = vasprintf( &msgbuf, format_str, ap );
1398 va_end( ap );
1399
1400 if (ret == -1)
1401 return;
1402
1403#if defined(HAVE_SYSLOG)
1404 syslog( priority, "%s", msgbuf );
1405#else
1406 DEBUG(0,("%s", msgbuf ));
1407#endif
1408 SAFE_FREE(msgbuf);
1409}
1410
1411/******** Solaris EA helper function prototypes ********/
1412#ifdef HAVE_ATTROPEN
1413#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1414static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1415static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1416static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1417static int solaris_unlinkat(int attrdirfd, const char *name);
1418static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1419static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1420#endif
1421
1422/**************************************************************************
1423 Wrappers for extented attribute calls. Based on the Linux package with
1424 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1425****************************************************************************/
1426
1427ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1428{
1429#if defined(HAVE_GETXATTR)
1430#ifndef XATTR_ADD_OPT
1431 return getxattr(path, name, value, size);
1432#else
1433 int options = 0;
1434 return getxattr(path, name, value, size, 0, options);
1435#endif
1436#elif defined(HAVE_GETEA)
1437 return getea(path, name, value, size);
1438#elif defined(HAVE_EXTATTR_GET_FILE)
1439 char *s;
1440 ssize_t retval;
1441 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1442 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1443 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1444 /*
1445 * The BSD implementation has a nasty habit of silently truncating
1446 * the returned value to the size of the buffer, so we have to check
1447 * that the buffer is large enough to fit the returned value.
1448 */
1449 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1450 if(retval > size) {
1451 errno = ERANGE;
1452 return -1;
1453 }
1454 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1455 return retval;
1456 }
1457
1458 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1459 return -1;
1460#elif defined(HAVE_ATTR_GET)
1461 int retval, flags = 0;
1462 int valuelength = (int)size;
1463 char *attrname = strchr(name,'.') + 1;
1464
1465 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1466
1467 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1468
1469 return retval ? retval : valuelength;
1470#elif defined(HAVE_ATTROPEN)
1471 ssize_t ret = -1;
1472 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1473 if (attrfd >= 0) {
1474 ret = solaris_read_xattr(attrfd, value, size);
1475 close(attrfd);
1476 }
1477 return ret;
1478#elif defined(__OS2__)
1479 return unigetxattr(path, 0, name, value, size);
1480#else
1481 errno = ENOSYS;
1482 return -1;
1483#endif
1484}
1485
1486ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1487{
1488#if defined(HAVE_LGETXATTR)
1489 return lgetxattr(path, name, value, size);
1490#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1491 int options = XATTR_NOFOLLOW;
1492 return getxattr(path, name, value, size, 0, options);
1493#elif defined(HAVE_LGETEA)
1494 return lgetea(path, name, value, size);
1495#elif defined(HAVE_EXTATTR_GET_LINK)
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 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1503 if(retval > size) {
1504 errno = ERANGE;
1505 return -1;
1506 }
1507 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1508 return retval;
1509 }
1510
1511 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1512 return -1;
1513#elif defined(HAVE_ATTR_GET)
1514 int retval, flags = ATTR_DONTFOLLOW;
1515 int valuelength = (int)size;
1516 char *attrname = strchr(name,'.') + 1;
1517
1518 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1519
1520 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1521
1522 return retval ? retval : valuelength;
1523#elif defined(HAVE_ATTROPEN)
1524 ssize_t ret = -1;
1525 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1526 if (attrfd >= 0) {
1527 ret = solaris_read_xattr(attrfd, value, size);
1528 close(attrfd);
1529 }
1530 return ret;
1531#else
1532 errno = ENOSYS;
1533 return -1;
1534#endif
1535}
1536
1537ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1538{
1539#if defined(HAVE_FGETXATTR)
1540#ifndef XATTR_ADD_OPT
1541 return fgetxattr(filedes, name, value, size);
1542#else
1543 int options = 0;
1544 return fgetxattr(filedes, name, value, size, 0, options);
1545#endif
1546#elif defined(HAVE_FGETEA)
1547 return fgetea(filedes, name, value, size);
1548#elif defined(HAVE_EXTATTR_GET_FD)
1549 char *s;
1550 ssize_t retval;
1551 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1552 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1553 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1554
1555 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1556 if(retval > size) {
1557 errno = ERANGE;
1558 return -1;
1559 }
1560 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1561 return retval;
1562 }
1563
1564 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1565 return -1;
1566#elif defined(HAVE_ATTR_GETF)
1567 int retval, flags = 0;
1568 int valuelength = (int)size;
1569 char *attrname = strchr(name,'.') + 1;
1570
1571 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1572
1573 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1574
1575 return retval ? retval : valuelength;
1576#elif defined(HAVE_ATTROPEN)
1577 ssize_t ret = -1;
1578 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1579 if (attrfd >= 0) {
1580 ret = solaris_read_xattr(attrfd, value, size);
1581 close(attrfd);
1582 }
1583 return ret;
1584#elif defined(__OS2__)
1585 return unigetxattr(0, filedes, name, value, size);
1586#else
1587 errno = ENOSYS;
1588 return -1;
1589#endif
1590}
1591
1592#if defined(HAVE_EXTATTR_LIST_FILE)
1593
1594#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1595
1596static struct {
1597 int space;
1598 const char *name;
1599 size_t len;
1600}
1601extattr[] = {
1602 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1603 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1604};
1605
1606typedef union {
1607 const char *path;
1608 int filedes;
1609} extattr_arg;
1610
1611static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1612{
1613 ssize_t list_size, total_size = 0;
1614 int i, t, len;
1615 char *buf;
1616 /* Iterate through extattr(2) namespaces */
1617 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1618 switch(type) {
1619#if defined(HAVE_EXTATTR_LIST_FILE)
1620 case 0:
1621 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1622 break;
1623#endif
1624#if defined(HAVE_EXTATTR_LIST_LINK)
1625 case 1:
1626 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1627 break;
1628#endif
1629#if defined(HAVE_EXTATTR_LIST_FD)
1630 case 2:
1631 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1632 break;
1633#endif
1634 default:
1635 errno = ENOSYS;
1636 return -1;
1637 }
1638 /* Some error happend. Errno should be set by the previous call */
1639 if(list_size < 0)
1640 return -1;
1641 /* No attributes */
1642 if(list_size == 0)
1643 continue;
1644 /* XXX: Call with an empty buffer may be used to calculate
1645 necessary buffer size. Unfortunately, we can't say, how
1646 many attributes were returned, so here is the potential
1647 problem with the emulation.
1648 */
1649 if(list == NULL) {
1650 /* Take the worse case of one char attribute names -
1651 two bytes per name plus one more for sanity.
1652 */
1653 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1654 continue;
1655 }
1656 /* Count necessary offset to fit namespace prefixes */
1657 len = 0;
1658 for(i = 0; i < list_size; i += list[i] + 1)
1659 len += extattr[t].len;
1660
1661 total_size += list_size + len;
1662 /* Buffer is too small to fit the results */
1663 if(total_size > size) {
1664 errno = ERANGE;
1665 return -1;
1666 }
1667 /* Shift results back, so we can prepend prefixes */
1668 buf = memmove(list + len, list, list_size);
1669
1670 for(i = 0; i < list_size; i += len + 1) {
1671 len = buf[i];
1672 strncpy(list, extattr[t].name, extattr[t].len + 1);
1673 list += extattr[t].len;
1674 strncpy(list, buf + i + 1, len);
1675 list[len] = '\0';
1676 list += len + 1;
1677 }
1678 size -= total_size;
1679 }
1680 return total_size;
1681}
1682
1683#endif
1684
1685#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1686static char attr_buffer[ATTR_MAX_VALUELEN];
1687
1688static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1689{
1690 int retval = 0, index;
1691 attrlist_cursor_t *cursor = 0;
1692 int total_size = 0;
1693 attrlist_t * al = (attrlist_t *)attr_buffer;
1694 attrlist_ent_t *ae;
1695 size_t ent_size, left = size;
1696 char *bp = list;
1697
1698 while (True) {
1699 if (filedes)
1700 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1701 else
1702 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1703 if (retval) break;
1704 for (index = 0; index < al->al_count; index++) {
1705 ae = ATTR_ENTRY(attr_buffer, index);
1706 ent_size = strlen(ae->a_name) + sizeof("user.");
1707 if (left >= ent_size) {
1708 strncpy(bp, "user.", sizeof("user."));
1709 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1710 bp += ent_size;
1711 left -= ent_size;
1712 } else if (size) {
1713 errno = ERANGE;
1714 retval = -1;
1715 break;
1716 }
1717 total_size += ent_size;
1718 }
1719 if (al->al_more == 0) break;
1720 }
1721 if (retval == 0) {
1722 flags |= ATTR_ROOT;
1723 cursor = 0;
1724 while (True) {
1725 if (filedes)
1726 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1727 else
1728 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1729 if (retval) break;
1730 for (index = 0; index < al->al_count; index++) {
1731 ae = ATTR_ENTRY(attr_buffer, index);
1732 ent_size = strlen(ae->a_name) + sizeof("system.");
1733 if (left >= ent_size) {
1734 strncpy(bp, "system.", sizeof("system."));
1735 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1736 bp += ent_size;
1737 left -= ent_size;
1738 } else if (size) {
1739 errno = ERANGE;
1740 retval = -1;
1741 break;
1742 }
1743 total_size += ent_size;
1744 }
1745 if (al->al_more == 0) break;
1746 }
1747 }
1748 return (ssize_t)(retval ? retval : total_size);
1749}
1750
1751#endif
1752
1753ssize_t sys_listxattr (const char *path, char *list, size_t size)
1754{
1755#if defined(HAVE_LISTXATTR)
1756#ifndef XATTR_ADD_OPT
1757 return listxattr(path, list, size);
1758#else
1759 int options = 0;
1760 return listxattr(path, list, size, options);
1761#endif
1762#elif defined(HAVE_LISTEA)
1763 return listea(path, list, size);
1764#elif defined(HAVE_EXTATTR_LIST_FILE)
1765 extattr_arg arg;
1766 arg.path = path;
1767 return bsd_attr_list(0, arg, list, size);
1768#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1769 return irix_attr_list(path, 0, list, size, 0);
1770#elif defined(HAVE_ATTROPEN)
1771 ssize_t ret = -1;
1772 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1773 if (attrdirfd >= 0) {
1774 ret = solaris_list_xattr(attrdirfd, list, size);
1775 close(attrdirfd);
1776 }
1777 return ret;
1778#elif defined(__OS2__)
1779 return unilistxattr(path, 0, list, size);
1780#else
1781 errno = ENOSYS;
1782 return -1;
1783#endif
1784}
1785
1786ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1787{
1788#if defined(HAVE_LLISTXATTR)
1789 return llistxattr(path, list, size);
1790#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1791 int options = XATTR_NOFOLLOW;
1792 return listxattr(path, list, size, options);
1793#elif defined(HAVE_LLISTEA)
1794 return llistea(path, list, size);
1795#elif defined(HAVE_EXTATTR_LIST_LINK)
1796 extattr_arg arg;
1797 arg.path = path;
1798 return bsd_attr_list(1, arg, list, size);
1799#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1800 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1801#elif defined(HAVE_ATTROPEN)
1802 ssize_t ret = -1;
1803 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1804 if (attrdirfd >= 0) {
1805 ret = solaris_list_xattr(attrdirfd, list, size);
1806 close(attrdirfd);
1807 }
1808 return ret;
1809#elif defined(__OS2__)
1810 return unilistxattr(path, 0, list, size);
1811#else
1812 errno = ENOSYS;
1813 return -1;
1814#endif
1815}
1816
1817ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1818{
1819#if defined(HAVE_FLISTXATTR)
1820#ifndef XATTR_ADD_OPT
1821 return flistxattr(filedes, list, size);
1822#else
1823 int options = 0;
1824 return flistxattr(filedes, list, size, options);
1825#endif
1826#elif defined(HAVE_FLISTEA)
1827 return flistea(filedes, list, size);
1828#elif defined(HAVE_EXTATTR_LIST_FD)
1829 extattr_arg arg;
1830 arg.filedes = filedes;
1831 return bsd_attr_list(2, arg, list, size);
1832#elif defined(HAVE_ATTR_LISTF)
1833 return irix_attr_list(NULL, filedes, list, size, 0);
1834#elif defined(HAVE_ATTROPEN)
1835 ssize_t ret = -1;
1836 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1837 if (attrdirfd >= 0) {
1838 ret = solaris_list_xattr(attrdirfd, list, size);
1839 close(attrdirfd);
1840 }
1841 return ret;
1842#elif defined(__OS2__)
1843 return unilistxattr(0, filedes, list, size);
1844#else
1845 errno = ENOSYS;
1846 return -1;
1847#endif
1848}
1849
1850int sys_removexattr (const char *path, const char *name)
1851{
1852#if defined(HAVE_REMOVEXATTR)
1853#ifndef XATTR_ADD_OPT
1854 return removexattr(path, name);
1855#else
1856 int options = 0;
1857 return removexattr(path, name, options);
1858#endif
1859#elif defined(HAVE_REMOVEEA)
1860 return removeea(path, name);
1861#elif defined(HAVE_EXTATTR_DELETE_FILE)
1862 char *s;
1863 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1864 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1865 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1866
1867 return extattr_delete_file(path, attrnamespace, attrname);
1868#elif defined(HAVE_ATTR_REMOVE)
1869 int flags = 0;
1870 char *attrname = strchr(name,'.') + 1;
1871
1872 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1873
1874 return attr_remove(path, attrname, flags);
1875#elif defined(HAVE_ATTROPEN)
1876 int ret = -1;
1877 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1878 if (attrdirfd >= 0) {
1879 ret = solaris_unlinkat(attrdirfd, name);
1880 close(attrdirfd);
1881 }
1882 return ret;
1883#elif defined(__OS2__)
1884 return uniremovexattr (path, 0, name);
1885#else
1886 errno = ENOSYS;
1887 return -1;
1888#endif
1889}
1890
1891int sys_lremovexattr (const char *path, const char *name)
1892{
1893#if defined(HAVE_LREMOVEXATTR)
1894 return lremovexattr(path, name);
1895#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1896 int options = XATTR_NOFOLLOW;
1897 return removexattr(path, name, options);
1898#elif defined(HAVE_LREMOVEEA)
1899 return lremoveea(path, name);
1900#elif defined(HAVE_EXTATTR_DELETE_LINK)
1901 char *s;
1902 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1903 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1904 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1905
1906 return extattr_delete_link(path, attrnamespace, attrname);
1907#elif defined(HAVE_ATTR_REMOVE)
1908 int flags = ATTR_DONTFOLLOW;
1909 char *attrname = strchr(name,'.') + 1;
1910
1911 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1912
1913 return attr_remove(path, attrname, flags);
1914#elif defined(HAVE_ATTROPEN)
1915 int ret = -1;
1916 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1917 if (attrdirfd >= 0) {
1918 ret = solaris_unlinkat(attrdirfd, name);
1919 close(attrdirfd);
1920 }
1921 return ret;
1922#elif defined(__OS2__)
1923 return uniremovexattr (path, 0, name);
1924#else
1925 errno = ENOSYS;
1926 return -1;
1927#endif
1928}
1929
1930int sys_fremovexattr (int filedes, const char *name)
1931{
1932#if defined(HAVE_FREMOVEXATTR)
1933#ifndef XATTR_ADD_OPT
1934 return fremovexattr(filedes, name);
1935#else
1936 int options = 0;
1937 return fremovexattr(filedes, name, options);
1938#endif
1939#elif defined(HAVE_FREMOVEEA)
1940 return fremoveea(filedes, name);
1941#elif defined(HAVE_EXTATTR_DELETE_FD)
1942 char *s;
1943 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1944 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1945 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1946
1947 return extattr_delete_fd(filedes, attrnamespace, attrname);
1948#elif defined(HAVE_ATTR_REMOVEF)
1949 int flags = 0;
1950 char *attrname = strchr(name,'.') + 1;
1951
1952 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1953
1954 return attr_removef(filedes, attrname, flags);
1955#elif defined(HAVE_ATTROPEN)
1956 int ret = -1;
1957 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1958 if (attrdirfd >= 0) {
1959 ret = solaris_unlinkat(attrdirfd, name);
1960 close(attrdirfd);
1961 }
1962 return ret;
1963#elif defined(__OS2__)
1964 return uniremovexattr (0, filedes, name);
1965#else
1966 errno = ENOSYS;
1967 return -1;
1968#endif
1969}
1970
1971int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1972{
1973#if defined(HAVE_SETXATTR)
1974#ifndef XATTR_ADD_OPT
1975 return setxattr(path, name, value, size, flags);
1976#else
1977 int options = 0;
1978 return setxattr(path, name, value, size, 0, options);
1979#endif
1980#elif defined(HAVE_SETEA)
1981 return setea(path, name, value, size, flags);
1982#elif defined(HAVE_EXTATTR_SET_FILE)
1983 char *s;
1984 int retval = 0;
1985 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1986 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1987 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1988 if (flags) {
1989 /* Check attribute existence */
1990 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1991 if (retval < 0) {
1992 /* REPLACE attribute, that doesn't exist */
1993 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1994 errno = ENOATTR;
1995 return -1;
1996 }
1997 /* Ignore other errors */
1998 }
1999 else {
2000 /* CREATE attribute, that already exists */
2001 if (flags & XATTR_CREATE) {
2002 errno = EEXIST;
2003 return -1;
2004 }
2005 }
2006 }
2007 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
2008 return (retval < 0) ? -1 : 0;
2009#elif defined(HAVE_ATTR_SET)
2010 int myflags = 0;
2011 char *attrname = strchr(name,'.') + 1;
2012
2013 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2014 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2015 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2016
2017 return attr_set(path, attrname, (const char *)value, size, myflags);
2018#elif defined(HAVE_ATTROPEN)
2019 int ret = -1;
2020 int myflags = O_RDWR;
2021 int attrfd;
2022 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2023 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2024 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2025 if (attrfd >= 0) {
2026 ret = solaris_write_xattr(attrfd, value, size);
2027 close(attrfd);
2028 }
2029 return ret;
2030#elif defined(__OS2__)
2031 return unisetxattr (path, 0, name, value, size, flags);
2032#else
2033 errno = ENOSYS;
2034 return -1;
2035#endif
2036}
2037
2038int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
2039{
2040#if defined(HAVE_LSETXATTR)
2041 return lsetxattr(path, name, value, size, flags);
2042#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
2043 int options = XATTR_NOFOLLOW;
2044 return setxattr(path, name, value, size, 0, options);
2045#elif defined(LSETEA)
2046 return lsetea(path, name, value, size, flags);
2047#elif defined(HAVE_EXTATTR_SET_LINK)
2048 char *s;
2049 int retval = 0;
2050 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2051 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2052 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2053 if (flags) {
2054 /* Check attribute existence */
2055 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
2056 if (retval < 0) {
2057 /* REPLACE attribute, that doesn't exist */
2058 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2059 errno = ENOATTR;
2060 return -1;
2061 }
2062 /* Ignore other errors */
2063 }
2064 else {
2065 /* CREATE attribute, that already exists */
2066 if (flags & XATTR_CREATE) {
2067 errno = EEXIST;
2068 return -1;
2069 }
2070 }
2071 }
2072
2073 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
2074 return (retval < 0) ? -1 : 0;
2075#elif defined(HAVE_ATTR_SET)
2076 int myflags = ATTR_DONTFOLLOW;
2077 char *attrname = strchr(name,'.') + 1;
2078
2079 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2080 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2081 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2082
2083 return attr_set(path, attrname, (const char *)value, size, myflags);
2084#elif defined(HAVE_ATTROPEN)
2085 int ret = -1;
2086 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
2087 int attrfd;
2088 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2089 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2090 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2091 if (attrfd >= 0) {
2092 ret = solaris_write_xattr(attrfd, value, size);
2093 close(attrfd);
2094 }
2095 return ret;
2096#elif defined(__OS2__)
2097 return unisetxattr (path, 0, name, value, size, flags);
2098#else
2099 errno = ENOSYS;
2100 return -1;
2101#endif
2102}
2103
2104int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
2105{
2106#if defined(HAVE_FSETXATTR)
2107#ifndef XATTR_ADD_OPT
2108 return fsetxattr(filedes, name, value, size, flags);
2109#else
2110 int options = 0;
2111 return fsetxattr(filedes, name, value, size, 0, options);
2112#endif
2113#elif defined(HAVE_FSETEA)
2114 return fsetea(filedes, name, value, size, flags);
2115#elif defined(HAVE_EXTATTR_SET_FD)
2116 char *s;
2117 int retval = 0;
2118 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
2119 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
2120 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
2121 if (flags) {
2122 /* Check attribute existence */
2123 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
2124 if (retval < 0) {
2125 /* REPLACE attribute, that doesn't exist */
2126 if (flags & XATTR_REPLACE && errno == ENOATTR) {
2127 errno = ENOATTR;
2128 return -1;
2129 }
2130 /* Ignore other errors */
2131 }
2132 else {
2133 /* CREATE attribute, that already exists */
2134 if (flags & XATTR_CREATE) {
2135 errno = EEXIST;
2136 return -1;
2137 }
2138 }
2139 }
2140 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
2141 return (retval < 0) ? -1 : 0;
2142#elif defined(HAVE_ATTR_SETF)
2143 int myflags = 0;
2144 char *attrname = strchr(name,'.') + 1;
2145
2146 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
2147 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
2148 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
2149
2150 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
2151#elif defined(HAVE_ATTROPEN)
2152 int ret = -1;
2153 int myflags = O_RDWR | O_XATTR;
2154 int attrfd;
2155 if (flags & XATTR_CREATE) myflags |= O_EXCL;
2156 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
2157 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
2158 if (attrfd >= 0) {
2159 ret = solaris_write_xattr(attrfd, value, size);
2160 close(attrfd);
2161 }
2162 return ret;
2163#elif defined(__OS2__)
2164 return unisetxattr (0, filedes, name, value, size, flags);
2165#else
2166 errno = ENOSYS;
2167 return -1;
2168#endif
2169}
2170
2171/**************************************************************************
2172 helper functions for Solaris' EA support
2173****************************************************************************/
2174#ifdef HAVE_ATTROPEN
2175static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
2176{
2177 struct stat sbuf;
2178
2179 if (fstat(attrfd, &sbuf) == -1) {
2180 errno = ENOATTR;
2181 return -1;
2182 }
2183
2184 /* This is to return the current size of the named extended attribute */
2185 if (size == 0) {
2186 return sbuf.st_size;
2187 }
2188
2189 /* check size and read xattr */
2190 if (sbuf.st_size > size) {
2191 errno = ERANGE;
2192 return -1;
2193 }
2194
2195 return read(attrfd, value, sbuf.st_size);
2196}
2197
2198static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
2199{
2200 ssize_t len = 0;
2201 DIR *dirp;
2202 struct dirent *de;
2203 int newfd = dup(attrdirfd);
2204 /* CAUTION: The originating file descriptor should not be
2205 used again following the call to fdopendir().
2206 For that reason we dup() the file descriptor
2207 here to make things more clear. */
2208 dirp = fdopendir(newfd);
2209
2210 while ((de = readdir(dirp))) {
2211 size_t listlen = strlen(de->d_name);
2212 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
2213 /* we don't want "." and ".." here: */
2214 DEBUG(10,("skipped EA %s\n",de->d_name));
2215 continue;
2216 }
2217
2218 if (size == 0) {
2219 /* return the current size of the list of extended attribute names*/
2220 len += listlen + 1;
2221 } else {
2222 /* check size and copy entrieѕ + nul into list. */
2223 if ((len + listlen + 1) > size) {
2224 errno = ERANGE;
2225 len = -1;
2226 break;
2227 } else {
2228 safe_strcpy(list + len, de->d_name, listlen);
2229 len += listlen;
2230 list[len] = '\0';
2231 ++len;
2232 }
2233 }
2234 }
2235
2236 if (closedir(dirp) == -1) {
2237 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2238 return -1;
2239 }
2240 return len;
2241}
2242
2243static int solaris_unlinkat(int attrdirfd, const char *name)
2244{
2245 if (unlinkat(attrdirfd, name, 0) == -1) {
2246 if (errno == ENOENT) {
2247 errno = ENOATTR;
2248 }
2249 return -1;
2250 }
2251 return 0;
2252}
2253
2254static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
2255{
2256 int filedes = attropen(path, attrpath, oflag, mode);
2257 if (filedes == -1) {
2258 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2259 if (errno == EINVAL) {
2260 errno = ENOTSUP;
2261 } else {
2262 errno = ENOATTR;
2263 }
2264 }
2265 return filedes;
2266}
2267
2268static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
2269{
2270 int filedes = openat(fildes, path, oflag, mode);
2271 if (filedes == -1) {
2272 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2273 if (errno == EINVAL) {
2274 errno = ENOTSUP;
2275 } else {
2276 errno = ENOATTR;
2277 }
2278 }
2279 return filedes;
2280}
2281
2282static int solaris_write_xattr(int attrfd, const char *value, size_t size)
2283{
2284 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2285 return 0;
2286 } else {
2287 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2288 return -1;
2289 }
2290}
2291#endif /*HAVE_ATTROPEN*/
2292
2293
2294/****************************************************************************
2295 Return the major devicenumber for UNIX extensions.
2296****************************************************************************/
2297
2298uint32 unix_dev_major(SMB_DEV_T dev)
2299{
2300#if defined(HAVE_DEVICE_MAJOR_FN)
2301 return (uint32)major(dev);
2302#else
2303 return (uint32)(dev >> 8);
2304#endif
2305}
2306
2307/****************************************************************************
2308 Return the minor devicenumber for UNIX extensions.
2309****************************************************************************/
2310
2311uint32 unix_dev_minor(SMB_DEV_T dev)
2312{
2313#if defined(HAVE_DEVICE_MINOR_FN)
2314 return (uint32)minor(dev);
2315#else
2316 return (uint32)(dev & 0xff);
2317#endif
2318}
2319
2320#if defined(WITH_AIO)
2321
2322/*******************************************************************
2323 An aio_read wrapper that will deal with 64-bit sizes.
2324********************************************************************/
2325
2326int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2327{
2328#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2329 return aio_read64(aiocb);
2330#elif defined(HAVE_AIO_READ)
2331 return aio_read(aiocb);
2332#else
2333 errno = ENOSYS;
2334 return -1;
2335#endif
2336}
2337
2338/*******************************************************************
2339 An aio_write wrapper that will deal with 64-bit sizes.
2340********************************************************************/
2341
2342int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2343{
2344#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2345 return aio_write64(aiocb);
2346#elif defined(HAVE_AIO_WRITE)
2347 return aio_write(aiocb);
2348#else
2349 errno = ENOSYS;
2350 return -1;
2351#endif
2352}
2353
2354/*******************************************************************
2355 An aio_return wrapper that will deal with 64-bit sizes.
2356********************************************************************/
2357
2358ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2359{
2360#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2361 return aio_return64(aiocb);
2362#elif defined(HAVE_AIO_RETURN)
2363 return aio_return(aiocb);
2364#else
2365 errno = ENOSYS;
2366 return -1;
2367#endif
2368}
2369
2370/*******************************************************************
2371 An aio_cancel wrapper that will deal with 64-bit sizes.
2372********************************************************************/
2373
2374int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2375{
2376#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2377 return aio_cancel64(fd, aiocb);
2378#elif defined(HAVE_AIO_CANCEL)
2379 return aio_cancel(fd, aiocb);
2380#else
2381 errno = ENOSYS;
2382 return -1;
2383#endif
2384}
2385
2386/*******************************************************************
2387 An aio_error wrapper that will deal with 64-bit sizes.
2388********************************************************************/
2389
2390int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2391{
2392#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2393 return aio_error64(aiocb);
2394#elif defined(HAVE_AIO_ERROR)
2395 return aio_error(aiocb);
2396#else
2397 errno = ENOSYS;
2398 return -1;
2399#endif
2400}
2401
2402/*******************************************************************
2403 An aio_fsync wrapper that will deal with 64-bit sizes.
2404********************************************************************/
2405
2406int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2407{
2408#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2409 return aio_fsync64(op, aiocb);
2410#elif defined(HAVE_AIO_FSYNC)
2411 return aio_fsync(op, aiocb);
2412#else
2413 errno = ENOSYS;
2414 return -1;
2415#endif
2416}
2417
2418/*******************************************************************
2419 An aio_fsync wrapper that will deal with 64-bit sizes.
2420********************************************************************/
2421
2422int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2423{
2424#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2425 return aio_suspend64(cblist, n, timeout);
2426#elif defined(HAVE_AIO_FSYNC)
2427 return aio_suspend(cblist, n, timeout);
2428#else
2429 errno = ENOSYS;
2430 return -1;
2431#endif
2432}
2433#else /* !WITH_AIO */
2434
2435int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2436{
2437 errno = ENOSYS;
2438 return -1;
2439}
2440
2441int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2442{
2443 errno = ENOSYS;
2444 return -1;
2445}
2446
2447ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2448{
2449 errno = ENOSYS;
2450 return -1;
2451}
2452
2453int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2454{
2455 errno = ENOSYS;
2456 return -1;
2457}
2458
2459int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2460{
2461 errno = ENOSYS;
2462 return -1;
2463}
2464
2465int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2466{
2467 errno = ENOSYS;
2468 return -1;
2469}
2470
2471int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2472{
2473 errno = ENOSYS;
2474 return -1;
2475}
2476#endif /* WITH_AIO */
2477
2478int sys_getpeereid( int s, uid_t *uid)
2479{
2480#if defined(HAVE_PEERCRED)
2481 struct ucred cred;
2482 socklen_t cred_len = sizeof(struct ucred);
2483 int ret;
2484
2485 ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2486 if (ret != 0) {
2487 return -1;
2488 }
2489
2490 if (cred_len != sizeof(struct ucred)) {
2491 errno = EINVAL;
2492 return -1;
2493 }
2494
2495 *uid = cred.uid;
2496 return 0;
2497#else
2498 errno = ENOSYS;
2499 return -1;
2500#endif
2501}
2502
2503int sys_getnameinfo(const struct sockaddr *psa,
2504 socklen_t salen,
2505 char *host,
2506 size_t hostlen,
2507 char *service,
2508 size_t servlen,
2509 int flags)
2510{
2511 /*
2512 * For Solaris we must make sure salen is the
2513 * correct length for the incoming sa_family.
2514 */
2515
2516 if (salen == sizeof(struct sockaddr_storage)) {
2517 salen = sizeof(struct sockaddr_in);
2518#if defined(HAVE_IPV6)
2519 if (psa->sa_family == AF_INET6) {
2520 salen = sizeof(struct sockaddr_in6);
2521 }
2522#endif
2523 }
2524 return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2525}
2526
2527int sys_connect(int fd, const struct sockaddr * addr)
2528{
2529 socklen_t salen = -1;
2530
2531 if (addr->sa_family == AF_INET) {
2532 salen = sizeof(struct sockaddr_in);
2533 } else if (addr->sa_family == AF_UNIX) {
2534 salen = sizeof(struct sockaddr_un);
2535 }
2536#if defined(HAVE_IPV6)
2537 else if (addr->sa_family == AF_INET6) {
2538 salen = sizeof(struct sockaddr_in6);
2539 }
2540#endif
2541
2542 return connect(fd, addr, salen);
2543}
Note: See TracBrowser for help on using the repository browser.