--- linux/fs/minix/namei.c 2018/04/24 18:06:06 1.1.1.2 +++ linux/fs/minix/namei.c 2018/04/24 18:14:30 1.1.1.7 @@ -1,19 +1,18 @@ /* * linux/fs/minix/namei.c * - * (C) 1991 Linus Torvalds + * Copyright (C) 1991, 1992 Linus Torvalds */ #include #include #include -#include +#include +#include +#include +#include -#include -#include -#include -#include -#include +#include /* * comment out this line if you want names > MINIX_NAME_LEN chars to be @@ -59,8 +58,7 @@ static int minix_match(int len,const cha static struct buffer_head * minix_find_entry(struct inode * dir, const char * name, int namelen, struct minix_dir_entry ** res_dir) { - int entries; - int block,i; + int entries, i; struct buffer_head * bh; struct minix_dir_entry * de; @@ -75,18 +73,16 @@ static struct buffer_head * minix_find_e namelen = MINIX_NAME_LEN; #endif entries = dir->i_size / (sizeof (struct minix_dir_entry)); - if (!(block = dir->i_data[0])) - return NULL; - if (!(bh = bread(dir->i_dev,block))) + bh = minix_bread(dir,0,0); + if (!bh) return NULL; i = 0; de = (struct minix_dir_entry *) bh->b_data; while (i < entries) { if ((char *)de >= BLOCK_SIZE+bh->b_data) { brelse(bh); - bh = NULL; - if (!(block = minix_bmap(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK)) || - !(bh = bread(dir->i_dev,block))) { + bh = minix_bread(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK,0); + if (!bh) { i += MINIX_DIR_ENTRIES_PER_BLOCK; continue; } @@ -103,40 +99,6 @@ static struct buffer_head * minix_find_e return NULL; } -struct inode * minix_follow_link(struct inode * dir, struct inode * inode) -{ - unsigned short fs; - struct buffer_head * bh; - - if (!dir) { - dir = current->root; - dir->i_count++; - } - if (!inode) { - iput(dir); - return NULL; - } - if (!S_ISLNK(inode->i_mode)) { - iput(dir); - return inode; - } - __asm__("mov %%fs,%0":"=r" (fs)); - if ((current->link_count > 5) || !inode->i_data[0] || - !(bh = bread(inode->i_dev, inode->i_data[0]))) { - iput(dir); - iput(inode); - return NULL; - } - iput(inode); - __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); - current->link_count++; - inode = _namei(bh->b_data,dir,1); - current->link_count--; - __asm__("mov %0,%%fs"::"r" (fs)); - brelse(bh); - return inode; -} - int minix_lookup(struct inode * dir,const char * name, int len, struct inode ** result) { @@ -178,7 +140,7 @@ int minix_lookup(struct inode * dir,cons static struct buffer_head * minix_add_entry(struct inode * dir, const char * name, int namelen, struct minix_dir_entry ** res_dir) { - int block,i; + int i; struct buffer_head * bh; struct minix_dir_entry * de; @@ -194,23 +156,17 @@ static struct buffer_head * minix_add_en #endif if (!namelen) return NULL; - if (!(block = dir->i_data[0])) - return NULL; - if (!(bh = bread(dir->i_dev,block))) + bh = minix_bread(dir,0,0); + if (!bh) return NULL; i = 0; de = (struct minix_dir_entry *) bh->b_data; while (1) { if ((char *)de >= BLOCK_SIZE+bh->b_data) { brelse(bh); - bh = NULL; - block = minix_create_block(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK); - if (!block) + bh = minix_bread(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK,1); + if (!bh) return NULL; - if (!(bh = bread(dir->i_dev,block))) { - i += MINIX_DIR_ENTRIES_PER_BLOCK; - continue; - } de = (struct minix_dir_entry *) bh->b_data; } if (i*sizeof(struct minix_dir_entry) >= dir->i_size) { @@ -249,11 +205,13 @@ int minix_create(struct inode * dir,cons iput(dir); return -ENOSPC; } + inode->i_op = &minix_file_inode_operations; inode->i_mode = mode; inode->i_dirt = 1; bh = minix_add_entry(dir,name,len,&de); if (!bh) { inode->i_nlink--; + inode->i_dirt = 1; iput(inode); iput(dir); return -ENOSPC; @@ -287,6 +245,25 @@ int minix_mknod(struct inode * dir, cons } inode->i_uid = current->euid; inode->i_mode = mode; + inode->i_op = NULL; + if (S_ISREG(inode->i_mode)) + inode->i_op = &minix_file_inode_operations; + else if (S_ISDIR(inode->i_mode)) + inode->i_op = &minix_dir_inode_operations; + else if (S_ISLNK(inode->i_mode)) + inode->i_op = &minix_symlink_inode_operations; + else if (S_ISCHR(inode->i_mode)) + inode->i_op = &minix_chrdev_inode_operations; + else if (S_ISBLK(inode->i_mode)) + inode->i_op = &minix_blkdev_inode_operations; + else if (S_ISFIFO(inode->i_mode)) { + inode->i_op = &minix_fifo_inode_operations; + inode->i_pipe = 1; + PIPE_BASE(*inode) = NULL; + PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; + } if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = rdev; inode->i_mtime = inode->i_atime = CURRENT_TIME; @@ -294,6 +271,7 @@ int minix_mknod(struct inode * dir, cons bh = minix_add_entry(dir,name,len,&de); if (!bh) { inode->i_nlink--; + inode->i_dirt = 1; iput(inode); iput(dir); return -ENOSPC; @@ -323,22 +301,17 @@ int minix_mkdir(struct inode * dir, cons iput(dir); return -ENOSPC; } - inode->i_size = 32; - inode->i_dirt = 1; + inode->i_op = &minix_dir_inode_operations; + inode->i_size = 2 * sizeof (struct minix_dir_entry); inode->i_mtime = inode->i_atime = CURRENT_TIME; - if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) { + dir_block = minix_bread(inode,0,1); + if (!dir_block) { iput(dir); inode->i_nlink--; + inode->i_dirt = 1; iput(inode); return -ENOSPC; } - inode->i_dirt = 1; - if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) { - iput(dir); - inode->i_nlink--; - iput(inode); - return -ERROR; - } de = (struct minix_dir_entry *) dir_block->b_data; de->inode=inode->i_ino; strcpy(de->name,"."); @@ -348,7 +321,7 @@ int minix_mkdir(struct inode * dir, cons inode->i_nlink = 2; dir_block->b_dirt = 1; brelse(dir_block); - inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask); + inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask); inode->i_dirt = 1; bh = minix_add_entry(dir,name,len,&de); if (!bh) { @@ -372,35 +345,31 @@ int minix_mkdir(struct inode * dir, cons */ static int empty_dir(struct inode * inode) { - int nr,block; - int len; + int nr, len; struct buffer_head * bh; struct minix_dir_entry * de; len = inode->i_size / sizeof (struct minix_dir_entry); - if (len<2 || !inode->i_data[0] || - !(bh=bread(inode->i_dev,inode->i_data[0]))) { + if (len<2 || !(bh = minix_bread(inode,0,0))) { printk("warning - bad directory on dev %04x\n",inode->i_dev); - return 0; + return 1; } de = (struct minix_dir_entry *) bh->b_data; if (de[0].inode != inode->i_ino || !de[1].inode || strcmp(".",de[0].name) || strcmp("..",de[1].name)) { printk("warning - bad directory on dev %04x\n",inode->i_dev); - return 0; + return 1; } nr = 2; de += 2; while (nr= (void *) (bh->b_data+BLOCK_SIZE)) { brelse(bh); - block = minix_bmap(inode,nr/MINIX_DIR_ENTRIES_PER_BLOCK); - if (!block) { + bh = minix_bread(inode,nr/MINIX_DIR_ENTRIES_PER_BLOCK,0); + if (!bh) { nr += MINIX_DIR_ENTRIES_PER_BLOCK; continue; } - if (!(bh=bread(inode->i_dev,block))) - return 0; de = (struct minix_dir_entry *) bh->b_data; } if (de->inode) { @@ -517,20 +486,15 @@ int minix_symlink(struct inode * dir, co return -ENOSPC; } inode->i_mode = S_IFLNK | 0777; - inode->i_dirt = 1; - if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) { + inode->i_op = &minix_symlink_inode_operations; + name_block = minix_bread(inode,0,1); + if (!name_block) { iput(dir); inode->i_nlink--; + inode->i_dirt = 1; iput(inode); return -ENOSPC; } - inode->i_dirt = 1; - if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) { - iput(dir); - inode->i_nlink--; - iput(inode); - return -ERROR; - } i = 0; while (i < 1023 && (c=get_fs_byte(symname++))) name_block->b_data[i++] = c; @@ -542,6 +506,7 @@ int minix_symlink(struct inode * dir, co bh = minix_find_entry(dir,name,len,&de); if (bh) { inode->i_nlink--; + inode->i_dirt = 1; iput(inode); brelse(bh); iput(dir); @@ -550,6 +515,7 @@ int minix_symlink(struct inode * dir, co bh = minix_add_entry(dir,name,len,&de); if (!bh) { inode->i_nlink--; + inode->i_dirt = 1; iput(inode); iput(dir); return -ENOSPC; @@ -667,6 +633,10 @@ start_up: old_inode = iget(old_dir->i_dev, old_de->inode); if (!old_inode) goto end_rename; + if ((old_dir->i_mode & S_ISVTX) && + current->euid != old_inode->i_uid && + current->euid != old_dir->i_uid && !suser()) + goto end_rename; new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de); if (new_bh) { new_inode = iget(new_dir->i_dev, new_de->inode); @@ -679,6 +649,10 @@ start_up: retval = 0; goto end_rename; } + if (S_ISDIR(new_inode->i_mode)) { + retval = -EEXIST; + goto end_rename; + } if (S_ISDIR(old_inode->i_mode)) { retval = -EEXIST; if (new_bh) @@ -690,9 +664,8 @@ start_up: if (subdir(new_dir, old_inode)) goto end_rename; retval = -EIO; - if (!old_inode->i_data[0]) - goto end_rename; - if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0]))) + dir_bh = minix_bread(old_inode,0,0); + if (!dir_bh) goto end_rename; if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; @@ -712,8 +685,10 @@ start_up: /* ok, that's it */ old_de->inode = 0; new_de->inode = old_inode->i_ino; - if (new_inode) + if (new_inode) { new_inode->i_nlink--; + new_inode->i_dirt = 1; + } old_bh->b_dirt = 1; new_bh->b_dirt = 1; if (dir_bh) { @@ -748,7 +723,7 @@ end_rename: int minix_rename(struct inode * old_dir, const char * old_name, int old_len, struct inode * new_dir, const char * new_name, int new_len) { - static struct task_struct * wait = NULL; + static struct wait_queue * wait = NULL; static int lock = 0; int result; @@ -761,31 +736,3 @@ int minix_rename(struct inode * old_dir, wake_up(&wait); return result; } - -int minix_readlink(struct inode * inode, char * buffer, int buflen) -{ - struct buffer_head * bh; - int i; - char c; - - if (!S_ISLNK(inode->i_mode)) { - iput(inode); - return -EINVAL; - } - if (buflen > 1023) - buflen = 1023; - if (inode->i_data[0]) - bh = bread(inode->i_dev, inode->i_data[0]); - else - bh = NULL; - iput(inode); - if (!bh) - return 0; - i = 0; - while (ib_data[i])) { - i++; - put_fs_byte(c,buffer++); - } - brelse(bh); - return i; -}