source: branches/samba-3.0/source/lib/system.c@ 162

Last change on this file since 162 was 161, checked in by Paul Smedley, 17 years ago

Update source to 3.0.34

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