Beispiel #1
0
static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
	int block;

	switch (cmd) {
		case FIBMAP:
			if (filp->f_inode->i_op == NULL)
				return -EBADF;
		    	if (filp->f_inode->i_op->bmap == NULL)
				return -EINVAL;
			verify_area((void *) arg,4);
			block = get_fs_long((long *) arg);
			block = filp->f_inode->i_op->bmap(filp->f_inode,block);
			put_fs_long(block,(long *) arg);
			return 0;
		case FIGETBSZ:
			if (filp->f_inode->i_sb == NULL)
				return -EBADF;
			verify_area((void *) arg,4);
			put_fs_long(filp->f_inode->i_sb->s_blocksize,
			    (long *) arg);
			return 0;
		case FIONREAD:
			verify_area((void *) arg,4);
			put_fs_long(filp->f_inode->i_size - filp->f_pos,
			    (long *) arg);
			return 0;
		default:
			return -EINVAL;
	}
}
Beispiel #2
0
static int do_get_ps_info(int arg)
{
	struct tstruct {
		int flag;
		int present[NR_TASKS];
		struct task_struct tasks[NR_TASKS];
	};
	struct tstruct *ts = (struct tstruct *)arg;
	struct task_struct **p;
	char *c, *d;
	int i, n = 0;
	
	verify_area((void *)arg, sizeof(struct tstruct));
		
	for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++)
		if (*p)
		{
			c = (char *)(*p);
			d = (char *)(ts->tasks+n);
			for (i=0 ; i<sizeof(struct task_struct) ; i++)
				put_fs_byte(*c++, d++);
			put_fs_long(1, (unsigned long *)(ts->present+n));
		}
		else	
			put_fs_long(0, (unsigned long *)(ts->present+n));
	return(0);			
}
Beispiel #3
0
static int
unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct unix_proto_data *upd, *peerupd;

	upd = UN_DATA(sock);
	peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;

	switch (cmd) {
	case TIOCINQ:
		verify_area((void *)arg, sizeof(unsigned long));
		if (UN_BUF_AVAIL(upd) || peerupd)
			put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
		else
			put_fs_long(1, (unsigned long *)arg); /* read EOF */
		break;

	case TIOCOUTQ:
		verify_area((void *)arg, sizeof(unsigned long));
		if (peerupd)
			put_fs_long(UN_BUF_SPACE(peerupd),
				    (unsigned long *)arg);
		else
			put_fs_long(0, (unsigned long *)arg);
		break;

	default:
		return -EINVAL;
	}
	return 0;
}
Beispiel #4
0
/* 向文件发送一个命令,如获取文件信息的命令,
 * 将文件的信息拷贝到arg所指向的内存,如关于文件的flag和版本等信息
 */
int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
		unsigned long arg)
{

	ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);

	switch (cmd) {
	case EXT2_IOC_GETFLAGS:
		put_fs_long (inode->u.ext2_i.i_flags, (long *) arg);
		return 0;
	case EXT2_IOC_SETFLAGS:
		if ((current->euid != inode->i_uid) && !suser())
			return -EPERM;
		if (IS_RDONLY(inode))
			return -EROFS;
		inode->u.ext2_i.i_flags = get_fs_long ((long *) arg);
		inode->i_ctime = CURRENT_TIME;
		inode->i_dirt = 1;
		return 0;
	case EXT2_IOC_GETVERSION:
		put_fs_long (inode->u.ext2_i.i_version, (long *) arg);
		return 0;
	case EXT2_IOC_SETVERSION:
		if ((current->euid != inode->i_uid) && !suser())
			return -EPERM;
		if (IS_RDONLY(inode))
			return -EROFS;
		inode->u.ext2_i.i_version = get_fs_long ((long *) arg);
		inode->i_ctime = CURRENT_TIME;
		inode->i_dirt = 1;
		return 0;
	default:
		return -EINVAL;
	}
}
Beispiel #5
0
int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
{
	int flag, code;
	struct task_struct ** p;

	verify_area(stat_addr,4);
repeat:
	flag=0;
	for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
		if (!*p || *p == current)
			continue;
		if ((*p)->father != current->pid)
			continue;
		if (pid>0) {
			if ((*p)->pid != pid)
				continue;
		} else if (!pid) {
			if ((*p)->pgrp != current->pgrp)
				continue;
		} else if (pid != -1) {
			if ((*p)->pgrp != -pid)
				continue;
		}
		switch ((*p)->state) {
			case TASK_STOPPED:
				if (!(options & WUNTRACED))
					continue;
				put_fs_long(0x7f,stat_addr);
				return (*p)->pid;
			case TASK_ZOMBIE:
				current->cutime += (*p)->utime;
				current->cstime += (*p)->stime;
				flag = (*p)->pid;
				code = (*p)->exit_code;
				release(*p);
				put_fs_long(code,stat_addr);
				return flag;
			default:
				flag=1;
				continue;
		}
	}
	if (flag) {
		if (options & WNOHANG)
			return 0;
		current->state=TASK_INTERRUPTIBLE;
		/*
		*当前进程 => 等待
		*/
		fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);
		schedule();
		if (!(current->signal &= ~(1<<(SIGCHLD-1))))
			goto repeat;
		else
			return -EINTR;
	}
	return -ECHILD;
}
Beispiel #6
0
static int msdos_readdir(struct inode *inode,struct file *filp,
    struct dirent *dirent,int count)
{
	int ino,i,i2,last;
	char c,*walk;
	struct buffer_head *bh;
	struct msdos_dir_entry *de;

	if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF;
	if (inode->i_ino == MSDOS_ROOT_INO) {
/* Fake . and .. for the root directory. */
		if (filp->f_pos == 2) filp->f_pos = 0;
		else if (filp->f_pos < 2) {
				walk = filp->f_pos++ ? ".." : ".";
				for (i = 0; *walk; walk++)
					put_fs_byte(*walk,dirent->d_name+i++);
				put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
				put_fs_byte(0,dirent->d_name+i);
				put_fs_word(i,&dirent->d_reclen);
				return i;
			}
	}
	if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
	bh = NULL;
	while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
		if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
			for (i = last = 0; i < 8; i++) {
				if (!(c = de->name[i])) break;
				if (c >= 'A' && c <= 'Z') c += 32;
				if (c != ' ') last = i+1;
				put_fs_byte(c,i+dirent->d_name);
			}
			i = last;
			put_fs_byte('.',i+dirent->d_name);
			i++;
			for (i2 = 0; i2 < 3; i2++) {
				if (!(c = de->ext[i2])) break;
				if (c >= 'A' && c <= 'Z') c += 32;
				if (c != ' ') last = i+1;
				put_fs_byte(c,i+dirent->d_name);
				i++;
			}
			if ((i = last) != 0) {
				if (!strcmp(de->name,MSDOS_DOT))
					ino = inode->i_ino;
				else if (!strcmp(de->name,MSDOS_DOTDOT))
						ino = msdos_parent_ino(inode,0);
				put_fs_long(ino,&dirent->d_ino);
				put_fs_byte(0,i+dirent->d_name);
				put_fs_word(i,&dirent->d_reclen);
				brelse(bh);
				return i;
			}
		}
	}
	if (bh) brelse(bh);
	return 0;
}
Beispiel #7
0
int sys_times(struct tms * tbuf)
{
	if (tbuf) {
		verify_area(tbuf,sizeof *tbuf);
		put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
		put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
		put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
		put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
	}
	return jiffies;
}
Beispiel #8
0
asmlinkage int sys_times(struct tms * tbuf)
{
	if (tbuf) {
		int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
		if (error)
			return error;
		put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
		put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
		put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
		put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
	}
	return jiffies;
}
Beispiel #9
0
static void hpfs_statfs(struct super_block *s, struct statfs *buf)
{
	/*
	 * count the bits in the bitmaps, unless we already have
	 */

	if (s->s_hpfs_n_free == -1) {
		s->s_hpfs_n_free = count_bitmap(s);
		s->s_hpfs_n_free_dnodes =
		    count_one_bitmap(s->s_dev, s->s_hpfs_dmap);
	}

	/*
	 * fill in the user statfs struct
	 */

	put_fs_long(s->s_magic, &buf->f_type);
	put_fs_long(512, &buf->f_bsize);
	put_fs_long(s->s_hpfs_fs_size, &buf->f_blocks);
	put_fs_long(s->s_hpfs_n_free, &buf->f_bfree);
	put_fs_long(s->s_hpfs_n_free, &buf->f_bavail);
	put_fs_long(s->s_hpfs_dirband_size, &buf->f_files);
	put_fs_long(s->s_hpfs_n_free_dnodes, &buf->f_ffree);
	put_fs_long(254, &buf->f_namelen);
}
Beispiel #10
0
asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
{
	int error;

	if (resource >= RLIM_NLIMITS)
		return -EINVAL;
	error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
	if (error)
		return error;
	put_fs_long(current->rlim[resource].rlim_cur, 
		    (unsigned long *) rlim);
	put_fs_long(current->rlim[resource].rlim_max, 
		    ((unsigned long *) rlim)+1);
	return 0;	
}
Beispiel #11
0
/*
 * sys_pipe() is the normal C calling standard for creating
 * a pipe. It's not the way unix traditionally does this, though.
 */
asmlinkage int sys_pipe(unsigned long * fildes)
{
	int fd[2];
	int error;

	error = verify_area(VERIFY_WRITE,fildes,8);
	if (error)
		return error;
	error = do_pipe(fd);
	if (error)
		return error;
	put_fs_long(fd[0],0+fildes);
	put_fs_long(fd[1],1+fildes);
	return 0;
}
Beispiel #12
0
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
	int err;
	switch(cmd) 
	{
		case TIOCOUTQ:
		{
			unsigned long amount;

			if (sk->state == TCP_LISTEN) return(-EINVAL);
			amount = sock_wspace(sk);
			err=verify_area(VERIFY_WRITE,(void *)arg,
					sizeof(unsigned long));
			if(err)
				return(err);
			put_fs_long(amount,(unsigned long *)arg);
			return(0);
		}

		case TIOCINQ:
		{
			struct sk_buff *skb;
			unsigned long amount;

			if (sk->state == TCP_LISTEN) return(-EINVAL);
			amount = 0;
			skb = skb_peek(&sk->receive_queue);
			if (skb != NULL) {
				/*
				 * We will only return the amount
				 * of this packet since that is all
				 * that will be read.
				 */
				amount = skb->len-sizeof(struct udphdr);
			}
			err=verify_area(VERIFY_WRITE,(void *)arg,
						sizeof(unsigned long));
			if(err)
				return(err);
			put_fs_long(amount,(unsigned long *)arg);
			return(0);
		}

		default:
			return(-EINVAL);
	}
	return(0);
}
Beispiel #13
0
/* 这个和pipe功能有相似之处,pipe是单工的,socketpair是双工的
 * family只能是UNIX域的。
 */
static int
sock_socketpair(int family, int type, int protocol, unsigned long usockvec[2])
{
  int fd1, fd2, i;
  struct socket *sock1, *sock2;
  int er;

  DPRINTF((net_debug,
	"NET: sock_socketpair: family = %d, type = %d, protocol = %d\n",
							family, type, protocol));

  /*
   * Obtain the first socket and check if the underlying protocol
   * supports the socketpair call.
   */
  /* 如果创建失败,则直接返回 */
  if ((fd1 = sock_socket(family, type, protocol)) < 0) return(fd1);
  sock1 = sockfd_lookup(fd1, NULL);
  if (!sock1->ops->socketpair) {
	sys_close(fd1);
	return(-EINVAL);
  }

  /* Now grab another socket and try to connect the two together. */
  if ((fd2 = sock_socket(family, type, protocol)) < 0) {
	sys_close(fd1);
	return(-EINVAL);
  }
  sock2 = sockfd_lookup(fd2, NULL);
  if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
	sys_close(fd1);
	sys_close(fd2);
	return(i);
  }
  sock1->conn = sock2;
  sock2->conn = sock1;
  /* 完成socketpair操作后,则这只套接字的状态为连接状态 */
  sock1->state = SS_CONNECTED;
  sock2->state = SS_CONNECTED;

  er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int));
  if(er)
  	return er;
  put_fs_long(fd1, &usockvec[0]);
  put_fs_long(fd2, &usockvec[1]);

  return(0);
}
Beispiel #14
0
static int proc_readbase(struct inode * inode, struct file * filp,
                         struct dirent * dirent, int count)
{
    struct proc_dir_entry * de;
    unsigned int pid, ino;
    int i,j;

    if (!inode || !S_ISDIR(inode->i_mode))
        return -EBADF;
    ino = inode->i_ino;
    pid = ino >> 16;
    for (i = 0 ; i < NR_TASKS ; i++)
        if (task[i] && task[i]->pid == pid)
            break;
    if (!pid || i >= NR_TASKS)
        return 0;
    if (((unsigned) filp->f_pos) < NR_BASE_DIRENTRY) {
        de = base_dir + filp->f_pos;
        filp->f_pos++;
        i = de->namelen;
        ino = de->low_ino;
        if (ino != 1)
            ino |= (pid << 16);
        put_fs_long(ino, &dirent->d_ino);
        put_fs_word(i,&dirent->d_reclen);
        put_fs_byte(0,i+dirent->d_name);
        j = i;
        while (i--)
            put_fs_byte(de->name[i], i+dirent->d_name);
        return j;
    }
    return 0;
}
Beispiel #15
0
int sys_waitpid(pid_t pid,int * stat_addr, int options)
{
	int flag=0;
	struct task_struct ** p;

	verify_area(stat_addr,4);
repeat:
	for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
		if (*p && *p != current &&
		   (pid==-1 || (*p)->pid==pid ||
		   (pid==0 && (*p)->pgrp==current->pgrp) ||
		   (pid<0 && (*p)->pgrp==-pid)))
			if ((*p)->father == current->pid) {
				flag=1;
				if ((*p)->state==TASK_ZOMBIE) {
					put_fs_long((*p)->exit_code,
						(unsigned long *) stat_addr);
					current->cutime += (*p)->utime;
					current->cstime += (*p)->stime;
					flag = (*p)->pid;
					release(*p);
					return flag;
				}
			}
	if (flag) {
		if (options & WNOHANG)
			return 0;
		sys_pause();
		if (!(current->signal &= ~(1<<(SIGCHLD-1))))
			goto repeat;
		else
			return -EINTR;
	}
	return -ECHILD;
}
Beispiel #16
0
/*
 * gets the current name or the name of the connected socket.
 */
static int
unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
		   int *usockaddr_len, int peer)
{
	struct unix_proto_data *upd;
	int len;

	PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
	       peer ? "peer" : "self");
	if (peer) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_getname: socket not connected\n");
			return -EINVAL;
		}
		upd = UN_DATA(sock->conn);
	}
	else
		upd = UN_DATA(sock);
	verify_area(usockaddr_len, sizeof(*usockaddr_len));
	if ((len = get_fs_long(usockaddr_len)) <= 0)
		return -EINVAL;
	if (len > upd->sockaddr_len)
		len = upd->sockaddr_len;
	if (len) {
		verify_area(usockaddr, len);
		memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
	}
	put_fs_long(len, usockaddr_len);
	return 0;
}
Beispiel #17
0
static int xiafs_readdir(struct inode * inode, 
		       struct file * filp, struct dirent * dirent, int count)
{
    u_int offset, i;
    struct buffer_head * bh;
    struct xiafs_direct * de;

    if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
        return -EBADF;
    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
        return -EBADF;
    while (filp->f_pos < inode->i_size) {
        offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
	if (!bh) {
	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
	    continue;
	}
	de = (struct xiafs_direct *) (offset + bh->b_data);
	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		de->d_rec_len < 12 || 
		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
		de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
		de->d_name_len > _XIAFS_NAME_LEN ||
		de->d_name[de->d_name_len] ) {
	        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 0;
	    }  
	    offset += de->d_rec_len;
	    filp->f_pos += de->d_rec_len;
	    if (de->d_ino) {
	        for (i = 0; i < de->d_name_len ; i++)
		    put_fs_byte(de->d_name[i],i+dirent->d_name);
		put_fs_byte(0,i+dirent->d_name);
		put_fs_long(de->d_ino,&dirent->d_ino);
		put_fs_word(i,&dirent->d_reclen);
		brelse(bh);
		if (!IS_RDONLY (inode)) {
		    inode->i_atime=CURRENT_TIME;		    
		    inode->i_dirt=1;
		}
		return i;
	    }
	    de = (struct xiafs_direct *) (offset + bh->b_data);
	}
	brelse(bh);
	if (offset > XIAFS_ZSIZE(inode->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return 0;
	}
    }
    if (!IS_RDONLY (inode)) {
	inode->i_atime=CURRENT_TIME;		    
	inode->i_dirt=1;
    }
    return 0;
}
Beispiel #18
0
static int
sock_socketpair(int family, int type, int protocol, int usockvec[2])
{
	int fd1, fd2, i;
	struct socket *sock1, *sock2;

	PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n",
	       family, type, protocol);

	/*
	 * obtain the first socket and check if the underlying protocol
	 * supports the socketpair call
	 */
	if ((fd1 = sock_socket(family, type, protocol)) < 0)
		return fd1;
	sock1 = sockfd_lookup(fd1, NULL);
	if (!sock1->ops->socketpair) {
		sys_close(fd1);
		return -EINVAL;
	}

	/*
	 * now grab another socket and try to connect the two together
	 */
	if ((fd2 = sock_socket(family, type, protocol)) < 0) {
		sys_close(fd1);
		return -EINVAL;
	}
	sock2 = sockfd_lookup(fd2, NULL);
	if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
		sys_close(fd1);
		sys_close(fd2);
		return i;
	}
	sock1->conn = sock2;
	sock2->conn = sock1;
	sock1->state = SS_CONNECTED;
	sock2->state = SS_CONNECTED;

	verify_area(usockvec, 2 * sizeof(int));
	put_fs_long(fd1, &usockvec[0]);
	put_fs_long(fd2, &usockvec[1]);

	return 0;
}
/*
	the scsi_ioctl() function differs from most ioctls in that it does
	not take a major/minor number as the dev filed.  Rather, it takes
	a pointer to a scsi_devices[] element, a structure. 
*/
int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
{
        char scsi_cmd[12];

	if ((cmd != 0 && dev->index > NR_SCSI_DEVICES))
		return -ENODEV;
	
	switch (cmd) {
	        case SCSI_IOCTL_GET_IDLUN:
	                verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
			put_fs_long(dev->id + (dev->lun << 8) + 
				    (dev->host->host_no << 16), (unsigned long *) arg);
			return 0;
		case SCSI_IOCTL_TAGGED_ENABLE:
			if(!suser())  return -EACCES;
			if(!dev->tagged_supported) return -EINVAL;
			dev->tagged_queue = 1;
			dev->current_tag = 1;
			break;
		case SCSI_IOCTL_TAGGED_DISABLE:
			if(!suser())  return -EACCES;
			if(!dev->tagged_supported) return -EINVAL;
			dev->tagged_queue = 0;
			dev->current_tag = 0;
			break;
		case SCSI_IOCTL_PROBE_HOST:
			return ioctl_probe(dev->host, arg);
		case SCSI_IOCTL_SEND_COMMAND:
			if(!suser())  return -EACCES;
			return ioctl_command((Scsi_Device *) dev, arg);
		case SCSI_IOCTL_DOORLOCK:
			if (!dev->removable || !dev->lockable) return 0;
		        scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
			scsi_cmd[1] = dev->lun << 5;
			scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
			scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
			return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
			break;
		case SCSI_IOCTL_DOORUNLOCK:
			if (!dev->removable || !dev->lockable) return 0;
		        scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
			scsi_cmd[1] = dev->lun << 5;
			scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
			scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
			return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
		case SCSI_IOCTL_TEST_UNIT_READY:
		        scsi_cmd[0] = TEST_UNIT_READY;
			scsi_cmd[1] = dev->lun << 5;
			scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
			scsi_cmd[4] = 0;
			return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
			break;
		default :			
			return -EINVAL;
	}
	return -EINVAL;
}
Beispiel #20
0
void isofs_statfs (struct super_block *sb, struct statfs *buf)
{
	put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
	put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
	put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
	put_fs_long(0, &buf->f_bfree);
	put_fs_long(0, &buf->f_bavail);
	put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
	put_fs_long(0, &buf->f_ffree);
	put_fs_long(NAME_MAX, &buf->f_namelen);
	/* Don't know what value to put in buf->f_fsid */
}
Beispiel #21
0
// 系统调用中断处理程序中真正的信号处理程序(在kernel/system_call.s,119 行)。
// 该段代码的主要作用是将信号的处理句柄插入到用户程序堆栈中,并在本系统调用结束
// 返回后立刻执行信号句柄程序,然后继续执行用户的程序。
void
do_signal (long signr, long eax, long ebx, long ecx, long edx,
	   long fs, long es, long ds,
	   long eip, long cs, long eflags, unsigned long *esp, long ss)
{
  unsigned long sa_handler;
  long old_eip = eip;
  struct sigaction *sa = current->sigaction + signr - 1;	//current->sigaction[signu-1]。
  int longs;
  unsigned long *tmp_esp;

  sa_handler = (unsigned long) sa->sa_handler;
// 如果信号句柄为SIG_IGN(忽略),则返回;如果句柄为SIG_DFL(默认处理),则如果信号是
// SIGCHLD 则返回,否则终止进程的执行
  if (sa_handler == 1)
    return;
  if (!sa_handler)
    {
      if (signr == SIGCHLD)
	return;
      else
	do_exit (1 << (signr - 1));	// [?? 为什么以信号位图为参数?不为什么!??]
// 这里应该是do_exit(1<<signr))。
    }
// 如果该信号句柄只需使用一次,则将该句柄置空(该信号句柄已经保存在sa_handler 指针中)。
  if (sa->sa_flags & SA_ONESHOT)
    sa->sa_handler = NULL;
// 下面这段代码将信号处理句柄插入到用户堆栈中,同时也将sa_restorer,signr,进程屏蔽码(如果
// SA_NOMASK 没置位),eax,ecx,edx 作为参数以及原调用系统调用的程序返回指针及标志寄存器值
// 压入堆栈。因此在本次系统调用中断(0x80)返回用户程序时会首先执行用户的信号句柄程序,然后
// 再继续执行用户程序。
// 将用户调用系统调用的代码指针eip 指向该信号处理句柄。
  *(&eip) = sa_handler;
// 如果允许信号自己的处理句柄收到信号自己,则也需要将进程的阻塞码压入堆栈。
  longs = (sa->sa_flags & SA_NOMASK) ? 7 : 8;
// 将原调用程序的用户的堆栈指针向下扩展7(或8)个长字(用来存放调用信号句柄的参数等),
// 并检查内存使用情况(例如如果内存超界则分配新页等)。
  *(&esp) -= longs;
  verify_area (esp, longs * 4);
// 在用户堆栈中从下到上存放sa_restorer, 信号signr, 屏蔽码blocked(如果SA_NOMASK 置位),
// eax, ecx, edx, eflags 和用户程序原代码指针。
  tmp_esp = esp;
  put_fs_long ((long) sa->sa_restorer, tmp_esp++);
  put_fs_long (signr, tmp_esp++);
  if (!(sa->sa_flags & SA_NOMASK))
    put_fs_long (current->blocked, tmp_esp++);
  put_fs_long (eax, tmp_esp++);
  put_fs_long (ecx, tmp_esp++);
  put_fs_long (edx, tmp_esp++);
  put_fs_long (eflags, tmp_esp++);
  put_fs_long (old_eip, tmp_esp++);
  current->blocked |= sa->sa_mask;	// 进程阻塞码(屏蔽码)添上sa_mask 中的码位。
}
Beispiel #22
0
void proc_statfs(struct super_block *sb, struct statfs *buf)
{
	put_fs_long(PROC_SUPER_MAGIC, &buf->f_type);
	put_fs_long(PAGE_SIZE/sizeof(long), &buf->f_bsize);
	put_fs_long(0, &buf->f_blocks);
	put_fs_long(0, &buf->f_bfree);
	put_fs_long(0, &buf->f_bavail);
	put_fs_long(0, &buf->f_files);
	put_fs_long(0, &buf->f_ffree);
	put_fs_long(NAME_MAX, &buf->f_namelen);
	/* Don't know what value to put in buf->f_fsid */
}
Beispiel #23
0
static int ext_readdir(struct inode * inode, struct file * filp,
	struct dirent * dirent, int count)
{
	unsigned int offset,i;
	char c;
	struct buffer_head * bh;
	struct ext_dir_entry * de;

	if (!inode || !S_ISDIR(inode->i_mode))
		return -EBADF;
	if (filp->f_pos % 8 != 0)
		return -EBADF;
	while (filp->f_pos < inode->i_size) {
		offset = filp->f_pos & 1023;
		bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
		if (!bh) {
			filp->f_pos += 1024-offset;
			continue;
		}
		de = (struct ext_dir_entry *) (offset + bh->b_data);
		while (offset < 1024 && filp->f_pos < inode->i_size) {
			if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
			    de->rec_len < de->name_len + 8 ||
			    (de->rec_len + filp->f_pos - 1) / 1024 > (filp->f_pos / 1024)) {
				printk ("ext_readdir: bad dir entry, skipping\n");
				printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n",
					inode->i_dev, inode->i_ino, offset, de->rec_len, de->name_len);
				filp->f_pos += 1024-offset;
				if (filp->f_pos > inode->i_size)
					filp->f_pos = inode->i_size;
				continue;
			}
			offset += de->rec_len;
			filp->f_pos += de->rec_len;
			if (de->inode) {
				for (i = 0; i < de->name_len; i++)
					if ((c = de->name[i]) != 0)
						put_fs_byte(c,i+dirent->d_name);
					else
						break;
				if (i) {
					put_fs_long(de->inode,&dirent->d_ino);
					put_fs_byte(0,i+dirent->d_name);
					put_fs_word(i,&dirent->d_reclen);
					brelse(bh);
					return i;
				}
			}
			de = (struct ext_dir_entry *) ((char *) de 
				+ de->rec_len);
		}
		brelse(bh);
	}
	return 0;
}
Beispiel #24
0
// 返回1970.1.1:0:0:0
int sys_time(long * tloc)
{
	int i;

	i = CURRENT_TIME;
	if (tloc) {
		verify_area(tloc,4);// 验证内存容量是否足够
		put_fs_long(i,(unsigned long *)tloc);	// 放入用户数据段tloc
	}
	return i;
}
Beispiel #25
0
int sys_time(long * tloc)
{
	int i;

	i = CURRENT_TIME;
	if (tloc) {
		verify_area(tloc,4);
		put_fs_long(i,(unsigned long *)tloc);
	}
	return i;
}
Beispiel #26
0
int sys_pipe(unsigned long * fildes)
{
	struct m_inode * inode;
	struct file * f[2];
	int fd[2];
	int i,j;

	j=0;
	for(i=0;j<2 && i<NR_FILE;i++)
		if (!file_table[i].f_count)
			(f[j++]=i+file_table)->f_count++;
	if (j==1)
		f[0]->f_count=0;
	if (j<2)
		return -1;
	j=0;
	for(i=0;j<2 && i<NR_OPEN;i++)
		if (!current->filp[i]) {
			current->filp[ fd[j]=i ] = f[j];
			j++;
		}
	if (j==1)
		current->filp[fd[0]]=NULL;
	if (j<2) {
		f[0]->f_count=f[1]->f_count=0;
		return -1;
	}
	if (!(inode=get_pipe_inode())) {
		current->filp[fd[0]] =
			current->filp[fd[1]] = NULL;
		f[0]->f_count = f[1]->f_count = 0;
		return -1;
	}
	f[0]->f_inode = f[1]->f_inode = inode;
	f[0]->f_pos = f[1]->f_pos = 0;
	f[0]->f_mode = 1;		/* read */
	f[1]->f_mode = 2;		/* write */
	put_fs_long(fd[0],0+fildes);
	put_fs_long(fd[1],1+fildes);
	return 0;
}
Beispiel #27
0
asmlinkage int sys_time(long *tloc) {
	int i, error;

	i = CURRENT_TIME;
	if (tloc) {
		error = verify_area(VERIFY_WRITE, tloc, 4);
		if (error)
			return error;
		put_fs_long(i,(unsigned long *)tloc);
	}
	return i;
}
Beispiel #28
0
static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	unix_socket *sk=sock->data;
	int err;
	long amount=0;

	switch(cmd)
	{

		case TIOCOUTQ:
			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
			if(err)
				return err;
			amount=sk->sndbuf-sk->wmem_alloc;
			if(amount<0)
				amount=0;
			put_fs_long(amount,(unsigned long *)arg);
			return 0;
		case TIOCINQ:
		{
			struct sk_buff *skb;
			if(sk->state==TCP_LISTEN)
				return -EINVAL;
			/* These two are safe on a single CPU system as only user tasks fiddle here */
			if((skb=skb_peek(&sk->receive_queue))!=NULL)
				amount=skb->len;
			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
			if(err)
				return err;
			put_fs_long(amount,(unsigned long *)arg);
			return 0;
		}

		default:
			return -EINVAL;
	}
	/*NOTREACHED*/
	return(0);
}
Beispiel #29
0
asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
	int error;

	if (tv) {
		struct timeval ktv;
		error = verify_area(VERIFY_WRITE, tv, sizeof *tv);
		if (error)
			return error;
		do_gettimeofday(&ktv);
		put_fs_long(ktv.tv_sec, (unsigned long *) &tv->tv_sec);
		put_fs_long(ktv.tv_usec, (unsigned long *) &tv->tv_usec);
	}
	if (tz) {
		error = verify_area(VERIFY_WRITE, tz, sizeof *tz);
		if (error)
			return error;
		put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
		put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
	}
	return 0;
}
Beispiel #30
0
void sysv_statfs(struct super_block *sb, struct statfs *buf)
{
    long tmp;

    put_fs_long(sb->s_magic, &buf->f_type);		/* type of filesystem */
    put_fs_long(sb->sv_block_size, &buf->f_bsize);	/* block size */
    put_fs_long(sb->sv_ndatazones, &buf->f_blocks);	/* total data blocks in file system */
    tmp = sysv_count_free_blocks(sb);
    put_fs_long(tmp, &buf->f_bfree);		/* free blocks in fs */
    put_fs_long(tmp, &buf->f_bavail);		/* free blocks available to non-superuser */
    put_fs_long(sb->sv_ninodes, &buf->f_files);	/* total file nodes in file system */
    put_fs_long(sysv_count_free_inodes(sb), &buf->f_ffree);	/* free file nodes in fs */
    put_fs_long(SYSV_NAMELEN, &buf->f_namelen);
    /* Don't know what value to put in buf->f_fsid */	/* file system id */
}