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

📄 sys_parisc32.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		vector++;		ivp++;		i--;	}	inode = file->f_dentry->d_inode;	/* VERIFY_WRITE actually means a read, as we write to user space */	retval = locks_verify_area((type == VERIFY_WRITE				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),				   inode, file, file->f_pos, tot_len);	if (retval) {		if (iov != iovstack)			kfree(iov);		return retval;	}	/* Then do the actual IO.  Note that sockets need to be handled	 * specially as they have atomicity guarantees and can handle	 * iovec's natively	 */	if (inode->i_sock) {		int err;		err = sock_readv_writev(type, inode, file, iov, count, tot_len);		if (iov != iovstack)			kfree(iov);		return err;	}	if (!file->f_op) {		if (iov != iovstack)			kfree(iov);		return -EINVAL;	}	/* VERIFY_WRITE actually means a read, as we write to user space */	fn = file->f_op->read;	if (type == VERIFY_READ)		fn = (IO_fn_t) file->f_op->write;			ivp = iov;	while (count > 0) {		void * base;		int len, nr;		base = ivp->iov_base;		len = ivp->iov_len;		ivp++;		count--;		nr = fn(file, base, len, &file->f_pos);		if (nr < 0) {			if (retval)				break;			retval = nr;			break;		}		retval += nr;		if (nr != len)			break;	}	if (iov != iovstack)		kfree(iov);	return retval;}asmlinkage longsys32_readv(int fd, struct iovec32 *vector, u32 count){	struct file *file;	ssize_t ret;	ret = -EBADF;	file = fget(fd);	if (!file)		goto bad_file;	if (file->f_op && (file->f_mode & FMODE_READ) &&	    (file->f_op->readv || file->f_op->read))		ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);	fput(file);bad_file:	return ret;}asmlinkage longsys32_writev(int fd, struct iovec32 *vector, u32 count){	struct file *file;	ssize_t ret;	ret = -EBADF;	file = fget(fd);	if(!file)		goto bad_file;	if (file->f_op && (file->f_mode & FMODE_WRITE) &&	    (file->f_op->writev || file->f_op->write))	        ret = do_readv_writev32(VERIFY_READ, file, vector, count);	fput(file);bad_file:	return ret;}/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/#include <net/scm.h>/* XXX This really belongs in some header file... -DaveM */#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 					   16 for IP, 16 for IPX,					   24 for IPv6,					   about 80 for AX.25 */extern struct socket *sockfd_lookup(int fd, int *err);/* XXX This as well... */extern __inline__ void sockfd_put(struct socket *sock){	fput(sock->file);}struct msghdr32 {        u32               msg_name;        int               msg_namelen;        u32               msg_iov;        __kernel_size_t32 msg_iovlen;        u32               msg_control;        __kernel_size_t32 msg_controllen;        unsigned          msg_flags;};struct cmsghdr32 {        __kernel_size_t32 cmsg_len;        int               cmsg_level;        int               cmsg_type;};/* Bleech... */#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \				    (struct cmsghdr32 *)(ctl) : \				    (struct cmsghdr32 *)NULL)#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,					      struct cmsghdr32 *__cmsg, int __cmsg_len){	struct cmsghdr32 * __ptr;	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +				     CMSG32_ALIGN(__cmsg_len));	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)		return NULL;	return __ptr;}__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,					    struct cmsghdr32 *__cmsg,					    int __cmsg_len){	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,			       __cmsg, __cmsg_len);}static inline int iov_from_user32_to_kern(struct iovec *kiov,					  struct iovec32 *uiov32,					  int niov){	int tot_len = 0;	while(niov > 0) {		u32 len, buf;		if(get_user(len, &uiov32->iov_len) ||		   get_user(buf, &uiov32->iov_base)) {			tot_len = -EFAULT;			break;		}		tot_len += len;		kiov->iov_base = (void *)A(buf);		kiov->iov_len = (__kernel_size_t) len;		uiov32++;		kiov++;		niov--;	}	return tot_len;}static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,					     struct msghdr32 *umsg){	u32 tmp1, tmp2, tmp3;	int err;	err = get_user(tmp1, &umsg->msg_name);	err |= __get_user(tmp2, &umsg->msg_iov);	err |= __get_user(tmp3, &umsg->msg_control);	if (err)		return -EFAULT;	kmsg->msg_name = (void *)A(tmp1);	kmsg->msg_iov = (struct iovec *)A(tmp2);	kmsg->msg_control = (void *)A(tmp3);	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);		return err;}/* I've named the args so it is easy to tell whose space the pointers are in. */static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,			  char *kern_address, int mode){	int tot_len;	if(kern_msg->msg_namelen) {		if(mode==VERIFY_READ) {			int err = move_addr_to_kernel(kern_msg->msg_name,						      kern_msg->msg_namelen,						      kern_address);			if(err < 0)				return err;		}		kern_msg->msg_name = kern_address;	} else		kern_msg->msg_name = NULL;	if(kern_msg->msg_iovlen > UIO_FASTIOV) {		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),				   GFP_KERNEL);		if(!kern_iov)			return -ENOMEM;	}	tot_len = iov_from_user32_to_kern(kern_iov,					  (struct iovec32 *)kern_msg->msg_iov,					  kern_msg->msg_iovlen);	if(tot_len >= 0)		kern_msg->msg_iov = kern_iov;	else if(kern_msg->msg_iovlen > UIO_FASTIOV)		kfree(kern_iov);	return tot_len;}/* There is a lot of hair here because the alignment rules (and * thus placement) of cmsg headers and length are different for * 32-bit apps.  -DaveM */static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,				       unsigned char *stackbuf, int stackbuf_size){	struct cmsghdr32 *ucmsg;	struct cmsghdr *kcmsg, *kcmsg_base;	__kernel_size_t32 ucmlen;	__kernel_size_t kcmlen, tmp;	kcmlen = 0;	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;	ucmsg = CMSG32_FIRSTHDR(kmsg);	while(ucmsg != NULL) {		if(get_user(ucmlen, &ucmsg->cmsg_len))			return -EFAULT;		/* Catch bogons. */		if(CMSG32_ALIGN(ucmlen) <		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))			return -EINVAL;		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)				   + ucmlen) > kmsg->msg_controllen)			return -EINVAL;		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +		       CMSG_ALIGN(sizeof(struct cmsghdr)));		kcmlen += tmp;		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);	}	if(kcmlen == 0)		return -EINVAL;	/* The kcmlen holds the 64-bit version of the control length.	 * It may not be modified as we do not stick it into the kmsg	 * until we have successfully copied over all of the data	 * from the user.	 */	if(kcmlen > stackbuf_size)		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);	if(kcmsg == NULL)		return -ENOBUFS;	/* Now copy them over neatly. */	memset(kcmsg, 0, kcmlen);	ucmsg = CMSG32_FIRSTHDR(kmsg);	while(ucmsg != NULL) {		__get_user(ucmlen, &ucmsg->cmsg_len);		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +		       CMSG_ALIGN(sizeof(struct cmsghdr)));		kcmsg->cmsg_len = tmp;		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);		/* Copy over the data. */		if(copy_from_user(CMSG_DATA(kcmsg),				  CMSG32_DATA(ucmsg),				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))			goto out_free_efault;		/* Advance. */		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);	}	/* Ok, looks like we made it.  Hook it up and return success. */	kmsg->msg_control = kcmsg_base;	kmsg->msg_controllen = kcmlen;	return 0;out_free_efault:	if(kcmsg_base != (struct cmsghdr *)stackbuf)		kfree(kcmsg_base);	return -EFAULT;}static void put_cmsg32(struct msghdr *kmsg, int level, int type,		       int len, void *data){	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;	struct cmsghdr32 cmhdr;	int cmlen = CMSG32_LEN(len);	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {		kmsg->msg_flags |= MSG_CTRUNC;		return;	}	if(kmsg->msg_controllen < cmlen) {		kmsg->msg_flags |= MSG_CTRUNC;		cmlen = kmsg->msg_controllen;	}	cmhdr.cmsg_level = level;	cmhdr.cmsg_type = type;	cmhdr.cmsg_len = cmlen;	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))		return;	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))		return;	cmlen = CMSG32_SPACE(len);	kmsg->msg_control += cmlen;	kmsg->msg_controllen -= cmlen;}static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm){	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);	int fdnum = scm->fp->count;	struct file **fp = scm->fp->fp;	int *cmfptr;	int err = 0, i;	if (fdnum < fdmax)		fdmax = fdnum;	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {		int new_fd;		err = get_unused_fd();		if (err < 0)			break;		new_fd = err;		err = put_user(new_fd, cmfptr);		if (err) {			put_unused_fd(new_fd);			break;		}		/* Bump the usage count and install the file. */		get_file(fp[i]);		fd_install(new_fd, fp[i]);	}	if (i > 0) {		int cmlen = CMSG32_LEN(i * sizeof(int));		if (!err)			err = put_user(SOL_SOCKET, &cm->cmsg_level);		if (!err)			err = put_user(SCM_RIGHTS, &cm->cmsg_type);		if (!err)			err = put_user(cmlen, &cm->cmsg_len);		if (!err) {			cmlen = CMSG32_SPACE(i * sizeof(int));			kmsg->msg_control += cmlen;			kmsg->msg_controllen -= cmlen;		}	}	if (i < fdnum)		kmsg->msg_flags |= MSG_CTRUNC;	/*	 * All of the files that fit in the message have had their	 * usage counts incremented, so we just free the list.	 */	__scm_destroy(scm);}/* In these cases we (currently) can just copy to data over verbatim * because all CMSGs created by the kernel have well defined types which * have the same layout in both the 32-bit and 64-bit API.  One must add * some special cased conversions here if we start sending control messages * with incompatible types. * * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after * we do our work.  The remaining cases are: * * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean *		IP_TTL		int			32-bit clean *		IP_TOS		__u8			32-bit clean *		IP_RECVOPTS	variable length		32-bit clean *		IP_RETOPTS	variable length		32-bit clean *		(these last two are clean because the types are defined *		 by the IPv4 protocol) *		IP_RECVERR	struct sock_extended_err + *				struct sockaddr_in	32-bit clean * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err + *				struct sockaddr_in6	32-bit clean *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean *		IPV6_HOPLIMIT	int			32-bit clean *		IPV6_FLOWINFO	u32			32-bit clean *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean */static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr){	unsigned char *workbuf, *wp;	unsigned long bufsz, space_avail;	struct cmsghdr *ucmsg;	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;	space_avail = kmsg->msg_controllen + bufsz;	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);	if(workbuf == NULL)		goto fail;	/* To make this more sane we assume the kernel sends back properly	 * formatted control messages.  Because of how the kernel will truncate	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.	 */	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;	while(((unsigned long)ucmsg) <=	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;		int clen64, clen32;		/* UCMSG is the 64-bit format CMSG entry in user-space.		 * KCMSG32 is within the kernel space temporary buffer		 * we use to convert into a 32-bit style CMSG.		 */		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);		clen64 = kcmsg32->cmsg_len;		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));		kcmsg32->cmsg_len = clen32;		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));	}	/* Copy back fixed up data, and adjust pointers. */	bufsz = (wp - workbuf);	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);	kmsg->msg_control = (struct cmsghdr *)		(((char *)orig_cmsg_uptr) + bufsz);	kmsg->msg_controllen = space_avail - bufsz;	kfree(workbuf);	return;fail:	/* If we leave the 64-bit format CMSG chunks in there,	 * the application could get confused and crash.  So to	 * ensure greater recovery, we report no CMSGs.	 */	kmsg->msg_controllen += bufsz;	kmsg->msg_control = (void *) orig_cmsg_uptr;}asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags){	struct socket *sock;	char address[MAX_SOCK_ADDR];	struct iovec iov[UIO_FASTIOV];	unsigned char ctl[sizeof(struct cmsghdr) + 20];	unsigned char *ctl_buf = ctl;	struct msghdr kern_msg;	int err, total_len;	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))		return -EFAULT;	if(kern_msg.msg_iovlen > UIO_MAXIOV)		return -EINVAL;	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);	if (err < 0)		goto out;	total_len = err;	if(kern_msg.msg_controllen) {		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));		if(err)			goto out_freeiov;		ctl_buf = kern_msg.msg_control;	}	kern_msg.msg_flags = user_flags;	sock = sockfd_lookup(fd, &err);	if (sock != NULL) {		if (sock->file->f_flags & O_NONBLOCK)			kern_msg.msg_flags |= MSG_DONTWAIT;		err = sock_sendmsg(sock, &kern_msg, total_len);		sockfd_put(sock);	}	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */	if(ctl_buf != ctl)		kfree(ctl_buf);out_freeiov:	if(kern_msg.msg_iov != iov)		kfree(kern_msg.msg_iov);out:	return err;}asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags){	struct iovec iovstack[UIO_FASTIOV];	struct msghdr kern_msg;	char addr[MAX_SOCK_ADDR];	struct socket *sock;	struct iovec *iov = iovstack;	struct sockaddr *uaddr;	int *uaddr_len;

⌨️ 快捷键说明

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