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

📄 sys_sunos.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int        retrans;    /* times to retry send */	char       *hostname;  /* server's hostname */	int        acregmin;   /* attr cache file min secs */	int        acregmax;   /* attr cache file max secs */	int        acdirmin;   /* attr cache dir min secs */	int        acdirmax;   /* attr cache dir max secs */	char       *netname;   /* server's netname */};extern dev_t get_unnamed_dev(void);extern void put_unnamed_dev(dev_t);extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);extern asmlinkage int sys_socket(int family, int type, int protocol);extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);/* Bind the socket on a local reserved port and connect it to the * remote server.  This on Linux/i386 is done by the mount program, * not by the kernel. */static intsunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr){	struct sockaddr_in local;	struct sockaddr_in server;	int    try_port;	struct socket *socket;	struct inode  *inode;	struct file   *file;	int    ret, result = 0;	file = fget(fd);	if (!file)		goto out;	inode = file->f_dentry->d_inode;	socket = &inode->u.socket_i;	local.sin_family = AF_INET;	local.sin_addr.s_addr = INADDR_ANY;	/* IPPORT_RESERVED = 1024, can't find the definition in the kernel */	try_port = 1024;	do {		local.sin_port = htons (--try_port);		ret = socket->ops->bind(socket, (struct sockaddr*)&local,					sizeof(local));	} while (ret && try_port > (1024 / 2));	if (ret)		goto out_putf;	server.sin_family = AF_INET;	server.sin_addr = addr->sin_addr;	server.sin_port = NFS_PORT;	/* Call sys_connect */	ret = socket->ops->connect (socket, (struct sockaddr *) &server,				    sizeof (server), file->f_flags);	if (ret >= 0)		result = 1;out_putf:	fput(file);out:	return result;}static int get_default (int value, int def_value){    if (value)	return value;    else	return def_value;}static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data){	int  server_fd;	char *the_name;	struct nfs_mount_data linux_nfs_mount;	struct sunos_nfs_mount_args sunos_mount;	/* Ok, here comes the fun part: Linux's nfs mount needs a	 * socket connection to the server, but SunOS mount does not	 * require this, so we use the information on the destination	 * address to create a socket and bind it to a reserved	 * port on this system	 */	if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))		return -EFAULT;	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);	if (server_fd < 0)		return -ENXIO;	if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr,				sizeof(*sunos_mount.addr)) ||	    copy_from_user(&linux_nfs_mount.root,sunos_mount.fh,				sizeof(*sunos_mount.fh))) {		sys_close (server_fd);		return -EFAULT;	}	if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){		sys_close (server_fd);		return -ENXIO;	}	/* Now, bind it to a locally reserved port */	linux_nfs_mount.version  = NFS_MOUNT_VERSION;	linux_nfs_mount.flags    = sunos_mount.flags;	linux_nfs_mount.fd       = server_fd;		linux_nfs_mount.rsize    = get_default (sunos_mount.rsize, 8192);	linux_nfs_mount.wsize    = get_default (sunos_mount.wsize, 8192);	linux_nfs_mount.timeo    = get_default (sunos_mount.timeo, 10);	linux_nfs_mount.retrans  = sunos_mount.retrans;		linux_nfs_mount.acregmin = sunos_mount.acregmin;	linux_nfs_mount.acregmax = sunos_mount.acregmax;	linux_nfs_mount.acdirmin = sunos_mount.acdirmin;	linux_nfs_mount.acdirmax = sunos_mount.acdirmax;	the_name = getname(sunos_mount.hostname);	if(IS_ERR(the_name))		return PTR_ERR(the_name);	strncpy (linux_nfs_mount.hostname, the_name, 254);	linux_nfs_mount.hostname [255] = 0;	putname (the_name);		return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);}asmlinkage intsunos_mount(char *type, char *dir, int flags, void *data){	int linux_flags = MS_MGC_MSK; /* new semantics */	int ret = -EINVAL;	char *dev_fname = 0;	char *dir_page, *type_page;	if (!capable (CAP_SYS_ADMIN))		return -EPERM;			lock_kernel();	/* We don't handle the integer fs type */	if ((flags & SMNT_NEWTYPE) == 0)		goto out;	/* Do not allow for those flags we don't support */	if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))		goto out;	if(flags & SMNT_REMOUNT)		linux_flags |= MS_REMOUNT;	if(flags & SMNT_RDONLY)		linux_flags |= MS_RDONLY;	if(flags & SMNT_NOSUID)		linux_flags |= MS_NOSUID;	dir_page = getname(dir);	ret = PTR_ERR(dir_page);	if (IS_ERR(dir_page))		goto out;	type_page = getname(type);	ret = PTR_ERR(type_page);	if (IS_ERR(type_page))		goto out1;	if(strcmp(type_page, "ext2") == 0) {		dev_fname = getname(data);	} else if(strcmp(type_page, "iso9660") == 0) {		dev_fname = getname(data);	} else if(strcmp(type_page, "minix") == 0) {		dev_fname = getname(data);	} else if(strcmp(type_page, "nfs") == 0) {		ret = sunos_nfs_mount (dir_page, flags, data);		goto out2;        } else if(strcmp(type_page, "ufs") == 0) {		printk("Warning: UFS filesystem mounts unsupported.\n");		ret = -ENODEV;		goto out2;	} else if(strcmp(type_page, "proc")) {		ret = -ENODEV;		goto out2;	}	ret = PTR_ERR(dev_fname);	if (IS_ERR(dev_fname))		goto out2;	ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);	if (dev_fname)		putname(dev_fname);out2:	putname(type_page);out1:	putname(dir_page);out:	unlock_kernel();	return ret;}extern asmlinkage int sys_setsid(void);extern asmlinkage int sys_setpgid(pid_t, pid_t);asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid){	int ret;	/* So stupid... */	if((!pid || pid == current->pid) &&	   !pgid) {		sys_setsid();		ret = 0;	} else {		ret = sys_setpgid(pid, pgid);	}	return ret;}/* So stupid... */extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru){	int ret;	ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru);	return ret;}extern int kill_pg(int, int, int);asmlinkage int sunos_killpg(int pgrp, int sig){	int ret;	lock_kernel();	ret = kill_pg(pgrp, sig, 0);	unlock_kernel();	return ret;}asmlinkage int sunos_audit(void){	lock_kernel();	printk ("sys_audit\n");	unlock_kernel();	return -1;}extern asmlinkage unsigned long sunos_gethostid(void){	unsigned long ret;	lock_kernel();	ret = ((unsigned long)idprom->id_machtype << 24) |		(unsigned long)idprom->id_sernum;	unlock_kernel();	return ret;}/* sysconf options, for SunOS compatibility */#define   _SC_ARG_MAX             1#define   _SC_CHILD_MAX           2#define   _SC_CLK_TCK             3#define   _SC_NGROUPS_MAX         4#define   _SC_OPEN_MAX            5#define   _SC_JOB_CONTROL         6#define   _SC_SAVED_IDS           7#define   _SC_VERSION             8extern asmlinkage long sunos_sysconf (int name){	long ret;	switch (name){	case _SC_ARG_MAX:		ret = ARG_MAX;		break;	case _SC_CHILD_MAX:		ret = CHILD_MAX;		break;	case _SC_CLK_TCK:		ret = HZ;		break;	case _SC_NGROUPS_MAX:		ret = NGROUPS_MAX;		break;	case _SC_OPEN_MAX:		ret = OPEN_MAX;		break;	case _SC_JOB_CONTROL:		ret = 1;	/* yes, we do support job control */		break;	case _SC_SAVED_IDS:		ret = 1;	/* yes, we do support saved uids  */		break;	case _SC_VERSION:		/* mhm, POSIX_VERSION is in /usr/include/unistd.h		 * should it go on /usr/include/linux?		 */		ret = 199009L; 		break;	default:		ret = -1;		break;	};	return ret;}asmlinkage int sunos_semsys(int op, unsigned long arg1, unsigned long arg2,			    unsigned long arg3, void *ptr){	union semun arg4;	int ret;	switch (op) {	case 0:		/* Most arguments match on a 1:1 basis but cmd doesn't */		switch(arg3) {		case 4:			arg3=GETPID; break;		case 5:			arg3=GETVAL; break;		case 6:			arg3=GETALL; break;		case 3:			arg3=GETNCNT; break;		case 7:			arg3=GETZCNT; break;		case 8:			arg3=SETVAL; break;		case 9:			arg3=SETALL; break;		}		/* sys_semctl(): */		arg4.__pad=ptr; /* value to modify semaphore to */		ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 );		break;	case 1:		/* sys_semget(): */		ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);		break;	case 2:		/* sys_semop(): */		ret = sys_semop((int)arg1, (struct sembuf *)arg2, (unsigned)arg3);		break;	default:		ret = -EINVAL;		break;	};	return ret;}asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2,			    unsigned long arg3, unsigned long arg4){	struct sparc_stackf *sp;	unsigned long arg5;	int rval;	switch(op) {	case 0:		rval = sys_msgget((key_t)arg1, (int)arg2);		break;	case 1:		rval = sys_msgctl((int)arg1, (int)arg2,				  (struct msqid_ds *)arg3);		break;	case 2:		lock_kernel();		sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP];		arg5 = sp->xxargs[0];		unlock_kernel();		rval = sys_msgrcv((int)arg1, (struct msgbuf *)arg2,				  (size_t)arg3, (long)arg4, (int)arg5);		break;	case 3:		rval = sys_msgsnd((int)arg1, (struct msgbuf *)arg2,				  (size_t)arg3, (int)arg4);		break;	default:		rval = -EINVAL;		break;	}	return rval;}asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2,			    unsigned long arg3){	unsigned long raddr;	int rval;	switch(op) {	case 0:		/* sys_shmat(): attach a shared memory area */		rval = sys_shmat((int)arg1,(char *)arg2,(int)arg3,&raddr);		if(!rval)			rval = (int) raddr;		break;	case 1:		/* sys_shmctl(): modify shared memory area attr. */		rval = sys_shmctl((int)arg1,(int)arg2,(struct shmid_ds *)arg3);		break;	case 2:		/* sys_shmdt(): detach a shared memory area */		rval = sys_shmdt((char *)arg1);		break;	case 3:		/* sys_shmget(): get a shared memory area */		rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);		break;	default:		rval = -EINVAL;		break;	};	return rval;}#define SUNOS_EWOULDBLOCK 35/* see the sunos man page read(2v) for an explanation   of this garbage. We use O_NDELAY to mark   file descriptors that have been set non-blocking    using 4.2BSD style calls. (tridge) */static inline int check_nonblock(int ret, int fd){	if (ret == -EAGAIN) {		struct file * file = fget(fd);		if (file) {			if (file->f_flags & O_NDELAY)				ret = -SUNOS_EWOULDBLOCK;			fput(file);		}	}	return ret;}extern asmlinkage int sys_read(unsigned int fd,char *buf,int count);extern asmlinkage int sys_write(unsigned int fd,char *buf,int count);extern asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags);extern asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags);extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen);extern asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count);extern asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count);asmlinkage int sunos_read(unsigned int fd,char *buf,int count){	int ret;	ret = check_nonblock(sys_read(fd,buf,count),fd);	return ret;}asmlinkage int sunos_readv(unsigned long fd, const struct iovec * vector, long count){	int ret;	ret = check_nonblock(sys_readv(fd,vector,count),fd);	return ret;}asmlinkage int sunos_write(unsigned int fd,char *buf,int count){	int ret;	ret = check_nonblock(sys_write(fd,buf,count),fd);	return ret;}asmlinkage int sunos_writev(unsigned long fd, const struct iovec * vector, long count){	int ret;	ret = check_nonblock(sys_writev(fd,vector,count),fd);	return ret;}asmlinkage int sunos_recv(int fd, void * ubuf, int size, unsigned flags){	int ret;	ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd);	return ret;}asmlinkage int sunos_send(int fd, void * buff, int len, unsigned flags){	int ret;	ret = check_nonblock(sys_send(fd,buff,len,flags),fd);	return ret;}extern asmlinkage int sys_setsockopt(int fd, int level, int optname,				     char *optval, int optlen);asmlinkage int sunos_socket(int family, int type, int protocol){	int ret, one = 1;	ret = sys_socket(family, type, protocol);	if (ret < 0)		goto out;	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,		       (char *)&one, sizeof(one));out:	return ret;}asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen){	int ret, one = 1;	while (1) {		ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);			if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)			break;	}	if (ret < 0)		goto out;	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,		       (char *)&one, sizeof(one));out:	return ret;}#define SUNOS_SV_INTERRUPT 2asmlinkage intsunos_sigaction(int sig, const struct old_sigaction *act,		struct old_sigaction *oact){	struct k_sigaction new_ka, old_ka;	int ret;	if(act) {		old_sigset_t mask;		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))			return -EFAULT;		__get_user(mask, &act->sa_mask);		new_ka.sa.sa_restorer = NULL;		new_ka.ka_restorer = NULL;		siginitset(&new_ka.sa.sa_mask, mask);		new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		/* In the clone() case we could copy half consistant		 * state to the user, however this could sleep and		 * deadlock us if we held the signal lock on SMP.  So for		 * now I take the easy way out and do no locking.		 * But then again we don't support SunOS lwp's anyways ;-)		 */		old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))			 return -EFAULT;		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);	}	return ret;}extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);extern asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen);asmlinkage int sunos_setsockopt(int fd, int level, int optname, char *optval,				int optlen){	int tr_opt = optname;	int ret;	if (level == SOL_IP) {		/* Multicast socketopts (ttl, membership) */		if (tr_opt >=2 && tr_opt <= 6)			tr_opt += 30;	}	ret = sys_setsockopt(fd, level, tr_opt, optval, optlen);	return ret;}asmlinkage int sunos_getsockopt(int fd, int level, int optname, char *optval,				int *optlen){	int tr_opt = optname;	int ret;	if (level == SOL_IP) {		/* Multicast socketopts (ttl, membership) */		if (tr_opt >=2 && tr_opt <= 6)			tr_opt += 30;	}	ret = sys_getsockopt(fd, level, tr_opt, optval, optlen);	return ret;}

⌨️ 快捷键说明

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