preparing for release of 2.2.3a
[Samba.git] / source / lib / system.c
bloba4420f5c6c2174237bcea530e2028b7f072f0ebc
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba system utilities
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Jeremy Allison 1998-2002
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 stat() wrapper that will deal with 64 bit filesizes.
78 ********************************************************************/
80 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
82 int ret;
83 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
84 ret = stat64(fname, sbuf);
85 #else
86 ret = stat(fname, sbuf);
87 #endif
88 /* we always want directories to appear zero size */
89 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
90 return ret;
93 /*******************************************************************
94 An fstat() wrapper that will deal with 64 bit filesizes.
95 ********************************************************************/
97 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
99 int ret;
100 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
101 ret = fstat64(fd, sbuf);
102 #else
103 ret = fstat(fd, sbuf);
104 #endif
105 /* we always want directories to appear zero size */
106 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
107 return ret;
110 /*******************************************************************
111 An lstat() wrapper that will deal with 64 bit filesizes.
112 ********************************************************************/
114 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
116 int ret;
117 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
118 ret = lstat64(fname, sbuf);
119 #else
120 ret = lstat(fname, sbuf);
121 #endif
122 /* we always want directories to appear zero size */
123 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
124 return ret;
127 /*******************************************************************
128 An ftruncate() wrapper that will deal with 64 bit filesizes.
129 ********************************************************************/
131 int sys_ftruncate(int fd, SMB_OFF_T offset)
133 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
134 return ftruncate64(fd, offset);
135 #else
136 return ftruncate(fd, offset);
137 #endif
140 /*******************************************************************
141 An lseek() wrapper that will deal with 64 bit filesizes.
142 ********************************************************************/
144 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
146 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
147 return lseek64(fd, offset, whence);
148 #else
149 return lseek(fd, offset, whence);
150 #endif
153 /*******************************************************************
154 An fseek() wrapper that will deal with 64 bit filesizes.
155 ********************************************************************/
157 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
159 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
160 return fseek64(fp, offset, whence);
161 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
162 return fseeko64(fp, offset, whence);
163 #else
164 return fseek(fp, offset, whence);
165 #endif
168 /*******************************************************************
169 An ftell() wrapper that will deal with 64 bit filesizes.
170 ********************************************************************/
172 SMB_OFF_T sys_ftell(FILE *fp)
174 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
175 return (SMB_OFF_T)ftell64(fp);
176 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
177 return (SMB_OFF_T)ftello64(fp);
178 #else
179 return (SMB_OFF_T)ftell(fp);
180 #endif
183 /*******************************************************************
184 A creat() wrapper that will deal with 64 bit filesizes.
185 ********************************************************************/
187 int sys_creat(const char *path, mode_t mode)
189 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
190 return creat64(path, mode);
191 #else
193 * If creat64 isn't defined then ensure we call a potential open64.
194 * JRA.
196 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
197 #endif
200 /*******************************************************************
201 An open() wrapper that will deal with 64 bit filesizes.
202 ********************************************************************/
204 int sys_open(const char *path, int oflag, mode_t mode)
206 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
207 return open64(path, oflag, mode);
208 #else
209 return open(path, oflag, mode);
210 #endif
213 /*******************************************************************
214 An fopen() wrapper that will deal with 64 bit filesizes.
215 ********************************************************************/
217 FILE *sys_fopen(const char *path, const char *type)
219 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
220 return fopen64(path, type);
221 #else
222 return fopen(path, type);
223 #endif
226 /*******************************************************************
227 A readdir wrapper that will deal with 64 bit filesizes.
228 ********************************************************************/
230 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
232 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
233 return readdir64(dirp);
234 #else
235 return readdir(dirp);
236 #endif
239 /*******************************************************************
240 An mknod() wrapper that will deal with 64 bit filesizes.
241 ********************************************************************/
243 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
245 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
247 return mknod64(path, mode, dev);
248 #else
249 return mknod(path, mode, dev);
250 #endif
251 #else
252 /* No mknod system call. */
253 errno = ENOSYS;
254 return -1;
255 #endif
258 /*******************************************************************
259 Wrapper for realpath.
260 ********************************************************************/
262 char *sys_realpath(const char *path, char *resolved_path)
264 #if defined(HAVE_REALPATH)
265 return realpath(path, resolved_path);
266 #else
267 /* As realpath is not a system call we can't return ENOSYS. */
268 errno = EINVAL;
269 return NULL;
270 #endif
273 /*******************************************************************
274 The wait() calls vary between systems
275 ********************************************************************/
277 int sys_waitpid(pid_t pid,int *status,int options)
279 #ifdef HAVE_WAITPID
280 return waitpid(pid,status,options);
281 #else /* HAVE_WAITPID */
282 return wait4(pid, status, options, NULL);
283 #endif /* HAVE_WAITPID */
286 /*******************************************************************
287 System wrapper for getwd
288 ********************************************************************/
290 char *sys_getwd(char *s)
292 char *wd;
293 #ifdef HAVE_GETCWD
294 wd = (char *)getcwd(s, sizeof (pstring));
295 #else
296 wd = (char *)getwd(s);
297 #endif
298 return wd;
301 /*******************************************************************
302 system wrapper for symlink
303 ********************************************************************/
305 int sys_symlink(const char *oldpath, const char *newpath)
307 #ifndef HAVE_SYMLINK
308 errno = ENOSYS;
309 return -1;
310 #else
311 return symlink(oldpath, newpath);
312 #endif
315 /*******************************************************************
316 system wrapper for readlink
317 ********************************************************************/
319 int sys_readlink(const char *path, char *buf, size_t bufsiz)
321 #ifndef HAVE_READLINK
322 errno = ENOSYS;
323 return -1;
324 #else
325 return readlink(path, buf, bufsiz);
326 #endif
329 /*******************************************************************
330 system wrapper for link
331 ********************************************************************/
333 int sys_link(const char *oldpath, const char *newpath)
335 #ifndef HAVE_LINK
336 errno = ENOSYS;
337 return -1;
338 #else
339 return link(oldpath, newpath);
340 #endif
343 /*******************************************************************
344 chown isn't used much but OS/2 doesn't have it
345 ********************************************************************/
347 int sys_chown(const char *fname,uid_t uid,gid_t gid)
349 #ifndef HAVE_CHOWN
350 static int done;
351 if (!done) {
352 DEBUG(1,("WARNING: no chown!\n"));
353 done=1;
355 #else
356 return(chown(fname,uid,gid));
357 #endif
360 /*******************************************************************
361 os/2 also doesn't have chroot
362 ********************************************************************/
363 int sys_chroot(const char *dname)
365 #ifndef HAVE_CHROOT
366 static int done;
367 if (!done) {
368 DEBUG(1,("WARNING: no chroot!\n"));
369 done=1;
371 errno = ENOSYS;
372 return -1;
373 #else
374 return(chroot(dname));
375 #endif
378 /**************************************************************************
379 A wrapper for gethostbyname() that tries avoids looking up hostnames
380 in the root domain, which can cause dial-on-demand links to come up for no
381 apparent reason.
382 ****************************************************************************/
384 struct hostent *sys_gethostbyname(const char *name)
386 #ifdef REDUCE_ROOT_DNS_LOOKUPS
387 char query[256], hostname[256];
388 char *domain;
390 /* Does this name have any dots in it? If so, make no change */
392 if (strchr(name, '.'))
393 return(gethostbyname(name));
395 /* Get my hostname, which should have domain name
396 attached. If not, just do the gethostname on the
397 original string.
400 gethostname(hostname, sizeof(hostname) - 1);
401 hostname[sizeof(hostname) - 1] = 0;
402 if ((domain = strchr(hostname, '.')) == NULL)
403 return(gethostbyname(name));
405 /* Attach domain name to query and do modified query.
406 If names too large, just do gethostname on the
407 original string.
410 if((strlen(name) + strlen(domain)) >= sizeof(query))
411 return(gethostbyname(name));
413 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
414 return(gethostbyname(query));
415 #else /* REDUCE_ROOT_DNS_LOOKUPS */
416 return(gethostbyname(name));
417 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
421 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
422 /**************************************************************************
423 Try and abstract process capabilities (for systems that have them).
424 ****************************************************************************/
425 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
427 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
428 cap_t cap = cap_get_proc();
430 if (cap == NULL) {
431 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
432 strerror(errno)));
433 return False;
436 if(enable)
437 cap->cap_effective |= CAP_NETWORK_MGT;
438 else
439 cap->cap_effective &= ~CAP_NETWORK_MGT;
441 if (cap_set_proc(cap) == -1) {
442 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
443 strerror(errno)));
444 cap_free(cap);
445 return False;
448 cap_free(cap);
450 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
452 return True;
455 /**************************************************************************
456 Try and abstract inherited process capabilities (for systems that have them).
457 ****************************************************************************/
459 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
461 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
462 cap_t cap = cap_get_proc();
464 if (cap == NULL) {
465 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
466 strerror(errno)));
467 return False;
470 if(enable)
471 cap->cap_inheritable |= CAP_NETWORK_MGT;
472 else
473 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
475 if (cap_set_proc(cap) == -1) {
476 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
477 strerror(errno)));
478 cap_free(cap);
479 return False;
482 cap_free(cap);
484 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
486 return True;
488 #endif
490 /****************************************************************************
491 Gain the oplock capability from the kernel if possible.
492 ****************************************************************************/
494 void oplock_set_capability(BOOL this_process, BOOL inherit)
496 #if HAVE_KERNEL_OPLOCKS_IRIX
497 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
498 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
499 #endif
502 /**************************************************************************
503 Wrapper for random().
504 ****************************************************************************/
506 long sys_random(void)
508 #if defined(HAVE_RANDOM)
509 return (long)random();
510 #elif defined(HAVE_RAND)
511 return (long)rand();
512 #else
513 DEBUG(0,("Error - no random function available !\n"));
514 exit(1);
515 #endif
518 /**************************************************************************
519 Wrapper for srandom().
520 ****************************************************************************/
522 void sys_srandom(unsigned int seed)
524 #if defined(HAVE_SRANDOM)
525 srandom(seed);
526 #elif defined(HAVE_SRAND)
527 srand(seed);
528 #else
529 DEBUG(0,("Error - no srandom function available !\n"));
530 exit(1);
531 #endif
534 /**************************************************************************
535 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
536 ****************************************************************************/
538 int groups_max(void)
540 #if defined(SYSCONF_SC_NGROUPS_MAX)
541 int ret = sysconf(_SC_NGROUPS_MAX);
542 return (ret == -1) ? NGROUPS_MAX : ret;
543 #else
544 return NGROUPS_MAX;
545 #endif
548 /**************************************************************************
549 Wrapper for getgroups. Deals with broken (int) case.
550 ****************************************************************************/
552 int sys_getgroups(int setlen, gid_t *gidset)
554 #if !defined(HAVE_BROKEN_GETGROUPS)
555 return getgroups(setlen, gidset);
556 #else
558 GID_T gid;
559 GID_T *group_list;
560 int i, ngroups;
562 if(setlen == 0) {
563 return getgroups(setlen, &gid);
567 * Broken case. We need to allocate a
568 * GID_T array of size setlen.
571 if(setlen < 0) {
572 errno = EINVAL;
573 return -1;
576 if (setlen == 0)
577 setlen = groups_max();
579 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
580 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
581 return -1;
584 if((ngroups = getgroups(setlen, group_list)) < 0) {
585 int saved_errno = errno;
586 SAFE_FREE(group_list);
587 errno = saved_errno;
588 return -1;
591 for(i = 0; i < ngroups; i++)
592 gidset[i] = (gid_t)group_list[i];
594 SAFE_FREE(group_list);
595 return ngroups;
596 #endif /* HAVE_BROKEN_GETGROUPS */
599 #ifdef HAVE_SETGROUPS
601 /**************************************************************************
602 Wrapper for setgroups. Deals with broken (int) case. Automatically used
603 if we have broken getgroups.
604 ****************************************************************************/
606 int sys_setgroups(int setlen, gid_t *gidset)
608 #if !defined(HAVE_BROKEN_GETGROUPS)
609 return setgroups(setlen, gidset);
610 #else
612 GID_T *group_list;
613 int i ;
615 if (setlen == 0)
616 return 0 ;
618 if (setlen < 0 || setlen > groups_max()) {
619 errno = EINVAL;
620 return -1;
624 * Broken case. We need to allocate a
625 * GID_T array of size setlen.
628 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
629 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
630 return -1;
633 for(i = 0; i < setlen; i++)
634 group_list[i] = (GID_T) gidset[i];
636 if(setgroups(setlen, group_list) != 0) {
637 int saved_errno = errno;
638 SAFE_FREE(group_list);
639 errno = saved_errno;
640 return -1;
643 SAFE_FREE(group_list);
644 return 0 ;
645 #endif /* HAVE_BROKEN_GETGROUPS */
648 #endif /* HAVE_SETGROUPS */
651 * We only wrap pw_name and pw_passwd for now as these
652 * are the only potentially modified fields.
655 /**************************************************************************
656 Helper function for getpwnam/getpwuid wrappers.
657 ****************************************************************************/
659 struct saved_pw {
660 fstring pw_name;
661 fstring pw_passwd;
662 fstring pw_gecos;
663 pstring pw_dir;
664 pstring pw_shell;
665 struct passwd pass;
668 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
669 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
671 static int num_lookups; /* Counter so we don't always use cache. */
672 #ifndef PW_RET_CACHE_MAX_LOOKUPS
673 #define PW_RET_CACHE_MAX_LOOKUPS 100
674 #endif
676 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
678 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
680 fstrcpy(dst->pw_name, pass->pw_name);
681 dst->pass.pw_name = dst->pw_name;
683 fstrcpy(dst->pw_passwd, pass->pw_passwd);
684 dst->pass.pw_passwd = dst->pw_passwd;
686 fstrcpy(dst->pw_gecos, pass->pw_gecos);
687 dst->pass.pw_gecos = dst->pw_gecos;
689 pstrcpy(dst->pw_dir, pass->pw_dir);
690 dst->pass.pw_dir = dst->pw_dir;
692 pstrcpy(dst->pw_shell, pass->pw_shell);
693 dst->pass.pw_shell = dst->pw_shell;
696 static struct passwd *setup_pwret(struct passwd *pass)
698 if (pass == NULL) {
699 /* Clear the caches. */
700 memset(&pw_cache, '\0', sizeof(struct saved_pw));
701 memset(&pw_mod, '\0', sizeof(struct saved_pw));
702 num_lookups = 0;
703 return NULL;
706 copy_pwent( &pw_mod, pass);
708 if (pass != &pw_cache.pass) {
710 /* If it's a cache miss we must also refill the cache. */
712 copy_pwent( &pw_cache, pass);
713 num_lookups = 1;
715 } else {
717 /* Cache hit. */
719 num_lookups++;
720 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
723 return &pw_mod.pass;
726 /**************************************************************************
727 Wrappers for setpwent(), getpwent() and endpwent()
728 ****************************************************************************/
730 void sys_setpwent(void)
732 setup_pwret(NULL); /* Clear cache. */
733 setpwent();
736 struct passwd *sys_getpwent(void)
738 return setup_pwret(getpwent());
741 void sys_endpwent(void)
743 setup_pwret(NULL); /* Clear cache. */
744 endpwent();
747 /**************************************************************************
748 Wrapper for getpwnam(). Always returns a static that can be modified.
749 ****************************************************************************/
751 struct passwd *sys_getpwnam(const char *name)
753 if (!name || !name[0])
754 return NULL;
756 /* check for a cache hit first */
757 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
758 return setup_pwret(&pw_cache.pass);
761 return setup_pwret(getpwnam(name));
764 /**************************************************************************
765 Wrapper for getpwuid(). Always returns a static that can be modified.
766 ****************************************************************************/
768 struct passwd *sys_getpwuid(uid_t uid)
770 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
771 return setup_pwret(&pw_cache.pass);
774 return setup_pwret(getpwuid(uid));
777 #if 0 /* NOT CURRENTLY USED - JRA */
778 /**************************************************************************
779 The following are the UNICODE versions of *all* system interface functions
780 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
781 which currently are left as ascii as they are not used other than in name
782 resolution.
783 ****************************************************************************/
785 /**************************************************************************
786 Wide stat. Just narrow and call sys_xxx.
787 ****************************************************************************/
789 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
791 pstring fname;
792 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
795 /**************************************************************************
796 Wide lstat. Just narrow and call sys_xxx.
797 ****************************************************************************/
799 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
801 pstring fname;
802 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
805 /**************************************************************************
806 Wide creat. Just narrow and call sys_xxx.
807 ****************************************************************************/
809 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
811 pstring fname;
812 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
815 /**************************************************************************
816 Wide open. Just narrow and call sys_xxx.
817 ****************************************************************************/
819 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
821 pstring fname;
822 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
825 /**************************************************************************
826 Wide fopen. Just narrow and call sys_xxx.
827 ****************************************************************************/
829 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
831 pstring fname;
832 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
835 /**************************************************************************
836 Wide opendir. Just narrow and call sys_xxx.
837 ****************************************************************************/
839 DIR *wsys_opendir(const smb_ucs2_t *wfname)
841 pstring fname;
842 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
845 /**************************************************************************
846 Wide readdir. Return a structure pointer containing a wide filename.
847 ****************************************************************************/
849 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
851 static SMB_STRUCT_WDIRENT retval;
852 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
854 if(!dirval)
855 return NULL;
858 * The only POSIX defined member of this struct is d_name.
861 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
863 return &retval;
866 /**************************************************************************
867 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
868 ****************************************************************************/
870 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
872 pstring fname;
873 char *p = sys_getwd(fname);
875 if(!p)
876 return NULL;
878 return unix_to_unicode(s, p, sizeof(wpstring));
881 /**************************************************************************
882 Wide chown. Just narrow and call sys_xxx.
883 ****************************************************************************/
885 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
887 pstring fname;
888 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
891 /**************************************************************************
892 Wide chroot. Just narrow and call sys_xxx.
893 ****************************************************************************/
895 int wsys_chroot(const smb_ucs2_t *wfname)
897 pstring fname;
898 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
901 /**************************************************************************
902 Wide getpwnam. Return a structure pointer containing wide names.
903 ****************************************************************************/
905 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
907 static SMB_STRUCT_WPASSWD retval;
908 fstring name;
909 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
911 if(!pwret)
912 return NULL;
914 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
915 retval.pw_passwd = pwret->pw_passwd;
916 retval.pw_uid = pwret->pw_uid;
917 retval.pw_gid = pwret->pw_gid;
918 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
919 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
920 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
922 return &retval;
925 /**************************************************************************
926 Wide getpwuid. Return a structure pointer containing wide names.
927 ****************************************************************************/
929 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
931 static SMB_STRUCT_WPASSWD retval;
932 struct passwd *pwret = sys_getpwuid(uid);
934 if(!pwret)
935 return NULL;
937 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
938 retval.pw_passwd = pwret->pw_passwd;
939 retval.pw_uid = pwret->pw_uid;
940 retval.pw_gid = pwret->pw_gid;
941 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
942 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
943 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
945 return &retval;
947 #endif /* NOT CURRENTLY USED - JRA */
949 /**************************************************************************
950 Extract a command into an arg list. Uses a static pstring for storage.
951 Caller frees returned arg list (which contains pointers into the static pstring).
952 ****************************************************************************/
954 static char **extract_args(const char *command)
956 static pstring trunc_cmd;
957 char *ptr;
958 int argcl;
959 char **argl = NULL;
960 int i;
962 pstrcpy(trunc_cmd, command);
964 if(!(ptr = strtok(trunc_cmd, " \t"))) {
965 errno = EINVAL;
966 return NULL;
970 * Count the args.
973 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
974 argcl++;
976 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
977 return NULL;
980 * Now do the extraction.
983 pstrcpy(trunc_cmd, command);
985 ptr = strtok(trunc_cmd, " \t");
986 i = 0;
987 argl[i++] = ptr;
989 while((ptr = strtok(NULL, " \t")) != NULL)
990 argl[i++] = ptr;
992 argl[i++] = NULL;
993 return argl;
996 /**************************************************************************
997 Wrapper for fork. Ensures that mypid is reset. Used so we can write
998 a sys_getpid() that only does a system call *once*.
999 ****************************************************************************/
1001 static pid_t mypid = (pid_t)-1;
1003 pid_t sys_fork(void)
1005 pid_t forkret = fork();
1007 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1008 mypid = (pid_t) -1;
1010 return forkret;
1013 /**************************************************************************
1014 Wrapper for getpid. Ensures we only do a system call *once*.
1015 ****************************************************************************/
1017 pid_t sys_getpid(void)
1019 if (mypid == (pid_t)-1)
1020 mypid = getpid();
1022 return mypid;
1025 /**************************************************************************
1026 Wrapper for popen. Safer as it doesn't search a path.
1027 Modified from the glibc sources.
1028 modified by tridge to return a file descriptor. We must kick our FILE* habit
1029 ****************************************************************************/
1031 typedef struct _popen_list
1033 int fd;
1034 pid_t child_pid;
1035 struct _popen_list *next;
1036 } popen_list;
1038 static popen_list *popen_chain;
1040 int sys_popen(const char *command)
1042 int parent_end, child_end;
1043 int pipe_fds[2];
1044 popen_list *entry = NULL;
1045 char **argl = NULL;
1047 if (pipe(pipe_fds) < 0)
1048 return -1;
1050 parent_end = pipe_fds[0];
1051 child_end = pipe_fds[1];
1053 if (!*command) {
1054 errno = EINVAL;
1055 goto err_exit;
1058 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1059 goto err_exit;
1061 ZERO_STRUCTP(entry);
1064 * Extract the command and args into a NULL terminated array.
1067 if(!(argl = extract_args(command)))
1068 goto err_exit;
1070 entry->child_pid = sys_fork();
1072 if (entry->child_pid == -1) {
1073 goto err_exit;
1076 if (entry->child_pid == 0) {
1079 * Child !
1082 int child_std_end = STDOUT_FILENO;
1083 popen_list *p;
1085 close(parent_end);
1086 if (child_end != child_std_end) {
1087 dup2 (child_end, child_std_end);
1088 close (child_end);
1092 * POSIX.2: "popen() shall ensure that any streams from previous
1093 * popen() calls that remain open in the parent process are closed
1094 * in the new child process."
1097 for (p = popen_chain; p; p = p->next)
1098 close(p->fd);
1100 execv(argl[0], argl);
1101 _exit (127);
1105 * Parent.
1108 close (child_end);
1109 SAFE_FREE(argl);
1111 /* Link into popen_chain. */
1112 entry->next = popen_chain;
1113 popen_chain = entry;
1114 entry->fd = parent_end;
1116 return entry->fd;
1118 err_exit:
1120 SAFE_FREE(entry);
1121 SAFE_FREE(argl);
1122 close(pipe_fds[0]);
1123 close(pipe_fds[1]);
1124 return -1;
1127 /**************************************************************************
1128 Wrapper for pclose. Modified from the glibc sources.
1129 ****************************************************************************/
1131 int sys_pclose(int fd)
1133 int wstatus;
1134 popen_list **ptr = &popen_chain;
1135 popen_list *entry = NULL;
1136 pid_t wait_pid;
1137 int status = -1;
1139 /* Unlink from popen_chain. */
1140 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1141 if ((*ptr)->fd == fd) {
1142 entry = *ptr;
1143 *ptr = (*ptr)->next;
1144 status = 0;
1145 break;
1149 if (status < 0 || close(entry->fd) < 0)
1150 return -1;
1153 * As Samba is catching and eating child process
1154 * exits we don't really care about the child exit
1155 * code, a -1 with errno = ECHILD will do fine for us.
1158 do {
1159 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1160 } while (wait_pid == -1 && errno == EINTR);
1162 SAFE_FREE(entry);
1164 if (wait_pid == -1)
1165 return -1;
1166 return wstatus;
1169 /**************************************************************************
1170 Wrappers for dlopen, dlsym, dlclose.
1171 ****************************************************************************/
1173 void *sys_dlopen(const char *name, int flags)
1175 #ifdef HAVE_LIBDL
1176 return dlopen(name, flags);
1177 #else
1178 return NULL;
1179 #endif
1182 void *sys_dlsym(void *handle, char *symbol)
1184 #ifdef HAVE_LIBDL
1185 return dlsym(handle, symbol);
1186 #else
1187 return NULL;
1188 #endif
1191 int sys_dlclose (void *handle)
1193 #ifdef HAVE_LIBDL
1194 return dlclose(handle);
1195 #else
1196 return 0;
1197 #endif
1200 const char *sys_dlerror(void)
1202 #ifdef HAVE_LIBDL
1203 return dlerror();
1204 #else
1205 return NULL;
1206 #endif