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

Last change on this file since 120 was 62, checked in by Paul Smedley, 18 years ago

Update source to 3.0.25c level

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