Patch based on work from James Peach <jpeach@sgi.com> to convert over to
[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-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  A readdir wrapper that will deal with 64 bit filesizes.
366 ********************************************************************/
367
368 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
369 {
370 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
371         return readdir64(dirp);
372 #else
373         return readdir(dirp);
374 #endif
375 }
376
377 /*******************************************************************
378  An mknod() wrapper that will deal with 64 bit filesizes.
379 ********************************************************************/
380
381 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
382 {
383 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
384 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
385         return mknod64(path, mode, dev);
386 #else
387         return mknod(path, mode, dev);
388 #endif
389 #else
390         /* No mknod system call. */
391         errno = ENOSYS;
392         return -1;
393 #endif
394 }
395
396 /*******************************************************************
397  Wrapper for realpath.
398 ********************************************************************/
399
400 char *sys_realpath(const char *path, char *resolved_path)
401 {
402 #if defined(HAVE_REALPATH)
403         return realpath(path, resolved_path);
404 #else
405         /* As realpath is not a system call we can't return ENOSYS. */
406         errno = EINVAL;
407         return NULL;
408 #endif
409 }
410
411 /*******************************************************************
412 The wait() calls vary between systems
413 ********************************************************************/
414
415 int sys_waitpid(pid_t pid,int *status,int options)
416 {
417 #ifdef HAVE_WAITPID
418         return waitpid(pid,status,options);
419 #else /* HAVE_WAITPID */
420         return wait4(pid, status, options, NULL);
421 #endif /* HAVE_WAITPID */
422 }
423
424 /*******************************************************************
425  System wrapper for getwd
426 ********************************************************************/
427
428 char *sys_getwd(char *s)
429 {
430         char *wd;
431 #ifdef HAVE_GETCWD
432         wd = (char *)getcwd(s, sizeof (pstring));
433 #else
434         wd = (char *)getwd(s);
435 #endif
436         return wd;
437 }
438
439 /*******************************************************************
440 system wrapper for symlink
441 ********************************************************************/
442
443 int sys_symlink(const char *oldpath, const char *newpath)
444 {
445 #ifndef HAVE_SYMLINK
446         errno = ENOSYS;
447         return -1;
448 #else
449         return symlink(oldpath, newpath);
450 #endif
451 }
452
453 /*******************************************************************
454 system wrapper for readlink
455 ********************************************************************/
456
457 int sys_readlink(const char *path, char *buf, size_t bufsiz)
458 {
459 #ifndef HAVE_READLINK
460         errno = ENOSYS;
461         return -1;
462 #else
463         return readlink(path, buf, bufsiz);
464 #endif
465 }
466
467 /*******************************************************************
468 system wrapper for link
469 ********************************************************************/
470
471 int sys_link(const char *oldpath, const char *newpath)
472 {
473 #ifndef HAVE_LINK
474         errno = ENOSYS;
475         return -1;
476 #else
477         return link(oldpath, newpath);
478 #endif
479 }
480
481 /*******************************************************************
482 chown isn't used much but OS/2 doesn't have it
483 ********************************************************************/
484
485 int sys_chown(const char *fname,uid_t uid,gid_t gid)
486 {
487 #ifndef HAVE_CHOWN
488         static int done;
489         if (!done) {
490                 DEBUG(1,("WARNING: no chown!\n"));
491                 done=1;
492         }
493 #else
494         return(chown(fname,uid,gid));
495 #endif
496 }
497
498 /*******************************************************************
499 os/2 also doesn't have chroot
500 ********************************************************************/
501 int sys_chroot(const char *dname)
502 {
503 #ifndef HAVE_CHROOT
504         static int done;
505         if (!done) {
506                 DEBUG(1,("WARNING: no chroot!\n"));
507                 done=1;
508         }
509         errno = ENOSYS;
510         return -1;
511 #else
512         return(chroot(dname));
513 #endif
514 }
515
516 /**************************************************************************
517 A wrapper for gethostbyname() that tries avoids looking up hostnames 
518 in the root domain, which can cause dial-on-demand links to come up for no
519 apparent reason.
520 ****************************************************************************/
521
522 struct hostent *sys_gethostbyname(const char *name)
523 {
524 #ifdef REDUCE_ROOT_DNS_LOOKUPS
525         char query[256], hostname[256];
526         char *domain;
527
528         /* Does this name have any dots in it? If so, make no change */
529
530         if (strchr_m(name, '.'))
531                 return(gethostbyname(name));
532
533         /* Get my hostname, which should have domain name 
534                 attached. If not, just do the gethostname on the
535                 original string. 
536         */
537
538         gethostname(hostname, sizeof(hostname) - 1);
539         hostname[sizeof(hostname) - 1] = 0;
540         if ((domain = strchr_m(hostname, '.')) == NULL)
541                 return(gethostbyname(name));
542
543         /* Attach domain name to query and do modified query.
544                 If names too large, just do gethostname on the
545                 original string.
546         */
547
548         if((strlen(name) + strlen(domain)) >= sizeof(query))
549                 return(gethostbyname(name));
550
551         slprintf(query, sizeof(query)-1, "%s%s", name, domain);
552         return(gethostbyname(query));
553 #else /* REDUCE_ROOT_DNS_LOOKUPS */
554         return(gethostbyname(name));
555 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
556 }
557
558
559 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
560 /**************************************************************************
561  Try and abstract process capabilities (for systems that have them).
562 ****************************************************************************/
563 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
564 {
565         if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
566                 cap_t cap = cap_get_proc();
567
568                 if (cap == NULL) {
569                         DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
570                                 strerror(errno)));
571                         return False;
572                 }
573
574                 if(enable)
575                         cap->cap_effective |= CAP_NETWORK_MGT;
576                 else
577                         cap->cap_effective &= ~CAP_NETWORK_MGT;
578
579                 if (cap_set_proc(cap) == -1) {
580                         DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
581                                 strerror(errno)));
582                         cap_free(cap);
583                         return False;
584                 }
585
586                 cap_free(cap);
587
588                 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
589         }
590         return True;
591 }
592
593 /**************************************************************************
594  Try and abstract inherited process capabilities (for systems that have them).
595 ****************************************************************************/
596
597 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
598 {
599         if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
600                 cap_t cap = cap_get_proc();
601
602                 if (cap == NULL) {
603                         DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
604                                 strerror(errno)));
605                         return False;
606                 }
607
608                 if(enable)
609                         cap->cap_inheritable |= CAP_NETWORK_MGT;
610                 else
611                         cap->cap_inheritable &= ~CAP_NETWORK_MGT;
612
613                 if (cap_set_proc(cap) == -1) {
614                         DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", 
615                                 strerror(errno)));
616                         cap_free(cap);
617                         return False;
618                 }
619
620                 cap_free(cap);
621
622                 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
623         }
624         return True;
625 }
626 #endif
627
628 /****************************************************************************
629  Gain the oplock capability from the kernel if possible.
630 ****************************************************************************/
631
632 void oplock_set_capability(BOOL this_process, BOOL inherit)
633 {
634 #if HAVE_KERNEL_OPLOCKS_IRIX
635         set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
636         set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
637 #endif
638 }
639
640 /**************************************************************************
641  Wrapper for random().
642 ****************************************************************************/
643
644 long sys_random(void)
645 {
646 #if defined(HAVE_RANDOM)
647         return (long)random();
648 #elif defined(HAVE_RAND)
649         return (long)rand();
650 #else
651         DEBUG(0,("Error - no random function available !\n"));
652         exit(1);
653 #endif
654 }
655
656 /**************************************************************************
657  Wrapper for srandom().
658 ****************************************************************************/
659
660 void sys_srandom(unsigned int seed)
661 {
662 #if defined(HAVE_SRANDOM)
663         srandom(seed);
664 #elif defined(HAVE_SRAND)
665         srand(seed);
666 #else
667         DEBUG(0,("Error - no srandom function available !\n"));
668         exit(1);
669 #endif
670 }
671
672 /**************************************************************************
673  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
674 ****************************************************************************/
675
676 int groups_max(void)
677 {
678 #if defined(SYSCONF_SC_NGROUPS_MAX)
679         int ret = sysconf(_SC_NGROUPS_MAX);
680         return (ret == -1) ? NGROUPS_MAX : ret;
681 #else
682         return NGROUPS_MAX;
683 #endif
684 }
685
686 /**************************************************************************
687  Wrapper for getgroups. Deals with broken (int) case.
688 ****************************************************************************/
689
690 int sys_getgroups(int setlen, gid_t *gidset)
691 {
692 #if !defined(HAVE_BROKEN_GETGROUPS)
693         return getgroups(setlen, gidset);
694 #else
695
696         GID_T gid;
697         GID_T *group_list;
698         int i, ngroups;
699
700         if(setlen == 0) {
701                 return getgroups(setlen, &gid);
702         }
703
704         /*
705          * Broken case. We need to allocate a
706          * GID_T array of size setlen.
707          */
708
709         if(setlen < 0) {
710                 errno = EINVAL; 
711                 return -1;
712         } 
713
714         if (setlen == 0)
715                 setlen = groups_max();
716
717         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
718                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
719                 return -1;
720         }
721
722         if((ngroups = getgroups(setlen, group_list)) < 0) {
723                 int saved_errno = errno;
724                 SAFE_FREE(group_list);
725                 errno = saved_errno;
726                 return -1;
727         }
728
729         for(i = 0; i < ngroups; i++)
730                 gidset[i] = (gid_t)group_list[i];
731
732         SAFE_FREE(group_list);
733         return ngroups;
734 #endif /* HAVE_BROKEN_GETGROUPS */
735 }
736
737
738 /**************************************************************************
739  Wrapper for setgroups. Deals with broken (int) case. Automatically used
740  if we have broken getgroups.
741 ****************************************************************************/
742
743 int sys_setgroups(int setlen, gid_t *gidset)
744 {
745 #if !defined(HAVE_SETGROUPS)
746         errno = ENOSYS;
747         return -1;
748 #endif /* HAVE_SETGROUPS */
749
750 #if !defined(HAVE_BROKEN_GETGROUPS)
751         return setgroups(setlen, gidset);
752 #else
753
754         GID_T *group_list;
755         int i ; 
756
757         if (setlen == 0)
758                 return 0 ;
759
760         if (setlen < 0 || setlen > groups_max()) {
761                 errno = EINVAL; 
762                 return -1;   
763         }
764
765         /*
766          * Broken case. We need to allocate a
767          * GID_T array of size setlen.
768          */
769
770         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
771                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
772                 return -1;    
773         }
774  
775         for(i = 0; i < setlen; i++) 
776                 group_list[i] = (GID_T) gidset[i]; 
777
778         if(setgroups(setlen, group_list) != 0) {
779                 int saved_errno = errno;
780                 SAFE_FREE(group_list);
781                 errno = saved_errno;
782                 return -1;
783         }
784  
785         SAFE_FREE(group_list);
786         return 0 ;
787 #endif /* HAVE_BROKEN_GETGROUPS */
788 }
789
790 /**************************************************************************
791  Wrappers for setpwent(), getpwent() and endpwent()
792 ****************************************************************************/
793
794 void sys_setpwent(void)
795 {
796         setpwent();
797 }
798
799 struct passwd *sys_getpwent(void)
800 {
801         return getpwent();
802 }
803
804 void sys_endpwent(void)
805 {
806         endpwent();
807 }
808
809 /**************************************************************************
810  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
811 ****************************************************************************/
812
813 struct passwd *sys_getpwnam(const char *name)
814 {
815         return getpwnam(name);
816 }
817
818 struct passwd *sys_getpwuid(uid_t uid)
819 {
820         return getpwuid(uid);
821 }
822
823 struct group *sys_getgrnam(const char *name)
824 {
825         return getgrnam(name);
826 }
827
828 struct group *sys_getgrgid(gid_t gid)
829 {
830         return getgrgid(gid);
831 }
832
833 #if 0 /* NOT CURRENTLY USED - JRA */
834 /**************************************************************************
835  The following are the UNICODE versions of *all* system interface functions
836  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
837  which currently are left as ascii as they are not used other than in name
838  resolution.
839 ****************************************************************************/
840
841 /**************************************************************************
842  Wide stat. Just narrow and call sys_xxx.
843 ****************************************************************************/
844
845 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
846 {
847         pstring fname;
848         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
849 }
850
851 /**************************************************************************
852  Wide lstat. Just narrow and call sys_xxx.
853 ****************************************************************************/
854
855 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
856 {
857         pstring fname;
858         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
859 }
860
861 /**************************************************************************
862  Wide creat. Just narrow and call sys_xxx.
863 ****************************************************************************/
864
865 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
866 {
867         pstring fname;
868         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
869 }
870
871 /**************************************************************************
872  Wide open. Just narrow and call sys_xxx.
873 ****************************************************************************/
874
875 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
876 {
877         pstring fname;
878         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
879 }
880
881 /**************************************************************************
882  Wide fopen. Just narrow and call sys_xxx.
883 ****************************************************************************/
884
885 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
886 {
887         pstring fname;
888         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
889 }
890
891 /**************************************************************************
892  Wide opendir. Just narrow and call sys_xxx.
893 ****************************************************************************/
894
895 DIR *wsys_opendir(const smb_ucs2_t *wfname)
896 {
897         pstring fname;
898         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
899 }
900
901 /**************************************************************************
902  Wide readdir. Return a structure pointer containing a wide filename.
903 ****************************************************************************/
904
905 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
906 {
907         static SMB_STRUCT_WDIRENT retval;
908         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
909
910         if(!dirval)
911                 return NULL;
912
913         /*
914          * The only POSIX defined member of this struct is d_name.
915          */
916
917         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
918
919         return &retval;
920 }
921
922 /**************************************************************************
923  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
924 ****************************************************************************/
925
926 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
927 {
928         pstring fname;
929         char *p = sys_getwd(fname);
930
931         if(!p)
932                 return NULL;
933
934         return unix_to_unicode(s, p, sizeof(wpstring));
935 }
936
937 /**************************************************************************
938  Wide chown. Just narrow and call sys_xxx.
939 ****************************************************************************/
940
941 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
942 {
943         pstring fname;
944         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
945 }
946
947 /**************************************************************************
948  Wide chroot. Just narrow and call sys_xxx.
949 ****************************************************************************/
950
951 int wsys_chroot(const smb_ucs2_t *wfname)
952 {
953         pstring fname;
954         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
955 }
956
957 /**************************************************************************
958  Wide getpwnam. Return a structure pointer containing wide names.
959 ****************************************************************************/
960
961 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
962 {
963         static SMB_STRUCT_WPASSWD retval;
964         fstring name;
965         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
966
967         if(!pwret)
968                 return NULL;
969
970         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
971         retval.pw_passwd = pwret->pw_passwd;
972         retval.pw_uid = pwret->pw_uid;
973         retval.pw_gid = pwret->pw_gid;
974         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
975         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
976         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
977
978         return &retval;
979 }
980
981 /**************************************************************************
982  Wide getpwuid. Return a structure pointer containing wide names.
983 ****************************************************************************/
984
985 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
986 {
987         static SMB_STRUCT_WPASSWD retval;
988         struct passwd *pwret = sys_getpwuid(uid);
989
990         if(!pwret)
991                 return NULL;
992
993         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
994         retval.pw_passwd = pwret->pw_passwd;
995         retval.pw_uid = pwret->pw_uid;
996         retval.pw_gid = pwret->pw_gid;
997         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
998         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
999         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1000
1001         return &retval;
1002 }
1003 #endif /* NOT CURRENTLY USED - JRA */
1004
1005 /**************************************************************************
1006  Extract a command into an arg list. Uses a static pstring for storage.
1007  Caller frees returned arg list (which contains pointers into the static pstring).
1008 ****************************************************************************/
1009
1010 static char **extract_args(const char *command)
1011 {
1012         static pstring trunc_cmd;
1013         char *ptr;
1014         int argcl;
1015         char **argl = NULL;
1016         int i;
1017
1018         pstrcpy(trunc_cmd, command);
1019
1020         if(!(ptr = strtok(trunc_cmd, " \t"))) {
1021                 errno = EINVAL;
1022                 return NULL;
1023         }
1024
1025         /*
1026          * Count the args.
1027          */
1028
1029         for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1030                 argcl++;
1031
1032         if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
1033                 return NULL;
1034
1035         /*
1036          * Now do the extraction.
1037          */
1038
1039         pstrcpy(trunc_cmd, command);
1040
1041         ptr = strtok(trunc_cmd, " \t");
1042         i = 0;
1043         argl[i++] = ptr;
1044
1045         while((ptr = strtok(NULL, " \t")) != NULL)
1046                 argl[i++] = ptr;
1047
1048         argl[i++] = NULL;
1049         return argl;
1050 }
1051
1052 /**************************************************************************
1053  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1054  a sys_getpid() that only does a system call *once*.
1055 ****************************************************************************/
1056
1057 static pid_t mypid = (pid_t)-1;
1058
1059 pid_t sys_fork(void)
1060 {
1061         pid_t forkret = fork();
1062
1063         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1064                 mypid = (pid_t) -1;
1065
1066         return forkret;
1067 }
1068
1069 /**************************************************************************
1070  Wrapper for getpid. Ensures we only do a system call *once*.
1071 ****************************************************************************/
1072
1073 pid_t sys_getpid(void)
1074 {
1075         if (mypid == (pid_t)-1)
1076                 mypid = getpid();
1077
1078         return mypid;
1079 }
1080
1081 /**************************************************************************
1082  Wrapper for popen. Safer as it doesn't search a path.
1083  Modified from the glibc sources.
1084  modified by tridge to return a file descriptor. We must kick our FILE* habit
1085 ****************************************************************************/
1086
1087 typedef struct _popen_list
1088 {
1089         int fd;
1090         pid_t child_pid;
1091         struct _popen_list *next;
1092 } popen_list;
1093
1094 static popen_list *popen_chain;
1095
1096 int sys_popen(const char *command)
1097 {
1098         int parent_end, child_end;
1099         int pipe_fds[2];
1100         popen_list *entry = NULL;
1101         char **argl = NULL;
1102
1103         if (pipe(pipe_fds) < 0)
1104                 return -1;
1105
1106         parent_end = pipe_fds[0];
1107         child_end = pipe_fds[1];
1108
1109         if (!*command) {
1110                 errno = EINVAL;
1111                 goto err_exit;
1112         }
1113
1114         if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1115                 goto err_exit;
1116
1117         ZERO_STRUCTP(entry);
1118
1119         /*
1120          * Extract the command and args into a NULL terminated array.
1121          */
1122
1123         if(!(argl = extract_args(command)))
1124                 goto err_exit;
1125
1126         entry->child_pid = sys_fork();
1127
1128         if (entry->child_pid == -1) {
1129                 goto err_exit;
1130         }
1131
1132         if (entry->child_pid == 0) {
1133
1134                 /*
1135                  * Child !
1136                  */
1137
1138                 int child_std_end = STDOUT_FILENO;
1139                 popen_list *p;
1140
1141                 close(parent_end);
1142                 if (child_end != child_std_end) {
1143                         dup2 (child_end, child_std_end);
1144                         close (child_end);
1145                 }
1146
1147                 /*
1148                  * POSIX.2:  "popen() shall ensure that any streams from previous
1149                  * popen() calls that remain open in the parent process are closed
1150                  * in the new child process."
1151                  */
1152
1153                 for (p = popen_chain; p; p = p->next)
1154                         close(p->fd);
1155
1156                 execv(argl[0], argl);
1157                 _exit (127);
1158         }
1159
1160         /*
1161          * Parent.
1162          */
1163
1164         close (child_end);
1165         SAFE_FREE(argl);
1166
1167         /* Link into popen_chain. */
1168         entry->next = popen_chain;
1169         popen_chain = entry;
1170         entry->fd = parent_end;
1171
1172         return entry->fd;
1173
1174 err_exit:
1175
1176         SAFE_FREE(entry);
1177         SAFE_FREE(argl);
1178         close(pipe_fds[0]);
1179         close(pipe_fds[1]);
1180         return -1;
1181 }
1182
1183 /**************************************************************************
1184  Wrapper for pclose. Modified from the glibc sources.
1185 ****************************************************************************/
1186
1187 int sys_pclose(int fd)
1188 {
1189         int wstatus;
1190         popen_list **ptr = &popen_chain;
1191         popen_list *entry = NULL;
1192         pid_t wait_pid;
1193         int status = -1;
1194
1195         /* Unlink from popen_chain. */
1196         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1197                 if ((*ptr)->fd == fd) {
1198                         entry = *ptr;
1199                         *ptr = (*ptr)->next;
1200                         status = 0;
1201                         break;
1202                 }
1203         }
1204
1205         if (status < 0 || close(entry->fd) < 0)
1206                 return -1;
1207
1208         /*
1209          * As Samba is catching and eating child process
1210          * exits we don't really care about the child exit
1211          * code, a -1 with errno = ECHILD will do fine for us.
1212          */
1213
1214         do {
1215                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1216         } while (wait_pid == -1 && errno == EINTR);
1217
1218         SAFE_FREE(entry);
1219
1220         if (wait_pid == -1)
1221                 return -1;
1222         return wstatus;
1223 }
1224
1225 /**************************************************************************
1226  Wrappers for dlopen, dlsym, dlclose.
1227 ****************************************************************************/
1228
1229 void *sys_dlopen(const char *name, int flags)
1230 {
1231 #if defined(HAVE_DLOPEN)
1232         return dlopen(name, flags);
1233 #else
1234         return NULL;
1235 #endif
1236 }
1237
1238 void *sys_dlsym(void *handle, const char *symbol)
1239 {
1240 #if defined(HAVE_DLSYM)
1241     return dlsym(handle, symbol);
1242 #else
1243     return NULL;
1244 #endif
1245 }
1246
1247 int sys_dlclose (void *handle)
1248 {
1249 #if defined(HAVE_DLCLOSE)
1250         return dlclose(handle);
1251 #else
1252         return 0;
1253 #endif
1254 }
1255
1256 const char *sys_dlerror(void)
1257 {
1258 #if defined(HAVE_DLERROR)
1259         return dlerror();
1260 #else
1261         return NULL;
1262 #endif
1263 }
1264
1265 int sys_dup2(int oldfd, int newfd) 
1266 {
1267 #if defined(HAVE_DUP2)
1268         return dup2(oldfd, newfd);
1269 #else
1270         errno = ENOSYS;
1271         return -1;
1272 #endif
1273 }
1274
1275 /**************************************************************************
1276  Wrapper for Admin Logs.
1277 ****************************************************************************/
1278
1279  void sys_adminlog(int priority, const char *format_str, ...) 
1280 {
1281         va_list ap;
1282         int ret;
1283         char *msgbuf = NULL;
1284
1285         va_start( ap, format_str );
1286         ret = vasprintf( &msgbuf, format_str, ap );
1287         va_end( ap );
1288
1289         if (ret == -1)
1290                 return;
1291
1292 #if defined(HAVE_SYSLOG)
1293         syslog( priority, "%s", msgbuf );
1294 #else
1295         DEBUG(0,("%s", msgbuf ));
1296 #endif
1297         SAFE_FREE(msgbuf);
1298 }
1299
1300 /**************************************************************************
1301  Wrappers for extented attribute calls. Based on the Linux package with
1302  support for IRIX also. Expand as other systems have them.
1303 ****************************************************************************/
1304
1305 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1306 {
1307 #if defined(HAVE_GETXATTR)
1308         return getxattr(path, name, value, size);
1309 #elif defined(HAVE_ATTR_GET)
1310         int retval, flags = 0;
1311         int valuelength = (int)size;
1312         char *attrname = strchr(name,'.') +1;
1313         
1314         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1315
1316         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1317
1318         return retval ? retval : valuelength;
1319 #else
1320         errno = ENOSYS;
1321         return -1;
1322 #endif
1323 }
1324
1325 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1326 {
1327 #if defined(HAVE_LGETXATTR)
1328         return lgetxattr(path, name, value, size);
1329 #elif defined(HAVE_ATTR_GET)
1330         int retval, flags = ATTR_DONTFOLLOW;
1331         int valuelength = (int)size;
1332         char *attrname = strchr(name,'.') +1;
1333         
1334         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1335
1336         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1337
1338         return retval ? retval : valuelength;
1339 #else
1340         errno = ENOSYS;
1341         return -1;
1342 #endif
1343 }
1344
1345 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1346 {
1347 #if defined(HAVE_FGETXATTR)
1348         return fgetxattr(filedes, name, value, size);
1349 #elif defined(HAVE_ATTR_GETF)
1350         int retval, flags = 0;
1351         int valuelength = (int)size;
1352         char *attrname = strchr(name,'.') +1;
1353         
1354         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1355
1356         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1357
1358         return retval ? retval : valuelength;
1359 #else
1360         errno = ENOSYS;
1361         return -1;
1362 #endif
1363 }
1364
1365 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1366 static char attr_buffer[ATTR_MAX_VALUELEN];
1367
1368 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1369 {
1370         int retval = 0, index;
1371         attrlist_cursor_t *cursor = 0;
1372         int total_size = 0;
1373         attrlist_t * al = (attrlist_t *)attr_buffer;
1374         attrlist_ent_t *ae;
1375         size_t ent_size, left = size;
1376         char *bp = list;
1377
1378         while (True) {
1379             if (filedes)
1380                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1381             else
1382                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1383             if (retval) break;
1384             for (index = 0; index < al->al_count; index++) {
1385                 ae = ATTR_ENTRY(attr_buffer, index);
1386                 ent_size = strlen(ae->a_name) + sizeof("user.");
1387                 if (left >= ent_size) {
1388                     strncpy(bp, "user.", sizeof("user."));
1389                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1390                     bp += ent_size;
1391                     left -= ent_size;
1392                 } else if (size) {
1393                     errno = ERANGE;
1394                     retval = -1;
1395                     break;
1396                 }
1397                 total_size += ent_size;
1398             }
1399             if (al->al_more == 0) break;
1400         }
1401         if (retval == 0) {
1402             flags |= ATTR_ROOT;
1403             cursor = 0;
1404             while (True) {
1405                 if (filedes)
1406                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1407                 else
1408                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1409                 if (retval) break;
1410                 for (index = 0; index < al->al_count; index++) {
1411                     ae = ATTR_ENTRY(attr_buffer, index);
1412                     ent_size = strlen(ae->a_name) + sizeof("system.");
1413                     if (left >= ent_size) {
1414                         strncpy(bp, "system.", sizeof("system."));
1415                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1416                         bp += ent_size;
1417                         left -= ent_size;
1418                     } else if (size) {
1419                         errno = ERANGE;
1420                         retval = -1;
1421                         break;
1422                     }
1423                     total_size += ent_size;
1424                 }
1425                 if (al->al_more == 0) break;
1426             }
1427         }
1428         return (ssize_t)(retval ? retval : total_size);
1429 }
1430
1431 #endif
1432
1433 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1434 {
1435 #if defined(HAVE_LISTXATTR)
1436         return listxattr(path, list, size);
1437 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1438         return irix_attr_list(path, 0, list, size, 0);
1439 #else
1440         errno = ENOSYS;
1441         return -1;
1442 #endif
1443 }
1444
1445 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1446 {
1447 #if defined(HAVE_LLISTXATTR)
1448         return llistxattr(path, list, size);
1449 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1450         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1451 #else
1452         errno = ENOSYS;
1453         return -1;
1454 #endif
1455 }
1456
1457 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1458 {
1459 #if defined(HAVE_FLISTXATTR)
1460         return flistxattr(filedes, list, size);
1461 #elif defined(HAVE_ATTR_LISTF)
1462         return irix_attr_list(NULL, filedes, list, size, 0);
1463 #else
1464         errno = ENOSYS;
1465         return -1;
1466 #endif
1467 }
1468
1469 int sys_removexattr (const char *path, const char *name)
1470 {
1471 #if defined(HAVE_REMOVEXATTR)
1472         return removexattr(path, name);
1473 #elif defined(HAVE_ATTR_REMOVE)
1474         int flags = 0;
1475         char *attrname = strchr(name,'.') +1;
1476         
1477         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1478
1479         return attr_remove(path, attrname, flags);
1480 #else
1481         errno = ENOSYS;
1482         return -1;
1483 #endif
1484 }
1485
1486 int sys_lremovexattr (const char *path, const char *name)
1487 {
1488 #if defined(HAVE_LREMOVEXATTR)
1489         return lremovexattr(path, name);
1490 #elif defined(HAVE_ATTR_REMOVE)
1491         int flags = ATTR_DONTFOLLOW;
1492         char *attrname = strchr(name,'.') +1;
1493         
1494         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1495
1496         return attr_remove(path, attrname, flags);
1497 #else
1498         errno = ENOSYS;
1499         return -1;
1500 #endif
1501 }
1502
1503 int sys_fremovexattr (int filedes, const char *name)
1504 {
1505 #if defined(HAVE_FREMOVEXATTR)
1506         return fremovexattr(filedes, name);
1507 #elif defined(HAVE_ATTR_REMOVEF)
1508         int flags = 0;
1509         char *attrname = strchr(name,'.') +1;
1510         
1511         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1512
1513         return attr_removef(filedes, attrname, flags);
1514 #else
1515         errno = ENOSYS;
1516         return -1;
1517 #endif
1518 }
1519
1520 #if !defined(HAVE_SETXATTR)
1521 #define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
1522 #define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
1523 #endif
1524
1525 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1526 {
1527 #if defined(HAVE_SETXATTR)
1528         return setxattr(path, name, value, size, flags);
1529 #elif defined(HAVE_ATTR_SET)
1530         int myflags = 0;
1531         char *attrname = strchr(name,'.') +1;
1532         
1533         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1534         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1535         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1536
1537         return attr_set(path, attrname, (const char *)value, size, myflags);
1538 #else
1539         errno = ENOSYS;
1540         return -1;
1541 #endif
1542 }
1543
1544 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1545 {
1546 #if defined(HAVE_LSETXATTR)
1547         return lsetxattr(path, name, value, size, flags);
1548 #elif defined(HAVE_ATTR_SET)
1549         int myflags = ATTR_DONTFOLLOW;
1550         char *attrname = strchr(name,'.') +1;
1551         
1552         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1553         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1554         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1555
1556         return attr_set(path, attrname, (const char *)value, size, myflags);
1557 #else
1558         errno = ENOSYS;
1559         return -1;
1560 #endif
1561 }
1562
1563 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1564 {
1565 #if defined(HAVE_FSETXATTR)
1566         return fsetxattr(filedes, name, value, size, flags);
1567 #elif defined(HAVE_ATTR_SETF)
1568         int myflags = 0;
1569         char *attrname = strchr(name,'.') +1;
1570         
1571         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1572         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1573         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1574
1575         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1576 #else
1577         errno = ENOSYS;
1578         return -1;
1579 #endif
1580 }