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; } }
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); }
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; }
/* 向文件发送一个命令,如获取文件信息的命令, * 将文件的信息拷贝到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; } }
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; }
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; }
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; }
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; }
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); }
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; }
/* * 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; }
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); }
/* 这个和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); }
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; }
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; }
/* * 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; }
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; }
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; }
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 */ }
// 系统调用中断处理程序中真正的信号处理程序(在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 中的码位。 }
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 */ }
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; }
// 返回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; }
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; }
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; }
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; }
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); }
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; }
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 */ }