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