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

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

Partial fix for ticket 69

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