diff --git a/open(add getdents).c b/open(add getdents).c new file mode 100644 index 0000000..f657447 --- /dev/null +++ b/open(add getdents).c @@ -0,0 +1,343 @@ +/* + * linux/fs/open.c + * + * (C) 1991 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int sys_ustat(int dev, struct ustat * ubuf) +{ + return -ENOSYS; +} + +int sys_utime(char * filename, struct utimbuf * times) +{ + struct m_inode * inode; + long actime,modtime; + + if (!(inode=namei(filename))) + return -ENOENT; + if (times) { + actime = get_fs_long((unsigned long *) ×->actime); + modtime = get_fs_long((unsigned long *) ×->modtime); + } else + actime = modtime = CURRENT_TIME; + inode->i_atime = actime; + inode->i_mtime = modtime; + inode->i_dirt = 1; + iput(inode); + return 0; +} + +/* + * XXX should we use the real or effective uid? BSD uses the real uid, + * so as to make this call useful to setuid programs. + */ +int sys_access(const char * filename,int mode) +{ + struct m_inode * inode; + int res, i_mode; + + mode &= 0007; + if (!(inode=namei(filename))) + return -EACCES; + i_mode = res = inode->i_mode & 0777; + iput(inode); + if (current->uid == inode->i_uid) + res >>= 6; + else if (current->gid == inode->i_gid) + res >>= 6; + if ((res & 0007 & mode) == mode) + return 0; + /* + * XXX we are doing this test last because we really should be + * swapping the effective with the real user id (temporarily), + * and then calling suser() routine. If we do call the + * suser() routine, it needs to be called last. + */ + if ((!current->uid) && + (!(mode & 1) || (i_mode & 0111))) + return 0; + return -EACCES; +} + +int sys_chdir(const char * filename) +{ + struct m_inode * inode; + + if (!(inode = namei(filename))) + return -ENOENT; + if (!S_ISDIR(inode->i_mode)) { + iput(inode); + return -ENOTDIR; + } + iput(current->pwd); + current->pwd = inode; + return (0); +} + +int sys_chroot(const char * filename) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if (!S_ISDIR(inode->i_mode)) { + iput(inode); + return -ENOTDIR; + } + iput(current->root); + current->root = inode; + return (0); +} + +int sys_chmod(const char * filename,int mode) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if ((current->euid != inode->i_uid) && !suser()) { + iput(inode); + return -EACCES; + } + inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777); + inode->i_dirt = 1; + iput(inode); + return 0; +} + +int sys_chown(const char * filename,int uid,int gid) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if (!suser()) { + iput(inode); + return -EACCES; + } + inode->i_uid=uid; + inode->i_gid=gid; + inode->i_dirt=1; + iput(inode); + return 0; +} + +int sys_open(const char * filename,int flag,int mode) +{ + struct m_inode * inode; + struct file * f; + int i,fd; + + mode &= 0777 & ~current->umask; + for(fd=0 ; fdfilp[fd]) + break; + if (fd>=NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<f_count) break; + if (i>=NR_FILE) + return -EINVAL; + (current->filp[fd]=f)->f_count++; + if ((i=open_namei(filename,flag,mode,&inode))<0) { + current->filp[fd]=NULL; + f->f_count=0; + return i; + } +/* ttys are somewhat special (ttyxx major==4, tty major==5) */ + if (S_ISCHR(inode->i_mode)) + if (MAJOR(inode->i_zone[0])==4) { + if (current->leader && current->tty<0) { + current->tty = MINOR(inode->i_zone[0]); + tty_table[current->tty].pgrp = current->pgrp; + } + } else if (MAJOR(inode->i_zone[0])==5) + if (current->tty<0) { + iput(inode); + current->filp[fd]=NULL; + f->f_count=0; + return -EPERM; + } +/* Likewise with block-devices: check for floppy_change */ + if (S_ISBLK(inode->i_mode)) + check_disk_change(inode->i_zone[0]); + f->f_mode = inode->i_mode; + f->f_flags = flag; + f->f_count = 1; + f->f_inode = inode; + f->f_pos = 0; + return (fd); +} + +int sys_creat(const char * pathname, int mode) +{ + return sys_open(pathname, O_CREAT | O_TRUNC, mode); +} + +int sys_close(unsigned int fd) +{ + struct file * filp; + + if (fd >= NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<filp[fd])) + return -EINVAL; + current->filp[fd] = NULL; + if (filp->f_count == 0) + panic("Close: file count is 0"); + if (--filp->f_count) + return (0); + iput(filp->f_inode); + return (0); +} +int find_entry1(struct m_inode ** dir,int find_node,struct dir_entry ** res_dir){ + int entries; + int block,i; + struct buffer_head * bh; + struct dir_entry * de; + struct super_block * sb; + entries = (*dir)->i_size / (sizeof (struct dir_entry)); + *res_dir = NULL; + if (!(block = (*dir)->i_zone[0])) + return NULL; + if (!(bh = bread((*dir)->i_dev,block))) + return NULL; + i = 0; + de = (struct dir_entry *) bh->b_data; + while (i < entries) { + if ((char *)de >= BLOCK_SIZE+bh->b_data) { + brelse(bh); + bh = NULL; + if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) || + !(bh = bread((*dir)->i_dev,block))) { + i += DIR_ENTRIES_PER_BLOCK; + continue; + } + de = (struct dir_entry *) bh->b_data; + } + if (de->inode == find_node) { + *res_dir = de; + return 0; + } + de++; + i++; + } + brelse(bh); + return -1; +} +long sys_getcwd(char *buf,size_t size){ + int entries; + int block,i; + int num = 19; + char s[20][NAME_LEN]; + struct buffer_head * bh; + struct dir_entry * de; + struct dir_entry * res_dir; + struct super_block * sb; + struct m_inode * dir =current->pwd; + struct m_inode * olddir =NULL; + while(1){ + olddir = dir; + if (olddir==current->root) + break; + if (!dir->i_zone[0]) + return NULL; + if(!(bh = bread(dir->i_dev,dir->i_zone[0])))//获得i节点指向的数据块 + return NULL; + de = (struct dir_entry *) bh->b_data; + int find = de->inode; + if (!(dir = iget(dir->i_dev,(de+1)->inode))){//dir更新并判断错误 + return NULL; + } + if(find_entry1(&dir,find,&res_dir)==-1){ + printk("getcwd error\n"); + return NULL; + } + strcpy(s[num--],res_dir->name); + } + char *buf1; + char *buf3 = buf1; + for(i=num+1;i<=19;i++){ + *buf3 = '/'; + *buf3++; + char *w = s[i]; + while(*w){ + *buf3 = (*w++); + *buf3++; + } + } + int len = strlen(buf1); + if(!buf) buf = (char *)malloc(len); + char *buf2 = buf; + int j; + for(j=0;jfilp[fd]->f_inode; + /*if(!(dir= current->filp[fd]->f_inode)) + return -1;*/ + int entries; + int block,i; + struct buffer_head * bh; + struct dir_entry * de; + struct super_block * sb; + struct linux_dirent * cur = (struct linux_dirent *)malloc(count) ; + char *oldcur = (char *)cur; + entries = dir->i_size / (sizeof (struct dir_entry)); + if (!(block = dir->i_zone[0])) + return -1; + if (!(bh = bread(dir->i_dev,block))) + return -1; + i = 0; + int fixsize = sizeof(long)+sizeof(off_t)+sizeof(unsigned short); + int pos = 0; + de = (struct dir_entry *) bh->b_data; + int nread=0; + while (i < entries) { + if ((char *)de >= BLOCK_SIZE+bh->b_data) { + brelse(bh); + bh = NULL; + if (!(block = bmap(dir,i/DIR_ENTRIES_PER_BLOCK)) || + !(bh = bread(dir->i_dev,block))) { + i += DIR_ENTRIES_PER_BLOCK; + continue; + } + de = (struct dir_entry *) bh->b_data; + } + cur->d_ino = de->inode; + cur->d_off = pos; + strcpy(cur->d_name,de->name); + cur->d_reclen = fixsize+sizeof(de->name); + pos += cur->d_reclen; + nread+=sizeof(de->name); + de++; + char *w = (char *)cur; + w = w+cur->d_reclen; + cur = (struct linux_dirent *)w; + i++; + } + brelse(bh); + char *s = (char *)dirp; + int j=0; + for(j;j