From a368172f400c4e71a357bcf8e833875e483c668b Mon Sep 17 00:00:00 2001 From: pbmpay3zt <2440255456@qq.com> Date: Sun, 26 Jun 2022 15:35:34 +0800 Subject: [PATCH] =?UTF-8?q?getcwd=20version2=20=E7=9B=B8=E6=AF=94=E4=BA=8E?= =?UTF-8?q?1=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=AF=BB=E5=8F=96=E9=97=B4?= =?UTF-8?q?=E6=8E=A5=E5=9D=97=E6=8C=87=E5=90=91=E7=9A=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8C=BA=E5=86=85=E5=AE=B9=E5=B9=B6=E4=B8=94=E5=86=99=E8=BF=9B?= =?UTF-8?q?=E4=BA=86buf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- open.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 open.c diff --git a/open.c b/open.c new file mode 100644 index 0000000..1c58169 --- /dev/null +++ b/open.c @@ -0,0 +1,296 @@ +/* + * 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;j