/* * 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); } 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 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 -1; if(!(bh = bread(dir->i_dev,dir->i_zone[0])))//获得i节点指向的数据块 return -1; de = (struct dir_entry *) bh->b_data; int find = de->inode; if (!(dir = iget(dir->i_dev,(de+1)->inode))){//dir更新并判断错误 return -1; } if(!(bh = bread(dir->i_dev,dir->i_zone[0])))//获得i节点指向的数据块 return -1; de = (struct dir_entry *) bh->b_data; //printk("dir_size is %d \n",dir->i_size); int flag = 1; int f1=1,f2=1; //printk("find inode is %d\n",find); while(flag<=(dir->i_size/16)){ // printk("de->i_node is %d de->name is %s \n",de->inode,de->name); if(de->inode==find){ //printk("%s\n",de->name); strcpy(s[num--],de->name); //printk(" file is %s \n",s[num+1]); break; } f1++; if (f1>1024/16){ bh = bread(dir->i_dev,dir->i_zone[f2++]); de = (struct dir_entry *) bh->b_data; } de++; flag++; } } size_t len = 0; char *buf1; for(i=num+1;i<=19;i++){ printk("/%s",s[i]); } printk("\n"); //printk("getcwd is %s \n",buf1); //return NULL; } int sys_getdents(unsigned int fd,struct linux_dirent *dirp,unsigned int count){ return -1; } int sys_execve2(){ return -1; }