2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1998
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.
24 extern int DEBUGLEVEL;
27 The idea is that this file will eventually have wrappers around all
28 important system calls in samba. The aims are:
30 - to enable easier porting by putting OS dependent stuff in here
32 - to allow for hooks into other "pseudo-filesystems"
34 - to allow easier integration of things like the japanese extensions
36 - to support the philosophy of Samba to expose the features of
37 the OS within the SMB model. In general whatever file/printer/variable
38 expansions/etc make sense to the OS should be acceptable to Samba.
43 /*******************************************************************
44 A wrapper for usleep in case we don't have one.
45 ********************************************************************/
47 int sys_usleep(long usecs)
54 * We need this braindamage as the glibc usleep
55 * is not SPEC1170 complient... grumble... JRA.
58 if(usecs < 0 || usecs > 1000000) {
66 #else /* HAVE_USLEEP */
68 * Fake it with select...
71 tval.tv_usec = usecs/1000;
72 select(0,NULL,NULL,NULL,&tval);
74 #endif /* HAVE_USLEEP */
77 /*******************************************************************
78 A stat() wrapper that will deal with 64 bit filesizes.
79 ********************************************************************/
81 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
84 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
85 ret = stat64(fname, sbuf);
87 ret = stat(fname, sbuf);
89 /* we always want directories to appear zero size */
90 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
94 /*******************************************************************
95 An fstat() wrapper that will deal with 64 bit filesizes.
96 ********************************************************************/
98 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
101 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
102 ret = fstat64(fd, sbuf);
104 ret = fstat(fd, sbuf);
106 /* we always want directories to appear zero size */
107 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
111 /*******************************************************************
112 An lstat() wrapper that will deal with 64 bit filesizes.
113 ********************************************************************/
115 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
118 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
119 ret = lstat64(fname, sbuf);
121 ret = lstat(fname, sbuf);
123 /* we always want directories to appear zero size */
124 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
128 /*******************************************************************
129 An ftruncate() wrapper that will deal with 64 bit filesizes.
130 ********************************************************************/
132 int sys_ftruncate(int fd, SMB_OFF_T offset)
134 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
135 return ftruncate64(fd, offset);
137 return ftruncate(fd, offset);
141 /*******************************************************************
142 An lseek() wrapper that will deal with 64 bit filesizes.
143 ********************************************************************/
145 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
147 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
148 return lseek64(fd, offset, whence);
150 return lseek(fd, offset, whence);
154 /*******************************************************************
155 An fseek() wrapper that will deal with 64 bit filesizes.
156 ********************************************************************/
158 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
160 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
161 return fseek64(fp, offset, whence);
162 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
163 return fseeko64(fp, offset, whence);
165 return fseek(fp, offset, whence);
169 /*******************************************************************
170 An ftell() wrapper that will deal with 64 bit filesizes.
171 ********************************************************************/
173 SMB_OFF_T sys_ftell(FILE *fp)
175 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
176 return (SMB_OFF_T)ftell64(fp);
177 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
178 return (SMB_OFF_T)ftello64(fp);
180 return (SMB_OFF_T)ftell(fp);
184 /*******************************************************************
185 A creat() wrapper that will deal with 64 bit filesizes.
186 ********************************************************************/
188 int sys_creat(const char *path, mode_t mode)
190 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
191 return creat64(path, mode);
194 * If creat64 isn't defined then ensure we call a potential open64.
197 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
201 /*******************************************************************
202 An open() wrapper that will deal with 64 bit filesizes.
203 ********************************************************************/
205 int sys_open(const char *path, int oflag, mode_t mode)
207 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
208 return open64(path, oflag, mode);
210 return open(path, oflag, mode);
214 /*******************************************************************
215 An fopen() wrapper that will deal with 64 bit filesizes.
216 ********************************************************************/
218 FILE *sys_fopen(const char *path, const char *type)
220 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
221 return fopen64(path, type);
223 return fopen(path, type);
227 /*******************************************************************
228 A readdir wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
231 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
234 return readdir64(dirp);
236 return readdir(dirp);
240 /*******************************************************************
241 The wait() calls vary between systems
242 ********************************************************************/
244 int sys_waitpid(pid_t pid,int *status,int options)
247 return waitpid(pid,status,options);
248 #else /* HAVE_WAITPID */
249 return wait4(pid, status, options, NULL);
250 #endif /* HAVE_WAITPID */
253 /*******************************************************************
254 system wrapper for getwd
255 ********************************************************************/
256 char *sys_getwd(char *s)
260 wd = (char *)getcwd(s, sizeof (pstring));
262 wd = (char *)getwd(s);
267 /*******************************************************************
268 system wrapper for symlink
269 ********************************************************************/
271 int sys_symlink(const char *oldpath, const char *newpath)
277 return symlink(oldpath, newpath);
281 /*******************************************************************
282 system wrapper for readlink
283 ********************************************************************/
285 int sys_readlink(const char *path, char *buf, size_t bufsiz)
287 #ifndef HAVE_READLINK
291 return readlink(path, buf, bufsiz);
295 /*******************************************************************
296 chown isn't used much but OS/2 doesn't have it
297 ********************************************************************/
299 int sys_chown(const char *fname,uid_t uid,gid_t gid)
304 DEBUG(1,("WARNING: no chown!\n"));
308 return(chown(fname,uid,gid));
312 /*******************************************************************
313 os/2 also doesn't have chroot
314 ********************************************************************/
315 int sys_chroot(const char *dname)
320 DEBUG(1,("WARNING: no chroot!\n"));
326 return(chroot(dname));
330 /**************************************************************************
331 A wrapper for gethostbyname() that tries avoids looking up hostnames
332 in the root domain, which can cause dial-on-demand links to come up for no
334 ****************************************************************************/
335 struct hostent *sys_gethostbyname(const char *name)
337 #ifdef REDUCE_ROOT_DNS_LOOKUPS
338 char query[256], hostname[256];
341 /* Does this name have any dots in it? If so, make no change */
343 if (strchr_m(name, '.'))
344 return(gethostbyname(name));
346 /* Get my hostname, which should have domain name
347 attached. If not, just do the gethostname on the
351 gethostname(hostname, sizeof(hostname) - 1);
352 hostname[sizeof(hostname) - 1] = 0;
353 if ((domain = strchr_m(hostname, '.')) == NULL)
354 return(gethostbyname(name));
356 /* Attach domain name to query and do modified query.
357 If names too large, just do gethostname on the
361 if((strlen(name) + strlen(domain)) >= sizeof(query))
362 return(gethostbyname(name));
364 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
365 return(gethostbyname(query));
366 #else /* REDUCE_ROOT_DNS_LOOKUPS */
367 return(gethostbyname(name));
368 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
372 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
373 /**************************************************************************
374 Try and abstract process capabilities (for systems that have them).
375 ****************************************************************************/
376 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
378 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
380 cap_t cap = cap_get_proc();
383 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
389 cap->cap_effective |= CAP_NETWORK_MGT;
391 cap->cap_effective &= ~CAP_NETWORK_MGT;
393 if (cap_set_proc(cap) == -1) {
394 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
402 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
407 /**************************************************************************
408 Try and abstract inherited process capabilities (for systems that have them).
409 ****************************************************************************/
411 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
413 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
415 cap_t cap = cap_get_proc();
418 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
424 cap->cap_inheritable |= CAP_NETWORK_MGT;
426 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
428 if (cap_set_proc(cap) == -1) {
429 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
437 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
443 /****************************************************************************
444 gain the oplock capability from the kernel if possible
445 ****************************************************************************/
446 void oplock_set_capability(BOOL this_process, BOOL inherit)
448 #if HAVE_KERNEL_OPLOCKS_IRIX
449 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
450 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
454 /**************************************************************************
455 Wrapper for random().
456 ****************************************************************************/
458 long sys_random(void)
460 #if defined(HAVE_RANDOM)
461 return (long)random();
462 #elif defined(HAVE_RAND)
465 DEBUG(0,("Error - no random function available !\n"));
470 /**************************************************************************
471 Wrapper for srandom().
472 ****************************************************************************/
474 void sys_srandom(unsigned int seed)
476 #if defined(HAVE_SRANDOM)
478 #elif defined(HAVE_SRAND)
481 DEBUG(0,("Error - no srandom function available !\n"));
486 /**************************************************************************
487 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
488 ****************************************************************************/
492 #if defined(SYSCONF_SC_NGROUPS_MAX)
493 int ret = sysconf(_SC_NGROUPS_MAX);
494 return (ret == -1) ? NGROUPS_MAX : ret;
500 /**************************************************************************
501 Wrapper for getgroups. Deals with broken (int) case.
502 ****************************************************************************/
504 int sys_getgroups(int setlen, gid_t *gidset)
506 #if !defined(HAVE_BROKEN_GETGROUPS)
507 return getgroups(setlen, gidset);
515 return getgroups(setlen, &gid);
519 * Broken case. We need to allocate a
520 * GID_T array of size setlen.
529 setlen = groups_max();
531 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
532 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
536 if((ngroups = getgroups(setlen, group_list)) < 0) {
537 int saved_errno = errno;
538 SAFE_FREE(group_list);
543 for(i = 0; i < ngroups; i++)
544 gidset[i] = (gid_t)group_list[i];
546 SAFE_FREE(group_list);
548 #endif /* HAVE_BROKEN_GETGROUPS */
551 #ifdef HAVE_SETGROUPS
553 /**************************************************************************
554 Wrapper for setgroups. Deals with broken (int) case. Automatically used
555 if we have broken getgroups.
556 ****************************************************************************/
558 int sys_setgroups(int setlen, gid_t *gidset)
560 #if !defined(HAVE_BROKEN_GETGROUPS)
561 return setgroups(setlen, gidset);
570 if (setlen < 0 || setlen > groups_max()) {
576 * Broken case. We need to allocate a
577 * GID_T array of size setlen.
580 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
581 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
585 for(i = 0; i < setlen; i++)
586 group_list[i] = (GID_T) gidset[i];
588 if(setgroups(setlen, group_list) != 0) {
589 int saved_errno = errno;
590 SAFE_FREE(group_list);
595 SAFE_FREE(group_list);
597 #endif /* HAVE_BROKEN_GETGROUPS */
600 #endif /* HAVE_SETGROUPS */
603 * We only wrap pw_name and pw_passwd for now as these
604 * are the only potentially modified fields.
607 /**************************************************************************
608 Helper function for getpwnam/getpwuid wrappers.
609 ****************************************************************************/
620 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
621 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
623 static int num_lookups; /* Counter so we don't always use cache. */
624 #ifndef PW_RET_CACHE_MAX_LOOKUPS
625 #define PW_RET_CACHE_MAX_LOOKUPS 100
628 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
630 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
632 fstrcpy(dst->pw_name, pass->pw_name);
633 dst->pass.pw_name = dst->pw_name;
635 fstrcpy(dst->pw_passwd, pass->pw_passwd);
636 dst->pass.pw_passwd = dst->pw_passwd;
638 fstrcpy(dst->pw_gecos, pass->pw_gecos);
639 dst->pass.pw_gecos = dst->pw_gecos;
641 pstrcpy(dst->pw_dir, pass->pw_dir);
642 dst->pass.pw_dir = dst->pw_dir;
644 pstrcpy(dst->pw_shell, pass->pw_shell);
645 dst->pass.pw_shell = dst->pw_shell;
648 static struct passwd *setup_pwret(struct passwd *pass)
651 /* Clear the caches. */
652 memset(&pw_cache, '\0', sizeof(struct saved_pw));
653 memset(&pw_mod, '\0', sizeof(struct saved_pw));
658 copy_pwent( &pw_mod, pass);
660 if (pass != &pw_cache.pass) {
662 /* If it's a cache miss we must also refill the cache. */
664 copy_pwent( &pw_cache, pass);
672 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
678 /**************************************************************************
679 Wrappers for setpwent(), getpwent() and endpwent()
680 ****************************************************************************/
682 void sys_setpwent(void)
684 setup_pwret(NULL); /* Clear cache. */
688 struct passwd *sys_getpwent(void)
690 return setup_pwret(getpwent());
693 void sys_endpwent(void)
695 setup_pwret(NULL); /* Clear cache. */
699 /**************************************************************************
700 Wrapper for getpwnam(). Always returns a static that can be modified.
701 ****************************************************************************/
703 struct passwd *sys_getpwnam(const char *name)
705 if (!name || !name[0])
708 /* check for a cache hit first */
709 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
710 return setup_pwret(&pw_cache.pass);
713 return setup_pwret(getpwnam(name));
716 /**************************************************************************
717 Wrapper for getpwuid(). Always returns a static that can be modified.
718 ****************************************************************************/
720 struct passwd *sys_getpwuid(uid_t uid)
722 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
723 return setup_pwret(&pw_cache.pass);
726 return setup_pwret(getpwuid(uid));
729 /**************************************************************************
730 Extract a command into an arg list. Uses a static pstring for storage.
731 Caller frees returned arg list (which contains pointers into the static pstring).
732 ****************************************************************************/
734 static char **extract_args(const char *command)
736 static pstring trunc_cmd;
742 pstrcpy(trunc_cmd, command);
744 if(!(ptr = strtok(trunc_cmd, " \t"))) {
753 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
756 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
760 * Now do the extraction.
763 pstrcpy(trunc_cmd, command);
765 ptr = strtok(trunc_cmd, " \t");
769 while((ptr = strtok(NULL, " \t")) != NULL)
776 /**************************************************************************
777 Wrapper for fork. Ensures that mypid is reset. Used so we can write
778 a sys_getpid() that only does a system call *once*.
779 ****************************************************************************/
781 static pid_t mypid = (pid_t)-1;
785 pid_t forkret = fork();
787 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
793 /**************************************************************************
794 Wrapper for getpid. Ensures we only do a system call *once*.
795 ****************************************************************************/
797 pid_t sys_getpid(void)
799 if (mypid == (pid_t)-1)
805 /**************************************************************************
806 Wrapper for popen. Safer as it doesn't search a path.
807 Modified from the glibc sources.
808 modified by tridge to return a file descriptor. We must kick our FILE* habit
809 ****************************************************************************/
811 typedef struct _popen_list
815 struct _popen_list *next;
818 static popen_list *popen_chain;
820 int sys_popen(const char *command)
822 int parent_end, child_end;
824 popen_list *entry = NULL;
827 if (pipe(pipe_fds) < 0)
830 parent_end = pipe_fds[0];
831 child_end = pipe_fds[1];
838 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
844 * Extract the command and args into a NULL terminated array.
847 if(!(argl = extract_args(command)))
850 entry->child_pid = sys_fork();
852 if (entry->child_pid == -1) {
856 if (entry->child_pid == 0) {
862 int child_std_end = STDOUT_FILENO;
866 if (child_end != child_std_end) {
867 dup2 (child_end, child_std_end);
872 * POSIX.2: "popen() shall ensure that any streams from previous
873 * popen() calls that remain open in the parent process are closed
874 * in the new child process."
877 for (p = popen_chain; p; p = p->next)
880 execv(argl[0], argl);
891 /* Link into popen_chain. */
892 entry->next = popen_chain;
894 entry->fd = parent_end;
907 /**************************************************************************
908 Wrapper for pclose. Modified from the glibc sources.
909 ****************************************************************************/
910 int sys_pclose(int fd)
913 popen_list **ptr = &popen_chain;
914 popen_list *entry = NULL;
918 /* Unlink from popen_chain. */
919 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
920 if ((*ptr)->fd == fd) {
928 if (status < 0 || close(entry->fd) < 0)
932 * As Samba is catching and eating child process
933 * exits we don't really care about the child exit
934 * code, a -1 with errno = ECHILD will do fine for us.
938 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
939 } while (wait_pid == -1 && errno == EINTR);
948 /**************************************************************************
949 Wrappers for dlopen, dlsym, dlclose.
950 ****************************************************************************/
952 void *sys_dlopen(const char *name, int flags)
955 return dlopen(name, flags);
961 void *sys_dlsym(void *handle, char *symbol)
964 return dlsym(handle, symbol);
970 int sys_dlclose (void *handle)
973 return dlclose(handle);
979 const char *sys_dlerror(void)