2 Unix SMB/CIFS implementation.
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.
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)
52 * We need this braindamage as the glibc usleep
53 * is not SPEC1170 complient... grumble... JRA.
56 if(usecs < 0 || usecs > 1000000) {
64 #else /* HAVE_USLEEP */
66 * Fake it with select...
69 tval.tv_usec = usecs/1000;
70 select(0,NULL,NULL,NULL,&tval);
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)
84 ret = read(fd, buf, count);
85 } while (ret == -1 && errno == EINTR);
89 /*******************************************************************
90 A write wrapper that will deal with EINTR.
91 ********************************************************************/
93 ssize_t sys_write(int fd, const void *buf, size_t count)
98 ret = write(fd, buf, count);
99 } while (ret == -1 && errno == EINTR);
103 /*******************************************************************
104 A send wrapper that will deal with EINTR.
105 ********************************************************************/
107 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
112 ret = send(s, msg, len, flags);
113 } while (ret == -1 && errno == EINTR);
117 /*******************************************************************
118 A sendto wrapper that will deal with EINTR.
119 ********************************************************************/
121 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
126 ret = sendto(s, msg, len, flags, to, tolen);
127 } while (ret == -1 && errno == EINTR);
131 /*******************************************************************
132 A recvfrom wrapper that will deal with EINTR.
133 ********************************************************************/
135 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
140 ret = recvfrom(s, buf, len, flags, from, fromlen);
141 } while (ret == -1 && errno == EINTR);
145 /*******************************************************************
146 A fcntl wrapper that will deal with EINTR.
147 ********************************************************************/
149 int sys_fcntl_ptr(int fd, int cmd, void *arg)
154 ret = fcntl(fd, cmd, arg);
155 } while (ret == -1 && errno == EINTR);
159 /*******************************************************************
160 A fcntl wrapper that will deal with EINTR.
161 ********************************************************************/
163 int sys_fcntl_long(int fd, int cmd, long arg)
168 ret = fcntl(fd, cmd, arg);
169 } while (ret == -1 && errno == EINTR);
173 /*******************************************************************
174 A stat() wrapper that will deal with 64 bit filesizes.
175 ********************************************************************/
177 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
180 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
181 ret = stat64(fname, sbuf);
183 ret = stat(fname, sbuf);
185 /* we always want directories to appear zero size */
186 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
190 /*******************************************************************
191 An fstat() wrapper that will deal with 64 bit filesizes.
192 ********************************************************************/
194 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
197 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
198 ret = fstat64(fd, sbuf);
200 ret = fstat(fd, sbuf);
202 /* we always want directories to appear zero size */
203 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
207 /*******************************************************************
208 An lstat() wrapper that will deal with 64 bit filesizes.
209 ********************************************************************/
211 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
215 ret = lstat64(fname, sbuf);
217 ret = lstat(fname, sbuf);
219 /* we always want directories to appear zero size */
220 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
224 /*******************************************************************
225 An ftruncate() wrapper that will deal with 64 bit filesizes.
226 ********************************************************************/
228 int sys_ftruncate(int fd, SMB_OFF_T offset)
230 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
231 return ftruncate64(fd, offset);
233 return ftruncate(fd, offset);
237 /*******************************************************************
238 An lseek() wrapper that will deal with 64 bit filesizes.
239 ********************************************************************/
241 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
243 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
244 return lseek64(fd, offset, whence);
246 return lseek(fd, offset, whence);
250 /*******************************************************************
251 A creat() wrapper that will deal with 64 bit filesizes.
252 ********************************************************************/
254 int sys_creat(const char *path, mode_t mode)
256 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
257 return creat64(path, mode);
260 * If creat64 isn't defined then ensure we call a potential open64.
263 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
267 /*******************************************************************
268 An open() wrapper that will deal with 64 bit filesizes.
269 ********************************************************************/
271 int sys_open(const char *path, int oflag, mode_t mode)
273 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
274 return open64(path, oflag, mode);
276 return open(path, oflag, mode);
280 /*******************************************************************
281 An fopen() wrapper that will deal with 64 bit filesizes.
282 ********************************************************************/
284 FILE *sys_fopen(const char *path, const char *type)
286 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
287 return fopen64(path, type);
289 return fopen(path, type);
293 /*******************************************************************
294 A readdir wrapper that will deal with 64 bit filesizes.
295 ********************************************************************/
297 struct smb_dirent *sys_readdir(DIR *dirp)
299 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
300 return readdir64(dirp);
302 return readdir(dirp);
306 /*******************************************************************
307 The wait() calls vary between systems
308 ********************************************************************/
310 int sys_waitpid(pid_t pid,int *status,int options)
313 return waitpid(pid,status,options);
314 #else /* HAVE_WAITPID */
315 return wait4(pid, status, options, NULL);
316 #endif /* HAVE_WAITPID */
319 /*******************************************************************
320 System wrapper for getwd
321 ********************************************************************/
323 char *sys_getwd(char *s)
327 wd = (char *)getcwd(s, sizeof (pstring));
329 wd = (char *)getwd(s);
334 /*******************************************************************
335 system wrapper for link
336 ********************************************************************/
338 int sys_link(const char *oldpath, const char *newpath)
344 return link(oldpath, newpath);
348 /*******************************************************************
349 os/2 also doesn't have chroot
350 ********************************************************************/
351 int sys_chroot(const char *dname)
356 DEBUG(1,("WARNING: no chroot!\n"));
362 return(chroot(dname));
366 /**************************************************************************
367 A wrapper for gethostbyname() that tries avoids looking up hostnames
368 in the root domain, which can cause dial-on-demand links to come up for no
370 ****************************************************************************/
372 struct hostent *sys_gethostbyname(const char *name)
374 #ifdef REDUCE_ROOT_DNS_LOOKUPS
375 char query[256], hostname[256];
378 /* Does this name have any dots in it? If so, make no change */
380 if (strchr_m(name, '.'))
381 return(gethostbyname(name));
383 /* Get my hostname, which should have domain name
384 attached. If not, just do the gethostname on the
388 gethostname(hostname, sizeof(hostname) - 1);
389 hostname[sizeof(hostname) - 1] = 0;
390 if ((domain = strchr_m(hostname, '.')) == NULL)
391 return(gethostbyname(name));
393 /* Attach domain name to query and do modified query.
394 If names too large, just do gethostname on the
398 if((strlen(name) + strlen(domain)) >= sizeof(query))
399 return(gethostbyname(name));
401 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
402 return(gethostbyname(query));
403 #else /* REDUCE_ROOT_DNS_LOOKUPS */
404 return(gethostbyname(name));
405 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
409 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
410 /**************************************************************************
411 Try and abstract process capabilities (for systems that have them).
412 ****************************************************************************/
413 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
415 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
416 cap_t cap = cap_get_proc();
419 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
425 cap->cap_effective |= CAP_NETWORK_MGT;
427 cap->cap_effective &= ~CAP_NETWORK_MGT;
429 if (cap_set_proc(cap) == -1) {
430 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
438 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
443 /**************************************************************************
444 Try and abstract inherited process capabilities (for systems that have them).
445 ****************************************************************************/
447 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
449 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
450 cap_t cap = cap_get_proc();
453 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
459 cap->cap_inheritable |= CAP_NETWORK_MGT;
461 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
463 if (cap_set_proc(cap) == -1) {
464 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
472 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
478 /****************************************************************************
479 Gain the oplock capability from the kernel if possible.
480 ****************************************************************************/
482 void oplock_set_capability(BOOL this_process, BOOL inherit)
484 #if HAVE_KERNEL_OPLOCKS_IRIX
485 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
486 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
490 /**************************************************************************
491 Wrapper for random().
492 ****************************************************************************/
494 long sys_random(void)
496 #if defined(HAVE_RANDOM)
497 return (long)random();
498 #elif defined(HAVE_RAND)
501 DEBUG(0,("Error - no random function available !\n"));
506 /**************************************************************************
507 Wrapper for srandom().
508 ****************************************************************************/
510 void sys_srandom(unsigned int seed)
512 #if defined(HAVE_SRANDOM)
514 #elif defined(HAVE_SRAND)
517 DEBUG(0,("Error - no srandom function available !\n"));
522 /**************************************************************************
523 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
524 ****************************************************************************/
528 #if defined(SYSCONF_SC_NGROUPS_MAX)
529 int ret = sysconf(_SC_NGROUPS_MAX);
530 return (ret == -1) ? NGROUPS_MAX : ret;
536 /**************************************************************************
537 Wrapper for getgroups. Deals with broken (int) case.
538 ****************************************************************************/
540 int sys_getgroups(int setlen, gid_t *gidset)
542 #if !defined(HAVE_BROKEN_GETGROUPS)
543 return getgroups(setlen, gidset);
551 return getgroups(setlen, &gid);
555 * Broken case. We need to allocate a
556 * GID_T array of size setlen.
565 setlen = groups_max();
567 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
568 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
572 if((ngroups = getgroups(setlen, group_list)) < 0) {
573 int saved_errno = errno;
574 SAFE_FREE(group_list);
579 for(i = 0; i < ngroups; i++)
580 gidset[i] = (gid_t)group_list[i];
582 SAFE_FREE(group_list);
584 #endif /* HAVE_BROKEN_GETGROUPS */
587 #ifdef HAVE_SETGROUPS
589 /**************************************************************************
590 Wrapper for setgroups. Deals with broken (int) case. Automatically used
591 if we have broken getgroups.
592 ****************************************************************************/
594 int sys_setgroups(int setlen, gid_t *gidset)
596 #if !defined(HAVE_BROKEN_GETGROUPS)
597 return setgroups(setlen, gidset);
606 if (setlen < 0 || setlen > groups_max()) {
612 * Broken case. We need to allocate a
613 * GID_T array of size setlen.
616 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
617 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
621 for(i = 0; i < setlen; i++)
622 group_list[i] = (GID_T) gidset[i];
624 if(setgroups(setlen, group_list) != 0) {
625 int saved_errno = errno;
626 SAFE_FREE(group_list);
631 SAFE_FREE(group_list);
633 #endif /* HAVE_BROKEN_GETGROUPS */
636 #endif /* HAVE_SETGROUPS */
638 struct passwd *sys_getpwent(void)
643 void sys_endpwent(void)
648 /**************************************************************************
649 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
650 ****************************************************************************/
652 struct passwd *sys_getpwnam(const char *name)
654 return getpwnam(name);
657 struct passwd *sys_getpwuid(uid_t uid)
659 return getpwuid(uid);
662 struct group *sys_getgrnam(const char *name)
664 return getgrnam(name);
667 struct group *sys_getgrgid(gid_t gid)
669 return getgrgid(gid);
673 /**************************************************************************
674 Extract a command into an arg list. Uses a static pstring for storage.
675 Caller frees returned arg list (which contains pointers into the static pstring).
676 ****************************************************************************/
678 static char **extract_args(const char *command)
680 static pstring trunc_cmd;
686 pstrcpy(trunc_cmd, command);
688 if(!(ptr = strtok(trunc_cmd, " \t"))) {
697 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
700 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
704 * Now do the extraction.
707 pstrcpy(trunc_cmd, command);
709 ptr = strtok(trunc_cmd, " \t");
713 while((ptr = strtok(NULL, " \t")) != NULL)
720 /**************************************************************************
721 Wrapper for popen. Safer as it doesn't search a path.
722 Modified from the glibc sources.
723 modified by tridge to return a file descriptor. We must kick our FILE* habit
724 ****************************************************************************/
726 typedef struct _popen_list
730 struct _popen_list *next;
733 static popen_list *popen_chain;
735 int sys_popen(const char *command)
737 int parent_end, child_end;
739 popen_list *entry = NULL;
742 if (pipe(pipe_fds) < 0)
745 parent_end = pipe_fds[0];
746 child_end = pipe_fds[1];
753 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
759 * Extract the command and args into a NULL terminated array.
762 if(!(argl = extract_args(command)))
765 entry->child_pid = fork();
767 if (entry->child_pid == -1) {
771 if (entry->child_pid == 0) {
777 int child_std_end = STDOUT_FILENO;
781 if (child_end != child_std_end) {
782 dup2 (child_end, child_std_end);
787 * POSIX.2: "popen() shall ensure that any streams from previous
788 * popen() calls that remain open in the parent process are closed
789 * in the new child process."
792 for (p = popen_chain; p; p = p->next)
795 execv(argl[0], argl);
806 /* Link into popen_chain. */
807 entry->next = popen_chain;
809 entry->fd = parent_end;
822 /**************************************************************************
823 Wrapper for pclose. Modified from the glibc sources.
824 ****************************************************************************/
826 int sys_pclose(int fd)
829 popen_list **ptr = &popen_chain;
830 popen_list *entry = NULL;
834 /* Unlink from popen_chain. */
835 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
836 if ((*ptr)->fd == fd) {
844 if (status < 0 || close(entry->fd) < 0)
848 * As Samba is catching and eating child process
849 * exits we don't really care about the child exit
850 * code, a -1 with errno = ECHILD will do fine for us.
854 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
855 } while (wait_pid == -1 && errno == EINTR);
864 /**************************************************************************
865 Wrappers for dlopen, dlsym, dlclose.
866 ****************************************************************************/
868 void *sys_dlopen(const char *name, int flags)
870 #if defined(HAVE_DLOPEN)
871 return dlopen(name, flags);
877 void *sys_dlsym(void *handle, const char *symbol)
879 #if defined(HAVE_DLSYM)
880 return dlsym(handle, symbol);
886 int sys_dlclose (void *handle)
888 #if defined(HAVE_DLCLOSE)
889 return dlclose(handle);
895 const char *sys_dlerror(void)
897 #if defined(HAVE_DLERROR)
904 int sys_dup2(int oldfd, int newfd)
906 #if defined(HAVE_DUP2)
907 return dup2(oldfd, newfd);