Patch based on work from James Peach <jpeach@sgi.com> to convert over to
[Samba/gebeck_regimport.git] / source3 / lib / system.c
blob16384c8bdf5a2ccc90d9204d6ecfbe7c6a947374
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 #else
494 return(chown(fname,uid,gid));
495 #endif
498 /*******************************************************************
499 os/2 also doesn't have chroot
500 ********************************************************************/
501 int sys_chroot(const char *dname)
503 #ifndef HAVE_CHROOT
504 static int done;
505 if (!done) {
506 DEBUG(1,("WARNING: no chroot!\n"));
507 done=1;
509 errno = ENOSYS;
510 return -1;
511 #else
512 return(chroot(dname));
513 #endif
516 /**************************************************************************
517 A wrapper for gethostbyname() that tries avoids looking up hostnames
518 in the root domain, which can cause dial-on-demand links to come up for no
519 apparent reason.
520 ****************************************************************************/
522 struct hostent *sys_gethostbyname(const char *name)
524 #ifdef REDUCE_ROOT_DNS_LOOKUPS
525 char query[256], hostname[256];
526 char *domain;
528 /* Does this name have any dots in it? If so, make no change */
530 if (strchr_m(name, '.'))
531 return(gethostbyname(name));
533 /* Get my hostname, which should have domain name
534 attached. If not, just do the gethostname on the
535 original string.
538 gethostname(hostname, sizeof(hostname) - 1);
539 hostname[sizeof(hostname) - 1] = 0;
540 if ((domain = strchr_m(hostname, '.')) == NULL)
541 return(gethostbyname(name));
543 /* Attach domain name to query and do modified query.
544 If names too large, just do gethostname on the
545 original string.
548 if((strlen(name) + strlen(domain)) >= sizeof(query))
549 return(gethostbyname(name));
551 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
552 return(gethostbyname(query));
553 #else /* REDUCE_ROOT_DNS_LOOKUPS */
554 return(gethostbyname(name));
555 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
559 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
560 /**************************************************************************
561 Try and abstract process capabilities (for systems that have them).
562 ****************************************************************************/
563 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
565 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
566 cap_t cap = cap_get_proc();
568 if (cap == NULL) {
569 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
570 strerror(errno)));
571 return False;
574 if(enable)
575 cap->cap_effective |= CAP_NETWORK_MGT;
576 else
577 cap->cap_effective &= ~CAP_NETWORK_MGT;
579 if (cap_set_proc(cap) == -1) {
580 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
581 strerror(errno)));
582 cap_free(cap);
583 return False;
586 cap_free(cap);
588 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
590 return True;
593 /**************************************************************************
594 Try and abstract inherited process capabilities (for systems that have them).
595 ****************************************************************************/
597 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
599 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
600 cap_t cap = cap_get_proc();
602 if (cap == NULL) {
603 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
604 strerror(errno)));
605 return False;
608 if(enable)
609 cap->cap_inheritable |= CAP_NETWORK_MGT;
610 else
611 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
613 if (cap_set_proc(cap) == -1) {
614 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
615 strerror(errno)));
616 cap_free(cap);
617 return False;
620 cap_free(cap);
622 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
624 return True;
626 #endif
628 /****************************************************************************
629 Gain the oplock capability from the kernel if possible.
630 ****************************************************************************/
632 void oplock_set_capability(BOOL this_process, BOOL inherit)
634 #if HAVE_KERNEL_OPLOCKS_IRIX
635 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
636 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
637 #endif
640 /**************************************************************************
641 Wrapper for random().
642 ****************************************************************************/
644 long sys_random(void)
646 #if defined(HAVE_RANDOM)
647 return (long)random();
648 #elif defined(HAVE_RAND)
649 return (long)rand();
650 #else
651 DEBUG(0,("Error - no random function available !\n"));
652 exit(1);
653 #endif
656 /**************************************************************************
657 Wrapper for srandom().
658 ****************************************************************************/
660 void sys_srandom(unsigned int seed)
662 #if defined(HAVE_SRANDOM)
663 srandom(seed);
664 #elif defined(HAVE_SRAND)
665 srand(seed);
666 #else
667 DEBUG(0,("Error - no srandom function available !\n"));
668 exit(1);
669 #endif
672 /**************************************************************************
673 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
674 ****************************************************************************/
676 int groups_max(void)
678 #if defined(SYSCONF_SC_NGROUPS_MAX)
679 int ret = sysconf(_SC_NGROUPS_MAX);
680 return (ret == -1) ? NGROUPS_MAX : ret;
681 #else
682 return NGROUPS_MAX;
683 #endif
686 /**************************************************************************
687 Wrapper for getgroups. Deals with broken (int) case.
688 ****************************************************************************/
690 int sys_getgroups(int setlen, gid_t *gidset)
692 #if !defined(HAVE_BROKEN_GETGROUPS)
693 return getgroups(setlen, gidset);
694 #else
696 GID_T gid;
697 GID_T *group_list;
698 int i, ngroups;
700 if(setlen == 0) {
701 return getgroups(setlen, &gid);
705 * Broken case. We need to allocate a
706 * GID_T array of size setlen.
709 if(setlen < 0) {
710 errno = EINVAL;
711 return -1;
714 if (setlen == 0)
715 setlen = groups_max();
717 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
718 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
719 return -1;
722 if((ngroups = getgroups(setlen, group_list)) < 0) {
723 int saved_errno = errno;
724 SAFE_FREE(group_list);
725 errno = saved_errno;
726 return -1;
729 for(i = 0; i < ngroups; i++)
730 gidset[i] = (gid_t)group_list[i];
732 SAFE_FREE(group_list);
733 return ngroups;
734 #endif /* HAVE_BROKEN_GETGROUPS */
738 /**************************************************************************
739 Wrapper for setgroups. Deals with broken (int) case. Automatically used
740 if we have broken getgroups.
741 ****************************************************************************/
743 int sys_setgroups(int setlen, gid_t *gidset)
745 #if !defined(HAVE_SETGROUPS)
746 errno = ENOSYS;
747 return -1;
748 #endif /* HAVE_SETGROUPS */
750 #if !defined(HAVE_BROKEN_GETGROUPS)
751 return setgroups(setlen, gidset);
752 #else
754 GID_T *group_list;
755 int i ;
757 if (setlen == 0)
758 return 0 ;
760 if (setlen < 0 || setlen > groups_max()) {
761 errno = EINVAL;
762 return -1;
766 * Broken case. We need to allocate a
767 * GID_T array of size setlen.
770 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
771 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
772 return -1;
775 for(i = 0; i < setlen; i++)
776 group_list[i] = (GID_T) gidset[i];
778 if(setgroups(setlen, group_list) != 0) {
779 int saved_errno = errno;
780 SAFE_FREE(group_list);
781 errno = saved_errno;
782 return -1;
785 SAFE_FREE(group_list);
786 return 0 ;
787 #endif /* HAVE_BROKEN_GETGROUPS */
790 /**************************************************************************
791 Wrappers for setpwent(), getpwent() and endpwent()
792 ****************************************************************************/
794 void sys_setpwent(void)
796 setpwent();
799 struct passwd *sys_getpwent(void)
801 return getpwent();
804 void sys_endpwent(void)
806 endpwent();
809 /**************************************************************************
810 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
811 ****************************************************************************/
813 struct passwd *sys_getpwnam(const char *name)
815 return getpwnam(name);
818 struct passwd *sys_getpwuid(uid_t uid)
820 return getpwuid(uid);
823 struct group *sys_getgrnam(const char *name)
825 return getgrnam(name);
828 struct group *sys_getgrgid(gid_t gid)
830 return getgrgid(gid);
833 #if 0 /* NOT CURRENTLY USED - JRA */
834 /**************************************************************************
835 The following are the UNICODE versions of *all* system interface functions
836 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
837 which currently are left as ascii as they are not used other than in name
838 resolution.
839 ****************************************************************************/
841 /**************************************************************************
842 Wide stat. Just narrow and call sys_xxx.
843 ****************************************************************************/
845 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
847 pstring fname;
848 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
851 /**************************************************************************
852 Wide lstat. Just narrow and call sys_xxx.
853 ****************************************************************************/
855 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
857 pstring fname;
858 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
861 /**************************************************************************
862 Wide creat. Just narrow and call sys_xxx.
863 ****************************************************************************/
865 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
867 pstring fname;
868 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
871 /**************************************************************************
872 Wide open. Just narrow and call sys_xxx.
873 ****************************************************************************/
875 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
877 pstring fname;
878 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
881 /**************************************************************************
882 Wide fopen. Just narrow and call sys_xxx.
883 ****************************************************************************/
885 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
887 pstring fname;
888 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
891 /**************************************************************************
892 Wide opendir. Just narrow and call sys_xxx.
893 ****************************************************************************/
895 DIR *wsys_opendir(const smb_ucs2_t *wfname)
897 pstring fname;
898 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
901 /**************************************************************************
902 Wide readdir. Return a structure pointer containing a wide filename.
903 ****************************************************************************/
905 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
907 static SMB_STRUCT_WDIRENT retval;
908 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
910 if(!dirval)
911 return NULL;
914 * The only POSIX defined member of this struct is d_name.
917 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
919 return &retval;
922 /**************************************************************************
923 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
924 ****************************************************************************/
926 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
928 pstring fname;
929 char *p = sys_getwd(fname);
931 if(!p)
932 return NULL;
934 return unix_to_unicode(s, p, sizeof(wpstring));
937 /**************************************************************************
938 Wide chown. Just narrow and call sys_xxx.
939 ****************************************************************************/
941 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
943 pstring fname;
944 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
947 /**************************************************************************
948 Wide chroot. Just narrow and call sys_xxx.
949 ****************************************************************************/
951 int wsys_chroot(const smb_ucs2_t *wfname)
953 pstring fname;
954 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
957 /**************************************************************************
958 Wide getpwnam. Return a structure pointer containing wide names.
959 ****************************************************************************/
961 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
963 static SMB_STRUCT_WPASSWD retval;
964 fstring name;
965 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
967 if(!pwret)
968 return NULL;
970 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
971 retval.pw_passwd = pwret->pw_passwd;
972 retval.pw_uid = pwret->pw_uid;
973 retval.pw_gid = pwret->pw_gid;
974 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
975 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
976 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
978 return &retval;
981 /**************************************************************************
982 Wide getpwuid. Return a structure pointer containing wide names.
983 ****************************************************************************/
985 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
987 static SMB_STRUCT_WPASSWD retval;
988 struct passwd *pwret = sys_getpwuid(uid);
990 if(!pwret)
991 return NULL;
993 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
994 retval.pw_passwd = pwret->pw_passwd;
995 retval.pw_uid = pwret->pw_uid;
996 retval.pw_gid = pwret->pw_gid;
997 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
998 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
999 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1001 return &retval;
1003 #endif /* NOT CURRENTLY USED - JRA */
1005 /**************************************************************************
1006 Extract a command into an arg list. Uses a static pstring for storage.
1007 Caller frees returned arg list (which contains pointers into the static pstring).
1008 ****************************************************************************/
1010 static char **extract_args(const char *command)
1012 static pstring trunc_cmd;
1013 char *ptr;
1014 int argcl;
1015 char **argl = NULL;
1016 int i;
1018 pstrcpy(trunc_cmd, command);
1020 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1021 errno = EINVAL;
1022 return NULL;
1026 * Count the args.
1029 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1030 argcl++;
1032 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
1033 return NULL;
1036 * Now do the extraction.
1039 pstrcpy(trunc_cmd, command);
1041 ptr = strtok(trunc_cmd, " \t");
1042 i = 0;
1043 argl[i++] = ptr;
1045 while((ptr = strtok(NULL, " \t")) != NULL)
1046 argl[i++] = ptr;
1048 argl[i++] = NULL;
1049 return argl;
1052 /**************************************************************************
1053 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1054 a sys_getpid() that only does a system call *once*.
1055 ****************************************************************************/
1057 static pid_t mypid = (pid_t)-1;
1059 pid_t sys_fork(void)
1061 pid_t forkret = fork();
1063 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1064 mypid = (pid_t) -1;
1066 return forkret;
1069 /**************************************************************************
1070 Wrapper for getpid. Ensures we only do a system call *once*.
1071 ****************************************************************************/
1073 pid_t sys_getpid(void)
1075 if (mypid == (pid_t)-1)
1076 mypid = getpid();
1078 return mypid;
1081 /**************************************************************************
1082 Wrapper for popen. Safer as it doesn't search a path.
1083 Modified from the glibc sources.
1084 modified by tridge to return a file descriptor. We must kick our FILE* habit
1085 ****************************************************************************/
1087 typedef struct _popen_list
1089 int fd;
1090 pid_t child_pid;
1091 struct _popen_list *next;
1092 } popen_list;
1094 static popen_list *popen_chain;
1096 int sys_popen(const char *command)
1098 int parent_end, child_end;
1099 int pipe_fds[2];
1100 popen_list *entry = NULL;
1101 char **argl = NULL;
1103 if (pipe(pipe_fds) < 0)
1104 return -1;
1106 parent_end = pipe_fds[0];
1107 child_end = pipe_fds[1];
1109 if (!*command) {
1110 errno = EINVAL;
1111 goto err_exit;
1114 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1115 goto err_exit;
1117 ZERO_STRUCTP(entry);
1120 * Extract the command and args into a NULL terminated array.
1123 if(!(argl = extract_args(command)))
1124 goto err_exit;
1126 entry->child_pid = sys_fork();
1128 if (entry->child_pid == -1) {
1129 goto err_exit;
1132 if (entry->child_pid == 0) {
1135 * Child !
1138 int child_std_end = STDOUT_FILENO;
1139 popen_list *p;
1141 close(parent_end);
1142 if (child_end != child_std_end) {
1143 dup2 (child_end, child_std_end);
1144 close (child_end);
1148 * POSIX.2: "popen() shall ensure that any streams from previous
1149 * popen() calls that remain open in the parent process are closed
1150 * in the new child process."
1153 for (p = popen_chain; p; p = p->next)
1154 close(p->fd);
1156 execv(argl[0], argl);
1157 _exit (127);
1161 * Parent.
1164 close (child_end);
1165 SAFE_FREE(argl);
1167 /* Link into popen_chain. */
1168 entry->next = popen_chain;
1169 popen_chain = entry;
1170 entry->fd = parent_end;
1172 return entry->fd;
1174 err_exit:
1176 SAFE_FREE(entry);
1177 SAFE_FREE(argl);
1178 close(pipe_fds[0]);
1179 close(pipe_fds[1]);
1180 return -1;
1183 /**************************************************************************
1184 Wrapper for pclose. Modified from the glibc sources.
1185 ****************************************************************************/
1187 int sys_pclose(int fd)
1189 int wstatus;
1190 popen_list **ptr = &popen_chain;
1191 popen_list *entry = NULL;
1192 pid_t wait_pid;
1193 int status = -1;
1195 /* Unlink from popen_chain. */
1196 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1197 if ((*ptr)->fd == fd) {
1198 entry = *ptr;
1199 *ptr = (*ptr)->next;
1200 status = 0;
1201 break;
1205 if (status < 0 || close(entry->fd) < 0)
1206 return -1;
1209 * As Samba is catching and eating child process
1210 * exits we don't really care about the child exit
1211 * code, a -1 with errno = ECHILD will do fine for us.
1214 do {
1215 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1216 } while (wait_pid == -1 && errno == EINTR);
1218 SAFE_FREE(entry);
1220 if (wait_pid == -1)
1221 return -1;
1222 return wstatus;
1225 /**************************************************************************
1226 Wrappers for dlopen, dlsym, dlclose.
1227 ****************************************************************************/
1229 void *sys_dlopen(const char *name, int flags)
1231 #if defined(HAVE_DLOPEN)
1232 return dlopen(name, flags);
1233 #else
1234 return NULL;
1235 #endif
1238 void *sys_dlsym(void *handle, const char *symbol)
1240 #if defined(HAVE_DLSYM)
1241 return dlsym(handle, symbol);
1242 #else
1243 return NULL;
1244 #endif
1247 int sys_dlclose (void *handle)
1249 #if defined(HAVE_DLCLOSE)
1250 return dlclose(handle);
1251 #else
1252 return 0;
1253 #endif
1256 const char *sys_dlerror(void)
1258 #if defined(HAVE_DLERROR)
1259 return dlerror();
1260 #else
1261 return NULL;
1262 #endif
1265 int sys_dup2(int oldfd, int newfd)
1267 #if defined(HAVE_DUP2)
1268 return dup2(oldfd, newfd);
1269 #else
1270 errno = ENOSYS;
1271 return -1;
1272 #endif
1275 /**************************************************************************
1276 Wrapper for Admin Logs.
1277 ****************************************************************************/
1279 void sys_adminlog(int priority, const char *format_str, ...)
1281 va_list ap;
1282 int ret;
1283 char *msgbuf = NULL;
1285 va_start( ap, format_str );
1286 ret = vasprintf( &msgbuf, format_str, ap );
1287 va_end( ap );
1289 if (ret == -1)
1290 return;
1292 #if defined(HAVE_SYSLOG)
1293 syslog( priority, "%s", msgbuf );
1294 #else
1295 DEBUG(0,("%s", msgbuf ));
1296 #endif
1297 SAFE_FREE(msgbuf);
1300 /**************************************************************************
1301 Wrappers for extented attribute calls. Based on the Linux package with
1302 support for IRIX also. Expand as other systems have them.
1303 ****************************************************************************/
1305 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1307 #if defined(HAVE_GETXATTR)
1308 return getxattr(path, name, value, size);
1309 #elif defined(HAVE_ATTR_GET)
1310 int retval, flags = 0;
1311 int valuelength = (int)size;
1312 char *attrname = strchr(name,'.') +1;
1314 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1316 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1318 return retval ? retval : valuelength;
1319 #else
1320 errno = ENOSYS;
1321 return -1;
1322 #endif
1325 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1327 #if defined(HAVE_LGETXATTR)
1328 return lgetxattr(path, name, value, size);
1329 #elif defined(HAVE_ATTR_GET)
1330 int retval, flags = ATTR_DONTFOLLOW;
1331 int valuelength = (int)size;
1332 char *attrname = strchr(name,'.') +1;
1334 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1336 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1338 return retval ? retval : valuelength;
1339 #else
1340 errno = ENOSYS;
1341 return -1;
1342 #endif
1345 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1347 #if defined(HAVE_FGETXATTR)
1348 return fgetxattr(filedes, name, value, size);
1349 #elif defined(HAVE_ATTR_GETF)
1350 int retval, flags = 0;
1351 int valuelength = (int)size;
1352 char *attrname = strchr(name,'.') +1;
1354 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1356 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1358 return retval ? retval : valuelength;
1359 #else
1360 errno = ENOSYS;
1361 return -1;
1362 #endif
1365 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1366 static char attr_buffer[ATTR_MAX_VALUELEN];
1368 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1370 int retval = 0, index;
1371 attrlist_cursor_t *cursor = 0;
1372 int total_size = 0;
1373 attrlist_t * al = (attrlist_t *)attr_buffer;
1374 attrlist_ent_t *ae;
1375 size_t ent_size, left = size;
1376 char *bp = list;
1378 while (True) {
1379 if (filedes)
1380 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1381 else
1382 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1383 if (retval) break;
1384 for (index = 0; index < al->al_count; index++) {
1385 ae = ATTR_ENTRY(attr_buffer, index);
1386 ent_size = strlen(ae->a_name) + sizeof("user.");
1387 if (left >= ent_size) {
1388 strncpy(bp, "user.", sizeof("user."));
1389 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1390 bp += ent_size;
1391 left -= ent_size;
1392 } else if (size) {
1393 errno = ERANGE;
1394 retval = -1;
1395 break;
1397 total_size += ent_size;
1399 if (al->al_more == 0) break;
1401 if (retval == 0) {
1402 flags |= ATTR_ROOT;
1403 cursor = 0;
1404 while (True) {
1405 if (filedes)
1406 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1407 else
1408 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1409 if (retval) break;
1410 for (index = 0; index < al->al_count; index++) {
1411 ae = ATTR_ENTRY(attr_buffer, index);
1412 ent_size = strlen(ae->a_name) + sizeof("system.");
1413 if (left >= ent_size) {
1414 strncpy(bp, "system.", sizeof("system."));
1415 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1416 bp += ent_size;
1417 left -= ent_size;
1418 } else if (size) {
1419 errno = ERANGE;
1420 retval = -1;
1421 break;
1423 total_size += ent_size;
1425 if (al->al_more == 0) break;
1428 return (ssize_t)(retval ? retval : total_size);
1431 #endif
1433 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1435 #if defined(HAVE_LISTXATTR)
1436 return listxattr(path, list, size);
1437 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1438 return irix_attr_list(path, 0, list, size, 0);
1439 #else
1440 errno = ENOSYS;
1441 return -1;
1442 #endif
1445 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1447 #if defined(HAVE_LLISTXATTR)
1448 return llistxattr(path, list, size);
1449 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1450 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1451 #else
1452 errno = ENOSYS;
1453 return -1;
1454 #endif
1457 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1459 #if defined(HAVE_FLISTXATTR)
1460 return flistxattr(filedes, list, size);
1461 #elif defined(HAVE_ATTR_LISTF)
1462 return irix_attr_list(NULL, filedes, list, size, 0);
1463 #else
1464 errno = ENOSYS;
1465 return -1;
1466 #endif
1469 int sys_removexattr (const char *path, const char *name)
1471 #if defined(HAVE_REMOVEXATTR)
1472 return removexattr(path, name);
1473 #elif defined(HAVE_ATTR_REMOVE)
1474 int flags = 0;
1475 char *attrname = strchr(name,'.') +1;
1477 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1479 return attr_remove(path, attrname, flags);
1480 #else
1481 errno = ENOSYS;
1482 return -1;
1483 #endif
1486 int sys_lremovexattr (const char *path, const char *name)
1488 #if defined(HAVE_LREMOVEXATTR)
1489 return lremovexattr(path, name);
1490 #elif defined(HAVE_ATTR_REMOVE)
1491 int flags = ATTR_DONTFOLLOW;
1492 char *attrname = strchr(name,'.') +1;
1494 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1496 return attr_remove(path, attrname, flags);
1497 #else
1498 errno = ENOSYS;
1499 return -1;
1500 #endif
1503 int sys_fremovexattr (int filedes, const char *name)
1505 #if defined(HAVE_FREMOVEXATTR)
1506 return fremovexattr(filedes, name);
1507 #elif defined(HAVE_ATTR_REMOVEF)
1508 int flags = 0;
1509 char *attrname = strchr(name,'.') +1;
1511 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1513 return attr_removef(filedes, attrname, flags);
1514 #else
1515 errno = ENOSYS;
1516 return -1;
1517 #endif
1520 #if !defined(HAVE_SETXATTR)
1521 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1522 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1523 #endif
1525 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1527 #if defined(HAVE_SETXATTR)
1528 return setxattr(path, name, value, size, flags);
1529 #elif defined(HAVE_ATTR_SET)
1530 int myflags = 0;
1531 char *attrname = strchr(name,'.') +1;
1533 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1534 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1535 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1537 return attr_set(path, attrname, (const char *)value, size, myflags);
1538 #else
1539 errno = ENOSYS;
1540 return -1;
1541 #endif
1544 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1546 #if defined(HAVE_LSETXATTR)
1547 return lsetxattr(path, name, value, size, flags);
1548 #elif defined(HAVE_ATTR_SET)
1549 int myflags = ATTR_DONTFOLLOW;
1550 char *attrname = strchr(name,'.') +1;
1552 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1553 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1554 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1556 return attr_set(path, attrname, (const char *)value, size, myflags);
1557 #else
1558 errno = ENOSYS;
1559 return -1;
1560 #endif
1563 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1565 #if defined(HAVE_FSETXATTR)
1566 return fsetxattr(filedes, name, value, size, flags);
1567 #elif defined(HAVE_ATTR_SETF)
1568 int myflags = 0;
1569 char *attrname = strchr(name,'.') +1;
1571 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1572 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1573 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1575 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1576 #else
1577 errno = ENOSYS;
1578 return -1;
1579 #endif