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