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