skel_ -> cap_
[Samba/gebeck_regimport.git] / source3 / lib / system.c
blobb020a20373054b8233fe4a09409598f4fe30b29b
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;
103 /*******************************************************************
104 A send wrapper that will deal with EINTR.
105 ********************************************************************/
107 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
109 ssize_t ret;
111 do {
112 ret = send(s, msg, len, flags);
113 } while (ret == -1 && errno == EINTR);
114 return ret;
117 /*******************************************************************
118 A sendto wrapper that will deal with EINTR.
119 ********************************************************************/
121 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
123 ssize_t ret;
125 do {
126 ret = sendto(s, msg, len, flags, to, tolen);
127 } while (ret == -1 && errno == EINTR);
128 return ret;
131 /*******************************************************************
132 A recvfrom wrapper that will deal with EINTR.
133 ********************************************************************/
135 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
137 ssize_t ret;
139 do {
140 ret = recvfrom(s, buf, len, flags, from, fromlen);
141 } while (ret == -1 && errno == EINTR);
142 return ret;
145 /*******************************************************************
146 A fcntl wrapper that will deal with EINTR.
147 ********************************************************************/
149 int sys_fcntl_ptr(int fd, int cmd, void *arg)
151 int ret;
153 do {
154 ret = fcntl(fd, cmd, arg);
155 } while (ret == -1 && errno == EINTR);
156 return ret;
159 /*******************************************************************
160 A fcntl wrapper that will deal with EINTR.
161 ********************************************************************/
163 int sys_fcntl_long(int fd, int cmd, long arg)
165 int ret;
167 do {
168 ret = fcntl(fd, cmd, arg);
169 } while (ret == -1 && errno == EINTR);
170 return ret;
173 /*******************************************************************
174 A stat() wrapper that will deal with 64 bit filesizes.
175 ********************************************************************/
177 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
179 int ret;
180 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
181 ret = stat64(fname, sbuf);
182 #else
183 ret = stat(fname, sbuf);
184 #endif
185 /* we always want directories to appear zero size */
186 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
187 return ret;
190 /*******************************************************************
191 An fstat() wrapper that will deal with 64 bit filesizes.
192 ********************************************************************/
194 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
196 int ret;
197 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
198 ret = fstat64(fd, sbuf);
199 #else
200 ret = fstat(fd, sbuf);
201 #endif
202 /* we always want directories to appear zero size */
203 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
204 return ret;
207 /*******************************************************************
208 An lstat() wrapper that will deal with 64 bit filesizes.
209 ********************************************************************/
211 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
213 int ret;
214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
215 ret = lstat64(fname, sbuf);
216 #else
217 ret = lstat(fname, sbuf);
218 #endif
219 /* we always want directories to appear zero size */
220 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
221 return ret;
224 /*******************************************************************
225 An ftruncate() wrapper that will deal with 64 bit filesizes.
226 ********************************************************************/
228 int sys_ftruncate(int fd, SMB_OFF_T offset)
230 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
231 return ftruncate64(fd, offset);
232 #else
233 return ftruncate(fd, offset);
234 #endif
237 /*******************************************************************
238 An lseek() wrapper that will deal with 64 bit filesizes.
239 ********************************************************************/
241 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
243 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
244 return lseek64(fd, offset, whence);
245 #else
246 return lseek(fd, offset, whence);
247 #endif
250 /*******************************************************************
251 An fseek() wrapper that will deal with 64 bit filesizes.
252 ********************************************************************/
254 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
256 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
257 return fseek64(fp, offset, whence);
258 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
259 return fseeko64(fp, offset, whence);
260 #else
261 return fseek(fp, offset, whence);
262 #endif
265 /*******************************************************************
266 An ftell() wrapper that will deal with 64 bit filesizes.
267 ********************************************************************/
269 SMB_OFF_T sys_ftell(FILE *fp)
271 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
272 return (SMB_OFF_T)ftell64(fp);
273 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
274 return (SMB_OFF_T)ftello64(fp);
275 #else
276 return (SMB_OFF_T)ftell(fp);
277 #endif
280 /*******************************************************************
281 A creat() wrapper that will deal with 64 bit filesizes.
282 ********************************************************************/
284 int sys_creat(const char *path, mode_t mode)
286 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
287 return creat64(path, mode);
288 #else
290 * If creat64 isn't defined then ensure we call a potential open64.
291 * JRA.
293 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
294 #endif
297 /*******************************************************************
298 An open() wrapper that will deal with 64 bit filesizes.
299 ********************************************************************/
301 int sys_open(const char *path, int oflag, mode_t mode)
303 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
304 return open64(path, oflag, mode);
305 #else
306 return open(path, oflag, mode);
307 #endif
310 /*******************************************************************
311 An fopen() wrapper that will deal with 64 bit filesizes.
312 ********************************************************************/
314 FILE *sys_fopen(const char *path, const char *type)
316 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
317 return fopen64(path, type);
318 #else
319 return fopen(path, type);
320 #endif
323 /*******************************************************************
324 A readdir wrapper that will deal with 64 bit filesizes.
325 ********************************************************************/
327 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
329 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
330 return readdir64(dirp);
331 #else
332 return readdir(dirp);
333 #endif
336 /*******************************************************************
337 An mknod() wrapper that will deal with 64 bit filesizes.
338 ********************************************************************/
340 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
342 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
343 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
344 return mknod64(path, mode, dev);
345 #else
346 return mknod(path, mode, dev);
347 #endif
348 #else
349 /* No mknod system call. */
350 errno = ENOSYS;
351 return -1;
352 #endif
355 /*******************************************************************
356 Wrapper for realpath.
357 ********************************************************************/
359 char *sys_realpath(const char *path, char *resolved_path)
361 #if defined(HAVE_REALPATH)
362 return realpath(path, resolved_path);
363 #else
364 /* As realpath is not a system call we can't return ENOSYS. */
365 errno = EINVAL;
366 return NULL;
367 #endif
370 /*******************************************************************
371 The wait() calls vary between systems
372 ********************************************************************/
374 int sys_waitpid(pid_t pid,int *status,int options)
376 #ifdef HAVE_WAITPID
377 return waitpid(pid,status,options);
378 #else /* HAVE_WAITPID */
379 return wait4(pid, status, options, NULL);
380 #endif /* HAVE_WAITPID */
383 /*******************************************************************
384 System wrapper for getwd
385 ********************************************************************/
387 char *sys_getwd(char *s)
389 char *wd;
390 #ifdef HAVE_GETCWD
391 wd = (char *)getcwd(s, sizeof (pstring));
392 #else
393 wd = (char *)getwd(s);
394 #endif
395 return wd;
398 /*******************************************************************
399 system wrapper for symlink
400 ********************************************************************/
402 int sys_symlink(const char *oldpath, const char *newpath)
404 #ifndef HAVE_SYMLINK
405 errno = ENOSYS;
406 return -1;
407 #else
408 return symlink(oldpath, newpath);
409 #endif
412 /*******************************************************************
413 system wrapper for readlink
414 ********************************************************************/
416 int sys_readlink(const char *path, char *buf, size_t bufsiz)
418 #ifndef HAVE_READLINK
419 errno = ENOSYS;
420 return -1;
421 #else
422 return readlink(path, buf, bufsiz);
423 #endif
426 /*******************************************************************
427 system wrapper for link
428 ********************************************************************/
430 int sys_link(const char *oldpath, const char *newpath)
432 #ifndef HAVE_LINK
433 errno = ENOSYS;
434 return -1;
435 #else
436 return link(oldpath, newpath);
437 #endif
440 /*******************************************************************
441 chown isn't used much but OS/2 doesn't have it
442 ********************************************************************/
444 int sys_chown(const char *fname,uid_t uid,gid_t gid)
446 #ifndef HAVE_CHOWN
447 static int done;
448 if (!done) {
449 DEBUG(1,("WARNING: no chown!\n"));
450 done=1;
452 #else
453 return(chown(fname,uid,gid));
454 #endif
457 /*******************************************************************
458 os/2 also doesn't have chroot
459 ********************************************************************/
460 int sys_chroot(const char *dname)
462 #ifndef HAVE_CHROOT
463 static int done;
464 if (!done) {
465 DEBUG(1,("WARNING: no chroot!\n"));
466 done=1;
468 errno = ENOSYS;
469 return -1;
470 #else
471 return(chroot(dname));
472 #endif
475 /**************************************************************************
476 A wrapper for gethostbyname() that tries avoids looking up hostnames
477 in the root domain, which can cause dial-on-demand links to come up for no
478 apparent reason.
479 ****************************************************************************/
481 struct hostent *sys_gethostbyname(const char *name)
483 #ifdef REDUCE_ROOT_DNS_LOOKUPS
484 char query[256], hostname[256];
485 char *domain;
487 /* Does this name have any dots in it? If so, make no change */
489 if (strchr_m(name, '.'))
490 return(gethostbyname(name));
492 /* Get my hostname, which should have domain name
493 attached. If not, just do the gethostname on the
494 original string.
497 gethostname(hostname, sizeof(hostname) - 1);
498 hostname[sizeof(hostname) - 1] = 0;
499 if ((domain = strchr_m(hostname, '.')) == NULL)
500 return(gethostbyname(name));
502 /* Attach domain name to query and do modified query.
503 If names too large, just do gethostname on the
504 original string.
507 if((strlen(name) + strlen(domain)) >= sizeof(query))
508 return(gethostbyname(name));
510 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
511 return(gethostbyname(query));
512 #else /* REDUCE_ROOT_DNS_LOOKUPS */
513 return(gethostbyname(name));
514 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
518 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
519 /**************************************************************************
520 Try and abstract process capabilities (for systems that have them).
521 ****************************************************************************/
522 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
524 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
525 cap_t cap = cap_get_proc();
527 if (cap == NULL) {
528 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
529 strerror(errno)));
530 return False;
533 if(enable)
534 cap->cap_effective |= CAP_NETWORK_MGT;
535 else
536 cap->cap_effective &= ~CAP_NETWORK_MGT;
538 if (cap_set_proc(cap) == -1) {
539 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
540 strerror(errno)));
541 cap_free(cap);
542 return False;
545 cap_free(cap);
547 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
549 return True;
552 /**************************************************************************
553 Try and abstract inherited process capabilities (for systems that have them).
554 ****************************************************************************/
556 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
558 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
559 cap_t cap = cap_get_proc();
561 if (cap == NULL) {
562 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
563 strerror(errno)));
564 return False;
567 if(enable)
568 cap->cap_inheritable |= CAP_NETWORK_MGT;
569 else
570 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
572 if (cap_set_proc(cap) == -1) {
573 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
574 strerror(errno)));
575 cap_free(cap);
576 return False;
579 cap_free(cap);
581 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
583 return True;
585 #endif
587 /****************************************************************************
588 Gain the oplock capability from the kernel if possible.
589 ****************************************************************************/
591 void oplock_set_capability(BOOL this_process, BOOL inherit)
593 #if HAVE_KERNEL_OPLOCKS_IRIX
594 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
595 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
596 #endif
599 /**************************************************************************
600 Wrapper for random().
601 ****************************************************************************/
603 long sys_random(void)
605 #if defined(HAVE_RANDOM)
606 return (long)random();
607 #elif defined(HAVE_RAND)
608 return (long)rand();
609 #else
610 DEBUG(0,("Error - no random function available !\n"));
611 exit(1);
612 #endif
615 /**************************************************************************
616 Wrapper for srandom().
617 ****************************************************************************/
619 void sys_srandom(unsigned int seed)
621 #if defined(HAVE_SRANDOM)
622 srandom(seed);
623 #elif defined(HAVE_SRAND)
624 srand(seed);
625 #else
626 DEBUG(0,("Error - no srandom function available !\n"));
627 exit(1);
628 #endif
631 /**************************************************************************
632 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
633 ****************************************************************************/
635 int groups_max(void)
637 #if defined(SYSCONF_SC_NGROUPS_MAX)
638 int ret = sysconf(_SC_NGROUPS_MAX);
639 return (ret == -1) ? NGROUPS_MAX : ret;
640 #else
641 return NGROUPS_MAX;
642 #endif
645 /**************************************************************************
646 Wrapper for getgroups. Deals with broken (int) case.
647 ****************************************************************************/
649 int sys_getgroups(int setlen, gid_t *gidset)
651 #if !defined(HAVE_BROKEN_GETGROUPS)
652 return getgroups(setlen, gidset);
653 #else
655 GID_T gid;
656 GID_T *group_list;
657 int i, ngroups;
659 if(setlen == 0) {
660 return getgroups(setlen, &gid);
664 * Broken case. We need to allocate a
665 * GID_T array of size setlen.
668 if(setlen < 0) {
669 errno = EINVAL;
670 return -1;
673 if (setlen == 0)
674 setlen = groups_max();
676 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
677 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
678 return -1;
681 if((ngroups = getgroups(setlen, group_list)) < 0) {
682 int saved_errno = errno;
683 SAFE_FREE(group_list);
684 errno = saved_errno;
685 return -1;
688 for(i = 0; i < ngroups; i++)
689 gidset[i] = (gid_t)group_list[i];
691 SAFE_FREE(group_list);
692 return ngroups;
693 #endif /* HAVE_BROKEN_GETGROUPS */
696 #ifdef HAVE_SETGROUPS
698 /**************************************************************************
699 Wrapper for setgroups. Deals with broken (int) case. Automatically used
700 if we have broken getgroups.
701 ****************************************************************************/
703 int sys_setgroups(int setlen, gid_t *gidset)
705 #if !defined(HAVE_BROKEN_GETGROUPS)
706 return setgroups(setlen, gidset);
707 #else
709 GID_T *group_list;
710 int i ;
712 if (setlen == 0)
713 return 0 ;
715 if (setlen < 0 || setlen > groups_max()) {
716 errno = EINVAL;
717 return -1;
721 * Broken case. We need to allocate a
722 * GID_T array of size setlen.
725 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
726 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
727 return -1;
730 for(i = 0; i < setlen; i++)
731 group_list[i] = (GID_T) gidset[i];
733 if(setgroups(setlen, group_list) != 0) {
734 int saved_errno = errno;
735 SAFE_FREE(group_list);
736 errno = saved_errno;
737 return -1;
740 SAFE_FREE(group_list);
741 return 0 ;
742 #endif /* HAVE_BROKEN_GETGROUPS */
745 #endif /* HAVE_SETGROUPS */
747 /**************************************************************************
748 Wrappers for setpwent(), getpwent() and endpwent()
749 ****************************************************************************/
751 void sys_setpwent(void)
753 setpwent();
756 struct passwd *sys_getpwent(void)
758 return getpwent();
761 void sys_endpwent(void)
763 endpwent();
766 /**************************************************************************
767 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
768 ****************************************************************************/
770 struct passwd *sys_getpwnam(const char *name)
772 return getpwnam(name);
775 struct passwd *sys_getpwuid(uid_t uid)
777 return getpwuid(uid);
780 struct group *sys_getgrnam(const char *name)
782 return getgrnam(name);
785 struct group *sys_getgrgid(gid_t gid)
787 return getgrgid(gid);
790 #if 0 /* NOT CURRENTLY USED - JRA */
791 /**************************************************************************
792 The following are the UNICODE versions of *all* system interface functions
793 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
794 which currently are left as ascii as they are not used other than in name
795 resolution.
796 ****************************************************************************/
798 /**************************************************************************
799 Wide stat. Just narrow and call sys_xxx.
800 ****************************************************************************/
802 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
804 pstring fname;
805 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
808 /**************************************************************************
809 Wide lstat. Just narrow and call sys_xxx.
810 ****************************************************************************/
812 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
814 pstring fname;
815 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
818 /**************************************************************************
819 Wide creat. Just narrow and call sys_xxx.
820 ****************************************************************************/
822 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
824 pstring fname;
825 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
828 /**************************************************************************
829 Wide open. Just narrow and call sys_xxx.
830 ****************************************************************************/
832 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
834 pstring fname;
835 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
838 /**************************************************************************
839 Wide fopen. Just narrow and call sys_xxx.
840 ****************************************************************************/
842 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
844 pstring fname;
845 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
848 /**************************************************************************
849 Wide opendir. Just narrow and call sys_xxx.
850 ****************************************************************************/
852 DIR *wsys_opendir(const smb_ucs2_t *wfname)
854 pstring fname;
855 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
858 /**************************************************************************
859 Wide readdir. Return a structure pointer containing a wide filename.
860 ****************************************************************************/
862 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
864 static SMB_STRUCT_WDIRENT retval;
865 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
867 if(!dirval)
868 return NULL;
871 * The only POSIX defined member of this struct is d_name.
874 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
876 return &retval;
879 /**************************************************************************
880 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
881 ****************************************************************************/
883 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
885 pstring fname;
886 char *p = sys_getwd(fname);
888 if(!p)
889 return NULL;
891 return unix_to_unicode(s, p, sizeof(wpstring));
894 /**************************************************************************
895 Wide chown. Just narrow and call sys_xxx.
896 ****************************************************************************/
898 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
900 pstring fname;
901 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
904 /**************************************************************************
905 Wide chroot. Just narrow and call sys_xxx.
906 ****************************************************************************/
908 int wsys_chroot(const smb_ucs2_t *wfname)
910 pstring fname;
911 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
914 /**************************************************************************
915 Wide getpwnam. Return a structure pointer containing wide names.
916 ****************************************************************************/
918 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
920 static SMB_STRUCT_WPASSWD retval;
921 fstring name;
922 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
924 if(!pwret)
925 return NULL;
927 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
928 retval.pw_passwd = pwret->pw_passwd;
929 retval.pw_uid = pwret->pw_uid;
930 retval.pw_gid = pwret->pw_gid;
931 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
932 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
933 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
935 return &retval;
938 /**************************************************************************
939 Wide getpwuid. Return a structure pointer containing wide names.
940 ****************************************************************************/
942 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
944 static SMB_STRUCT_WPASSWD retval;
945 struct passwd *pwret = sys_getpwuid(uid);
947 if(!pwret)
948 return NULL;
950 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
951 retval.pw_passwd = pwret->pw_passwd;
952 retval.pw_uid = pwret->pw_uid;
953 retval.pw_gid = pwret->pw_gid;
954 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
955 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
956 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
958 return &retval;
960 #endif /* NOT CURRENTLY USED - JRA */
962 /**************************************************************************
963 Extract a command into an arg list. Uses a static pstring for storage.
964 Caller frees returned arg list (which contains pointers into the static pstring).
965 ****************************************************************************/
967 static char **extract_args(const char *command)
969 static pstring trunc_cmd;
970 char *ptr;
971 int argcl;
972 char **argl = NULL;
973 int i;
975 pstrcpy(trunc_cmd, command);
977 if(!(ptr = strtok(trunc_cmd, " \t"))) {
978 errno = EINVAL;
979 return NULL;
983 * Count the args.
986 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
987 argcl++;
989 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
990 return NULL;
993 * Now do the extraction.
996 pstrcpy(trunc_cmd, command);
998 ptr = strtok(trunc_cmd, " \t");
999 i = 0;
1000 argl[i++] = ptr;
1002 while((ptr = strtok(NULL, " \t")) != NULL)
1003 argl[i++] = ptr;
1005 argl[i++] = NULL;
1006 return argl;
1009 /**************************************************************************
1010 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1011 a sys_getpid() that only does a system call *once*.
1012 ****************************************************************************/
1014 static pid_t mypid = (pid_t)-1;
1016 pid_t sys_fork(void)
1018 pid_t forkret = fork();
1020 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1021 mypid = (pid_t) -1;
1023 return forkret;
1026 /**************************************************************************
1027 Wrapper for getpid. Ensures we only do a system call *once*.
1028 ****************************************************************************/
1030 pid_t sys_getpid(void)
1032 if (mypid == (pid_t)-1)
1033 mypid = getpid();
1035 return mypid;
1038 /**************************************************************************
1039 Wrapper for popen. Safer as it doesn't search a path.
1040 Modified from the glibc sources.
1041 modified by tridge to return a file descriptor. We must kick our FILE* habit
1042 ****************************************************************************/
1044 typedef struct _popen_list
1046 int fd;
1047 pid_t child_pid;
1048 struct _popen_list *next;
1049 } popen_list;
1051 static popen_list *popen_chain;
1053 int sys_popen(const char *command)
1055 int parent_end, child_end;
1056 int pipe_fds[2];
1057 popen_list *entry = NULL;
1058 char **argl = NULL;
1060 if (pipe(pipe_fds) < 0)
1061 return -1;
1063 parent_end = pipe_fds[0];
1064 child_end = pipe_fds[1];
1066 if (!*command) {
1067 errno = EINVAL;
1068 goto err_exit;
1071 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1072 goto err_exit;
1074 ZERO_STRUCTP(entry);
1077 * Extract the command and args into a NULL terminated array.
1080 if(!(argl = extract_args(command)))
1081 goto err_exit;
1083 entry->child_pid = sys_fork();
1085 if (entry->child_pid == -1) {
1086 goto err_exit;
1089 if (entry->child_pid == 0) {
1092 * Child !
1095 int child_std_end = STDOUT_FILENO;
1096 popen_list *p;
1098 close(parent_end);
1099 if (child_end != child_std_end) {
1100 dup2 (child_end, child_std_end);
1101 close (child_end);
1105 * POSIX.2: "popen() shall ensure that any streams from previous
1106 * popen() calls that remain open in the parent process are closed
1107 * in the new child process."
1110 for (p = popen_chain; p; p = p->next)
1111 close(p->fd);
1113 execv(argl[0], argl);
1114 _exit (127);
1118 * Parent.
1121 close (child_end);
1122 SAFE_FREE(argl);
1124 /* Link into popen_chain. */
1125 entry->next = popen_chain;
1126 popen_chain = entry;
1127 entry->fd = parent_end;
1129 return entry->fd;
1131 err_exit:
1133 SAFE_FREE(entry);
1134 SAFE_FREE(argl);
1135 close(pipe_fds[0]);
1136 close(pipe_fds[1]);
1137 return -1;
1140 /**************************************************************************
1141 Wrapper for pclose. Modified from the glibc sources.
1142 ****************************************************************************/
1144 int sys_pclose(int fd)
1146 int wstatus;
1147 popen_list **ptr = &popen_chain;
1148 popen_list *entry = NULL;
1149 pid_t wait_pid;
1150 int status = -1;
1152 /* Unlink from popen_chain. */
1153 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1154 if ((*ptr)->fd == fd) {
1155 entry = *ptr;
1156 *ptr = (*ptr)->next;
1157 status = 0;
1158 break;
1162 if (status < 0 || close(entry->fd) < 0)
1163 return -1;
1166 * As Samba is catching and eating child process
1167 * exits we don't really care about the child exit
1168 * code, a -1 with errno = ECHILD will do fine for us.
1171 do {
1172 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1173 } while (wait_pid == -1 && errno == EINTR);
1175 SAFE_FREE(entry);
1177 if (wait_pid == -1)
1178 return -1;
1179 return wstatus;
1182 /**************************************************************************
1183 Wrappers for dlopen, dlsym, dlclose.
1184 ****************************************************************************/
1186 void *sys_dlopen(const char *name, int flags)
1188 #if defined(HAVE_DLOPEN)
1189 return dlopen(name, flags);
1190 #else
1191 return NULL;
1192 #endif
1195 void *sys_dlsym(void *handle, const char *symbol)
1197 #if defined(HAVE_DLSYM)
1198 return dlsym(handle, symbol);
1199 #else
1200 return NULL;
1201 #endif
1204 int sys_dlclose (void *handle)
1206 #if defined(HAVE_DLCLOSE)
1207 return dlclose(handle);
1208 #else
1209 return 0;
1210 #endif
1213 const char *sys_dlerror(void)
1215 #if defined(HAVE_DLERROR)
1216 return dlerror();
1217 #else
1218 return NULL;
1219 #endif
1222 int sys_dup2(int oldfd, int newfd)
1224 #if defined(HAVE_DUP2)
1225 return dup2(oldfd, newfd);
1226 #else
1227 errno = ENOSYS;
1228 return -1;
1229 #endif
1232 /**************************************************************************
1233 Wrapper for Admin Logs.
1234 ****************************************************************************/
1236 void sys_adminlog(int priority, const char *format_str, ...)
1238 va_list ap;
1239 int ret;
1240 char *msgbuf = NULL;
1242 va_start( ap, format_str );
1243 ret = vasprintf( &msgbuf, format_str, ap );
1244 va_end( ap );
1246 if (ret == -1)
1247 return;
1249 #if defined(HAVE_SYSLOG)
1250 syslog( priority, "%s", msgbuf );
1251 #else
1252 DEBUG(0,("%s", msgbuf ));
1253 #endif
1254 SAFE_FREE(msgbuf);
1257 /**************************************************************************
1258 Wrappers for extented attribute calls. Based on the Linux package with
1259 support for IRIX also. Expand as other systems have them.
1260 ****************************************************************************/
1262 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1264 #if defined(HAVE_GETXATTR)
1265 return getxattr(path, name, value, size);
1266 #elif defined(HAVE_ATTR_GET)
1267 int retval, flags = 0;
1268 int valuelength = (int)size;
1269 char *attrname = strchr(name,'.') +1;
1271 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1273 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1275 return retval ? retval : valuelength;
1276 #else
1277 errno = ENOSYS;
1278 return -1;
1279 #endif
1282 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1284 #if defined(HAVE_LGETXATTR)
1285 return lgetxattr(path, name, value, size);
1286 #elif defined(HAVE_ATTR_GET)
1287 int retval, flags = ATTR_DONTFOLLOW;
1288 int valuelength = (int)size;
1289 char *attrname = strchr(name,'.') +1;
1291 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1293 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1295 return retval ? retval : valuelength;
1296 #else
1297 errno = ENOSYS;
1298 return -1;
1299 #endif
1302 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1304 #if defined(HAVE_FGETXATTR)
1305 return fgetxattr(filedes, name, value, size);
1306 #elif defined(HAVE_ATTR_GETF)
1307 int retval, flags = 0;
1308 int valuelength = (int)size;
1309 char *attrname = strchr(name,'.') +1;
1311 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1313 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1315 return retval ? retval : valuelength;
1316 #else
1317 errno = ENOSYS;
1318 return -1;
1319 #endif
1322 #if defined(HAVE_ATTR_LIST)
1323 static char attr_buffer[ATTR_MAX_VALUELEN];
1325 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1327 int retval = 0, index;
1328 attrlist_cursor_t *cursor = 0;
1329 int total_size = 0;
1330 attrlist_t * al = (attrlist_t *)attr_buffer;
1331 attrlist_ent_t *ae;
1332 size_t ent_size, left = size;
1333 char *bp = list;
1335 while (True) {
1336 if (filedes)
1337 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1338 else
1339 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1340 if (retval) break;
1341 for (index = 0; index < al->al_count; index++) {
1342 ae = ATTR_ENTRY(attr_buffer, index);
1343 ent_size = strlen(ae->a_name) + sizeof("user.");
1344 if (left >= ent_size) {
1345 strncpy(bp, "user.", sizeof("user."));
1346 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1347 bp += ent_size;
1348 left -= ent_size;
1349 } else if (size) {
1350 errno = ERANGE;
1351 retval = -1;
1352 break;
1354 total_size += ent_size;
1356 if (al->al_more == 0) break;
1358 if (retval == 0) {
1359 flags |= ATTR_ROOT;
1360 cursor = 0;
1361 while (True) {
1362 if (filedes)
1363 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1364 else
1365 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1366 if (retval) break;
1367 for (index = 0; index < al->al_count; index++) {
1368 ae = ATTR_ENTRY(attr_buffer, index);
1369 ent_size = strlen(ae->a_name) + sizeof("system.");
1370 if (left >= ent_size) {
1371 strncpy(bp, "system.", sizeof("system."));
1372 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1373 bp += ent_size;
1374 left -= ent_size;
1375 } else if (size) {
1376 errno = ERANGE;
1377 retval = -1;
1378 break;
1380 total_size += ent_size;
1382 if (al->al_more == 0) break;
1385 return (ssize_t)(retval ? retval : total_size);
1388 #endif
1390 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1392 #if defined(HAVE_LISTXATTR)
1393 return listxattr(path, list, size);
1394 #elif defined(HAVE_ATTR_LIST)
1395 return irix_attr_list(path, 0, list, size, 0);
1396 #else
1397 errno = ENOSYS;
1398 return -1;
1399 #endif
1402 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1404 #if defined(HAVE_LLISTXATTR)
1405 return llistxattr(path, list, size);
1406 #elif defined(HAVE_ATTR_LIST)
1407 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1408 #else
1409 errno = ENOSYS;
1410 return -1;
1411 #endif
1414 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1416 #if defined(HAVE_FLISTXATTR)
1417 return flistxattr(filedes, list, size);
1418 #elif defined(HAVE_ATTR_LISTF)
1419 return irix_attr_list(NULL, filedes, list, size, 0);
1420 #else
1421 errno = ENOSYS;
1422 return -1;
1423 #endif
1426 int sys_removexattr (const char *path, const char *name)
1428 #if defined(HAVE_REMOVEXATTR)
1429 return removexattr(path, name);
1430 #elif defined(HAVE_ATTR_REMOVE)
1431 int flags = 0;
1432 char *attrname = strchr(name,'.') +1;
1434 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1436 return attr_remove(path, attrname, flags);
1437 #else
1438 errno = ENOSYS;
1439 return -1;
1440 #endif
1443 int sys_lremovexattr (const char *path, const char *name)
1445 #if defined(HAVE_LREMOVEXATTR)
1446 return lremovexattr(path, name);
1447 #elif defined(HAVE_ATTR_REMOVE)
1448 int flags = ATTR_DONTFOLLOW;
1449 char *attrname = strchr(name,'.') +1;
1451 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1453 return attr_remove(path, attrname, flags);
1454 #else
1455 errno = ENOSYS;
1456 return -1;
1457 #endif
1460 int sys_fremovexattr (int filedes, const char *name)
1462 #if defined(HAVE_FREMOVEXATTR)
1463 return fremovexattr(filedes, name);
1464 #elif defined(HAVE_ATTR_REMOVEF)
1465 int flags = 0;
1466 char *attrname = strchr(name,'.') +1;
1468 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1470 return attr_removef(filedes, attrname, flags);
1471 #else
1472 errno = ENOSYS;
1473 return -1;
1474 #endif
1477 #if !defined(HAVE_SETXATTR)
1478 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1479 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1480 #endif
1482 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1484 #if defined(HAVE_SETXATTR)
1485 return setxattr(path, name, value, size, flags);
1486 #elif defined(HAVE_ATTR_SET)
1487 int myflags = 0;
1488 char *attrname = strchr(name,'.') +1;
1490 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1491 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1492 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1494 return attr_set(path, attrname, (const char *)value, size, myflags);
1495 #else
1496 errno = ENOSYS;
1497 return -1;
1498 #endif
1501 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1503 #if defined(HAVE_LSETXATTR)
1504 return lsetxattr(path, name, value, size, flags);
1505 #elif defined(HAVE_ATTR_SET)
1506 int myflags = ATTR_DONTFOLLOW;
1507 char *attrname = strchr(name,'.') +1;
1509 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1510 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1511 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1513 return attr_set(path, attrname, (const char *)value, size, myflags);
1514 #else
1515 errno = ENOSYS;
1516 return -1;
1517 #endif
1520 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1522 #if defined(HAVE_FSETXATTR)
1523 return fsetxattr(filedes, name, value, size, flags);
1524 #elif defined(HAVE_ATTR_SETF)
1525 int myflags = 0;
1526 char *attrname = strchr(name,'.') +1;
1528 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1529 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1530 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1532 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1533 #else
1534 errno = ENOSYS;
1535 return -1;
1536 #endif