r3220: merging current 3.0 code to release branch
[Samba.git] / source / lib / system.c
blobb27ac5c00ad51cc31a2cc1075302ca13ea4960f4
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2002
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
25 The idea is that this file will eventually have wrappers around all
26 important system calls in samba. The aims are:
28 - to enable easier porting by putting OS dependent stuff in here
30 - to allow for hooks into other "pseudo-filesystems"
32 - to allow easier integration of things like the japanese extensions
34 - to support the philosophy of Samba to expose the features of
35 the OS within the SMB model. In general whatever file/printer/variable
36 expansions/etc make sense to the OS should be acceptable to Samba.
41 /*******************************************************************
42 A wrapper for usleep in case we don't have one.
43 ********************************************************************/
45 int sys_usleep(long usecs)
47 #ifndef HAVE_USLEEP
48 struct timeval tval;
49 #endif
52 * We need this braindamage as the glibc usleep
53 * is not SPEC1170 complient... grumble... JRA.
56 if(usecs < 0 || usecs > 1000000) {
57 errno = EINVAL;
58 return -1;
61 #if HAVE_USLEEP
62 usleep(usecs);
63 return 0;
64 #else /* HAVE_USLEEP */
66 * Fake it with select...
68 tval.tv_sec = 0;
69 tval.tv_usec = usecs/1000;
70 select(0,NULL,NULL,NULL,&tval);
71 return 0;
72 #endif /* HAVE_USLEEP */
75 /*******************************************************************
76 A read wrapper that will deal with EINTR.
77 ********************************************************************/
79 ssize_t sys_read(int fd, void *buf, size_t count)
81 ssize_t ret;
83 do {
84 ret = read(fd, buf, count);
85 } while (ret == -1 && errno == EINTR);
86 return ret;
89 /*******************************************************************
90 A write wrapper that will deal with EINTR.
91 ********************************************************************/
93 ssize_t sys_write(int fd, const void *buf, size_t count)
95 ssize_t ret;
97 do {
98 ret = write(fd, buf, count);
99 } while (ret == -1 && errno == EINTR);
100 return ret;
104 /*******************************************************************
105 A pread wrapper that will deal with EINTR and 64-bit file offsets.
106 ********************************************************************/
108 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
109 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
111 ssize_t ret;
113 do {
114 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
115 ret = pread64(fd, buf, count, off);
116 #else
117 ret = pread(fd, buf, count, off);
118 #endif
119 } while (ret == -1 && errno == EINTR);
120 return ret;
122 #endif
124 /*******************************************************************
125 A write wrapper that will deal with EINTR and 64-bit file offsets.
126 ********************************************************************/
128 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
129 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
131 ssize_t ret;
133 do {
134 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
135 ret = pwrite64(fd, buf, count, off);
136 #else
137 ret = pwrite(fd, buf, count, off);
138 #endif
139 } while (ret == -1 && errno == EINTR);
140 return ret;
142 #endif
144 /*******************************************************************
145 A send wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
150 ssize_t ret;
152 do {
153 ret = send(s, msg, len, flags);
154 } while (ret == -1 && errno == EINTR);
155 return ret;
158 /*******************************************************************
159 A sendto wrapper that will deal with EINTR.
160 ********************************************************************/
162 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
164 ssize_t ret;
166 do {
167 ret = sendto(s, msg, len, flags, to, tolen);
168 } while (ret == -1 && errno == EINTR);
169 return ret;
172 /*******************************************************************
173 A recvfrom wrapper that will deal with EINTR.
174 ********************************************************************/
176 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
178 ssize_t ret;
180 do {
181 ret = recvfrom(s, buf, len, flags, from, fromlen);
182 } while (ret == -1 && errno == EINTR);
183 return ret;
186 /*******************************************************************
187 A fcntl wrapper that will deal with EINTR.
188 ********************************************************************/
190 int sys_fcntl_ptr(int fd, int cmd, void *arg)
192 int ret;
194 do {
195 ret = fcntl(fd, cmd, arg);
196 } while (ret == -1 && errno == EINTR);
197 return ret;
200 /*******************************************************************
201 A fcntl wrapper that will deal with EINTR.
202 ********************************************************************/
204 int sys_fcntl_long(int fd, int cmd, long arg)
206 int ret;
208 do {
209 ret = fcntl(fd, cmd, arg);
210 } while (ret == -1 && errno == EINTR);
211 return ret;
214 /*******************************************************************
215 A stat() wrapper that will deal with 64 bit filesizes.
216 ********************************************************************/
218 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
220 int ret;
221 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
222 ret = stat64(fname, sbuf);
223 #else
224 ret = stat(fname, sbuf);
225 #endif
226 /* we always want directories to appear zero size */
227 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
228 return ret;
231 /*******************************************************************
232 An fstat() wrapper that will deal with 64 bit filesizes.
233 ********************************************************************/
235 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
237 int ret;
238 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
239 ret = fstat64(fd, sbuf);
240 #else
241 ret = fstat(fd, sbuf);
242 #endif
243 /* we always want directories to appear zero size */
244 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
245 return ret;
248 /*******************************************************************
249 An lstat() wrapper that will deal with 64 bit filesizes.
250 ********************************************************************/
252 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
254 int ret;
255 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
256 ret = lstat64(fname, sbuf);
257 #else
258 ret = lstat(fname, sbuf);
259 #endif
260 /* we always want directories to appear zero size */
261 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
262 return ret;
265 /*******************************************************************
266 An ftruncate() wrapper that will deal with 64 bit filesizes.
267 ********************************************************************/
269 int sys_ftruncate(int fd, SMB_OFF_T offset)
271 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
272 return ftruncate64(fd, offset);
273 #else
274 return ftruncate(fd, offset);
275 #endif
278 /*******************************************************************
279 An lseek() wrapper that will deal with 64 bit filesizes.
280 ********************************************************************/
282 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
284 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
285 return lseek64(fd, offset, whence);
286 #else
287 return lseek(fd, offset, whence);
288 #endif
291 /*******************************************************************
292 An fseek() wrapper that will deal with 64 bit filesizes.
293 ********************************************************************/
295 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
297 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
298 return fseek64(fp, offset, whence);
299 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
300 return fseeko64(fp, offset, whence);
301 #else
302 return fseek(fp, offset, whence);
303 #endif
306 /*******************************************************************
307 An ftell() wrapper that will deal with 64 bit filesizes.
308 ********************************************************************/
310 SMB_OFF_T sys_ftell(FILE *fp)
312 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
313 return (SMB_OFF_T)ftell64(fp);
314 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
315 return (SMB_OFF_T)ftello64(fp);
316 #else
317 return (SMB_OFF_T)ftell(fp);
318 #endif
321 /*******************************************************************
322 A creat() wrapper that will deal with 64 bit filesizes.
323 ********************************************************************/
325 int sys_creat(const char *path, mode_t mode)
327 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
328 return creat64(path, mode);
329 #else
331 * If creat64 isn't defined then ensure we call a potential open64.
332 * JRA.
334 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
335 #endif
338 /*******************************************************************
339 An open() wrapper that will deal with 64 bit filesizes.
340 ********************************************************************/
342 int sys_open(const char *path, int oflag, mode_t mode)
344 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
345 return open64(path, oflag, mode);
346 #else
347 return open(path, oflag, mode);
348 #endif
351 /*******************************************************************
352 An fopen() wrapper that will deal with 64 bit filesizes.
353 ********************************************************************/
355 FILE *sys_fopen(const char *path, const char *type)
357 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
358 return fopen64(path, type);
359 #else
360 return fopen(path, type);
361 #endif
364 /*******************************************************************
365 A readdir wrapper that will deal with 64 bit filesizes.
366 ********************************************************************/
368 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
370 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
371 return readdir64(dirp);
372 #else
373 return readdir(dirp);
374 #endif
377 /*******************************************************************
378 An mknod() wrapper that will deal with 64 bit filesizes.
379 ********************************************************************/
381 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
383 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
384 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
385 return mknod64(path, mode, dev);
386 #else
387 return mknod(path, mode, dev);
388 #endif
389 #else
390 /* No mknod system call. */
391 errno = ENOSYS;
392 return -1;
393 #endif
396 /*******************************************************************
397 Wrapper for realpath.
398 ********************************************************************/
400 char *sys_realpath(const char *path, char *resolved_path)
402 #if defined(HAVE_REALPATH)
403 return realpath(path, resolved_path);
404 #else
405 /* As realpath is not a system call we can't return ENOSYS. */
406 errno = EINVAL;
407 return NULL;
408 #endif
411 /*******************************************************************
412 The wait() calls vary between systems
413 ********************************************************************/
415 int sys_waitpid(pid_t pid,int *status,int options)
417 #ifdef HAVE_WAITPID
418 return waitpid(pid,status,options);
419 #else /* HAVE_WAITPID */
420 return wait4(pid, status, options, NULL);
421 #endif /* HAVE_WAITPID */
424 /*******************************************************************
425 System wrapper for getwd
426 ********************************************************************/
428 char *sys_getwd(char *s)
430 char *wd;
431 #ifdef HAVE_GETCWD
432 wd = (char *)getcwd(s, sizeof (pstring));
433 #else
434 wd = (char *)getwd(s);
435 #endif
436 return wd;
439 /*******************************************************************
440 system wrapper for symlink
441 ********************************************************************/
443 int sys_symlink(const char *oldpath, const char *newpath)
445 #ifndef HAVE_SYMLINK
446 errno = ENOSYS;
447 return -1;
448 #else
449 return symlink(oldpath, newpath);
450 #endif
453 /*******************************************************************
454 system wrapper for readlink
455 ********************************************************************/
457 int sys_readlink(const char *path, char *buf, size_t bufsiz)
459 #ifndef HAVE_READLINK
460 errno = ENOSYS;
461 return -1;
462 #else
463 return readlink(path, buf, bufsiz);
464 #endif
467 /*******************************************************************
468 system wrapper for link
469 ********************************************************************/
471 int sys_link(const char *oldpath, const char *newpath)
473 #ifndef HAVE_LINK
474 errno = ENOSYS;
475 return -1;
476 #else
477 return link(oldpath, newpath);
478 #endif
481 /*******************************************************************
482 chown isn't used much but OS/2 doesn't have it
483 ********************************************************************/
485 int sys_chown(const char *fname,uid_t uid,gid_t gid)
487 #ifndef HAVE_CHOWN
488 static int done;
489 if (!done) {
490 DEBUG(1,("WARNING: no chown!\n"));
491 done=1;
493 errno = ENOSYS;
494 return -1;
495 #else
496 return(chown(fname,uid,gid));
497 #endif
500 /*******************************************************************
501 os/2 also doesn't have chroot
502 ********************************************************************/
503 int sys_chroot(const char *dname)
505 #ifndef HAVE_CHROOT
506 static int done;
507 if (!done) {
508 DEBUG(1,("WARNING: no chroot!\n"));
509 done=1;
511 errno = ENOSYS;
512 return -1;
513 #else
514 return(chroot(dname));
515 #endif
518 /**************************************************************************
519 A wrapper for gethostbyname() that tries avoids looking up hostnames
520 in the root domain, which can cause dial-on-demand links to come up for no
521 apparent reason.
522 ****************************************************************************/
524 struct hostent *sys_gethostbyname(const char *name)
526 #ifdef REDUCE_ROOT_DNS_LOOKUPS
527 char query[256], hostname[256];
528 char *domain;
530 /* Does this name have any dots in it? If so, make no change */
532 if (strchr_m(name, '.'))
533 return(gethostbyname(name));
535 /* Get my hostname, which should have domain name
536 attached. If not, just do the gethostname on the
537 original string.
540 gethostname(hostname, sizeof(hostname) - 1);
541 hostname[sizeof(hostname) - 1] = 0;
542 if ((domain = strchr_m(hostname, '.')) == NULL)
543 return(gethostbyname(name));
545 /* Attach domain name to query and do modified query.
546 If names too large, just do gethostname on the
547 original string.
550 if((strlen(name) + strlen(domain)) >= sizeof(query))
551 return(gethostbyname(name));
553 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
554 return(gethostbyname(query));
555 #else /* REDUCE_ROOT_DNS_LOOKUPS */
556 return(gethostbyname(name));
557 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
561 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
562 /**************************************************************************
563 Try and abstract process capabilities (for systems that have them).
564 ****************************************************************************/
565 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
567 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
568 cap_t cap = cap_get_proc();
570 if (cap == NULL) {
571 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
572 strerror(errno)));
573 return False;
576 if(enable)
577 cap->cap_effective |= CAP_NETWORK_MGT;
578 else
579 cap->cap_effective &= ~CAP_NETWORK_MGT;
581 if (cap_set_proc(cap) == -1) {
582 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
583 strerror(errno)));
584 cap_free(cap);
585 return False;
588 cap_free(cap);
590 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
592 return True;
595 /**************************************************************************
596 Try and abstract inherited process capabilities (for systems that have them).
597 ****************************************************************************/
599 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
601 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
602 cap_t cap = cap_get_proc();
604 if (cap == NULL) {
605 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
606 strerror(errno)));
607 return False;
610 if(enable)
611 cap->cap_inheritable |= CAP_NETWORK_MGT;
612 else
613 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
615 if (cap_set_proc(cap) == -1) {
616 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
617 strerror(errno)));
618 cap_free(cap);
619 return False;
622 cap_free(cap);
624 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
626 return True;
628 #endif
630 /****************************************************************************
631 Gain the oplock capability from the kernel if possible.
632 ****************************************************************************/
634 void oplock_set_capability(BOOL this_process, BOOL inherit)
636 #if HAVE_KERNEL_OPLOCKS_IRIX
637 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
638 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
639 #endif
642 /**************************************************************************
643 Wrapper for random().
644 ****************************************************************************/
646 long sys_random(void)
648 #if defined(HAVE_RANDOM)
649 return (long)random();
650 #elif defined(HAVE_RAND)
651 return (long)rand();
652 #else
653 DEBUG(0,("Error - no random function available !\n"));
654 exit(1);
655 #endif
658 /**************************************************************************
659 Wrapper for srandom().
660 ****************************************************************************/
662 void sys_srandom(unsigned int seed)
664 #if defined(HAVE_SRANDOM)
665 srandom(seed);
666 #elif defined(HAVE_SRAND)
667 srand(seed);
668 #else
669 DEBUG(0,("Error - no srandom function available !\n"));
670 exit(1);
671 #endif
674 /**************************************************************************
675 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
676 ****************************************************************************/
678 int groups_max(void)
680 #if defined(SYSCONF_SC_NGROUPS_MAX)
681 int ret = sysconf(_SC_NGROUPS_MAX);
682 return (ret == -1) ? NGROUPS_MAX : ret;
683 #else
684 return NGROUPS_MAX;
685 #endif
688 /**************************************************************************
689 Wrapper for getgroups. Deals with broken (int) case.
690 ****************************************************************************/
692 int sys_getgroups(int setlen, gid_t *gidset)
694 #if !defined(HAVE_BROKEN_GETGROUPS)
695 return getgroups(setlen, gidset);
696 #else
698 GID_T gid;
699 GID_T *group_list;
700 int i, ngroups;
702 if(setlen == 0) {
703 return getgroups(setlen, &gid);
707 * Broken case. We need to allocate a
708 * GID_T array of size setlen.
711 if(setlen < 0) {
712 errno = EINVAL;
713 return -1;
716 if (setlen == 0)
717 setlen = groups_max();
719 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
720 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
721 return -1;
724 if((ngroups = getgroups(setlen, group_list)) < 0) {
725 int saved_errno = errno;
726 SAFE_FREE(group_list);
727 errno = saved_errno;
728 return -1;
731 for(i = 0; i < ngroups; i++)
732 gidset[i] = (gid_t)group_list[i];
734 SAFE_FREE(group_list);
735 return ngroups;
736 #endif /* HAVE_BROKEN_GETGROUPS */
740 /**************************************************************************
741 Wrapper for setgroups. Deals with broken (int) case. Automatically used
742 if we have broken getgroups.
743 ****************************************************************************/
745 int sys_setgroups(int setlen, gid_t *gidset)
747 #if !defined(HAVE_SETGROUPS)
748 errno = ENOSYS;
749 return -1;
750 #endif /* HAVE_SETGROUPS */
752 #if !defined(HAVE_BROKEN_GETGROUPS)
753 return setgroups(setlen, gidset);
754 #else
756 GID_T *group_list;
757 int i ;
759 if (setlen == 0)
760 return 0 ;
762 if (setlen < 0 || setlen > groups_max()) {
763 errno = EINVAL;
764 return -1;
768 * Broken case. We need to allocate a
769 * GID_T array of size setlen.
772 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
773 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
774 return -1;
777 for(i = 0; i < setlen; i++)
778 group_list[i] = (GID_T) gidset[i];
780 if(setgroups(setlen, group_list) != 0) {
781 int saved_errno = errno;
782 SAFE_FREE(group_list);
783 errno = saved_errno;
784 return -1;
787 SAFE_FREE(group_list);
788 return 0 ;
789 #endif /* HAVE_BROKEN_GETGROUPS */
792 /**************************************************************************
793 Wrappers for setpwent(), getpwent() and endpwent()
794 ****************************************************************************/
796 void sys_setpwent(void)
798 setpwent();
801 struct passwd *sys_getpwent(void)
803 return getpwent();
806 void sys_endpwent(void)
808 endpwent();
811 /**************************************************************************
812 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
813 ****************************************************************************/
815 struct passwd *sys_getpwnam(const char *name)
817 return getpwnam(name);
820 struct passwd *sys_getpwuid(uid_t uid)
822 return getpwuid(uid);
825 struct group *sys_getgrnam(const char *name)
827 return getgrnam(name);
830 struct group *sys_getgrgid(gid_t gid)
832 return getgrgid(gid);
835 #if 0 /* NOT CURRENTLY USED - JRA */
836 /**************************************************************************
837 The following are the UNICODE versions of *all* system interface functions
838 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
839 which currently are left as ascii as they are not used other than in name
840 resolution.
841 ****************************************************************************/
843 /**************************************************************************
844 Wide stat. Just narrow and call sys_xxx.
845 ****************************************************************************/
847 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
849 pstring fname;
850 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
853 /**************************************************************************
854 Wide lstat. Just narrow and call sys_xxx.
855 ****************************************************************************/
857 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
859 pstring fname;
860 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
863 /**************************************************************************
864 Wide creat. Just narrow and call sys_xxx.
865 ****************************************************************************/
867 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
869 pstring fname;
870 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
873 /**************************************************************************
874 Wide open. Just narrow and call sys_xxx.
875 ****************************************************************************/
877 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
879 pstring fname;
880 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
883 /**************************************************************************
884 Wide fopen. Just narrow and call sys_xxx.
885 ****************************************************************************/
887 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
889 pstring fname;
890 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
893 /**************************************************************************
894 Wide opendir. Just narrow and call sys_xxx.
895 ****************************************************************************/
897 DIR *wsys_opendir(const smb_ucs2_t *wfname)
899 pstring fname;
900 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
903 /**************************************************************************
904 Wide readdir. Return a structure pointer containing a wide filename.
905 ****************************************************************************/
907 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
909 static SMB_STRUCT_WDIRENT retval;
910 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
912 if(!dirval)
913 return NULL;
916 * The only POSIX defined member of this struct is d_name.
919 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
921 return &retval;
924 /**************************************************************************
925 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
926 ****************************************************************************/
928 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
930 pstring fname;
931 char *p = sys_getwd(fname);
933 if(!p)
934 return NULL;
936 return unix_to_unicode(s, p, sizeof(wpstring));
939 /**************************************************************************
940 Wide chown. Just narrow and call sys_xxx.
941 ****************************************************************************/
943 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
945 pstring fname;
946 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
949 /**************************************************************************
950 Wide chroot. Just narrow and call sys_xxx.
951 ****************************************************************************/
953 int wsys_chroot(const smb_ucs2_t *wfname)
955 pstring fname;
956 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
959 /**************************************************************************
960 Wide getpwnam. Return a structure pointer containing wide names.
961 ****************************************************************************/
963 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
965 static SMB_STRUCT_WPASSWD retval;
966 fstring name;
967 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
969 if(!pwret)
970 return NULL;
972 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
973 retval.pw_passwd = pwret->pw_passwd;
974 retval.pw_uid = pwret->pw_uid;
975 retval.pw_gid = pwret->pw_gid;
976 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
977 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
978 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
980 return &retval;
983 /**************************************************************************
984 Wide getpwuid. Return a structure pointer containing wide names.
985 ****************************************************************************/
987 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
989 static SMB_STRUCT_WPASSWD retval;
990 struct passwd *pwret = sys_getpwuid(uid);
992 if(!pwret)
993 return NULL;
995 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
996 retval.pw_passwd = pwret->pw_passwd;
997 retval.pw_uid = pwret->pw_uid;
998 retval.pw_gid = pwret->pw_gid;
999 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1000 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1001 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1003 return &retval;
1005 #endif /* NOT CURRENTLY USED - JRA */
1007 /**************************************************************************
1008 Extract a command into an arg list. Uses a static pstring for storage.
1009 Caller frees returned arg list (which contains pointers into the static pstring).
1010 ****************************************************************************/
1012 static char **extract_args(const char *command)
1014 static pstring trunc_cmd;
1015 char *ptr;
1016 int argcl;
1017 char **argl = NULL;
1018 int i;
1020 pstrcpy(trunc_cmd, command);
1022 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1023 errno = EINVAL;
1024 return NULL;
1028 * Count the args.
1031 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1032 argcl++;
1034 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
1035 return NULL;
1038 * Now do the extraction.
1041 pstrcpy(trunc_cmd, command);
1043 ptr = strtok(trunc_cmd, " \t");
1044 i = 0;
1045 argl[i++] = ptr;
1047 while((ptr = strtok(NULL, " \t")) != NULL)
1048 argl[i++] = ptr;
1050 argl[i++] = NULL;
1051 return argl;
1054 /**************************************************************************
1055 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1056 a sys_getpid() that only does a system call *once*.
1057 ****************************************************************************/
1059 static pid_t mypid = (pid_t)-1;
1061 pid_t sys_fork(void)
1063 pid_t forkret = fork();
1065 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1066 mypid = (pid_t) -1;
1068 return forkret;
1071 /**************************************************************************
1072 Wrapper for getpid. Ensures we only do a system call *once*.
1073 ****************************************************************************/
1075 pid_t sys_getpid(void)
1077 if (mypid == (pid_t)-1)
1078 mypid = getpid();
1080 return mypid;
1083 /**************************************************************************
1084 Wrapper for popen. Safer as it doesn't search a path.
1085 Modified from the glibc sources.
1086 modified by tridge to return a file descriptor. We must kick our FILE* habit
1087 ****************************************************************************/
1089 typedef struct _popen_list
1091 int fd;
1092 pid_t child_pid;
1093 struct _popen_list *next;
1094 } popen_list;
1096 static popen_list *popen_chain;
1098 int sys_popen(const char *command)
1100 int parent_end, child_end;
1101 int pipe_fds[2];
1102 popen_list *entry = NULL;
1103 char **argl = NULL;
1105 if (pipe(pipe_fds) < 0)
1106 return -1;
1108 parent_end = pipe_fds[0];
1109 child_end = pipe_fds[1];
1111 if (!*command) {
1112 errno = EINVAL;
1113 goto err_exit;
1116 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1117 goto err_exit;
1119 ZERO_STRUCTP(entry);
1122 * Extract the command and args into a NULL terminated array.
1125 if(!(argl = extract_args(command)))
1126 goto err_exit;
1128 entry->child_pid = sys_fork();
1130 if (entry->child_pid == -1) {
1131 goto err_exit;
1134 if (entry->child_pid == 0) {
1137 * Child !
1140 int child_std_end = STDOUT_FILENO;
1141 popen_list *p;
1143 close(parent_end);
1144 if (child_end != child_std_end) {
1145 dup2 (child_end, child_std_end);
1146 close (child_end);
1150 * POSIX.2: "popen() shall ensure that any streams from previous
1151 * popen() calls that remain open in the parent process are closed
1152 * in the new child process."
1155 for (p = popen_chain; p; p = p->next)
1156 close(p->fd);
1158 execv(argl[0], argl);
1159 _exit (127);
1163 * Parent.
1166 close (child_end);
1167 SAFE_FREE(argl);
1169 /* Link into popen_chain. */
1170 entry->next = popen_chain;
1171 popen_chain = entry;
1172 entry->fd = parent_end;
1174 return entry->fd;
1176 err_exit:
1178 SAFE_FREE(entry);
1179 SAFE_FREE(argl);
1180 close(pipe_fds[0]);
1181 close(pipe_fds[1]);
1182 return -1;
1185 /**************************************************************************
1186 Wrapper for pclose. Modified from the glibc sources.
1187 ****************************************************************************/
1189 int sys_pclose(int fd)
1191 int wstatus;
1192 popen_list **ptr = &popen_chain;
1193 popen_list *entry = NULL;
1194 pid_t wait_pid;
1195 int status = -1;
1197 /* Unlink from popen_chain. */
1198 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1199 if ((*ptr)->fd == fd) {
1200 entry = *ptr;
1201 *ptr = (*ptr)->next;
1202 status = 0;
1203 break;
1207 if (status < 0 || close(entry->fd) < 0)
1208 return -1;
1211 * As Samba is catching and eating child process
1212 * exits we don't really care about the child exit
1213 * code, a -1 with errno = ECHILD will do fine for us.
1216 do {
1217 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1218 } while (wait_pid == -1 && errno == EINTR);
1220 SAFE_FREE(entry);
1222 if (wait_pid == -1)
1223 return -1;
1224 return wstatus;
1227 /**************************************************************************
1228 Wrappers for dlopen, dlsym, dlclose.
1229 ****************************************************************************/
1231 void *sys_dlopen(const char *name, int flags)
1233 #if defined(HAVE_DLOPEN)
1234 return dlopen(name, flags);
1235 #else
1236 return NULL;
1237 #endif
1240 void *sys_dlsym(void *handle, const char *symbol)
1242 #if defined(HAVE_DLSYM)
1243 return dlsym(handle, symbol);
1244 #else
1245 return NULL;
1246 #endif
1249 int sys_dlclose (void *handle)
1251 #if defined(HAVE_DLCLOSE)
1252 return dlclose(handle);
1253 #else
1254 return 0;
1255 #endif
1258 const char *sys_dlerror(void)
1260 #if defined(HAVE_DLERROR)
1261 return dlerror();
1262 #else
1263 return NULL;
1264 #endif
1267 int sys_dup2(int oldfd, int newfd)
1269 #if defined(HAVE_DUP2)
1270 return dup2(oldfd, newfd);
1271 #else
1272 errno = ENOSYS;
1273 return -1;
1274 #endif
1277 /**************************************************************************
1278 Wrapper for Admin Logs.
1279 ****************************************************************************/
1281 void sys_adminlog(int priority, const char *format_str, ...)
1283 va_list ap;
1284 int ret;
1285 char *msgbuf = NULL;
1287 va_start( ap, format_str );
1288 ret = vasprintf( &msgbuf, format_str, ap );
1289 va_end( ap );
1291 if (ret == -1)
1292 return;
1294 #if defined(HAVE_SYSLOG)
1295 syslog( priority, "%s", msgbuf );
1296 #else
1297 DEBUG(0,("%s", msgbuf ));
1298 #endif
1299 SAFE_FREE(msgbuf);
1302 /**************************************************************************
1303 Wrappers for extented attribute calls. Based on the Linux package with
1304 support for IRIX also. Expand as other systems have them.
1305 ****************************************************************************/
1307 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1309 #if defined(HAVE_GETXATTR)
1310 return getxattr(path, name, value, size);
1311 #elif defined(HAVE_ATTR_GET)
1312 int retval, flags = 0;
1313 int valuelength = (int)size;
1314 char *attrname = strchr(name,'.') +1;
1316 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1318 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1320 return retval ? retval : valuelength;
1321 #else
1322 errno = ENOSYS;
1323 return -1;
1324 #endif
1327 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1329 #if defined(HAVE_LGETXATTR)
1330 return lgetxattr(path, name, value, size);
1331 #elif defined(HAVE_ATTR_GET)
1332 int retval, flags = ATTR_DONTFOLLOW;
1333 int valuelength = (int)size;
1334 char *attrname = strchr(name,'.') +1;
1336 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1338 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1340 return retval ? retval : valuelength;
1341 #else
1342 errno = ENOSYS;
1343 return -1;
1344 #endif
1347 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1349 #if defined(HAVE_FGETXATTR)
1350 return fgetxattr(filedes, name, value, size);
1351 #elif defined(HAVE_ATTR_GETF)
1352 int retval, flags = 0;
1353 int valuelength = (int)size;
1354 char *attrname = strchr(name,'.') +1;
1356 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1358 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1360 return retval ? retval : valuelength;
1361 #else
1362 errno = ENOSYS;
1363 return -1;
1364 #endif
1367 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1368 static char attr_buffer[ATTR_MAX_VALUELEN];
1370 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1372 int retval = 0, index;
1373 attrlist_cursor_t *cursor = 0;
1374 int total_size = 0;
1375 attrlist_t * al = (attrlist_t *)attr_buffer;
1376 attrlist_ent_t *ae;
1377 size_t ent_size, left = size;
1378 char *bp = list;
1380 while (True) {
1381 if (filedes)
1382 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1383 else
1384 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1385 if (retval) break;
1386 for (index = 0; index < al->al_count; index++) {
1387 ae = ATTR_ENTRY(attr_buffer, index);
1388 ent_size = strlen(ae->a_name) + sizeof("user.");
1389 if (left >= ent_size) {
1390 strncpy(bp, "user.", sizeof("user."));
1391 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1392 bp += ent_size;
1393 left -= ent_size;
1394 } else if (size) {
1395 errno = ERANGE;
1396 retval = -1;
1397 break;
1399 total_size += ent_size;
1401 if (al->al_more == 0) break;
1403 if (retval == 0) {
1404 flags |= ATTR_ROOT;
1405 cursor = 0;
1406 while (True) {
1407 if (filedes)
1408 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1409 else
1410 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1411 if (retval) break;
1412 for (index = 0; index < al->al_count; index++) {
1413 ae = ATTR_ENTRY(attr_buffer, index);
1414 ent_size = strlen(ae->a_name) + sizeof("system.");
1415 if (left >= ent_size) {
1416 strncpy(bp, "system.", sizeof("system."));
1417 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1418 bp += ent_size;
1419 left -= ent_size;
1420 } else if (size) {
1421 errno = ERANGE;
1422 retval = -1;
1423 break;
1425 total_size += ent_size;
1427 if (al->al_more == 0) break;
1430 return (ssize_t)(retval ? retval : total_size);
1433 #endif
1435 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1437 #if defined(HAVE_LISTXATTR)
1438 return listxattr(path, list, size);
1439 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1440 return irix_attr_list(path, 0, list, size, 0);
1441 #else
1442 errno = ENOSYS;
1443 return -1;
1444 #endif
1447 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1449 #if defined(HAVE_LLISTXATTR)
1450 return llistxattr(path, list, size);
1451 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1452 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1453 #else
1454 errno = ENOSYS;
1455 return -1;
1456 #endif
1459 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1461 #if defined(HAVE_FLISTXATTR)
1462 return flistxattr(filedes, list, size);
1463 #elif defined(HAVE_ATTR_LISTF)
1464 return irix_attr_list(NULL, filedes, list, size, 0);
1465 #else
1466 errno = ENOSYS;
1467 return -1;
1468 #endif
1471 int sys_removexattr (const char *path, const char *name)
1473 #if defined(HAVE_REMOVEXATTR)
1474 return removexattr(path, name);
1475 #elif defined(HAVE_ATTR_REMOVE)
1476 int flags = 0;
1477 char *attrname = strchr(name,'.') +1;
1479 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1481 return attr_remove(path, attrname, flags);
1482 #else
1483 errno = ENOSYS;
1484 return -1;
1485 #endif
1488 int sys_lremovexattr (const char *path, const char *name)
1490 #if defined(HAVE_LREMOVEXATTR)
1491 return lremovexattr(path, name);
1492 #elif defined(HAVE_ATTR_REMOVE)
1493 int flags = ATTR_DONTFOLLOW;
1494 char *attrname = strchr(name,'.') +1;
1496 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1498 return attr_remove(path, attrname, flags);
1499 #else
1500 errno = ENOSYS;
1501 return -1;
1502 #endif
1505 int sys_fremovexattr (int filedes, const char *name)
1507 #if defined(HAVE_FREMOVEXATTR)
1508 return fremovexattr(filedes, name);
1509 #elif defined(HAVE_ATTR_REMOVEF)
1510 int flags = 0;
1511 char *attrname = strchr(name,'.') +1;
1513 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1515 return attr_removef(filedes, attrname, flags);
1516 #else
1517 errno = ENOSYS;
1518 return -1;
1519 #endif
1522 #if !defined(HAVE_SETXATTR)
1523 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1524 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1525 #endif
1527 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1529 #if defined(HAVE_SETXATTR)
1530 return setxattr(path, name, value, size, flags);
1531 #elif defined(HAVE_ATTR_SET)
1532 int myflags = 0;
1533 char *attrname = strchr(name,'.') +1;
1535 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1536 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1537 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1539 return attr_set(path, attrname, (const char *)value, size, myflags);
1540 #else
1541 errno = ENOSYS;
1542 return -1;
1543 #endif
1546 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1548 #if defined(HAVE_LSETXATTR)
1549 return lsetxattr(path, name, value, size, flags);
1550 #elif defined(HAVE_ATTR_SET)
1551 int myflags = ATTR_DONTFOLLOW;
1552 char *attrname = strchr(name,'.') +1;
1554 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1555 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1556 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1558 return attr_set(path, attrname, (const char *)value, size, myflags);
1559 #else
1560 errno = ENOSYS;
1561 return -1;
1562 #endif
1565 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1567 #if defined(HAVE_FSETXATTR)
1568 return fsetxattr(filedes, name, value, size, flags);
1569 #elif defined(HAVE_ATTR_SETF)
1570 int myflags = 0;
1571 char *attrname = strchr(name,'.') +1;
1573 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1574 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1575 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1577 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1578 #else
1579 errno = ENOSYS;
1580 return -1;
1581 #endif
1584 /****************************************************************************
1585 Return the major devicenumber for UNIX extensions.
1586 ****************************************************************************/
1588 uint32 unix_dev_major(SMB_DEV_T dev)
1590 #if defined(HAVE_DEVICE_MAJOR_FN)
1591 return (uint32)major(dev);
1592 #else
1593 return (uint32)(dev >> 8);
1594 #endif
1597 /****************************************************************************
1598 Return the minor devicenumber for UNIX extensions.
1599 ****************************************************************************/
1601 uint32 unix_dev_minor(SMB_DEV_T dev)
1603 #if defined(HAVE_DEVICE_MINOR_FN)
1604 return (uint32)minor(dev);
1605 #else
1606 return (uint32)(dev & 0xff);
1607 #endif