r6303: Setting up for 3.0.15pre1
[Samba.git] / source / lib / system.c
bloba2e5352aa5f802b8c02651e1cfdaeacd2ada286c
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2002
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.
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.
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.
22 #include "includes.h"
25 The idea is that this file will eventually have wrappers around all
26 important system calls in samba. The aims are:
28 - to enable easier porting by putting OS dependent stuff in here
30 - to allow for hooks into other "pseudo-filesystems"
32 - to allow easier integration of things like the japanese extensions
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.
41 /*******************************************************************
42 A wrapper for usleep in case we don't have one.
43 ********************************************************************/
45 int sys_usleep(long usecs)
47 #ifndef HAVE_USLEEP
48 struct timeval tval;
49 #endif
52 * We need this braindamage as the glibc usleep
53 * is not SPEC1170 complient... grumble... JRA.
56 if(usecs < 0 || usecs > 1000000) {
57 errno = EINVAL;
58 return -1;
61 #if HAVE_USLEEP
62 usleep(usecs);
63 return 0;
64 #else /* HAVE_USLEEP */
66 * Fake it with select...
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 */
75 /*******************************************************************
76 A read wrapper that will deal with EINTR.
77 ********************************************************************/
79 ssize_t sys_read(int fd, void *buf, size_t count)
81 ssize_t ret;
83 do {
84 ret = read(fd, buf, count);
85 } while (ret == -1 && errno == EINTR);
86 return ret;
89 /*******************************************************************
90 A write wrapper that will deal with EINTR.
91 ********************************************************************/
93 ssize_t sys_write(int fd, const void *buf, size_t count)
95 ssize_t ret;
97 do {
98 ret = write(fd, buf, count);
99 } while (ret == -1 && errno == EINTR);
100 return ret;
104 /*******************************************************************
105 A pread wrapper that will deal with EINTR and 64-bit file offsets.
106 ********************************************************************/
108 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
109 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
111 ssize_t ret;
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;
122 #endif
124 /*******************************************************************
125 A write wrapper that will deal with EINTR and 64-bit file offsets.
126 ********************************************************************/
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)
131 ssize_t ret;
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;
142 #endif
144 /*******************************************************************
145 A send wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
150 ssize_t ret;
152 do {
153 ret = send(s, msg, len, flags);
154 } while (ret == -1 && errno == EINTR);
155 return ret;
158 /*******************************************************************
159 A sendto wrapper that will deal with EINTR.
160 ********************************************************************/
162 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
164 ssize_t ret;
166 do {
167 ret = sendto(s, msg, len, flags, to, tolen);
168 } while (ret == -1 && errno == EINTR);
169 return ret;
172 /*******************************************************************
173 A recvfrom wrapper that will deal with EINTR.
174 ********************************************************************/
176 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
178 ssize_t ret;
180 do {
181 ret = recvfrom(s, buf, len, flags, from, fromlen);
182 } while (ret == -1 && errno == EINTR);
183 return ret;
186 /*******************************************************************
187 A fcntl wrapper that will deal with EINTR.
188 ********************************************************************/
190 int sys_fcntl_ptr(int fd, int cmd, void *arg)
192 int ret;
194 do {
195 ret = fcntl(fd, cmd, arg);
196 } while (ret == -1 && errno == EINTR);
197 return ret;
200 /*******************************************************************
201 A fcntl wrapper that will deal with EINTR.
202 ********************************************************************/
204 int sys_fcntl_long(int fd, int cmd, long arg)
206 int ret;
208 do {
209 ret = fcntl(fd, cmd, arg);
210 } while (ret == -1 && errno == EINTR);
211 return ret;
214 /*******************************************************************
215 A stat() wrapper that will deal with 64 bit filesizes.
216 ********************************************************************/
218 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
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;
231 /*******************************************************************
232 An fstat() wrapper that will deal with 64 bit filesizes.
233 ********************************************************************/
235 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
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;
248 /*******************************************************************
249 An lstat() wrapper that will deal with 64 bit filesizes.
250 ********************************************************************/
252 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
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;
265 /*******************************************************************
266 An ftruncate() wrapper that will deal with 64 bit filesizes.
267 ********************************************************************/
269 int sys_ftruncate(int fd, SMB_OFF_T offset)
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
278 /*******************************************************************
279 An lseek() wrapper that will deal with 64 bit filesizes.
280 ********************************************************************/
282 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
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
291 /*******************************************************************
292 An fseek() wrapper that will deal with 64 bit filesizes.
293 ********************************************************************/
295 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
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
306 /*******************************************************************
307 An ftell() wrapper that will deal with 64 bit filesizes.
308 ********************************************************************/
310 SMB_OFF_T sys_ftell(FILE *fp)
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
321 /*******************************************************************
322 A creat() wrapper that will deal with 64 bit filesizes.
323 ********************************************************************/
325 int sys_creat(const char *path, mode_t mode)
327 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
328 return creat64(path, mode);
329 #else
331 * If creat64 isn't defined then ensure we call a potential open64.
332 * JRA.
334 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
335 #endif
338 /*******************************************************************
339 An open() wrapper that will deal with 64 bit filesizes.
340 ********************************************************************/
342 int sys_open(const char *path, int oflag, mode_t mode)
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
351 /*******************************************************************
352 An fopen() wrapper that will deal with 64 bit filesizes.
353 ********************************************************************/
355 FILE *sys_fopen(const char *path, const char *type)
357 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
358 return fopen64(path, type);
359 #else
360 return fopen(path, type);
361 #endif
364 /*******************************************************************
365 An opendir wrapper that will deal with 64 bit filesizes.
366 ********************************************************************/
368 DIR *sys_opendir(const char *name)
370 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
371 return opendir64(name);
372 #else
373 return opendir(name);
374 #endif
377 /*******************************************************************
378 A readdir wrapper that will deal with 64 bit filesizes.
379 ********************************************************************/
381 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
383 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
384 return readdir64(dirp);
385 #else
386 return readdir(dirp);
387 #endif
390 /*******************************************************************
391 A seekdir wrapper that will deal with 64 bit filesizes.
392 ********************************************************************/
394 void sys_seekdir(DIR *dirp, long offset)
396 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
397 seekdir64(dirp, offset);
398 #else
399 seekdir(dirp, offset);
400 #endif
403 /*******************************************************************
404 A telldir wrapper that will deal with 64 bit filesizes.
405 ********************************************************************/
407 long sys_telldir(DIR *dirp)
409 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
410 return (long)telldir64(dirp);
411 #else
412 return (long)telldir(dirp);
413 #endif
416 /*******************************************************************
417 A rewinddir wrapper that will deal with 64 bit filesizes.
418 ********************************************************************/
420 void sys_rewinddir(DIR *dirp)
422 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
423 rewinddir64(dirp);
424 #else
425 rewinddir(dirp);
426 #endif
429 /*******************************************************************
430 A close wrapper that will deal with 64 bit filesizes.
431 ********************************************************************/
433 int sys_closedir(DIR *dirp)
435 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
436 return closedir64(dirp);
437 #else
438 return closedir(dirp);
439 #endif
442 /*******************************************************************
443 An mknod() wrapper that will deal with 64 bit filesizes.
444 ********************************************************************/
446 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
448 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
450 return mknod64(path, mode, dev);
451 #else
452 return mknod(path, mode, dev);
453 #endif
454 #else
455 /* No mknod system call. */
456 errno = ENOSYS;
457 return -1;
458 #endif
461 /*******************************************************************
462 Wrapper for realpath.
463 ********************************************************************/
465 char *sys_realpath(const char *path, char *resolved_path)
467 #if defined(HAVE_REALPATH)
468 return realpath(path, resolved_path);
469 #else
470 /* As realpath is not a system call we can't return ENOSYS. */
471 errno = EINVAL;
472 return NULL;
473 #endif
476 /*******************************************************************
477 The wait() calls vary between systems
478 ********************************************************************/
480 int sys_waitpid(pid_t pid,int *status,int options)
482 #ifdef HAVE_WAITPID
483 return waitpid(pid,status,options);
484 #else /* HAVE_WAITPID */
485 return wait4(pid, status, options, NULL);
486 #endif /* HAVE_WAITPID */
489 /*******************************************************************
490 System wrapper for getwd
491 ********************************************************************/
493 char *sys_getwd(char *s)
495 char *wd;
496 #ifdef HAVE_GETCWD
497 wd = (char *)getcwd(s, sizeof (pstring));
498 #else
499 wd = (char *)getwd(s);
500 #endif
501 return wd;
504 /*******************************************************************
505 system wrapper for symlink
506 ********************************************************************/
508 int sys_symlink(const char *oldpath, const char *newpath)
510 #ifndef HAVE_SYMLINK
511 errno = ENOSYS;
512 return -1;
513 #else
514 return symlink(oldpath, newpath);
515 #endif
518 /*******************************************************************
519 system wrapper for readlink
520 ********************************************************************/
522 int sys_readlink(const char *path, char *buf, size_t bufsiz)
524 #ifndef HAVE_READLINK
525 errno = ENOSYS;
526 return -1;
527 #else
528 return readlink(path, buf, bufsiz);
529 #endif
532 /*******************************************************************
533 system wrapper for link
534 ********************************************************************/
536 int sys_link(const char *oldpath, const char *newpath)
538 #ifndef HAVE_LINK
539 errno = ENOSYS;
540 return -1;
541 #else
542 return link(oldpath, newpath);
543 #endif
546 /*******************************************************************
547 chown isn't used much but OS/2 doesn't have it
548 ********************************************************************/
550 int sys_chown(const char *fname,uid_t uid,gid_t gid)
552 #ifndef HAVE_CHOWN
553 static int done;
554 if (!done) {
555 DEBUG(1,("WARNING: no chown!\n"));
556 done=1;
558 errno = ENOSYS;
559 return -1;
560 #else
561 return(chown(fname,uid,gid));
562 #endif
565 /*******************************************************************
566 os/2 also doesn't have chroot
567 ********************************************************************/
568 int sys_chroot(const char *dname)
570 #ifndef HAVE_CHROOT
571 static int done;
572 if (!done) {
573 DEBUG(1,("WARNING: no chroot!\n"));
574 done=1;
576 errno = ENOSYS;
577 return -1;
578 #else
579 return(chroot(dname));
580 #endif
583 /**************************************************************************
584 A wrapper for gethostbyname() that tries avoids looking up hostnames
585 in the root domain, which can cause dial-on-demand links to come up for no
586 apparent reason.
587 ****************************************************************************/
589 struct hostent *sys_gethostbyname(const char *name)
591 #ifdef REDUCE_ROOT_DNS_LOOKUPS
592 char query[256], hostname[256];
593 char *domain;
595 /* Does this name have any dots in it? If so, make no change */
597 if (strchr_m(name, '.'))
598 return(gethostbyname(name));
600 /* Get my hostname, which should have domain name
601 attached. If not, just do the gethostname on the
602 original string.
605 gethostname(hostname, sizeof(hostname) - 1);
606 hostname[sizeof(hostname) - 1] = 0;
607 if ((domain = strchr_m(hostname, '.')) == NULL)
608 return(gethostbyname(name));
610 /* Attach domain name to query and do modified query.
611 If names too large, just do gethostname on the
612 original string.
615 if((strlen(name) + strlen(domain)) >= sizeof(query))
616 return(gethostbyname(name));
618 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
619 return(gethostbyname(query));
620 #else /* REDUCE_ROOT_DNS_LOOKUPS */
621 return(gethostbyname(name));
622 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
626 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
627 /**************************************************************************
628 Try and abstract process capabilities (for systems that have them).
629 ****************************************************************************/
630 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
632 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
633 cap_t cap = cap_get_proc();
635 if (cap == NULL) {
636 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
637 strerror(errno)));
638 return False;
641 if(enable)
642 cap->cap_effective |= CAP_NETWORK_MGT;
643 else
644 cap->cap_effective &= ~CAP_NETWORK_MGT;
646 if (cap_set_proc(cap) == -1) {
647 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
648 strerror(errno)));
649 cap_free(cap);
650 return False;
653 cap_free(cap);
655 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
657 return True;
660 /**************************************************************************
661 Try and abstract inherited process capabilities (for systems that have them).
662 ****************************************************************************/
664 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
666 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
667 cap_t cap = cap_get_proc();
669 if (cap == NULL) {
670 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
671 strerror(errno)));
672 return False;
675 if(enable)
676 cap->cap_inheritable |= CAP_NETWORK_MGT;
677 else
678 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
680 if (cap_set_proc(cap) == -1) {
681 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
682 strerror(errno)));
683 cap_free(cap);
684 return False;
687 cap_free(cap);
689 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
691 return True;
693 #endif
695 /****************************************************************************
696 Gain the oplock capability from the kernel if possible.
697 ****************************************************************************/
699 void oplock_set_capability(BOOL this_process, BOOL inherit)
701 #if HAVE_KERNEL_OPLOCKS_IRIX
702 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
703 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
704 #endif
707 /**************************************************************************
708 Wrapper for random().
709 ****************************************************************************/
711 long sys_random(void)
713 #if defined(HAVE_RANDOM)
714 return (long)random();
715 #elif defined(HAVE_RAND)
716 return (long)rand();
717 #else
718 DEBUG(0,("Error - no random function available !\n"));
719 exit(1);
720 #endif
723 /**************************************************************************
724 Wrapper for srandom().
725 ****************************************************************************/
727 void sys_srandom(unsigned int seed)
729 #if defined(HAVE_SRANDOM)
730 srandom(seed);
731 #elif defined(HAVE_SRAND)
732 srand(seed);
733 #else
734 DEBUG(0,("Error - no srandom function available !\n"));
735 exit(1);
736 #endif
739 /**************************************************************************
740 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
741 ****************************************************************************/
743 int groups_max(void)
745 #if defined(SYSCONF_SC_NGROUPS_MAX)
746 int ret = sysconf(_SC_NGROUPS_MAX);
747 return (ret == -1) ? NGROUPS_MAX : ret;
748 #else
749 return NGROUPS_MAX;
750 #endif
753 /**************************************************************************
754 Wrapper for getgroups. Deals with broken (int) case.
755 ****************************************************************************/
757 int sys_getgroups(int setlen, gid_t *gidset)
759 #if !defined(HAVE_BROKEN_GETGROUPS)
760 return getgroups(setlen, gidset);
761 #else
763 GID_T gid;
764 GID_T *group_list;
765 int i, ngroups;
767 if(setlen == 0) {
768 return getgroups(setlen, &gid);
772 * Broken case. We need to allocate a
773 * GID_T array of size setlen.
776 if(setlen < 0) {
777 errno = EINVAL;
778 return -1;
781 if (setlen == 0)
782 setlen = groups_max();
784 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
785 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
786 return -1;
789 if((ngroups = getgroups(setlen, group_list)) < 0) {
790 int saved_errno = errno;
791 SAFE_FREE(group_list);
792 errno = saved_errno;
793 return -1;
796 for(i = 0; i < ngroups; i++)
797 gidset[i] = (gid_t)group_list[i];
799 SAFE_FREE(group_list);
800 return ngroups;
801 #endif /* HAVE_BROKEN_GETGROUPS */
805 /**************************************************************************
806 Wrapper for setgroups. Deals with broken (int) case. Automatically used
807 if we have broken getgroups.
808 ****************************************************************************/
810 int sys_setgroups(int setlen, gid_t *gidset)
812 #if !defined(HAVE_SETGROUPS)
813 errno = ENOSYS;
814 return -1;
815 #endif /* HAVE_SETGROUPS */
817 #if !defined(HAVE_BROKEN_GETGROUPS)
818 return setgroups(setlen, gidset);
819 #else
821 GID_T *group_list;
822 int i ;
824 if (setlen == 0)
825 return 0 ;
827 if (setlen < 0 || setlen > groups_max()) {
828 errno = EINVAL;
829 return -1;
833 * Broken case. We need to allocate a
834 * GID_T array of size setlen.
837 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
838 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
839 return -1;
842 for(i = 0; i < setlen; i++)
843 group_list[i] = (GID_T) gidset[i];
845 if(setgroups(setlen, group_list) != 0) {
846 int saved_errno = errno;
847 SAFE_FREE(group_list);
848 errno = saved_errno;
849 return -1;
852 SAFE_FREE(group_list);
853 return 0 ;
854 #endif /* HAVE_BROKEN_GETGROUPS */
857 /**************************************************************************
858 Wrappers for setpwent(), getpwent() and endpwent()
859 ****************************************************************************/
861 void sys_setpwent(void)
863 setpwent();
866 struct passwd *sys_getpwent(void)
868 return getpwent();
871 void sys_endpwent(void)
873 endpwent();
876 /**************************************************************************
877 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
878 ****************************************************************************/
880 struct passwd *sys_getpwnam(const char *name)
882 return getpwnam(name);
885 struct passwd *sys_getpwuid(uid_t uid)
887 return getpwuid(uid);
890 struct group *sys_getgrnam(const char *name)
892 return getgrnam(name);
895 struct group *sys_getgrgid(gid_t gid)
897 return getgrgid(gid);
900 #if 0 /* NOT CURRENTLY USED - JRA */
901 /**************************************************************************
902 The following are the UNICODE versions of *all* system interface functions
903 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
904 which currently are left as ascii as they are not used other than in name
905 resolution.
906 ****************************************************************************/
908 /**************************************************************************
909 Wide stat. Just narrow and call sys_xxx.
910 ****************************************************************************/
912 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
914 pstring fname;
915 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
918 /**************************************************************************
919 Wide lstat. Just narrow and call sys_xxx.
920 ****************************************************************************/
922 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
924 pstring fname;
925 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
928 /**************************************************************************
929 Wide creat. Just narrow and call sys_xxx.
930 ****************************************************************************/
932 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
934 pstring fname;
935 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
938 /**************************************************************************
939 Wide open. Just narrow and call sys_xxx.
940 ****************************************************************************/
942 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
944 pstring fname;
945 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
948 /**************************************************************************
949 Wide fopen. Just narrow and call sys_xxx.
950 ****************************************************************************/
952 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
954 pstring fname;
955 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
958 /**************************************************************************
959 Wide opendir. Just narrow and call sys_xxx.
960 ****************************************************************************/
962 DIR *wsys_opendir(const smb_ucs2_t *wfname)
964 pstring fname;
965 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
968 /**************************************************************************
969 Wide readdir. Return a structure pointer containing a wide filename.
970 ****************************************************************************/
972 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
974 static SMB_STRUCT_WDIRENT retval;
975 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
977 if(!dirval)
978 return NULL;
981 * The only POSIX defined member of this struct is d_name.
984 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
986 return &retval;
989 /**************************************************************************
990 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
991 ****************************************************************************/
993 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
995 pstring fname;
996 char *p = sys_getwd(fname);
998 if(!p)
999 return NULL;
1001 return unix_to_unicode(s, p, sizeof(wpstring));
1004 /**************************************************************************
1005 Wide chown. Just narrow and call sys_xxx.
1006 ****************************************************************************/
1008 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1010 pstring fname;
1011 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1014 /**************************************************************************
1015 Wide chroot. Just narrow and call sys_xxx.
1016 ****************************************************************************/
1018 int wsys_chroot(const smb_ucs2_t *wfname)
1020 pstring fname;
1021 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1024 /**************************************************************************
1025 Wide getpwnam. Return a structure pointer containing wide names.
1026 ****************************************************************************/
1028 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1030 static SMB_STRUCT_WPASSWD retval;
1031 fstring name;
1032 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1034 if(!pwret)
1035 return NULL;
1037 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1038 retval.pw_passwd = pwret->pw_passwd;
1039 retval.pw_uid = pwret->pw_uid;
1040 retval.pw_gid = pwret->pw_gid;
1041 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1042 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1043 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1045 return &retval;
1048 /**************************************************************************
1049 Wide getpwuid. Return a structure pointer containing wide names.
1050 ****************************************************************************/
1052 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1054 static SMB_STRUCT_WPASSWD retval;
1055 struct passwd *pwret = sys_getpwuid(uid);
1057 if(!pwret)
1058 return NULL;
1060 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1061 retval.pw_passwd = pwret->pw_passwd;
1062 retval.pw_uid = pwret->pw_uid;
1063 retval.pw_gid = pwret->pw_gid;
1064 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1065 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1066 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1068 return &retval;
1070 #endif /* NOT CURRENTLY USED - JRA */
1072 /**************************************************************************
1073 Extract a command into an arg list. Uses a static pstring for storage.
1074 Caller frees returned arg list (which contains pointers into the static pstring).
1075 ****************************************************************************/
1077 static char **extract_args(const char *command)
1079 static pstring trunc_cmd;
1080 char *ptr;
1081 int argcl;
1082 char **argl = NULL;
1083 int i;
1085 pstrcpy(trunc_cmd, command);
1087 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1088 errno = EINVAL;
1089 return NULL;
1093 * Count the args.
1096 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1097 argcl++;
1099 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1100 return NULL;
1103 * Now do the extraction.
1106 pstrcpy(trunc_cmd, command);
1108 ptr = strtok(trunc_cmd, " \t");
1109 i = 0;
1110 argl[i++] = ptr;
1112 while((ptr = strtok(NULL, " \t")) != NULL)
1113 argl[i++] = ptr;
1115 argl[i++] = NULL;
1116 return argl;
1119 /**************************************************************************
1120 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1121 a sys_getpid() that only does a system call *once*.
1122 ****************************************************************************/
1124 static pid_t mypid = (pid_t)-1;
1126 pid_t sys_fork(void)
1128 pid_t forkret = fork();
1130 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1131 mypid = (pid_t) -1;
1133 return forkret;
1136 /**************************************************************************
1137 Wrapper for getpid. Ensures we only do a system call *once*.
1138 ****************************************************************************/
1140 pid_t sys_getpid(void)
1142 if (mypid == (pid_t)-1)
1143 mypid = getpid();
1145 return mypid;
1148 /**************************************************************************
1149 Wrapper for popen. Safer as it doesn't search a path.
1150 Modified from the glibc sources.
1151 modified by tridge to return a file descriptor. We must kick our FILE* habit
1152 ****************************************************************************/
1154 typedef struct _popen_list
1156 int fd;
1157 pid_t child_pid;
1158 struct _popen_list *next;
1159 } popen_list;
1161 static popen_list *popen_chain;
1163 int sys_popen(const char *command)
1165 int parent_end, child_end;
1166 int pipe_fds[2];
1167 popen_list *entry = NULL;
1168 char **argl = NULL;
1170 if (pipe(pipe_fds) < 0)
1171 return -1;
1173 parent_end = pipe_fds[0];
1174 child_end = pipe_fds[1];
1176 if (!*command) {
1177 errno = EINVAL;
1178 goto err_exit;
1181 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1182 goto err_exit;
1184 ZERO_STRUCTP(entry);
1187 * Extract the command and args into a NULL terminated array.
1190 if(!(argl = extract_args(command)))
1191 goto err_exit;
1193 entry->child_pid = sys_fork();
1195 if (entry->child_pid == -1) {
1196 goto err_exit;
1199 if (entry->child_pid == 0) {
1202 * Child !
1205 int child_std_end = STDOUT_FILENO;
1206 popen_list *p;
1208 close(parent_end);
1209 if (child_end != child_std_end) {
1210 dup2 (child_end, child_std_end);
1211 close (child_end);
1215 * POSIX.2: "popen() shall ensure that any streams from previous
1216 * popen() calls that remain open in the parent process are closed
1217 * in the new child process."
1220 for (p = popen_chain; p; p = p->next)
1221 close(p->fd);
1223 execv(argl[0], argl);
1224 _exit (127);
1228 * Parent.
1231 close (child_end);
1232 SAFE_FREE(argl);
1234 /* Link into popen_chain. */
1235 entry->next = popen_chain;
1236 popen_chain = entry;
1237 entry->fd = parent_end;
1239 return entry->fd;
1241 err_exit:
1243 SAFE_FREE(entry);
1244 SAFE_FREE(argl);
1245 close(pipe_fds[0]);
1246 close(pipe_fds[1]);
1247 return -1;
1250 /**************************************************************************
1251 Wrapper for pclose. Modified from the glibc sources.
1252 ****************************************************************************/
1254 int sys_pclose(int fd)
1256 int wstatus;
1257 popen_list **ptr = &popen_chain;
1258 popen_list *entry = NULL;
1259 pid_t wait_pid;
1260 int status = -1;
1262 /* Unlink from popen_chain. */
1263 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1264 if ((*ptr)->fd == fd) {
1265 entry = *ptr;
1266 *ptr = (*ptr)->next;
1267 status = 0;
1268 break;
1272 if (status < 0 || close(entry->fd) < 0)
1273 return -1;
1276 * As Samba is catching and eating child process
1277 * exits we don't really care about the child exit
1278 * code, a -1 with errno = ECHILD will do fine for us.
1281 do {
1282 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1283 } while (wait_pid == -1 && errno == EINTR);
1285 SAFE_FREE(entry);
1287 if (wait_pid == -1)
1288 return -1;
1289 return wstatus;
1292 /**************************************************************************
1293 Wrappers for dlopen, dlsym, dlclose.
1294 ****************************************************************************/
1296 void *sys_dlopen(const char *name, int flags)
1298 #if defined(HAVE_DLOPEN)
1299 return dlopen(name, flags);
1300 #else
1301 return NULL;
1302 #endif
1305 void *sys_dlsym(void *handle, const char *symbol)
1307 #if defined(HAVE_DLSYM)
1308 return dlsym(handle, symbol);
1309 #else
1310 return NULL;
1311 #endif
1314 int sys_dlclose (void *handle)
1316 #if defined(HAVE_DLCLOSE)
1317 return dlclose(handle);
1318 #else
1319 return 0;
1320 #endif
1323 const char *sys_dlerror(void)
1325 #if defined(HAVE_DLERROR)
1326 return dlerror();
1327 #else
1328 return NULL;
1329 #endif
1332 int sys_dup2(int oldfd, int newfd)
1334 #if defined(HAVE_DUP2)
1335 return dup2(oldfd, newfd);
1336 #else
1337 errno = ENOSYS;
1338 return -1;
1339 #endif
1342 /**************************************************************************
1343 Wrapper for Admin Logs.
1344 ****************************************************************************/
1346 void sys_adminlog(int priority, const char *format_str, ...)
1348 va_list ap;
1349 int ret;
1350 char *msgbuf = NULL;
1352 va_start( ap, format_str );
1353 ret = vasprintf( &msgbuf, format_str, ap );
1354 va_end( ap );
1356 if (ret == -1)
1357 return;
1359 #if defined(HAVE_SYSLOG)
1360 syslog( priority, "%s", msgbuf );
1361 #else
1362 DEBUG(0,("%s", msgbuf ));
1363 #endif
1364 SAFE_FREE(msgbuf);
1367 /**************************************************************************
1368 Wrappers for extented attribute calls. Based on the Linux package with
1369 support for IRIX also. Expand as other systems have them.
1370 ****************************************************************************/
1372 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1374 #if defined(HAVE_GETXATTR)
1375 return getxattr(path, name, value, size);
1376 #elif defined(HAVE_EXTATTR_GET_FILE)
1377 char *s;
1378 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1379 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1380 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1382 return extattr_get_file(path, attrnamespace, attrname, value, size);
1383 #elif defined(HAVE_ATTR_GET)
1384 int retval, flags = 0;
1385 int valuelength = (int)size;
1386 char *attrname = strchr(name,'.') + 1;
1388 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1390 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1392 return retval ? retval : valuelength;
1393 #else
1394 errno = ENOSYS;
1395 return -1;
1396 #endif
1399 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1401 #if defined(HAVE_LGETXATTR)
1402 return lgetxattr(path, name, value, size);
1403 #elif defined(HAVE_EXTATTR_GET_LINK)
1404 char *s;
1405 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1406 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1407 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1409 return extattr_get_link(path, attrnamespace, attrname, value, size);
1410 #elif defined(HAVE_ATTR_GET)
1411 int retval, flags = ATTR_DONTFOLLOW;
1412 int valuelength = (int)size;
1413 char *attrname = strchr(name,'.') + 1;
1415 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1417 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1419 return retval ? retval : valuelength;
1420 #else
1421 errno = ENOSYS;
1422 return -1;
1423 #endif
1426 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1428 #if defined(HAVE_FGETXATTR)
1429 return fgetxattr(filedes, name, value, size);
1430 #elif defined(HAVE_EXTATTR_GET_FD)
1431 char *s;
1432 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1433 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1434 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1436 return extattr_get_fd(filedes, attrnamespace, attrname, value, size);
1437 #elif defined(HAVE_ATTR_GETF)
1438 int retval, flags = 0;
1439 int valuelength = (int)size;
1440 char *attrname = strchr(name,'.') + 1;
1442 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1444 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1446 return retval ? retval : valuelength;
1447 #else
1448 errno = ENOSYS;
1449 return -1;
1450 #endif
1453 #if defined(HAVE_EXTATTR_LIST_FILE)
1455 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1457 static struct {
1458 int space;
1459 const char *name;
1460 size_t len;
1462 extattr[] = {
1463 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1464 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1467 typedef union {
1468 const char *path;
1469 int filedes;
1470 } extattr_arg;
1472 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1474 ssize_t list_size, total_size = 0;
1475 int i, t, len;
1476 char *buf;
1477 /* Iterate through extattr(2) namespaces */
1478 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1479 switch(type) {
1480 #if defined(HAVE_EXTATTR_LIST_FILE)
1481 case 0:
1482 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1483 break;
1484 #endif
1485 #if defined(HAVE_EXTATTR_LIST_LINK)
1486 case 1:
1487 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1488 break;
1489 #endif
1490 #if defined(HAVE_EXTATTR_LIST_FD)
1491 case 2:
1492 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1493 break;
1494 #endif
1495 default:
1496 errno = ENOSYS;
1497 return -1;
1499 /* Some error happend. Errno should be set by the previous call */
1500 if(list_size < 0)
1501 return -1;
1502 /* No attributes */
1503 if(list_size == 0)
1504 continue;
1505 /* XXX: Call with an empty buffer may be used to calculate
1506 necessary buffer size. Unfortunately, we can't say, how
1507 many attributes were returned, so here is the potential
1508 problem with the emulation.
1510 if(list == NULL) {
1511 /* Take the worse case of one char attribute names -
1512 two bytes per name plus one more for sanity.
1514 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1515 continue;
1517 /* Count necessary offset to fit namespace prefixes */
1518 len = 0;
1519 for(i = 0; i < list_size; i += list[i] + 1)
1520 len += extattr[t].len;
1522 total_size += list_size + len;
1523 /* Buffer is too small to fit the results */
1524 if(total_size > size) {
1525 errno = ERANGE;
1526 return -1;
1528 /* Shift the results back, so we can prepend prefixes */
1529 buf = memmove(list + len, list, list_size);
1531 for(i = 0; i < list_size; i += len + 1) {
1532 len = buf[i];
1533 strncpy(list, extattr[t].name, extattr[t].len + 1);
1534 list += extattr[t].len;
1535 strncpy(list, buf + i + 1, len);
1536 list[len] = '\0';
1537 list += len + 1;
1539 size -= total_size;
1541 return total_size;
1544 #endif
1546 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1547 static char attr_buffer[ATTR_MAX_VALUELEN];
1549 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1551 int retval = 0, index;
1552 attrlist_cursor_t *cursor = 0;
1553 int total_size = 0;
1554 attrlist_t * al = (attrlist_t *)attr_buffer;
1555 attrlist_ent_t *ae;
1556 size_t ent_size, left = size;
1557 char *bp = list;
1559 while (True) {
1560 if (filedes)
1561 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1562 else
1563 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1564 if (retval) break;
1565 for (index = 0; index < al->al_count; index++) {
1566 ae = ATTR_ENTRY(attr_buffer, index);
1567 ent_size = strlen(ae->a_name) + sizeof("user.");
1568 if (left >= ent_size) {
1569 strncpy(bp, "user.", sizeof("user."));
1570 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1571 bp += ent_size;
1572 left -= ent_size;
1573 } else if (size) {
1574 errno = ERANGE;
1575 retval = -1;
1576 break;
1578 total_size += ent_size;
1580 if (al->al_more == 0) break;
1582 if (retval == 0) {
1583 flags |= ATTR_ROOT;
1584 cursor = 0;
1585 while (True) {
1586 if (filedes)
1587 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1588 else
1589 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1590 if (retval) break;
1591 for (index = 0; index < al->al_count; index++) {
1592 ae = ATTR_ENTRY(attr_buffer, index);
1593 ent_size = strlen(ae->a_name) + sizeof("system.");
1594 if (left >= ent_size) {
1595 strncpy(bp, "system.", sizeof("system."));
1596 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1597 bp += ent_size;
1598 left -= ent_size;
1599 } else if (size) {
1600 errno = ERANGE;
1601 retval = -1;
1602 break;
1604 total_size += ent_size;
1606 if (al->al_more == 0) break;
1609 return (ssize_t)(retval ? retval : total_size);
1612 #endif
1614 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1616 #if defined(HAVE_LISTXATTR)
1617 return listxattr(path, list, size);
1618 #elif defined(HAVE_EXTATTR_LIST_FILE)
1619 extattr_arg arg;
1620 arg.path = path;
1621 return bsd_attr_list(0, arg, list, size);
1622 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1623 return irix_attr_list(path, 0, list, size, 0);
1624 #else
1625 errno = ENOSYS;
1626 return -1;
1627 #endif
1630 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1632 #if defined(HAVE_LLISTXATTR)
1633 return llistxattr(path, list, size);
1634 #elif defined(HAVE_EXTATTR_LIST_LINK)
1635 extattr_arg arg;
1636 arg.path = path;
1637 return bsd_attr_list(1, arg, list, size);
1638 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1639 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1640 #else
1641 errno = ENOSYS;
1642 return -1;
1643 #endif
1646 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1648 #if defined(HAVE_FLISTXATTR)
1649 return flistxattr(filedes, list, size);
1650 #elif defined(HAVE_EXTATTR_LIST_FD)
1651 extattr_arg arg;
1652 arg.filedes = filedes;
1653 return bsd_attr_list(2, arg, list, size);
1654 #elif defined(HAVE_ATTR_LISTF)
1655 return irix_attr_list(NULL, filedes, list, size, 0);
1656 #else
1657 errno = ENOSYS;
1658 return -1;
1659 #endif
1662 int sys_removexattr (const char *path, const char *name)
1664 #if defined(HAVE_REMOVEXATTR)
1665 return removexattr(path, name);
1666 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1667 char *s;
1668 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1669 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1670 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1672 return extattr_delete_file(path, attrnamespace, attrname);
1673 #elif defined(HAVE_ATTR_REMOVE)
1674 int flags = 0;
1675 char *attrname = strchr(name,'.') + 1;
1677 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1679 return attr_remove(path, attrname, flags);
1680 #else
1681 errno = ENOSYS;
1682 return -1;
1683 #endif
1686 int sys_lremovexattr (const char *path, const char *name)
1688 #if defined(HAVE_LREMOVEXATTR)
1689 return lremovexattr(path, name);
1690 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1691 char *s;
1692 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1693 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1694 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1696 return extattr_delete_link(path, attrnamespace, attrname);
1697 #elif defined(HAVE_ATTR_REMOVE)
1698 int flags = ATTR_DONTFOLLOW;
1699 char *attrname = strchr(name,'.') + 1;
1701 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1703 return attr_remove(path, attrname, flags);
1704 #else
1705 errno = ENOSYS;
1706 return -1;
1707 #endif
1710 int sys_fremovexattr (int filedes, const char *name)
1712 #if defined(HAVE_FREMOVEXATTR)
1713 return fremovexattr(filedes, name);
1714 #elif defined(HAVE_EXTATTR_DELETE_FD)
1715 char *s;
1716 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1717 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1718 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1720 return extattr_delete_fd(filedes, attrnamespace, attrname);
1721 #elif defined(HAVE_ATTR_REMOVEF)
1722 int flags = 0;
1723 char *attrname = strchr(name,'.') + 1;
1725 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1727 return attr_removef(filedes, attrname, flags);
1728 #else
1729 errno = ENOSYS;
1730 return -1;
1731 #endif
1734 #if !defined(HAVE_SETXATTR)
1735 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1736 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1737 #endif
1739 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1741 #if defined(HAVE_SETXATTR)
1742 return setxattr(path, name, value, size, flags);
1743 #elif defined(HAVE_EXTATTR_SET_FILE)
1744 char *s;
1745 int retval = 0;
1746 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1747 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1748 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1750 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1751 return (retval < 0) ? -1 : 0;
1752 #elif defined(HAVE_ATTR_SET)
1753 int myflags = 0;
1754 char *attrname = strchr(name,'.') + 1;
1756 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1757 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1758 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1760 return attr_set(path, attrname, (const char *)value, size, myflags);
1761 #else
1762 errno = ENOSYS;
1763 return -1;
1764 #endif
1767 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1769 #if defined(HAVE_LSETXATTR)
1770 return lsetxattr(path, name, value, size, flags);
1771 #elif defined(HAVE_EXTATTR_SET_LINK)
1772 char *s;
1773 int retval = 0;
1774 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1775 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1776 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1778 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1779 return (retval < 0) ? -1 : 0;
1780 #elif defined(HAVE_ATTR_SET)
1781 int myflags = ATTR_DONTFOLLOW;
1782 char *attrname = strchr(name,'.') + 1;
1784 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1785 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1786 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1788 return attr_set(path, attrname, (const char *)value, size, myflags);
1789 #else
1790 errno = ENOSYS;
1791 return -1;
1792 #endif
1795 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1797 #if defined(HAVE_FSETXATTR)
1798 return fsetxattr(filedes, name, value, size, flags);
1799 #elif defined(HAVE_EXTATTR_SET_FD)
1800 char *s;
1801 int retval = 0;
1802 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1803 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1804 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1806 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1807 return (retval < 0) ? -1 : 0;
1808 #elif defined(HAVE_ATTR_SETF)
1809 int myflags = 0;
1810 char *attrname = strchr(name,'.') + 1;
1812 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1813 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1814 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1816 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1817 #else
1818 errno = ENOSYS;
1819 return -1;
1820 #endif
1823 /****************************************************************************
1824 Return the major devicenumber for UNIX extensions.
1825 ****************************************************************************/
1827 uint32 unix_dev_major(SMB_DEV_T dev)
1829 #if defined(HAVE_DEVICE_MAJOR_FN)
1830 return (uint32)major(dev);
1831 #else
1832 return (uint32)(dev >> 8);
1833 #endif
1836 /****************************************************************************
1837 Return the minor devicenumber for UNIX extensions.
1838 ****************************************************************************/
1840 uint32 unix_dev_minor(SMB_DEV_T dev)
1842 #if defined(HAVE_DEVICE_MINOR_FN)
1843 return (uint32)minor(dev);
1844 #else
1845 return (uint32)(dev & 0xff);
1846 #endif