1 /* 2 * linux/fs/minix/namei.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 #include "minix.h" 8 9 static int add_nondir(struct dentry *dentry, struct inode *inode) 10 { 11 int err = minix_add_link(dentry, inode); 12 if (!err) { 13 d_instantiate(dentry, inode); 14 return 0; 15 } 16 inode_dec_link_count(inode); 17 iput(inode); 18 return err; 19 } 20 21 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) 22 { 23 struct inode * inode = NULL; 24 ino_t ino; 25 26 if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen) 27 return ERR_PTR(-ENAMETOOLONG); 28 29 ino = minix_inode_by_name(dentry); 30 if (ino) { 31 inode = minix_iget(dir->i_sb, ino); 32 if (IS_ERR(inode)) 33 return ERR_CAST(inode); 34 } 35 d_add(dentry, inode); 36 return NULL; 37 } 38 39 static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) 40 { 41 int error; 42 struct inode *inode; 43 44 if (!old_valid_dev(rdev)) 45 return -EINVAL; 46 47 inode = minix_new_inode(dir, mode, &error); 48 49 if (inode) { 50 minix_set_inode(inode, rdev); 51 mark_inode_dirty(inode); 52 error = add_nondir(dentry, inode); 53 } 54 return error; 55 } 56 57 static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, 58 bool excl) 59 { 60 return minix_mknod(dir, dentry, mode, 0); 61 } 62 63 static int minix_symlink(struct inode * dir, struct dentry *dentry, 64 const char * symname) 65 { 66 int err = -ENAMETOOLONG; 67 int i = strlen(symname)+1; 68 struct inode * inode; 69 70 if (i > dir->i_sb->s_blocksize) 71 goto out; 72 73 inode = minix_new_inode(dir, S_IFLNK | 0777, &err); 74 if (!inode) 75 goto out; 76 77 minix_set_inode(inode, 0); 78 err = page_symlink(inode, symname, i); 79 if (err) 80 goto out_fail; 81 82 err = add_nondir(dentry, inode); 83 out: 84 return err; 85 86 out_fail: 87 inode_dec_link_count(inode); 88 iput(inode); 89 goto out; 90 } 91 92 static int minix_link(struct dentry * old_dentry, struct inode * dir, 93 struct dentry *dentry) 94 { 95 struct inode *inode = old_dentry->d_inode; 96 97 inode->i_ctime = CURRENT_TIME_SEC; 98 inode_inc_link_count(inode); 99 ihold(inode); 100 return add_nondir(dentry, inode); 101 } 102 103 static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) 104 { 105 struct inode * inode; 106 int err; 107 108 inode_inc_link_count(dir); 109 110 inode = minix_new_inode(dir, S_IFDIR | mode, &err); 111 if (!inode) 112 goto out_dir; 113 114 minix_set_inode(inode, 0); 115 116 inode_inc_link_count(inode); 117 118 err = minix_make_empty(inode, dir); 119 if (err) 120 goto out_fail; 121 122 err = minix_add_link(dentry, inode); 123 if (err) 124 goto out_fail; 125 126 d_instantiate(dentry, inode); 127 out: 128 return err; 129 130 out_fail: 131 inode_dec_link_count(inode); 132 inode_dec_link_count(inode); 133 iput(inode); 134 out_dir: 135 inode_dec_link_count(dir); 136 goto out; 137 } 138 139 static int minix_unlink(struct inode * dir, struct dentry *dentry) 140 { 141 int err = -ENOENT; 142 struct inode * inode = dentry->d_inode; 143 struct page * page; 144 struct minix_dir_entry * de; 145 146 de = minix_find_entry(dentry, &page); 147 if (!de) 148 goto end_unlink; 149 150 err = minix_delete_entry(de, page); 151 if (err) 152 goto end_unlink; 153 154 inode->i_ctime = dir->i_ctime; 155 inode_dec_link_count(inode); 156 end_unlink: 157 return err; 158 } 159 160 static int minix_rmdir(struct inode * dir, struct dentry *dentry) 161 { 162 struct inode * inode = dentry->d_inode; 163 int err = -ENOTEMPTY; 164 165 if (minix_empty_dir(inode)) { 166 err = minix_unlink(dir, dentry); 167 if (!err) { 168 inode_dec_link_count(dir); 169 inode_dec_link_count(inode); 170 } 171 } 172 return err; 173 } 174 175 static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, 176 struct inode * new_dir, struct dentry *new_dentry) 177 { 178 struct inode * old_inode = old_dentry->d_inode; 179 struct inode * new_inode = new_dentry->d_inode; 180 struct page * dir_page = NULL; 181 struct minix_dir_entry * dir_de = NULL; 182 struct page * old_page; 183 struct minix_dir_entry * old_de; 184 int err = -ENOENT; 185 186 old_de = minix_find_entry(old_dentry, &old_page); 187 if (!old_de) 188 goto out; 189 190 if (S_ISDIR(old_inode->i_mode)) { 191 err = -EIO; 192 dir_de = minix_dotdot(old_inode, &dir_page); 193 if (!dir_de) 194 goto out_old; 195 } 196 197 if (new_inode) { 198 struct page * new_page; 199 struct minix_dir_entry * new_de; 200 201 err = -ENOTEMPTY; 202 if (dir_de && !minix_empty_dir(new_inode)) 203 goto out_dir; 204 205 err = -ENOENT; 206 new_de = minix_find_entry(new_dentry, &new_page); 207 if (!new_de) 208 goto out_dir; 209 minix_set_link(new_de, new_page, old_inode); 210 new_inode->i_ctime = CURRENT_TIME_SEC; 211 if (dir_de) 212 drop_nlink(new_inode); 213 inode_dec_link_count(new_inode); 214 } else { 215 err = minix_add_link(new_dentry, old_inode); 216 if (err) 217 goto out_dir; 218 if (dir_de) 219 inode_inc_link_count(new_dir); 220 } 221 222 minix_delete_entry(old_de, old_page); 223 mark_inode_dirty(old_inode); 224 225 if (dir_de) { 226 minix_set_link(dir_de, dir_page, new_dir); 227 inode_dec_link_count(old_dir); 228 } 229 return 0; 230 231 out_dir: 232 if (dir_de) { 233 kunmap(dir_page); 234 page_cache_release(dir_page); 235 } 236 out_old: 237 kunmap(old_page); 238 page_cache_release(old_page); 239 out: 240 return err; 241 } 242 243 /* 244 * directories can handle most operations... 245 */ 246 const struct inode_operations minix_dir_inode_operations = { 247 .create = minix_create, 248 .lookup = minix_lookup, 249 .link = minix_link, 250 .unlink = minix_unlink, 251 .symlink = minix_symlink, 252 .mkdir = minix_mkdir, 253 .rmdir = minix_rmdir, 254 .mknod = minix_mknod, 255 .rename = minix_rename, 256 .getattr = minix_getattr, 257 }; 258