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