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

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

Updates to sys_read and sys_write to address read/write failures with EINTR - addresses tickets 69 and 71

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