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

📄 sys_sparc32.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		switch (_NSIG_WORDS) {		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];		}		if (copy_to_user (set, &s32, sizeof(sigset_t32)))			return -EFAULT;	}	return ret;}asmlinkage intsys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,		      struct timespec32 *uts, __kernel_size_t32 sigsetsize){	int ret, sig;	sigset_t these;	sigset_t32 these32;	struct timespec ts;	siginfo_t info;	long timeout = 0;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		return -EINVAL;	if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))		return -EFAULT;	switch (_NSIG_WORDS) {	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);	}			/*	 * Invert the set of allowed signals to get those we	 * want to block.	 */	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));	signotset(&these);	if (uts) {		if (get_user (ts.tv_sec, &uts->tv_sec) ||		    get_user (ts.tv_nsec, &uts->tv_nsec))			return -EINVAL;		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0		    || ts.tv_sec < 0)			return -EINVAL;	}	spin_lock_irq(&current->sigmask_lock);	sig = dequeue_signal(&these, &info);	if (!sig) {		/* None ready -- temporarily unblock those we're interested		   in so that we'll be awakened when they arrive.  */		sigset_t oldblocked = current->blocked;		sigandsets(&current->blocked, &current->blocked, &these);		recalc_sigpending(current);		spin_unlock_irq(&current->sigmask_lock);		timeout = MAX_SCHEDULE_TIMEOUT;		if (uts)			timeout = (timespec_to_jiffies(&ts)				   + (ts.tv_sec || ts.tv_nsec));		current->state = TASK_INTERRUPTIBLE;		timeout = schedule_timeout(timeout);		spin_lock_irq(&current->sigmask_lock);		sig = dequeue_signal(&these, &info);		current->blocked = oldblocked;		recalc_sigpending(current);	}	spin_unlock_irq(&current->sigmask_lock);	if (sig) {		ret = sig;		if (uinfo) {			if (copy_siginfo_to_user32(uinfo, &info))				ret = -EFAULT;		}	} else {		ret = -EAGAIN;		if (timeout)			ret = -EINTR;	}	return ret;}extern asmlinkage intsys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);asmlinkage intsys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo){	siginfo_t info;	int ret;	mm_segment_t old_fs = get_fs();		if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))		return -EFAULT;	set_fs (KERNEL_DS);	ret = sys_rt_sigqueueinfo(pid, sig, &info);	set_fs (old_fs);	return ret;}struct tms32 {	__kernel_clock_t32 tms_utime;	__kernel_clock_t32 tms_stime;	__kernel_clock_t32 tms_cutime;	__kernel_clock_t32 tms_cstime;};                                extern asmlinkage long sys_times(struct tms * tbuf);asmlinkage long sys32_times(struct tms32 *tbuf){	struct tms t;	long ret;	mm_segment_t old_fs = get_fs ();	int err;		set_fs (KERNEL_DS);	ret = sys_times(tbuf ? &t : NULL);	set_fs (old_fs);	if (tbuf) {		err = put_user (t.tms_utime, &tbuf->tms_utime);		err |= __put_user (t.tms_stime, &tbuf->tms_stime);		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);		if (err)			ret = -EFAULT;	}	return ret;}#define RLIM_INFINITY32	0x7fffffff#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)struct rlimit32 {	u32	rlim_cur;	u32	rlim_max;};extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim){	struct rlimit r;	int ret;	mm_segment_t old_fs = get_fs ();		set_fs (KERNEL_DS);	ret = sys_getrlimit(resource, &r);	set_fs (old_fs);	if (!ret) {		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);	}	return ret;}extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim){	struct rlimit r;	int ret;	mm_segment_t old_fs = get_fs ();	if (resource >= RLIM_NLIMITS) return -EINVAL;		if (get_user (r.rlim_cur, &rlim->rlim_cur) ||	    __get_user (r.rlim_max, &rlim->rlim_max))		return -EFAULT;	if (r.rlim_cur == RLIM_INFINITY32)		r.rlim_cur = RLIM_INFINITY;	if (r.rlim_max == RLIM_INFINITY32)		r.rlim_max = RLIM_INFINITY;	set_fs (KERNEL_DS);	ret = sys_setrlimit(resource, &r);	set_fs (old_fs);	return ret;}extern asmlinkage int sys_getrusage(int who, struct rusage *ru);asmlinkage int sys32_getrusage(int who, struct rusage32 *ru){	struct rusage r;	int ret;	mm_segment_t old_fs = get_fs();			set_fs (KERNEL_DS);	ret = sys_getrusage(who, &r);	set_fs (old_fs);	if (put_rusage (ru, &r)) return -EFAULT;	return ret;}/* 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) {		

⌨️ 快捷键说明

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