Add initshutdown pipe commands to rpcclient. Second part of fix to bug
[Samba/gebeck_regimport.git] / source / lib / system.c
blob2e95efec79b4f08c14bb08b92a8f6f15a8c5bd93
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 */
697 /**************************************************************************
698 Wrapper for setgroups. Deals with broken (int) case. Automatically used
699 if we have broken getgroups.
700 ****************************************************************************/
702 int sys_setgroups(int setlen, gid_t *gidset)
704 #if !defined(HAVE_SETGROUPS)
705 errno = ENOSYS;
706 return -1;
707 #endif /* HAVE_SETGROUPS */
709 #if !defined(HAVE_BROKEN_GETGROUPS)
710 return setgroups(setlen, gidset);
711 #else
713 GID_T *group_list;
714 int i ;
716 if (setlen == 0)
717 return 0 ;
719 if (setlen < 0 || setlen > groups_max()) {
720 errno = EINVAL;
721 return -1;
725 * Broken case. We need to allocate a
726 * GID_T array of size setlen.
729 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
730 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
731 return -1;
734 for(i = 0; i < setlen; i++)
735 group_list[i] = (GID_T) gidset[i];
737 if(setgroups(setlen, group_list) != 0) {
738 int saved_errno = errno;
739 SAFE_FREE(group_list);
740 errno = saved_errno;
741 return -1;
744 SAFE_FREE(group_list);
745 return 0 ;
746 #endif /* HAVE_BROKEN_GETGROUPS */
749 /**************************************************************************
750 Wrappers for setpwent(), getpwent() and endpwent()
751 ****************************************************************************/
753 void sys_setpwent(void)
755 setpwent();
758 struct passwd *sys_getpwent(void)
760 return getpwent();
763 void sys_endpwent(void)
765 endpwent();
768 /**************************************************************************
769 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
770 ****************************************************************************/
772 struct passwd *sys_getpwnam(const char *name)
774 return getpwnam(name);
777 struct passwd *sys_getpwuid(uid_t uid)
779 return getpwuid(uid);
782 struct group *sys_getgrnam(const char *name)
784 return getgrnam(name);
787 struct group *sys_getgrgid(gid_t gid)
789 return getgrgid(gid);
792 #if 0 /* NOT CURRENTLY USED - JRA */
793 /**************************************************************************
794 The following are the UNICODE versions of *all* system interface functions
795 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
796 which currently are left as ascii as they are not used other than in name
797 resolution.
798 ****************************************************************************/
800 /**************************************************************************
801 Wide stat. Just narrow and call sys_xxx.
802 ****************************************************************************/
804 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
806 pstring fname;
807 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
810 /**************************************************************************
811 Wide lstat. Just narrow and call sys_xxx.
812 ****************************************************************************/
814 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
816 pstring fname;
817 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
820 /**************************************************************************
821 Wide creat. Just narrow and call sys_xxx.
822 ****************************************************************************/
824 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
826 pstring fname;
827 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
830 /**************************************************************************
831 Wide open. Just narrow and call sys_xxx.
832 ****************************************************************************/
834 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
836 pstring fname;
837 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
840 /**************************************************************************
841 Wide fopen. Just narrow and call sys_xxx.
842 ****************************************************************************/
844 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
846 pstring fname;
847 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
850 /**************************************************************************
851 Wide opendir. Just narrow and call sys_xxx.
852 ****************************************************************************/
854 DIR *wsys_opendir(const smb_ucs2_t *wfname)
856 pstring fname;
857 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
860 /**************************************************************************
861 Wide readdir. Return a structure pointer containing a wide filename.
862 ****************************************************************************/
864 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
866 static SMB_STRUCT_WDIRENT retval;
867 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
869 if(!dirval)
870 return NULL;
873 * The only POSIX defined member of this struct is d_name.
876 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
878 return &retval;
881 /**************************************************************************
882 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
883 ****************************************************************************/
885 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
887 pstring fname;
888 char *p = sys_getwd(fname);
890 if(!p)
891 return NULL;
893 return unix_to_unicode(s, p, sizeof(wpstring));
896 /**************************************************************************
897 Wide chown. Just narrow and call sys_xxx.
898 ****************************************************************************/
900 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
902 pstring fname;
903 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
906 /**************************************************************************
907 Wide chroot. Just narrow and call sys_xxx.
908 ****************************************************************************/
910 int wsys_chroot(const smb_ucs2_t *wfname)
912 pstring fname;
913 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
916 /**************************************************************************
917 Wide getpwnam. Return a structure pointer containing wide names.
918 ****************************************************************************/
920 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
922 static SMB_STRUCT_WPASSWD retval;
923 fstring name;
924 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
926 if(!pwret)
927 return NULL;
929 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
930 retval.pw_passwd = pwret->pw_passwd;
931 retval.pw_uid = pwret->pw_uid;
932 retval.pw_gid = pwret->pw_gid;
933 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
934 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
935 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
937 return &retval;
940 /**************************************************************************
941 Wide getpwuid. Return a structure pointer containing wide names.
942 ****************************************************************************/
944 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
946 static SMB_STRUCT_WPASSWD retval;
947 struct passwd *pwret = sys_getpwuid(uid);
949 if(!pwret)
950 return NULL;
952 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
953 retval.pw_passwd = pwret->pw_passwd;
954 retval.pw_uid = pwret->pw_uid;
955 retval.pw_gid = pwret->pw_gid;
956 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
957 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
958 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
960 return &retval;
962 #endif /* NOT CURRENTLY USED - JRA */
964 /**************************************************************************
965 Extract a command into an arg list. Uses a static pstring for storage.
966 Caller frees returned arg list (which contains pointers into the static pstring).
967 ****************************************************************************/
969 static char **extract_args(const char *command)
971 static pstring trunc_cmd;
972 char *ptr;
973 int argcl;
974 char **argl = NULL;
975 int i;
977 pstrcpy(trunc_cmd, command);
979 if(!(ptr = strtok(trunc_cmd, " \t"))) {
980 errno = EINVAL;
981 return NULL;
985 * Count the args.
988 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
989 argcl++;
991 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
992 return NULL;
995 * Now do the extraction.
998 pstrcpy(trunc_cmd, command);
1000 ptr = strtok(trunc_cmd, " \t");
1001 i = 0;
1002 argl[i++] = ptr;
1004 while((ptr = strtok(NULL, " \t")) != NULL)
1005 argl[i++] = ptr;
1007 argl[i++] = NULL;
1008 return argl;
1011 /**************************************************************************
1012 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1013 a sys_getpid() that only does a system call *once*.
1014 ****************************************************************************/
1016 static pid_t mypid = (pid_t)-1;
1018 pid_t sys_fork(void)
1020 pid_t forkret = fork();
1022 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1023 mypid = (pid_t) -1;
1025 return forkret;
1028 /**************************************************************************
1029 Wrapper for getpid. Ensures we only do a system call *once*.
1030 ****************************************************************************/
1032 pid_t sys_getpid(void)
1034 if (mypid == (pid_t)-1)
1035 mypid = getpid();
1037 return mypid;
1040 /**************************************************************************
1041 Wrapper for popen. Safer as it doesn't search a path.
1042 Modified from the glibc sources.
1043 modified by tridge to return a file descriptor. We must kick our FILE* habit
1044 ****************************************************************************/
1046 typedef struct _popen_list
1048 int fd;
1049 pid_t child_pid;
1050 struct _popen_list *next;
1051 } popen_list;
1053 static popen_list *popen_chain;
1055 int sys_popen(const char *command)
1057 int parent_end, child_end;
1058 int pipe_fds[2];
1059 popen_list *entry = NULL;
1060 char **argl = NULL;
1062 if (pipe(pipe_fds) < 0)
1063 return -1;
1065 parent_end = pipe_fds[0];
1066 child_end = pipe_fds[1];
1068 if (!*command) {
1069 errno = EINVAL;
1070 goto err_exit;
1073 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1074 goto err_exit;
1076 ZERO_STRUCTP(entry);
1079 * Extract the command and args into a NULL terminated array.
1082 if(!(argl = extract_args(command)))
1083 goto err_exit;
1085 entry->child_pid = sys_fork();
1087 if (entry->child_pid == -1) {
1088 goto err_exit;
1091 if (entry->child_pid == 0) {
1094 * Child !
1097 int child_std_end = STDOUT_FILENO;
1098 popen_list *p;
1100 close(parent_end);
1101 if (child_end != child_std_end) {
1102 dup2 (child_end, child_std_end);
1103 close (child_end);
1107 * POSIX.2: "popen() shall ensure that any streams from previous
1108 * popen() calls that remain open in the parent process are closed
1109 * in the new child process."
1112 for (p = popen_chain; p; p = p->next)
1113 close(p->fd);
1115 execv(argl[0], argl);
1116 _exit (127);
1120 * Parent.
1123 close (child_end);
1124 SAFE_FREE(argl);
1126 /* Link into popen_chain. */
1127 entry->next = popen_chain;
1128 popen_chain = entry;
1129 entry->fd = parent_end;
1131 return entry->fd;
1133 err_exit:
1135 SAFE_FREE(entry);
1136 SAFE_FREE(argl);
1137 close(pipe_fds[0]);
1138 close(pipe_fds[1]);
1139 return -1;
1142 /**************************************************************************
1143 Wrapper for pclose. Modified from the glibc sources.
1144 ****************************************************************************/
1146 int sys_pclose(int fd)
1148 int wstatus;
1149 popen_list **ptr = &popen_chain;
1150 popen_list *entry = NULL;
1151 pid_t wait_pid;
1152 int status = -1;
1154 /* Unlink from popen_chain. */
1155 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1156 if ((*ptr)->fd == fd) {
1157 entry = *ptr;
1158 *ptr = (*ptr)->next;
1159 status = 0;
1160 break;
1164 if (status < 0 || close(entry->fd) < 0)
1165 return -1;
1168 * As Samba is catching and eating child process
1169 * exits we don't really care about the child exit
1170 * code, a -1 with errno = ECHILD will do fine for us.
1173 do {
1174 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1175 } while (wait_pid == -1 && errno == EINTR);
1177 SAFE_FREE(entry);
1179 if (wait_pid == -1)
1180 return -1;
1181 return wstatus;
1184 /**************************************************************************
1185 Wrappers for dlopen, dlsym, dlclose.
1186 ****************************************************************************/
1188 void *sys_dlopen(const char *name, int flags)
1190 #if defined(HAVE_DLOPEN)
1191 return dlopen(name, flags);
1192 #else
1193 return NULL;
1194 #endif
1197 void *sys_dlsym(void *handle, const char *symbol)
1199 #if defined(HAVE_DLSYM)
1200 return dlsym(handle, symbol);
1201 #else
1202 return NULL;
1203 #endif
1206 int sys_dlclose (void *handle)
1208 #if defined(HAVE_DLCLOSE)
1209 return dlclose(handle);
1210 #else
1211 return 0;
1212 #endif
1215 const char *sys_dlerror(void)
1217 #if defined(HAVE_DLERROR)
1218 return dlerror();
1219 #else
1220 return NULL;
1221 #endif
1224 int sys_dup2(int oldfd, int newfd)
1226 #if defined(HAVE_DUP2)
1227 return dup2(oldfd, newfd);
1228 #else
1229 errno = ENOSYS;
1230 return -1;
1231 #endif
1234 /**************************************************************************
1235 Wrapper for Admin Logs.
1236 ****************************************************************************/
1238 void sys_adminlog(int priority, const char *format_str, ...)
1240 va_list ap;
1241 int ret;
1242 char *msgbuf = NULL;
1244 va_start( ap, format_str );
1245 ret = vasprintf( &msgbuf, format_str, ap );
1246 va_end( ap );
1248 if (ret == -1)
1249 return;
1251 #if defined(HAVE_SYSLOG)
1252 syslog( priority, "%s", msgbuf );
1253 #else
1254 DEBUG(0,("%s", msgbuf ));
1255 #endif
1256 SAFE_FREE(msgbuf);
1259 /**************************************************************************
1260 Wrappers for extented attribute calls. Based on the Linux package with
1261 support for IRIX also. Expand as other systems have them.
1262 ****************************************************************************/
1264 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1266 #if defined(HAVE_GETXATTR)
1267 return getxattr(path, name, value, size);
1268 #elif defined(HAVE_ATTR_GET)
1269 int retval, flags = 0;
1270 int valuelength = (int)size;
1271 char *attrname = strchr(name,'.') +1;
1273 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1275 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1277 return retval ? retval : valuelength;
1278 #else
1279 errno = ENOSYS;
1280 return -1;
1281 #endif
1284 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1286 #if defined(HAVE_LGETXATTR)
1287 return lgetxattr(path, name, value, size);
1288 #elif defined(HAVE_ATTR_GET)
1289 int retval, flags = ATTR_DONTFOLLOW;
1290 int valuelength = (int)size;
1291 char *attrname = strchr(name,'.') +1;
1293 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1295 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1297 return retval ? retval : valuelength;
1298 #else
1299 errno = ENOSYS;
1300 return -1;
1301 #endif
1304 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1306 #if defined(HAVE_FGETXATTR)
1307 return fgetxattr(filedes, name, value, size);
1308 #elif defined(HAVE_ATTR_GETF)
1309 int retval, flags = 0;
1310 int valuelength = (int)size;
1311 char *attrname = strchr(name,'.') +1;
1313 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1315 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1317 return retval ? retval : valuelength;
1318 #else
1319 errno = ENOSYS;
1320 return -1;
1321 #endif
1324 #if defined(HAVE_ATTR_LIST)
1325 static char attr_buffer[ATTR_MAX_VALUELEN];
1327 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1329 int retval = 0, index;
1330 attrlist_cursor_t *cursor = 0;
1331 int total_size = 0;
1332 attrlist_t * al = (attrlist_t *)attr_buffer;
1333 attrlist_ent_t *ae;
1334 size_t ent_size, left = size;
1335 char *bp = list;
1337 while (True) {
1338 if (filedes)
1339 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1340 else
1341 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1342 if (retval) break;
1343 for (index = 0; index < al->al_count; index++) {
1344 ae = ATTR_ENTRY(attr_buffer, index);
1345 ent_size = strlen(ae->a_name) + sizeof("user.");
1346 if (left >= ent_size) {
1347 strncpy(bp, "user.", sizeof("user."));
1348 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1349 bp += ent_size;
1350 left -= ent_size;
1351 } else if (size) {
1352 errno = ERANGE;
1353 retval = -1;
1354 break;
1356 total_size += ent_size;
1358 if (al->al_more == 0) break;
1360 if (retval == 0) {
1361 flags |= ATTR_ROOT;
1362 cursor = 0;
1363 while (True) {
1364 if (filedes)
1365 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1366 else
1367 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1368 if (retval) break;
1369 for (index = 0; index < al->al_count; index++) {
1370 ae = ATTR_ENTRY(attr_buffer, index);
1371 ent_size = strlen(ae->a_name) + sizeof("system.");
1372 if (left >= ent_size) {
1373 strncpy(bp, "system.", sizeof("system."));
1374 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1375 bp += ent_size;
1376 left -= ent_size;
1377 } else if (size) {
1378 errno = ERANGE;
1379 retval = -1;
1380 break;
1382 total_size += ent_size;
1384 if (al->al_more == 0) break;
1387 return (ssize_t)(retval ? retval : total_size);
1390 #endif
1392 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1394 #if defined(HAVE_LISTXATTR)
1395 return listxattr(path, list, size);
1396 #elif defined(HAVE_ATTR_LIST)
1397 return irix_attr_list(path, 0, list, size, 0);
1398 #else
1399 errno = ENOSYS;
1400 return -1;
1401 #endif
1404 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1406 #if defined(HAVE_LLISTXATTR)
1407 return llistxattr(path, list, size);
1408 #elif defined(HAVE_ATTR_LIST)
1409 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1410 #else
1411 errno = ENOSYS;
1412 return -1;
1413 #endif
1416 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1418 #if defined(HAVE_FLISTXATTR)
1419 return flistxattr(filedes, list, size);
1420 #elif defined(HAVE_ATTR_LISTF)
1421 return irix_attr_list(NULL, filedes, list, size, 0);
1422 #else
1423 errno = ENOSYS;
1424 return -1;
1425 #endif
1428 int sys_removexattr (const char *path, const char *name)
1430 #if defined(HAVE_REMOVEXATTR)
1431 return removexattr(path, name);
1432 #elif defined(HAVE_ATTR_REMOVE)
1433 int flags = 0;
1434 char *attrname = strchr(name,'.') +1;
1436 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1438 return attr_remove(path, attrname, flags);
1439 #else
1440 errno = ENOSYS;
1441 return -1;
1442 #endif
1445 int sys_lremovexattr (const char *path, const char *name)
1447 #if defined(HAVE_LREMOVEXATTR)
1448 return lremovexattr(path, name);
1449 #elif defined(HAVE_ATTR_REMOVE)
1450 int flags = ATTR_DONTFOLLOW;
1451 char *attrname = strchr(name,'.') +1;
1453 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1455 return attr_remove(path, attrname, flags);
1456 #else
1457 errno = ENOSYS;
1458 return -1;
1459 #endif
1462 int sys_fremovexattr (int filedes, const char *name)
1464 #if defined(HAVE_FREMOVEXATTR)
1465 return fremovexattr(filedes, name);
1466 #elif defined(HAVE_ATTR_REMOVEF)
1467 int flags = 0;
1468 char *attrname = strchr(name,'.') +1;
1470 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1472 return attr_removef(filedes, attrname, flags);
1473 #else
1474 errno = ENOSYS;
1475 return -1;
1476 #endif
1479 #if !defined(HAVE_SETXATTR)
1480 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1481 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1482 #endif
1484 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1486 #if defined(HAVE_SETXATTR)
1487 return setxattr(path, name, value, size, flags);
1488 #elif defined(HAVE_ATTR_SET)
1489 int myflags = 0;
1490 char *attrname = strchr(name,'.') +1;
1492 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1493 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1494 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1496 return attr_set(path, attrname, (const char *)value, size, myflags);
1497 #else
1498 errno = ENOSYS;
1499 return -1;
1500 #endif
1503 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1505 #if defined(HAVE_LSETXATTR)
1506 return lsetxattr(path, name, value, size, flags);
1507 #elif defined(HAVE_ATTR_SET)
1508 int myflags = ATTR_DONTFOLLOW;
1509 char *attrname = strchr(name,'.') +1;
1511 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1512 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1513 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1515 return attr_set(path, attrname, (const char *)value, size, myflags);
1516 #else
1517 errno = ENOSYS;
1518 return -1;
1519 #endif
1522 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1524 #if defined(HAVE_FSETXATTR)
1525 return fsetxattr(filedes, name, value, size, flags);
1526 #elif defined(HAVE_ATTR_SETF)
1527 int myflags = 0;
1528 char *attrname = strchr(name,'.') +1;
1530 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1531 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1532 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1534 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1535 #else
1536 errno = ENOSYS;
1537 return -1;
1538 #endif