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

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

Update branch to 3.0.31 release

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