r13676: have to return a value from a non-void function
[Samba.git] / source / lib / system.c
blobf38001cb7bdf4704bf4d27c5300ec0c9809f59e0
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2005
6 Copyright (C) Timur Bakeyev 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
26 The idea is that this file will eventually have wrappers around all
27 important system calls in samba. The aims are:
29 - to enable easier porting by putting OS dependent stuff in here
31 - to allow for hooks into other "pseudo-filesystems"
33 - to allow easier integration of things like the japanese extensions
35 - to support the philosophy of Samba to expose the features of
36 the OS within the SMB model. In general whatever file/printer/variable
37 expansions/etc make sense to the OS should be acceptable to Samba.
42 /*******************************************************************
43 A wrapper for usleep in case we don't have one.
44 ********************************************************************/
46 int sys_usleep(long usecs)
48 #ifndef HAVE_USLEEP
49 struct timeval tval;
50 #endif
53 * We need this braindamage as the glibc usleep
54 * is not SPEC1170 complient... grumble... JRA.
57 if(usecs < 0 || usecs > 1000000) {
58 errno = EINVAL;
59 return -1;
62 #if HAVE_USLEEP
63 usleep(usecs);
64 return 0;
65 #else /* HAVE_USLEEP */
67 * Fake it with select...
69 tval.tv_sec = 0;
70 tval.tv_usec = usecs/1000;
71 select(0,NULL,NULL,NULL,&tval);
72 return 0;
73 #endif /* HAVE_USLEEP */
76 /*******************************************************************
77 A read wrapper that will deal with EINTR.
78 ********************************************************************/
80 ssize_t sys_read(int fd, void *buf, size_t count)
82 ssize_t ret;
84 do {
85 ret = read(fd, buf, count);
86 } while (ret == -1 && errno == EINTR);
87 return ret;
90 /*******************************************************************
91 A write wrapper that will deal with EINTR.
92 ********************************************************************/
94 ssize_t sys_write(int fd, const void *buf, size_t count)
96 ssize_t ret;
98 do {
99 ret = write(fd, buf, count);
100 } while (ret == -1 && errno == EINTR);
101 return ret;
105 /*******************************************************************
106 A pread wrapper that will deal with EINTR and 64-bit file offsets.
107 ********************************************************************/
109 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
110 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
112 ssize_t ret;
114 do {
115 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
116 ret = pread64(fd, buf, count, off);
117 #else
118 ret = pread(fd, buf, count, off);
119 #endif
120 } while (ret == -1 && errno == EINTR);
121 return ret;
123 #endif
125 /*******************************************************************
126 A write wrapper that will deal with EINTR and 64-bit file offsets.
127 ********************************************************************/
129 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
130 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
132 ssize_t ret;
134 do {
135 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
136 ret = pwrite64(fd, buf, count, off);
137 #else
138 ret = pwrite(fd, buf, count, off);
139 #endif
140 } while (ret == -1 && errno == EINTR);
141 return ret;
143 #endif
145 /*******************************************************************
146 A send wrapper that will deal with EINTR.
147 ********************************************************************/
149 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
151 ssize_t ret;
153 do {
154 ret = send(s, msg, len, flags);
155 } while (ret == -1 && errno == EINTR);
156 return ret;
159 /*******************************************************************
160 A sendto wrapper that will deal with EINTR.
161 ********************************************************************/
163 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
165 ssize_t ret;
167 do {
168 ret = sendto(s, msg, len, flags, to, tolen);
169 } while (ret == -1 && errno == EINTR);
170 return ret;
173 /*******************************************************************
174 A recvfrom wrapper that will deal with EINTR.
175 ********************************************************************/
177 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
179 ssize_t ret;
181 do {
182 ret = recvfrom(s, buf, len, flags, from, fromlen);
183 } while (ret == -1 && errno == EINTR);
184 return ret;
187 /*******************************************************************
188 A fcntl wrapper that will deal with EINTR.
189 ********************************************************************/
191 int sys_fcntl_ptr(int fd, int cmd, void *arg)
193 int ret;
195 do {
196 ret = fcntl(fd, cmd, arg);
197 } while (ret == -1 && errno == EINTR);
198 return ret;
201 /*******************************************************************
202 A fcntl wrapper that will deal with EINTR.
203 ********************************************************************/
205 int sys_fcntl_long(int fd, int cmd, long arg)
207 int ret;
209 do {
210 ret = fcntl(fd, cmd, arg);
211 } while (ret == -1 && errno == EINTR);
212 return ret;
215 /*******************************************************************
216 A stat() wrapper that will deal with 64 bit filesizes.
217 ********************************************************************/
219 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
221 int ret;
222 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
223 ret = stat64(fname, sbuf);
224 #else
225 ret = stat(fname, sbuf);
226 #endif
227 /* we always want directories to appear zero size */
228 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
229 return ret;
232 /*******************************************************************
233 An fstat() wrapper that will deal with 64 bit filesizes.
234 ********************************************************************/
236 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
238 int ret;
239 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
240 ret = fstat64(fd, sbuf);
241 #else
242 ret = fstat(fd, sbuf);
243 #endif
244 /* we always want directories to appear zero size */
245 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
246 return ret;
249 /*******************************************************************
250 An lstat() wrapper that will deal with 64 bit filesizes.
251 ********************************************************************/
253 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
255 int ret;
256 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
257 ret = lstat64(fname, sbuf);
258 #else
259 ret = lstat(fname, sbuf);
260 #endif
261 /* we always want directories to appear zero size */
262 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
263 return ret;
266 /*******************************************************************
267 An ftruncate() wrapper that will deal with 64 bit filesizes.
268 ********************************************************************/
270 int sys_ftruncate(int fd, SMB_OFF_T offset)
272 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
273 return ftruncate64(fd, offset);
274 #else
275 return ftruncate(fd, offset);
276 #endif
279 /*******************************************************************
280 An lseek() wrapper that will deal with 64 bit filesizes.
281 ********************************************************************/
283 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
285 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
286 return lseek64(fd, offset, whence);
287 #else
288 return lseek(fd, offset, whence);
289 #endif
292 /*******************************************************************
293 An fseek() wrapper that will deal with 64 bit filesizes.
294 ********************************************************************/
296 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
298 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
299 return fseek64(fp, offset, whence);
300 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
301 return fseeko64(fp, offset, whence);
302 #else
303 return fseek(fp, offset, whence);
304 #endif
307 /*******************************************************************
308 An ftell() wrapper that will deal with 64 bit filesizes.
309 ********************************************************************/
311 SMB_OFF_T sys_ftell(FILE *fp)
313 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
314 return (SMB_OFF_T)ftell64(fp);
315 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
316 return (SMB_OFF_T)ftello64(fp);
317 #else
318 return (SMB_OFF_T)ftell(fp);
319 #endif
322 /*******************************************************************
323 A creat() wrapper that will deal with 64 bit filesizes.
324 ********************************************************************/
326 int sys_creat(const char *path, mode_t mode)
328 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
329 return creat64(path, mode);
330 #else
332 * If creat64 isn't defined then ensure we call a potential open64.
333 * JRA.
335 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
336 #endif
339 /*******************************************************************
340 An open() wrapper that will deal with 64 bit filesizes.
341 ********************************************************************/
343 int sys_open(const char *path, int oflag, mode_t mode)
345 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
346 return open64(path, oflag, mode);
347 #else
348 return open(path, oflag, mode);
349 #endif
352 /*******************************************************************
353 An fopen() wrapper that will deal with 64 bit filesizes.
354 ********************************************************************/
356 FILE *sys_fopen(const char *path, const char *type)
358 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
359 return fopen64(path, type);
360 #else
361 return fopen(path, type);
362 #endif
365 /*******************************************************************
366 An opendir wrapper that will deal with 64 bit filesizes.
367 ********************************************************************/
369 SMB_STRUCT_DIR *sys_opendir(const char *name)
371 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
372 return opendir64(name);
373 #else
374 return opendir(name);
375 #endif
378 /*******************************************************************
379 A readdir wrapper that will deal with 64 bit filesizes.
380 ********************************************************************/
382 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
384 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
385 return readdir64(dirp);
386 #else
387 return readdir(dirp);
388 #endif
391 /*******************************************************************
392 A seekdir wrapper that will deal with 64 bit filesizes.
393 ********************************************************************/
395 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
397 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
398 seekdir64(dirp, offset);
399 #else
400 seekdir(dirp, offset);
401 #endif
404 /*******************************************************************
405 A telldir wrapper that will deal with 64 bit filesizes.
406 ********************************************************************/
408 long sys_telldir(SMB_STRUCT_DIR *dirp)
410 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
411 return (long)telldir64(dirp);
412 #else
413 return (long)telldir(dirp);
414 #endif
417 /*******************************************************************
418 A rewinddir wrapper that will deal with 64 bit filesizes.
419 ********************************************************************/
421 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
423 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
424 rewinddir64(dirp);
425 #else
426 rewinddir(dirp);
427 #endif
430 /*******************************************************************
431 A close wrapper that will deal with 64 bit filesizes.
432 ********************************************************************/
434 int sys_closedir(SMB_STRUCT_DIR *dirp)
436 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
437 return closedir64(dirp);
438 #else
439 return closedir(dirp);
440 #endif
443 /*******************************************************************
444 An mknod() wrapper that will deal with 64 bit filesizes.
445 ********************************************************************/
447 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
449 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
450 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
451 return mknod64(path, mode, dev);
452 #else
453 return mknod(path, mode, dev);
454 #endif
455 #else
456 /* No mknod system call. */
457 errno = ENOSYS;
458 return -1;
459 #endif
462 /*******************************************************************
463 Wrapper for realpath.
464 ********************************************************************/
466 char *sys_realpath(const char *path, char *resolved_path)
468 #if defined(HAVE_REALPATH)
469 return realpath(path, resolved_path);
470 #else
471 /* As realpath is not a system call we can't return ENOSYS. */
472 errno = EINVAL;
473 return NULL;
474 #endif
477 /*******************************************************************
478 The wait() calls vary between systems
479 ********************************************************************/
481 int sys_waitpid(pid_t pid,int *status,int options)
483 #ifdef HAVE_WAITPID
484 return waitpid(pid,status,options);
485 #else /* HAVE_WAITPID */
486 return wait4(pid, status, options, NULL);
487 #endif /* HAVE_WAITPID */
490 /*******************************************************************
491 System wrapper for getwd
492 ********************************************************************/
494 char *sys_getwd(char *s)
496 char *wd;
497 #ifdef HAVE_GETCWD
498 wd = (char *)getcwd(s, sizeof (pstring));
499 #else
500 wd = (char *)getwd(s);
501 #endif
502 return wd;
505 /*******************************************************************
506 system wrapper for symlink
507 ********************************************************************/
509 int sys_symlink(const char *oldpath, const char *newpath)
511 #ifndef HAVE_SYMLINK
512 errno = ENOSYS;
513 return -1;
514 #else
515 return symlink(oldpath, newpath);
516 #endif
519 /*******************************************************************
520 system wrapper for readlink
521 ********************************************************************/
523 int sys_readlink(const char *path, char *buf, size_t bufsiz)
525 #ifndef HAVE_READLINK
526 errno = ENOSYS;
527 return -1;
528 #else
529 return readlink(path, buf, bufsiz);
530 #endif
533 /*******************************************************************
534 system wrapper for link
535 ********************************************************************/
537 int sys_link(const char *oldpath, const char *newpath)
539 #ifndef HAVE_LINK
540 errno = ENOSYS;
541 return -1;
542 #else
543 return link(oldpath, newpath);
544 #endif
547 /*******************************************************************
548 chown isn't used much but OS/2 doesn't have it
549 ********************************************************************/
551 int sys_chown(const char *fname,uid_t uid,gid_t gid)
553 #ifndef HAVE_CHOWN
554 static int done;
555 if (!done) {
556 DEBUG(1,("WARNING: no chown!\n"));
557 done=1;
559 errno = ENOSYS;
560 return -1;
561 #else
562 return(chown(fname,uid,gid));
563 #endif
566 /*******************************************************************
567 os/2 also doesn't have chroot
568 ********************************************************************/
569 int sys_chroot(const char *dname)
571 #ifndef HAVE_CHROOT
572 static int done;
573 if (!done) {
574 DEBUG(1,("WARNING: no chroot!\n"));
575 done=1;
577 errno = ENOSYS;
578 return -1;
579 #else
580 return(chroot(dname));
581 #endif
584 /**************************************************************************
585 A wrapper for gethostbyname() that tries avoids looking up hostnames
586 in the root domain, which can cause dial-on-demand links to come up for no
587 apparent reason.
588 ****************************************************************************/
590 struct hostent *sys_gethostbyname(const char *name)
592 #ifdef REDUCE_ROOT_DNS_LOOKUPS
593 char query[256], hostname[256];
594 char *domain;
596 /* Does this name have any dots in it? If so, make no change */
598 if (strchr_m(name, '.'))
599 return(gethostbyname(name));
601 /* Get my hostname, which should have domain name
602 attached. If not, just do the gethostname on the
603 original string.
606 gethostname(hostname, sizeof(hostname) - 1);
607 hostname[sizeof(hostname) - 1] = 0;
608 if ((domain = strchr_m(hostname, '.')) == NULL)
609 return(gethostbyname(name));
611 /* Attach domain name to query and do modified query.
612 If names too large, just do gethostname on the
613 original string.
616 if((strlen(name) + strlen(domain)) >= sizeof(query))
617 return(gethostbyname(name));
619 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
620 return(gethostbyname(query));
621 #else /* REDUCE_ROOT_DNS_LOOKUPS */
622 return(gethostbyname(name));
623 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
627 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
628 /**************************************************************************
629 Try and abstract process capabilities (for systems that have them).
630 ****************************************************************************/
631 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
633 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
634 cap_t cap = cap_get_proc();
636 if (cap == NULL) {
637 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
638 strerror(errno)));
639 return False;
642 if(enable)
643 cap->cap_effective |= CAP_NETWORK_MGT;
644 else
645 cap->cap_effective &= ~CAP_NETWORK_MGT;
647 if (cap_set_proc(cap) == -1) {
648 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
649 strerror(errno)));
650 cap_free(cap);
651 return False;
654 cap_free(cap);
656 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
658 return True;
661 /**************************************************************************
662 Try and abstract inherited process capabilities (for systems that have them).
663 ****************************************************************************/
665 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
667 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
668 cap_t cap = cap_get_proc();
670 if (cap == NULL) {
671 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
672 strerror(errno)));
673 return False;
676 if(enable)
677 cap->cap_inheritable |= CAP_NETWORK_MGT;
678 else
679 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
681 if (cap_set_proc(cap) == -1) {
682 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
683 strerror(errno)));
684 cap_free(cap);
685 return False;
688 cap_free(cap);
690 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
692 return True;
694 #endif
696 /****************************************************************************
697 Gain the oplock capability from the kernel if possible.
698 ****************************************************************************/
700 void oplock_set_capability(BOOL this_process, BOOL inherit)
702 #if HAVE_KERNEL_OPLOCKS_IRIX
703 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
704 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
705 #endif
708 /**************************************************************************
709 Wrapper for random().
710 ****************************************************************************/
712 long sys_random(void)
714 #if defined(HAVE_RANDOM)
715 return (long)random();
716 #elif defined(HAVE_RAND)
717 return (long)rand();
718 #else
719 DEBUG(0,("Error - no random function available !\n"));
720 exit(1);
721 #endif
724 /**************************************************************************
725 Wrapper for srandom().
726 ****************************************************************************/
728 void sys_srandom(unsigned int seed)
730 #if defined(HAVE_SRANDOM)
731 srandom(seed);
732 #elif defined(HAVE_SRAND)
733 srand(seed);
734 #else
735 DEBUG(0,("Error - no srandom function available !\n"));
736 exit(1);
737 #endif
740 /**************************************************************************
741 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
742 ****************************************************************************/
744 int groups_max(void)
746 #if defined(SYSCONF_SC_NGROUPS_MAX)
747 int ret = sysconf(_SC_NGROUPS_MAX);
748 return (ret == -1) ? NGROUPS_MAX : ret;
749 #else
750 return NGROUPS_MAX;
751 #endif
754 /**************************************************************************
755 Wrapper for getgroups. Deals with broken (int) case.
756 ****************************************************************************/
758 int sys_getgroups(int setlen, gid_t *gidset)
760 #if !defined(HAVE_BROKEN_GETGROUPS)
761 return getgroups(setlen, gidset);
762 #else
764 GID_T gid;
765 GID_T *group_list;
766 int i, ngroups;
768 if(setlen == 0) {
769 return getgroups(setlen, &gid);
773 * Broken case. We need to allocate a
774 * GID_T array of size setlen.
777 if(setlen < 0) {
778 errno = EINVAL;
779 return -1;
782 if (setlen == 0)
783 setlen = groups_max();
785 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
786 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
787 return -1;
790 if((ngroups = getgroups(setlen, group_list)) < 0) {
791 int saved_errno = errno;
792 SAFE_FREE(group_list);
793 errno = saved_errno;
794 return -1;
797 for(i = 0; i < ngroups; i++)
798 gidset[i] = (gid_t)group_list[i];
800 SAFE_FREE(group_list);
801 return ngroups;
802 #endif /* HAVE_BROKEN_GETGROUPS */
806 /**************************************************************************
807 Wrapper for setgroups. Deals with broken (int) case. Automatically used
808 if we have broken getgroups.
809 ****************************************************************************/
811 int sys_setgroups(int setlen, gid_t *gidset)
813 #if !defined(HAVE_SETGROUPS)
814 errno = ENOSYS;
815 return -1;
816 #endif /* HAVE_SETGROUPS */
818 #if !defined(HAVE_BROKEN_GETGROUPS)
819 return setgroups(setlen, gidset);
820 #else
822 GID_T *group_list;
823 int i ;
825 if (setlen == 0)
826 return 0 ;
828 if (setlen < 0 || setlen > groups_max()) {
829 errno = EINVAL;
830 return -1;
834 * Broken case. We need to allocate a
835 * GID_T array of size setlen.
838 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
839 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
840 return -1;
843 for(i = 0; i < setlen; i++)
844 group_list[i] = (GID_T) gidset[i];
846 if(setgroups(setlen, group_list) != 0) {
847 int saved_errno = errno;
848 SAFE_FREE(group_list);
849 errno = saved_errno;
850 return -1;
853 SAFE_FREE(group_list);
854 return 0 ;
855 #endif /* HAVE_BROKEN_GETGROUPS */
858 /**************************************************************************
859 Wrappers for setpwent(), getpwent() and endpwent()
860 ****************************************************************************/
862 void sys_setpwent(void)
864 setpwent();
867 struct passwd *sys_getpwent(void)
869 return getpwent();
872 void sys_endpwent(void)
874 endpwent();
877 /**************************************************************************
878 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
879 ****************************************************************************/
881 struct passwd *sys_getpwnam(const char *name)
883 return getpwnam(name);
886 struct passwd *sys_getpwuid(uid_t uid)
888 return getpwuid(uid);
891 struct group *sys_getgrnam(const char *name)
893 return getgrnam(name);
896 struct group *sys_getgrgid(gid_t gid)
898 return getgrgid(gid);
901 #if 0 /* NOT CURRENTLY USED - JRA */
902 /**************************************************************************
903 The following are the UNICODE versions of *all* system interface functions
904 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
905 which currently are left as ascii as they are not used other than in name
906 resolution.
907 ****************************************************************************/
909 /**************************************************************************
910 Wide stat. Just narrow and call sys_xxx.
911 ****************************************************************************/
913 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
915 pstring fname;
916 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
919 /**************************************************************************
920 Wide lstat. Just narrow and call sys_xxx.
921 ****************************************************************************/
923 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
925 pstring fname;
926 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
929 /**************************************************************************
930 Wide creat. Just narrow and call sys_xxx.
931 ****************************************************************************/
933 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
935 pstring fname;
936 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
939 /**************************************************************************
940 Wide open. Just narrow and call sys_xxx.
941 ****************************************************************************/
943 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
945 pstring fname;
946 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
949 /**************************************************************************
950 Wide fopen. Just narrow and call sys_xxx.
951 ****************************************************************************/
953 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
955 pstring fname;
956 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
959 /**************************************************************************
960 Wide opendir. Just narrow and call sys_xxx.
961 ****************************************************************************/
963 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
965 pstring fname;
966 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
969 /**************************************************************************
970 Wide readdir. Return a structure pointer containing a wide filename.
971 ****************************************************************************/
973 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
975 static SMB_STRUCT_WDIRENT retval;
976 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
978 if(!dirval)
979 return NULL;
982 * The only POSIX defined member of this struct is d_name.
985 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
987 return &retval;
990 /**************************************************************************
991 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
992 ****************************************************************************/
994 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
996 pstring fname;
997 char *p = sys_getwd(fname);
999 if(!p)
1000 return NULL;
1002 return unix_to_unicode(s, p, sizeof(wpstring));
1005 /**************************************************************************
1006 Wide chown. Just narrow and call sys_xxx.
1007 ****************************************************************************/
1009 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1011 pstring fname;
1012 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1015 /**************************************************************************
1016 Wide chroot. Just narrow and call sys_xxx.
1017 ****************************************************************************/
1019 int wsys_chroot(const smb_ucs2_t *wfname)
1021 pstring fname;
1022 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1025 /**************************************************************************
1026 Wide getpwnam. Return a structure pointer containing wide names.
1027 ****************************************************************************/
1029 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1031 static SMB_STRUCT_WPASSWD retval;
1032 fstring name;
1033 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1035 if(!pwret)
1036 return NULL;
1038 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1039 retval.pw_passwd = pwret->pw_passwd;
1040 retval.pw_uid = pwret->pw_uid;
1041 retval.pw_gid = pwret->pw_gid;
1042 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1043 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1044 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1046 return &retval;
1049 /**************************************************************************
1050 Wide getpwuid. Return a structure pointer containing wide names.
1051 ****************************************************************************/
1053 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1055 static SMB_STRUCT_WPASSWD retval;
1056 struct passwd *pwret = sys_getpwuid(uid);
1058 if(!pwret)
1059 return NULL;
1061 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1062 retval.pw_passwd = pwret->pw_passwd;
1063 retval.pw_uid = pwret->pw_uid;
1064 retval.pw_gid = pwret->pw_gid;
1065 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1066 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1067 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1069 return &retval;
1071 #endif /* NOT CURRENTLY USED - JRA */
1073 /**************************************************************************
1074 Extract a command into an arg list. Uses a static pstring for storage.
1075 Caller frees returned arg list (which contains pointers into the static pstring).
1076 ****************************************************************************/
1078 static char **extract_args(const char *command)
1080 static pstring trunc_cmd;
1081 char *ptr;
1082 int argcl;
1083 char **argl = NULL;
1084 int i;
1086 pstrcpy(trunc_cmd, command);
1088 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1089 errno = EINVAL;
1090 return NULL;
1094 * Count the args.
1097 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1098 argcl++;
1100 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1101 return NULL;
1104 * Now do the extraction.
1107 pstrcpy(trunc_cmd, command);
1109 ptr = strtok(trunc_cmd, " \t");
1110 i = 0;
1111 argl[i++] = ptr;
1113 while((ptr = strtok(NULL, " \t")) != NULL)
1114 argl[i++] = ptr;
1116 argl[i++] = NULL;
1117 return argl;
1120 /**************************************************************************
1121 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1122 a sys_getpid() that only does a system call *once*.
1123 ****************************************************************************/
1125 static pid_t mypid = (pid_t)-1;
1127 pid_t sys_fork(void)
1129 pid_t forkret = fork();
1131 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1132 mypid = (pid_t) -1;
1134 return forkret;
1137 /**************************************************************************
1138 Wrapper for getpid. Ensures we only do a system call *once*.
1139 ****************************************************************************/
1141 pid_t sys_getpid(void)
1143 if (mypid == (pid_t)-1)
1144 mypid = getpid();
1146 return mypid;
1149 /**************************************************************************
1150 Wrapper for popen. Safer as it doesn't search a path.
1151 Modified from the glibc sources.
1152 modified by tridge to return a file descriptor. We must kick our FILE* habit
1153 ****************************************************************************/
1155 typedef struct _popen_list
1157 int fd;
1158 pid_t child_pid;
1159 struct _popen_list *next;
1160 } popen_list;
1162 static popen_list *popen_chain;
1164 int sys_popen(const char *command)
1166 int parent_end, child_end;
1167 int pipe_fds[2];
1168 popen_list *entry = NULL;
1169 char **argl = NULL;
1171 if (pipe(pipe_fds) < 0)
1172 return -1;
1174 parent_end = pipe_fds[0];
1175 child_end = pipe_fds[1];
1177 if (!*command) {
1178 errno = EINVAL;
1179 goto err_exit;
1182 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1183 goto err_exit;
1185 ZERO_STRUCTP(entry);
1188 * Extract the command and args into a NULL terminated array.
1191 if(!(argl = extract_args(command)))
1192 goto err_exit;
1194 entry->child_pid = sys_fork();
1196 if (entry->child_pid == -1) {
1197 goto err_exit;
1200 if (entry->child_pid == 0) {
1203 * Child !
1206 int child_std_end = STDOUT_FILENO;
1207 popen_list *p;
1209 close(parent_end);
1210 if (child_end != child_std_end) {
1211 dup2 (child_end, child_std_end);
1212 close (child_end);
1216 * POSIX.2: "popen() shall ensure that any streams from previous
1217 * popen() calls that remain open in the parent process are closed
1218 * in the new child process."
1221 for (p = popen_chain; p; p = p->next)
1222 close(p->fd);
1224 execv(argl[0], argl);
1225 _exit (127);
1229 * Parent.
1232 close (child_end);
1233 SAFE_FREE(argl);
1235 /* Link into popen_chain. */
1236 entry->next = popen_chain;
1237 popen_chain = entry;
1238 entry->fd = parent_end;
1240 return entry->fd;
1242 err_exit:
1244 SAFE_FREE(entry);
1245 SAFE_FREE(argl);
1246 close(pipe_fds[0]);
1247 close(pipe_fds[1]);
1248 return -1;
1251 /**************************************************************************
1252 Wrapper for pclose. Modified from the glibc sources.
1253 ****************************************************************************/
1255 int sys_pclose(int fd)
1257 int wstatus;
1258 popen_list **ptr = &popen_chain;
1259 popen_list *entry = NULL;
1260 pid_t wait_pid;
1261 int status = -1;
1263 /* Unlink from popen_chain. */
1264 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1265 if ((*ptr)->fd == fd) {
1266 entry = *ptr;
1267 *ptr = (*ptr)->next;
1268 status = 0;
1269 break;
1273 if (status < 0 || close(entry->fd) < 0)
1274 return -1;
1277 * As Samba is catching and eating child process
1278 * exits we don't really care about the child exit
1279 * code, a -1 with errno = ECHILD will do fine for us.
1282 do {
1283 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1284 } while (wait_pid == -1 && errno == EINTR);
1286 SAFE_FREE(entry);
1288 if (wait_pid == -1)
1289 return -1;
1290 return wstatus;
1293 /**************************************************************************
1294 Wrappers for dlopen, dlsym, dlclose.
1295 ****************************************************************************/
1297 void *sys_dlopen(const char *name, int flags)
1299 #if defined(HAVE_DLOPEN)
1300 return dlopen(name, flags);
1301 #else
1302 return NULL;
1303 #endif
1306 void *sys_dlsym(void *handle, const char *symbol)
1308 #if defined(HAVE_DLSYM)
1309 return dlsym(handle, symbol);
1310 #else
1311 return NULL;
1312 #endif
1315 int sys_dlclose (void *handle)
1317 #if defined(HAVE_DLCLOSE)
1318 return dlclose(handle);
1319 #else
1320 return 0;
1321 #endif
1324 const char *sys_dlerror(void)
1326 #if defined(HAVE_DLERROR)
1327 return dlerror();
1328 #else
1329 return NULL;
1330 #endif
1333 int sys_dup2(int oldfd, int newfd)
1335 #if defined(HAVE_DUP2)
1336 return dup2(oldfd, newfd);
1337 #else
1338 errno = ENOSYS;
1339 return -1;
1340 #endif
1343 /**************************************************************************
1344 Wrapper for Admin Logs.
1345 ****************************************************************************/
1347 void sys_adminlog(int priority, const char *format_str, ...)
1349 va_list ap;
1350 int ret;
1351 char *msgbuf = NULL;
1353 va_start( ap, format_str );
1354 ret = vasprintf( &msgbuf, format_str, ap );
1355 va_end( ap );
1357 if (ret == -1)
1358 return;
1360 #if defined(HAVE_SYSLOG)
1361 syslog( priority, "%s", msgbuf );
1362 #else
1363 DEBUG(0,("%s", msgbuf ));
1364 #endif
1365 SAFE_FREE(msgbuf);
1368 /**************************************************************************
1369 Wrappers for extented attribute calls. Based on the Linux package with
1370 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1371 ****************************************************************************/
1373 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1375 #if defined(HAVE_GETXATTR)
1376 return getxattr(path, name, value, size);
1377 #elif defined(HAVE_GETEA)
1378 return getea(path, name, value, size);
1379 #elif defined(HAVE_EXTATTR_GET_FILE)
1380 char *s;
1381 ssize_t retval;
1382 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1383 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1384 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1386 * The BSD implementation has a nasty habit of silently truncating
1387 * the returned value to the size of the buffer, so we have to check
1388 * that the buffer is large enough to fit the returned value.
1390 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1391 if(retval > size) {
1392 errno = ERANGE;
1393 return -1;
1395 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1396 return retval;
1399 DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1400 return -1;
1401 #elif defined(HAVE_ATTR_GET)
1402 int retval, flags = 0;
1403 int valuelength = (int)size;
1404 char *attrname = strchr(name,'.') + 1;
1406 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1408 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1410 return retval ? retval : valuelength;
1411 #else
1412 errno = ENOSYS;
1413 return -1;
1414 #endif
1417 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1419 #if defined(HAVE_LGETXATTR)
1420 return lgetxattr(path, name, value, size);
1421 #elif defined(HAVE_LGETEA)
1422 return lgetea(path, name, value, size);
1423 #elif defined(HAVE_EXTATTR_GET_LINK)
1424 char *s;
1425 ssize_t retval;
1426 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1427 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1428 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1430 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1431 if(retval > size) {
1432 errno = ERANGE;
1433 return -1;
1435 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1436 return retval;
1439 DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1440 return -1;
1441 #elif defined(HAVE_ATTR_GET)
1442 int retval, flags = ATTR_DONTFOLLOW;
1443 int valuelength = (int)size;
1444 char *attrname = strchr(name,'.') + 1;
1446 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1448 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1450 return retval ? retval : valuelength;
1451 #else
1452 errno = ENOSYS;
1453 return -1;
1454 #endif
1457 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1459 #if defined(HAVE_FGETXATTR)
1460 return fgetxattr(filedes, name, value, size);
1461 #elif defined(HAVE_FGETEA)
1462 return fgetea(filedes, name, value, size);
1463 #elif defined(HAVE_EXTATTR_GET_FD)
1464 char *s;
1465 ssize_t retval;
1466 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1467 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1468 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1470 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1471 if(retval > size) {
1472 errno = ERANGE;
1473 return -1;
1475 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1476 return retval;
1479 DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1480 return -1;
1481 #elif defined(HAVE_ATTR_GETF)
1482 int retval, flags = 0;
1483 int valuelength = (int)size;
1484 char *attrname = strchr(name,'.') + 1;
1486 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1488 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1490 return retval ? retval : valuelength;
1491 #else
1492 errno = ENOSYS;
1493 return -1;
1494 #endif
1497 #if defined(HAVE_EXTATTR_LIST_FILE)
1499 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
1501 static struct {
1502 int space;
1503 const char *name;
1504 size_t len;
1506 extattr[] = {
1507 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1508 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1511 typedef union {
1512 const char *path;
1513 int filedes;
1514 } extattr_arg;
1516 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
1518 ssize_t list_size, total_size = 0;
1519 int i, t, len;
1520 char *buf;
1521 /* Iterate through extattr(2) namespaces */
1522 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1523 switch(type) {
1524 #if defined(HAVE_EXTATTR_LIST_FILE)
1525 case 0:
1526 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1527 break;
1528 #endif
1529 #if defined(HAVE_EXTATTR_LIST_LINK)
1530 case 1:
1531 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1532 break;
1533 #endif
1534 #if defined(HAVE_EXTATTR_LIST_FD)
1535 case 2:
1536 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1537 break;
1538 #endif
1539 default:
1540 errno = ENOSYS;
1541 return -1;
1543 /* Some error happend. Errno should be set by the previous call */
1544 if(list_size < 0)
1545 return -1;
1546 /* No attributes */
1547 if(list_size == 0)
1548 continue;
1549 /* XXX: Call with an empty buffer may be used to calculate
1550 necessary buffer size. Unfortunately, we can't say, how
1551 many attributes were returned, so here is the potential
1552 problem with the emulation.
1554 if(list == NULL) {
1555 /* Take the worse case of one char attribute names -
1556 two bytes per name plus one more for sanity.
1558 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1559 continue;
1561 /* Count necessary offset to fit namespace prefixes */
1562 len = 0;
1563 for(i = 0; i < list_size; i += list[i] + 1)
1564 len += extattr[t].len;
1566 total_size += list_size + len;
1567 /* Buffer is too small to fit the results */
1568 if(total_size > size) {
1569 errno = ERANGE;
1570 return -1;
1572 /* Shift results back, so we can prepend prefixes */
1573 buf = memmove(list + len, list, list_size);
1575 for(i = 0; i < list_size; i += len + 1) {
1576 len = buf[i];
1577 strncpy(list, extattr[t].name, extattr[t].len + 1);
1578 list += extattr[t].len;
1579 strncpy(list, buf + i + 1, len);
1580 list[len] = '\0';
1581 list += len + 1;
1583 size -= total_size;
1585 return total_size;
1588 #endif
1590 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1591 static char attr_buffer[ATTR_MAX_VALUELEN];
1593 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1595 int retval = 0, index;
1596 attrlist_cursor_t *cursor = 0;
1597 int total_size = 0;
1598 attrlist_t * al = (attrlist_t *)attr_buffer;
1599 attrlist_ent_t *ae;
1600 size_t ent_size, left = size;
1601 char *bp = list;
1603 while (True) {
1604 if (filedes)
1605 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1606 else
1607 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1608 if (retval) break;
1609 for (index = 0; index < al->al_count; index++) {
1610 ae = ATTR_ENTRY(attr_buffer, index);
1611 ent_size = strlen(ae->a_name) + sizeof("user.");
1612 if (left >= ent_size) {
1613 strncpy(bp, "user.", sizeof("user."));
1614 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1615 bp += ent_size;
1616 left -= ent_size;
1617 } else if (size) {
1618 errno = ERANGE;
1619 retval = -1;
1620 break;
1622 total_size += ent_size;
1624 if (al->al_more == 0) break;
1626 if (retval == 0) {
1627 flags |= ATTR_ROOT;
1628 cursor = 0;
1629 while (True) {
1630 if (filedes)
1631 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1632 else
1633 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1634 if (retval) break;
1635 for (index = 0; index < al->al_count; index++) {
1636 ae = ATTR_ENTRY(attr_buffer, index);
1637 ent_size = strlen(ae->a_name) + sizeof("system.");
1638 if (left >= ent_size) {
1639 strncpy(bp, "system.", sizeof("system."));
1640 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1641 bp += ent_size;
1642 left -= ent_size;
1643 } else if (size) {
1644 errno = ERANGE;
1645 retval = -1;
1646 break;
1648 total_size += ent_size;
1650 if (al->al_more == 0) break;
1653 return (ssize_t)(retval ? retval : total_size);
1656 #endif
1658 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1660 #if defined(HAVE_LISTXATTR)
1661 return listxattr(path, list, size);
1662 #elif defined(HAVE_LISTEA)
1663 return listea(path, list, size);
1664 #elif defined(HAVE_EXTATTR_LIST_FILE)
1665 extattr_arg arg;
1666 arg.path = path;
1667 return bsd_attr_list(0, arg, list, size);
1668 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1669 return irix_attr_list(path, 0, list, size, 0);
1670 #else
1671 errno = ENOSYS;
1672 return -1;
1673 #endif
1676 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1678 #if defined(HAVE_LLISTXATTR)
1679 return llistxattr(path, list, size);
1680 #elif defined(HAVE_LLISTEA)
1681 return llistea(path, list, size);
1682 #elif defined(HAVE_EXTATTR_LIST_LINK)
1683 extattr_arg arg;
1684 arg.path = path;
1685 return bsd_attr_list(1, arg, list, size);
1686 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1687 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1688 #else
1689 errno = ENOSYS;
1690 return -1;
1691 #endif
1694 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1696 #if defined(HAVE_FLISTXATTR)
1697 return flistxattr(filedes, list, size);
1698 #elif defined(HAVE_FLISTEA)
1699 return flistea(filedes, list, size);
1700 #elif defined(HAVE_EXTATTR_LIST_FD)
1701 extattr_arg arg;
1702 arg.filedes = filedes;
1703 return bsd_attr_list(2, arg, list, size);
1704 #elif defined(HAVE_ATTR_LISTF)
1705 return irix_attr_list(NULL, filedes, list, size, 0);
1706 #else
1707 errno = ENOSYS;
1708 return -1;
1709 #endif
1712 int sys_removexattr (const char *path, const char *name)
1714 #if defined(HAVE_REMOVEXATTR)
1715 return removexattr(path, name);
1716 #elif defined(HAVE_REMOVEEA)
1717 return removeea(path, name);
1718 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1719 char *s;
1720 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1721 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1722 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1724 return extattr_delete_file(path, attrnamespace, attrname);
1725 #elif defined(HAVE_ATTR_REMOVE)
1726 int flags = 0;
1727 char *attrname = strchr(name,'.') + 1;
1729 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1731 return attr_remove(path, attrname, flags);
1732 #else
1733 errno = ENOSYS;
1734 return -1;
1735 #endif
1738 int sys_lremovexattr (const char *path, const char *name)
1740 #if defined(HAVE_LREMOVEXATTR)
1741 return lremovexattr(path, name);
1742 #elif defined(HAVE_LREMOVEEA)
1743 return lremoveea(path, name);
1744 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1745 char *s;
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 return extattr_delete_link(path, attrnamespace, attrname);
1751 #elif defined(HAVE_ATTR_REMOVE)
1752 int flags = ATTR_DONTFOLLOW;
1753 char *attrname = strchr(name,'.') + 1;
1755 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1757 return attr_remove(path, attrname, flags);
1758 #else
1759 errno = ENOSYS;
1760 return -1;
1761 #endif
1764 int sys_fremovexattr (int filedes, const char *name)
1766 #if defined(HAVE_FREMOVEXATTR)
1767 return fremovexattr(filedes, name);
1768 #elif defined(HAVE_FREMOVEEA)
1769 return fremoveea(filedes, name);
1770 #elif defined(HAVE_EXTATTR_DELETE_FD)
1771 char *s;
1772 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1773 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1774 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1776 return extattr_delete_fd(filedes, attrnamespace, attrname);
1777 #elif defined(HAVE_ATTR_REMOVEF)
1778 int flags = 0;
1779 char *attrname = strchr(name,'.') + 1;
1781 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1783 return attr_removef(filedes, attrname, flags);
1784 #else
1785 errno = ENOSYS;
1786 return -1;
1787 #endif
1790 #if !defined(HAVE_SETXATTR)
1791 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1792 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1793 #endif
1795 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1797 #if defined(HAVE_SETXATTR)
1798 return setxattr(path, name, value, size, flags);
1799 #elif defined(HAVE_SETEA)
1800 return setea(path, name, value, size, flags);
1801 #elif defined(HAVE_EXTATTR_SET_FILE)
1802 char *s;
1803 int retval = 0;
1804 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1805 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1806 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1807 if (flags) {
1808 /* Check attribute existence */
1809 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1810 if (retval < 0) {
1811 /* REPLACE attribute, that doesn't exist */
1812 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1813 errno = ENOATTR;
1814 return -1;
1816 /* Ignore other errors */
1818 else {
1819 /* CREATE attribute, that already exists */
1820 if (flags & XATTR_CREATE) {
1821 errno = EEXIST;
1822 return -1;
1826 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1827 return (retval < 0) ? -1 : 0;
1828 #elif defined(HAVE_ATTR_SET)
1829 int myflags = 0;
1830 char *attrname = strchr(name,'.') + 1;
1832 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1833 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1834 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1836 return attr_set(path, attrname, (const char *)value, size, myflags);
1837 #else
1838 errno = ENOSYS;
1839 return -1;
1840 #endif
1843 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1845 #if defined(HAVE_LSETXATTR)
1846 return lsetxattr(path, name, value, size, flags);
1847 #elif defined(LSETEA)
1848 return lsetea(path, name, value, size, flags);
1849 #elif defined(HAVE_EXTATTR_SET_LINK)
1850 char *s;
1851 int retval = 0;
1852 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1853 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1854 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1855 if (flags) {
1856 /* Check attribute existence */
1857 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1858 if (retval < 0) {
1859 /* REPLACE attribute, that doesn't exist */
1860 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1861 errno = ENOATTR;
1862 return -1;
1864 /* Ignore other errors */
1866 else {
1867 /* CREATE attribute, that already exists */
1868 if (flags & XATTR_CREATE) {
1869 errno = EEXIST;
1870 return -1;
1875 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1876 return (retval < 0) ? -1 : 0;
1877 #elif defined(HAVE_ATTR_SET)
1878 int myflags = ATTR_DONTFOLLOW;
1879 char *attrname = strchr(name,'.') + 1;
1881 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1882 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1883 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1885 return attr_set(path, attrname, (const char *)value, size, myflags);
1886 #else
1887 errno = ENOSYS;
1888 return -1;
1889 #endif
1892 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1894 #if defined(HAVE_FSETXATTR)
1895 return fsetxattr(filedes, name, value, size, flags);
1896 #elif defined(HAVE_FSETEA)
1897 return fsetea(filedes, name, value, size, flags);
1898 #elif defined(HAVE_EXTATTR_SET_FD)
1899 char *s;
1900 int retval = 0;
1901 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
1902 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1903 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1904 if (flags) {
1905 /* Check attribute existence */
1906 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1907 if (retval < 0) {
1908 /* REPLACE attribute, that doesn't exist */
1909 if (flags & XATTR_REPLACE && errno == ENOATTR) {
1910 errno = ENOATTR;
1911 return -1;
1913 /* Ignore other errors */
1915 else {
1916 /* CREATE attribute, that already exists */
1917 if (flags & XATTR_CREATE) {
1918 errno = EEXIST;
1919 return -1;
1923 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1924 return (retval < 0) ? -1 : 0;
1925 #elif defined(HAVE_ATTR_SETF)
1926 int myflags = 0;
1927 char *attrname = strchr(name,'.') + 1;
1929 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1930 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1931 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1933 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1934 #else
1935 errno = ENOSYS;
1936 return -1;
1937 #endif
1940 /****************************************************************************
1941 Return the major devicenumber for UNIX extensions.
1942 ****************************************************************************/
1944 uint32 unix_dev_major(SMB_DEV_T dev)
1946 #if defined(HAVE_DEVICE_MAJOR_FN)
1947 return (uint32)major(dev);
1948 #else
1949 return (uint32)(dev >> 8);
1950 #endif
1953 /****************************************************************************
1954 Return the minor devicenumber for UNIX extensions.
1955 ****************************************************************************/
1957 uint32 unix_dev_minor(SMB_DEV_T dev)
1959 #if defined(HAVE_DEVICE_MINOR_FN)
1960 return (uint32)minor(dev);
1961 #else
1962 return (uint32)(dev & 0xff);
1963 #endif
1966 #if defined(WITH_AIO)
1968 /*******************************************************************
1969 An aio_read wrapper that will deal with 64-bit sizes.
1970 ********************************************************************/
1972 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
1974 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
1975 return aio_read64(aiocb);
1976 #elif defined(HAVE_AIO_READ)
1977 return aio_read(aiocb);
1978 #else
1979 errno = ENOSYS;
1980 return -1;
1981 #endif
1984 /*******************************************************************
1985 An aio_write wrapper that will deal with 64-bit sizes.
1986 ********************************************************************/
1988 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
1990 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
1991 return aio_write64(aiocb);
1992 #elif defined(HAVE_AIO_WRITE)
1993 return aio_write(aiocb);
1994 #else
1995 errno = ENOSYS;
1996 return -1;
1997 #endif
2000 /*******************************************************************
2001 An aio_return wrapper that will deal with 64-bit sizes.
2002 ********************************************************************/
2004 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2006 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2007 return aio_return64(aiocb);
2008 #elif defined(HAVE_AIO_RETURN)
2009 return aio_return(aiocb);
2010 #else
2011 errno = ENOSYS;
2012 return -1;
2013 #endif
2016 /*******************************************************************
2017 An aio_cancel wrapper that will deal with 64-bit sizes.
2018 ********************************************************************/
2020 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2022 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2023 return aio_cancel64(fd, aiocb);
2024 #elif defined(HAVE_AIO_CANCEL)
2025 return aio_cancel(fd, aiocb);
2026 #else
2027 errno = ENOSYS;
2028 return -1;
2029 #endif
2032 /*******************************************************************
2033 An aio_error wrapper that will deal with 64-bit sizes.
2034 ********************************************************************/
2036 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2038 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2039 return aio_error64(aiocb);
2040 #elif defined(HAVE_AIO_ERROR)
2041 return aio_error(aiocb);
2042 #else
2043 errno = ENOSYS;
2044 return -1;
2045 #endif
2048 /*******************************************************************
2049 An aio_fsync wrapper that will deal with 64-bit sizes.
2050 ********************************************************************/
2052 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2054 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2055 return aio_fsync64(op, aiocb);
2056 #elif defined(HAVE_AIO_FSYNC)
2057 return aio_fsync(op, aiocb);
2058 #else
2059 errno = ENOSYS;
2060 return -1;
2061 #endif
2064 /*******************************************************************
2065 An aio_fsync wrapper that will deal with 64-bit sizes.
2066 ********************************************************************/
2068 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2070 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2071 return aio_suspend64(cblist, n, timeout);
2072 #elif defined(HAVE_AIO_FSYNC)
2073 return aio_suspend(cblist, n, timeout);
2074 #else
2075 errno = ENOSYS;
2076 return -1;
2077 #endif
2079 #else /* !WITH_AIO */
2081 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
2083 errno = ENOSYS;
2084 return -1;
2087 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
2089 errno = ENOSYS;
2090 return -1;
2093 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
2095 errno = ENOSYS;
2096 return -1;
2099 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
2101 errno = ENOSYS;
2102 return -1;
2105 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
2107 errno = ENOSYS;
2108 return -1;
2111 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
2113 errno = ENOSYS;
2114 return -1;
2117 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
2119 errno = ENOSYS;
2120 return -1;
2122 #endif /* WITH_AIO */