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.
42 /*******************************************************************
43 this replaces the normal select() system call
44 return if some data has arrived on one of the file descriptors
46 ********************************************************************/
48 static int pollfd(int fd)
54 #elif defined(TCRDCHK)
55 (void)ioctl(fd, TCRDCHK, &r);
57 (void)ioctl(fd, FIONREAD, &r);
63 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
74 for (i=0;i<maxfd;i++) {
75 if (FD_ISSET(i,fds) && pollfd(i)>0) {
82 memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
86 if (tval && tval->tv_sec < counter) return(0);
92 #else /* !NO_SELECT */
93 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
96 struct pollfd pfd[256];
103 for( i = 0; i < maxfd; i++) {
104 if(FD_ISSET(i,fds)) {
105 struct pollfd *pfdp = &pfd[maxpoll++];
107 pfdp->events = POLLIN;
112 timeout = (tval != NULL) ? (tval->tv_sec * 1000) + (tval->tv_usec/1000) :
116 pollrtn = poll( &pfd[0], maxpoll, timeout);
117 } while (pollrtn<0 && errno == EINTR);
121 for( i = 0; i < maxpoll; i++)
122 if( pfd[i].revents & POLLIN )
123 FD_SET(pfd[i].fd,fds);
132 if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
134 selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
135 } while (selrtn<0 && errno == EINTR);
139 #endif /* USE_POLL */
140 #endif /* NO_SELECT */
142 /*******************************************************************
143 A wrapper for usleep in case we don't have one.
144 ********************************************************************/
146 int sys_usleep(long usecs)
153 * We need this braindamage as the glibc usleep
154 * is not SPEC1170 complient... grumble... JRA.
157 if(usecs < 0 || usecs > 1000000) {
165 #else /* HAVE_USLEEP */
167 * Fake it with select...
170 tval.tv_usec = usecs/1000;
171 select(0,NULL,NULL,NULL,&tval);
173 #endif /* HAVE_USLEEP */
176 /*******************************************************************
177 A stat() wrapper that will deal with 64 bit filesizes.
178 ********************************************************************/
180 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
183 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
184 ret = stat64(fname, sbuf);
186 ret = stat(fname, sbuf);
188 /* we always want directories to appear zero size */
189 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
193 /*******************************************************************
194 An fstat() wrapper that will deal with 64 bit filesizes.
195 ********************************************************************/
197 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
200 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
201 ret = fstat64(fd, sbuf);
203 ret = fstat(fd, sbuf);
205 /* we always want directories to appear zero size */
206 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
210 /*******************************************************************
211 An lstat() wrapper that will deal with 64 bit filesizes.
212 ********************************************************************/
214 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
217 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
218 ret = lstat64(fname, sbuf);
220 ret = lstat(fname, sbuf);
222 /* we always want directories to appear zero size */
223 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
227 /*******************************************************************
228 An ftruncate() wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
231 int sys_ftruncate(int fd, SMB_OFF_T offset)
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
234 return ftruncate64(fd, offset);
236 return ftruncate(fd, offset);
240 /*******************************************************************
241 An lseek() wrapper that will deal with 64 bit filesizes.
242 ********************************************************************/
244 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
247 return lseek64(fd, offset, whence);
249 return lseek(fd, offset, whence);
253 /*******************************************************************
254 An fseek() wrapper that will deal with 64 bit filesizes.
255 ********************************************************************/
257 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
259 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
260 return fseek64(fp, offset, whence);
261 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
262 return fseeko64(fp, offset, whence);
264 return fseek(fp, offset, whence);
268 /*******************************************************************
269 An ftell() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
272 SMB_OFF_T sys_ftell(FILE *fp)
274 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
275 return (SMB_OFF_T)ftell64(fp);
276 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
277 return (SMB_OFF_T)ftello64(fp);
279 return (SMB_OFF_T)ftell(fp);
283 /*******************************************************************
284 A creat() wrapper that will deal with 64 bit filesizes.
285 ********************************************************************/
287 int sys_creat(const char *path, mode_t mode)
289 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
290 return creat64(path, mode);
293 * If creat64 isn't defined then ensure we call a potential open64.
296 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
300 /*******************************************************************
301 An open() wrapper that will deal with 64 bit filesizes.
302 ********************************************************************/
304 int sys_open(const char *path, int oflag, mode_t mode)
306 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
307 return open64(path, oflag, mode);
309 return open(path, oflag, mode);
313 /*******************************************************************
314 An fopen() wrapper that will deal with 64 bit filesizes.
315 ********************************************************************/
317 FILE *sys_fopen(const char *path, const char *type)
319 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
320 return fopen64(path, type);
322 return fopen(path, type);
326 #if defined(HAVE_MMAP)
328 /*******************************************************************
329 An mmap() wrapper that will deal with 64 bit filesizes.
330 ********************************************************************/
332 void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
335 return mmap64(addr, len, prot, flags, fd, offset);
337 return mmap(addr, len, prot, flags, fd, offset);
341 #endif /* HAVE_MMAP */
343 /*******************************************************************
344 A readdir wrapper that will deal with 64 bit filesizes.
345 ********************************************************************/
347 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
349 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
350 return readdir64(dirp);
352 return readdir(dirp);
356 /*******************************************************************
357 The wait() calls vary between systems
358 ********************************************************************/
360 int sys_waitpid(pid_t pid,int *status,int options)
363 return waitpid(pid,status,options);
364 #else /* HAVE_WAITPID */
365 return wait4(pid, status, options, NULL);
366 #endif /* HAVE_WAITPID */
369 /*******************************************************************
370 system wrapper for getwd
371 ********************************************************************/
372 char *sys_getwd(char *s)
376 wd = (char *)getcwd(s, sizeof (pstring));
378 wd = (char *)getwd(s);
383 /*******************************************************************
384 chown isn't used much but OS/2 doesn't have it
385 ********************************************************************/
387 int sys_chown(const char *fname,uid_t uid,gid_t gid)
392 DEBUG(1,("WARNING: no chown!\n"));
396 return(chown(fname,uid,gid));
400 /*******************************************************************
401 os/2 also doesn't have chroot
402 ********************************************************************/
403 int sys_chroot(const char *dname)
408 DEBUG(1,("WARNING: no chroot!\n"));
412 return(chroot(dname));
416 /**************************************************************************
417 A wrapper for gethostbyname() that tries avoids looking up hostnames
418 in the root domain, which can cause dial-on-demand links to come up for no
420 ****************************************************************************/
421 struct hostent *sys_gethostbyname(const char *name)
423 #ifdef REDUCE_ROOT_DNS_LOOKUPS
424 char query[256], hostname[256];
427 /* Does this name have any dots in it? If so, make no change */
429 if (strchr(name, '.'))
430 return(gethostbyname(name));
432 /* Get my hostname, which should have domain name
433 attached. If not, just do the gethostname on the
437 gethostname(hostname, sizeof(hostname) - 1);
438 hostname[sizeof(hostname) - 1] = 0;
439 if ((domain = strchr(hostname, '.')) == NULL)
440 return(gethostbyname(name));
442 /* Attach domain name to query and do modified query.
443 If names too large, just do gethostname on the
447 if((strlen(name) + strlen(domain)) >= sizeof(query))
448 return(gethostbyname(name));
450 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
451 return(gethostbyname(query));
452 #else /* REDUCE_ROOT_DNS_LOOKUPS */
453 return(gethostbyname(name));
454 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
458 /**************************************************************************
459 Try and abstract process capabilities (for systems that have them).
460 ****************************************************************************/
462 BOOL set_process_capability( uint32 cap_flag, BOOL enable )
464 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
465 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
467 cap_t cap = cap_get_proc();
470 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
476 cap->cap_effective |= CAP_NETWORK_MGT;
478 cap->cap_effective &= ~CAP_NETWORK_MGT;
480 if (cap_set_proc(cap) == -1) {
481 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
489 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
495 /**************************************************************************
496 Try and abstract inherited process capabilities (for systems that have them).
497 ****************************************************************************/
499 BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
501 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
502 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
504 cap_t cap = cap_get_proc();
507 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
513 cap->cap_inheritable |= CAP_NETWORK_MGT;
515 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
517 if (cap_set_proc(cap) == -1) {
518 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
526 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
532 /**************************************************************************
533 Wrapper for random().
534 ****************************************************************************/
536 long sys_random(void)
538 #if defined(HAVE_RANDOM)
539 return (long)random();
540 #elif defined(HAVE_RAND)
543 DEBUG(0,("Error - no random function available !\n"));
548 /**************************************************************************
549 Wrapper for srandom().
550 ****************************************************************************/
552 void sys_srandom(unsigned int seed)
554 #if defined(HAVE_SRANDOM)
556 #elif defined(HAVE_SRAND)
559 DEBUG(0,("Error - no srandom function available !\n"));
564 /**************************************************************************
565 Wrapper for getgroups. Deals with broken (int) case.
566 ****************************************************************************/
568 int sys_getgroups(int setlen, gid_t *gidset)
570 #if !defined(HAVE_BROKEN_GETGROUPS)
571 return getgroups(setlen, gidset);
579 return getgroups(setlen, &gid);
583 * Broken case. We need to allocate a
584 * GID_T array of size setlen.
595 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
596 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
600 if((ngroups = getgroups(setlen, group_list)) < 0) {
601 int saved_errno = errno;
602 free((char *)group_list);
607 for(i = 0; i < ngroups; i++)
608 gidset[i] = (gid_t)group_list[i];
610 free((char *)group_list);
612 #endif /* HAVE_BROKEN_GETGROUPS */
615 #ifdef HAVE_SETGROUPS
617 /**************************************************************************
618 Wrapper for setgroups. Deals with broken (int) case. Automatically used
619 if we have broken getgroups.
620 ****************************************************************************/
622 int sys_setgroups(int setlen, gid_t *gidset)
624 #if !defined(HAVE_BROKEN_GETGROUPS)
625 return setgroups(setlen, gidset);
635 if (setlen > NGROUPS_MAX) {
642 * Broken case. We need to allocate a
643 * GID_T array of size setlen.
649 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
650 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
654 for(i = 0; i < setlen; i++)
655 group_list[i] = (GID_T) gidset[i];
657 if(setgroups(setlen, group_list) != 0) {
658 int saved_errno = errno;
659 free((char *)group_list);
664 free((char *)group_list);
666 #endif /* HAVE_BROKEN_GETGROUPS */
669 #endif /* HAVE_SETGROUPS */
672 * We only wrap pw_name and pw_passwd for now as these
673 * are the only potentially modified fields.
676 /**************************************************************************
677 Helper function for getpwnam/getpwuid wrappers.
678 ****************************************************************************/
680 static struct passwd *setup_pwret(struct passwd *pass)
682 static pstring pw_name;
683 static pstring pw_passwd;
684 static struct passwd pw_ret;
691 memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
695 pw_ret.pw_name = pw_name;
696 pstrcpy(pw_ret.pw_name, pass->pw_name);
701 pw_ret.pw_passwd = pw_passwd;
702 pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
708 /**************************************************************************
709 Wrapper for getpwnam(). Always returns a static that can be modified.
710 ****************************************************************************/
712 struct passwd *sys_getpwnam(const char *name)
714 return setup_pwret(getpwnam(name));
717 /**************************************************************************
718 Wrapper for getpwuid(). Always returns a static that can be modified.
719 ****************************************************************************/
721 struct passwd *sys_getpwuid(uid_t uid)
723 return setup_pwret(getpwuid(uid));