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

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

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

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