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