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