source: trunk/samba-3.0.25pre1/source/lib/system.c@ 5

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

Initial code import

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