⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_sunos.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: sys_sunos.c,v 1.130 2000/08/12 13:25:41 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * * Based upon preliminary work which is: * * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) * */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/mman.h>#include <linux/mm.h>#include <linux/swap.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/resource.h>#include <linux/ipc.h>#include <linux/shm.h>#include <linux/msg.h>#include <linux/sem.h>#include <linux/signal.h>#include <linux/uio.h>#include <linux/utsname.h>#include <linux/major.h>#include <linux/stat.h>#include <linux/malloc.h>#include <linux/pagemap.h>#include <linux/errno.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#ifndef KERNEL_DS#include <linux/segment.h>#endif#include <asm/page.h>#include <asm/pgtable.h>#include <asm/pconf.h>#include <asm/idprom.h> /* for gethostid() */#include <asm/unistd.h>#include <asm/system.h>/* For the nfs mount emulation */#include <linux/socket.h>#include <linux/in.h>#include <linux/nfs.h>#include <linux/nfs2.h>#include <linux/nfs_mount.h>/* for sunos_select */#include <linux/time.h>#include <linux/personality.h>/* NR_OPEN is now larger and dynamic in recent kernels. */#define SUNOS_NR_OPEN	256/* We use the SunOS mmap() semantics. */asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,				    unsigned long prot, unsigned long flags,				    unsigned long fd, unsigned long off){	struct file * file = NULL;	unsigned long retval, ret_type;	if(flags & MAP_NORESERVE) {		static int cnt;		if (cnt++ < 10)			printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",			       current->comm);		flags &= ~MAP_NORESERVE;	}	retval = -EBADF;	if(!(flags & MAP_ANONYMOUS)) {		if (fd >= SUNOS_NR_OPEN)			goto out;		file = fget(fd);		if (!file)			goto out;	}	retval = -EINVAL;	/* If this is ld.so or a shared library doing an mmap	 * of /dev/zero, transform it into an anonymous mapping.	 * SunOS is so stupid some times... hmph!	 */	if (file) {		if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR &&		   MINOR(file->f_dentry->d_inode->i_rdev) == 5) {			flags |= MAP_ANONYMOUS;			fput(file);			file = 0;		}	}	ret_type = flags & _MAP_NEW;	flags &= ~_MAP_NEW;	if(!(flags & MAP_FIXED))		addr = 0;	else {		if (ARCH_SUN4C_SUN4 &&		    (len > 0x20000000 ||		     ((flags & MAP_FIXED) &&		      addr < 0xe0000000 && addr + len > 0x20000000)))			goto out_putf;		/* See asm-sparc/uaccess.h */		if (len > TASK_SIZE - PAGE_SIZE ||		    addr + len > TASK_SIZE - PAGE_SIZE)			goto out_putf;	}	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);	down(&current->mm->mmap_sem);	retval = do_mmap(file, addr, len, prot, flags, off);	up(&current->mm->mmap_sem);	if(!ret_type)		retval = ((retval < PAGE_OFFSET) ? 0 : retval);out_putf:	if (file)		fput(file);out:	return retval;}/* lmbench calls this, just say "yeah, ok" */asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg){	return 0;}/* SunOS is completely broken... it returns 0 on success, otherwise * ENOMEM.  For sys_sbrk() it wants the old brk value as a return * on success and ENOMEM as before on failure. */asmlinkage int sunos_brk(unsigned long brk){	int freepages, retval = -ENOMEM;	unsigned long rlim;	unsigned long newbrk, oldbrk;	down(&current->mm->mmap_sem);	if(ARCH_SUN4C_SUN4) {		if(brk >= 0x20000000 && brk < 0xe0000000) {			goto out;		}	}	if (brk < current->mm->end_code)		goto out;	newbrk = PAGE_ALIGN(brk);	oldbrk = PAGE_ALIGN(current->mm->brk);	retval = 0;	if (oldbrk == newbrk) {		current->mm->brk = brk;		goto out;	}	/*	 * Always allow shrinking brk	 */	if (brk <= current->mm->brk) {		current->mm->brk = brk;		do_munmap(current->mm, newbrk, oldbrk-newbrk);		goto out;	}	/*	 * Check against rlimit and stack..	 */	retval = -ENOMEM;	rlim = current->rlim[RLIMIT_DATA].rlim_cur;	if (rlim >= RLIM_INFINITY)		rlim = ~0;	if (brk - current->mm->end_code > rlim)		goto out;	/*	 * Check against existing mmap mappings.	 */	if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))		goto out;	/*	 * stupid algorithm to decide if we have enough memory: while	 * simple, it hopefully works in most obvious cases.. Easy to	 * fool it, but this should catch most mistakes.	 */	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;	freepages += atomic_read(&page_cache_size);	freepages >>= 1;	freepages += nr_free_pages();	freepages += nr_swap_pages;	freepages -= num_physpages >> 4;	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;	if (freepages < 0)		goto out;	/*	 * Ok, we have probably got enough memory - let it rip.	 */	current->mm->brk = brk;	do_brk(oldbrk, newbrk-oldbrk);	retval = 0;out:	up(&current->mm->mmap_sem);	return retval;}asmlinkage unsigned long sunos_sbrk(int increment){	int error;	unsigned long oldbrk;	/* This should do it hopefully... */	lock_kernel();	oldbrk = current->mm->brk;	error = sunos_brk(((int) current->mm->brk) + increment);	if(!error)		error = oldbrk;	unlock_kernel();	return error;}/* XXX Completely undocumented, and completely magic... * XXX I believe it is to increase the size of the stack by * XXX argument 'increment' and return the new end of stack * XXX area.  Wheee... */asmlinkage unsigned long sunos_sstk(int increment){	lock_kernel();	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",	       current->comm, increment);	unlock_kernel();	return -1;}/* Give hints to the kernel as to what paging strategy to use... * Completely bogus, don't remind me. */#define VA_NORMAL     0 /* Normal vm usage expected */#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */static char *vstrings[] = {	"VA_NORMAL",	"VA_ABNORMAL",	"VA_SEQUENTIAL",	"VA_INVALIDATE",};asmlinkage void sunos_vadvise(unsigned long strategy){	/* I wanna see who uses this... */	lock_kernel();	printk("%s: Advises us to use %s paging strategy\n",	       current->comm,	       strategy <= 3 ? vstrings[strategy] : "BOGUS");	unlock_kernel();}/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE * resource limit and is for backwards compatibility with older sunos * revs. */asmlinkage long sunos_getdtablesize(void){	return SUNOS_NR_OPEN;}#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask){	unsigned long old;	spin_lock_irq(&current->sigmask_lock);	old = current->blocked.sig[0];	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return old;}asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask){	unsigned long retval;	spin_lock_irq(&current->sigmask_lock);	retval = current->blocked.sig[0];	current->blocked.sig[0] = (newmask & _BLOCKABLE);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return retval;}/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    *//* getdents system call, the format of the structure just has a different *//* layout (d_off+d_ino instead of d_ino+d_off) */struct sunos_dirent {    long           d_off;    unsigned long  d_ino;    unsigned short d_reclen;    unsigned short d_namlen;    char           d_name[1];};struct sunos_dirent_callback {    struct sunos_dirent *curr;    struct sunos_dirent *previous;    int count;    int error;};#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))static int sunos_filldir(void * __buf, const char * name, int namlen,			 off_t offset, ino_t ino, unsigned int d_type){	struct sunos_dirent * dirent;	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail.. */	if (reclen > buf->count)		return -EINVAL;	dirent = buf->previous;	if (dirent)		put_user(offset, &dirent->d_off);	dirent = buf->curr;	buf->previous = dirent;	put_user(ino, &dirent->d_ino);	put_user(namlen, &dirent->d_namlen);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	((char *) dirent) += reclen;	buf->curr = dirent;	buf->count -= reclen;	return 0;}asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt){	struct file * file;	struct sunos_dirent * lastdirent;	struct sunos_dirent_callback buf;	int error = -EBADF;	if (fd >= SUNOS_NR_OPEN)		goto out;	file = fget(fd);	if (!file)		goto out;	error = -EINVAL;	if (cnt < (sizeof(struct sunos_dirent) + 255))		goto out_putf;	buf.curr = (struct sunos_dirent *) dirent;	buf.previous = NULL;	buf.count = cnt;	buf.error = 0;	error = vfs_readdir(file, sunos_filldir, &buf);	if (error < 0)		goto out_putf;	lastdirent = buf.previous;	error = buf.error;	if (lastdirent) {		put_user(file->f_pos, &lastdirent->d_off);		error = cnt - buf.count;	}out_putf:	fput(file);out:	return error;}/* Old sunos getdirentries, severely broken compatibility stuff here. */struct sunos_direntry {    unsigned long  d_ino;    unsigned short d_reclen;    unsigned short d_namlen;    char           d_name[1];};struct sunos_direntry_callback {    struct sunos_direntry *curr;    struct sunos_direntry *previous;    int count;    int error;};static int sunos_filldirentry(void * __buf, const char * name, int namlen,			      off_t offset, ino_t ino, unsigned int d_type){	struct sunos_direntry * dirent;	struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail.. */	if (reclen > buf->count)		return -EINVAL;	dirent = buf->previous;	dirent = buf->curr;	buf->previous = dirent;	put_user(ino, &dirent->d_ino);	put_user(namlen, &dirent->d_namlen);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	((char *) dirent) += reclen;	buf->curr = dirent;	buf->count -= reclen;	return 0;}asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsigned int *basep){	struct file * file;	struct sunos_direntry * lastdirent;	struct sunos_direntry_callback buf;	int error = -EBADF;	if (fd >= SUNOS_NR_OPEN)		goto out;	file = fget(fd);	if (!file)		goto out;	error = -EINVAL;	if(cnt < (sizeof(struct sunos_direntry) + 255))		goto out_putf;	buf.curr = (struct sunos_direntry *) dirent;	buf.previous = NULL;	buf.count = cnt;	buf.error = 0;	error = vfs_readdir(file, sunos_filldirentry, &buf);	if (error < 0)		goto out_putf;	lastdirent = buf.previous;	error = buf.error;	if (lastdirent) {		put_user(file->f_pos, basep);		error = cnt - buf.count;	}out_putf:	fput(file);out:	return error;}struct sunos_utsname {	char sname[9];	char nname[9];	char nnext[56];	char rel[9];	char ver[9];	char mach[9];};asmlinkage int sunos_uname(struct sunos_utsname *name){	int ret;	down_read(&uts_sem);	ret = copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1);	if (!ret) {		ret |= __copy_to_user(&name->nname[0], &system_utsname.nodename[0], sizeof(name->nname) - 1);		ret |= __put_user('\0', &name->nname[8]);		ret |= __copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);		ret |= __copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);		ret |= __copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);	}	up_read(&uts_sem);	return ret;}asmlinkage int sunos_nosys(void){	struct pt_regs *regs;	siginfo_t info;	static int cnt;	lock_kernel();	regs = current->thread.kregs;	info.si_signo = SIGSYS;	info.si_errno = 0;	info.si_code = __SI_FAULT|0x100;	info.si_addr = (void *)regs->pc;	info.si_trapno = regs->u_regs[UREG_G1];	send_sig_info(SIGSYS, &info, current);	if (cnt++ < 4) {		printk("Process makes ni_syscall number %d, register dump:\n",		       (int) regs->u_regs[UREG_G1]);		show_regs(regs);	}	unlock_kernel();	return -ENOSYS;}/* This is not a real and complete implementation yet, just to keep * the easy SunOS binaries happy. */asmlinkage int sunos_fpathconf(int fd, int name){	int ret;	switch(name) {	case _PCONF_LINK:		ret = LINK_MAX;		break;	case _PCONF_CANON:		ret = MAX_CANON;		break;	case _PCONF_INPUT:		ret = MAX_INPUT;		break;	case _PCONF_NAME:		ret = NAME_MAX;		break;	case _PCONF_PATH:		ret = PATH_MAX;		break;	case _PCONF_PIPE:		ret = PIPE_BUF;		break;	case _PCONF_CHRESTRICT:		/* XXX Investigate XXX */		ret = 1;		break;	case _PCONF_NOTRUNC:		/* XXX Investigate XXX */	case _PCONF_VDISABLE:		ret = 0;		break;	default:		ret = -EINVAL;		break;	}	return ret;}asmlinkage int sunos_pathconf(char *path, int name){	int ret;	ret = sunos_fpathconf(0, name); /* XXX cheese XXX */	return ret;}/* SunOS mount system call emulation */extern asmlinkage intsys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp){	int ret;	/* SunOS binaries expect that select won't change the tvp contents */	ret = sys_select (width, inp, outp, exp, tvp);	if (ret == -EINTR && tvp) {		time_t sec, usec;		__get_user(sec, &tvp->tv_sec);		__get_user(usec, &tvp->tv_usec);		if (sec == 0 && usec == 0)			ret = 0;	}	return ret;}asmlinkage void sunos_nop(void){	return;}/* SunOS mount/umount. */#define SMNT_RDONLY       1#define SMNT_NOSUID       2#define SMNT_NEWTYPE      4#define SMNT_GRPID        8#define SMNT_REMOUNT      16#define SMNT_NOSUB        32#define SMNT_MULTI        64#define SMNT_SYS5         128struct sunos_fh_t {	char fh_data [NFS_FHSIZE];};struct sunos_nfs_mount_args {	struct sockaddr_in  *addr; /* file server address */	struct nfs_fh *fh;     /* File handle to be mounted */	int        flags;      /* flags */	int        wsize;      /* write size in bytes */	int        rsize;      /* read size in bytes */	int        timeo;      /* initial timeout in .1 secs */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -