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));
726 /**************************************************************************
727 The following are the UNICODE versions of *all* system interface functions
728 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
729 which currently are left as ascii as they are not used other than in name
731 ****************************************************************************/
733 /**************************************************************************
734 Wide stat. Just narrow and call sys_xxx.
735 ****************************************************************************/
737 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
740 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
743 /**************************************************************************
744 Wide lstat. Just narrow and call sys_xxx.
745 ****************************************************************************/
747 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
750 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
753 /**************************************************************************
754 Wide creat. Just narrow and call sys_xxx.
755 ****************************************************************************/
757 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
760 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
763 /**************************************************************************
764 Wide open. Just narrow and call sys_xxx.
765 ****************************************************************************/
767 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
770 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
773 /**************************************************************************
774 Wide fopen. Just narrow and call sys_xxx.
775 ****************************************************************************/
777 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
780 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
783 /**************************************************************************
784 Wide opendir. Just narrow and call sys_xxx.
785 ****************************************************************************/
787 DIR *wsys_opendir(const smb_ucs2_t *wfname)
790 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
793 /**************************************************************************
794 Wide readdir. Return a structure pointer containing a wide filename.
795 ****************************************************************************/
797 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
799 static SMB_STRUCT_WDIRENT retval;
800 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
805 retval.d_ino = (SMB_INO_T)dirval->d_ino;
806 retval.d_off = (SMB_OFF_T)dirval->d_off;
807 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
808 retval.d_reclen = wstrlen(retval.d_name);
813 /**************************************************************************
814 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
815 ****************************************************************************/
817 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
820 char *p = sys_getwd(fname);
825 return unix_to_unicode(s, p, sizeof(wpstring));
828 /**************************************************************************
829 Wide chown. Just narrow and call sys_xxx.
830 ****************************************************************************/
832 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
835 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
838 /**************************************************************************
839 Wide chroot. Just narrow and call sys_xxx.
840 ****************************************************************************/
842 int wsys_chroot(const smb_ucs2_t *wfname)
845 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
848 /**************************************************************************
849 Wide getpwnam. Return a structure pointer containing wide names.
850 ****************************************************************************/
852 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
854 static SMB_STRUCT_WPASSWD retval;
856 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
861 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
862 retval.pw_passwd = pwret->pw_passwd;
863 retval.pw_uid = pwret->pw_uid;
864 retval.pw_gid = pwret->pw_gid;
865 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
866 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
867 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
872 /**************************************************************************
873 Wide getpwuid. Return a structure pointer containing wide names.
874 ****************************************************************************/
876 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
878 static SMB_STRUCT_WPASSWD retval;
879 struct passwd *pwret = sys_getpwuid(uid);
884 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
885 retval.pw_passwd = pwret->pw_passwd;
886 retval.pw_uid = pwret->pw_uid;
887 retval.pw_gid = pwret->pw_gid;
888 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
889 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
890 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));