1 /* 2 * linux/fs/sysv/namei.c 3 * 4 * minix/namei.c 5 * Copyright (C) 1991, 1992 Linus Torvalds 6 * 7 * coh/namei.c 8 * Copyright (C) 1993 Pascal Haible, Bruno Haible 9 * 10 * sysv/namei.c 11 * Copyright (C) 1993 Bruno Haible 12 * Copyright (C) 1997, 1998 Krzysztof G. Baranowski 13 */ 14 15 #include <linux/pagemap.h> 16 #include <linux/smp_lock.h> 17 #include "sysv.h" 18 19 static inline void inc_count(struct inode *inode) 20 { 21 inode->i_nlink++; 22 mark_inode_dirty(inode); 23 } 24 25 static inline void dec_count(struct inode *inode) 26 { 27 inode->i_nlink--; 28 mark_inode_dirty(inode); 29 } 30 31 static int add_nondir(struct dentry *dentry, struct inode *inode) 32 { 33 int err = sysv_add_link(dentry, inode); 34 if (!err) { 35 d_instantiate(dentry, inode); 36 return 0; 37 } 38 dec_count(inode); 39 iput(inode); 40 return err; 41 } 42 43 static int sysv_hash(struct dentry *dentry, struct qstr *qstr) 44 { 45 /* Truncate the name in place, avoids having to define a compare 46 function. */ 47 if (qstr->len > SYSV_NAMELEN) { 48 qstr->len = SYSV_NAMELEN; 49 qstr->hash = full_name_hash(qstr->name, qstr->len); 50 } 51 return 0; 52 } 53 54 struct dentry_operations sysv_dentry_operations = { 55 .d_hash = sysv_hash, 56 }; 57 58 static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) 59 { 60 struct inode * inode = NULL; 61 ino_t ino; 62 63 dentry->d_op = dir->i_sb->s_root->d_op; 64 if (dentry->d_name.len > SYSV_NAMELEN) 65 return ERR_PTR(-ENAMETOOLONG); 66 ino = sysv_inode_by_name(dentry); 67 68 if (ino) { 69 inode = iget(dir->i_sb, ino); 70 if (!inode) 71 return ERR_PTR(-EACCES); 72 } 73 d_add(dentry, inode); 74 return NULL; 75 } 76 77 static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) 78 { 79 struct inode * inode; 80 int err; 81 82 if (!old_valid_dev(rdev)) 83 return -EINVAL; 84 85 inode = sysv_new_inode(dir, mode); 86 err = PTR_ERR(inode); 87 88 if (!IS_ERR(inode)) { 89 sysv_set_inode(inode, rdev); 90 mark_inode_dirty(inode); 91 err = add_nondir(dentry, inode); 92 } 93 return err; 94 } 95 96 static int sysv_create(struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd) 97 { 98 return sysv_mknod(dir, dentry, mode, 0); 99 } 100 101 static int sysv_symlink(struct inode * dir, struct dentry * dentry, 102 const char * symname) 103 { 104 int err = -ENAMETOOLONG; 105 int l = strlen(symname)+1; 106 struct inode * inode; 107 108 if (l > dir->i_sb->s_blocksize) 109 goto out; 110 111 inode = sysv_new_inode(dir, S_IFLNK|0777); 112 err = PTR_ERR(inode); 113 if (IS_ERR(inode)) 114 goto out; 115 116 sysv_set_inode(inode, 0); 117 err = page_symlink(inode, symname, l); 118 if (err) 119 goto out_fail; 120 121 mark_inode_dirty(inode); 122 err = add_nondir(dentry, inode); 123 out: 124 return err; 125 126 out_fail: 127 dec_count(inode); 128 iput(inode); 129 goto out; 130 } 131 132 static int sysv_link(struct dentry * old_dentry, struct inode * dir, 133 struct dentry * dentry) 134 { 135 struct inode *inode = old_dentry->d_inode; 136 137 if (inode->i_nlink >= SYSV_SB(inode->i_sb)->s_link_max) 138 return -EMLINK; 139 140 inode->i_ctime = CURRENT_TIME_SEC; 141 inc_count(inode); 142 atomic_inc(&inode->i_count); 143 144 return add_nondir(dentry, inode); 145 } 146 147 static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) 148 { 149 struct inode * inode; 150 int err = -EMLINK; 151 152 if (dir->i_nlink >= SYSV_SB(dir->i_sb)->s_link_max) 153 goto out; 154 inc_count(dir); 155 156 inode = sysv_new_inode(dir, S_IFDIR|mode); 157 err = PTR_ERR(inode); 158 if (IS_ERR(inode)) 159 goto out_dir; 160 161 sysv_set_inode(inode, 0); 162 163 inc_count(inode); 164 165 err = sysv_make_empty(inode, dir); 166 if (err) 167 goto out_fail; 168 169 err = sysv_add_link(dentry, inode); 170 if (err) 171 goto out_fail; 172 173 d_instantiate(dentry, inode); 174 out: 175 return err; 176 177 out_fail: 178 dec_count(inode); 179 dec_count(inode); 180 iput(inode); 181 out_dir: 182 dec_count(dir); 183 goto out; 184 } 185 186 static int sysv_unlink(struct inode * dir, struct dentry * dentry) 187 { 188 struct inode * inode = dentry->d_inode; 189 struct page * page; 190 struct sysv_dir_entry * de; 191 int err = -ENOENT; 192 193 de = sysv_find_entry(dentry, &page); 194 if (!de) 195 goto out; 196 197 err = sysv_delete_entry (de, page); 198 if (err) 199 goto out; 200 201 inode->i_ctime = dir->i_ctime; 202 dec_count(inode); 203 out: 204 return err; 205 } 206 207 static int sysv_rmdir(struct inode * dir, struct dentry * dentry) 208 { 209 struct inode *inode = dentry->d_inode; 210 int err = -ENOTEMPTY; 211 212 if (sysv_empty_dir(inode)) { 213 err = sysv_unlink(dir, dentry); 214 if (!err) { 215 inode->i_size = 0; 216 dec_count(inode); 217 dec_count(dir); 218 } 219 } 220 return err; 221 } 222 223 /* 224 * Anybody can rename anything with this: the permission checks are left to the 225 * higher-level routines. 226 */ 227 static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, 228 struct inode * new_dir, struct dentry * new_dentry) 229 { 230 struct inode * old_inode = old_dentry->d_inode; 231 struct inode * new_inode = new_dentry->d_inode; 232 struct page * dir_page = NULL; 233 struct sysv_dir_entry * dir_de = NULL; 234 struct page * old_page; 235 struct sysv_dir_entry * old_de; 236 int err = -ENOENT; 237 238 old_de = sysv_find_entry(old_dentry, &old_page); 239 if (!old_de) 240 goto out; 241 242 if (S_ISDIR(old_inode->i_mode)) { 243 err = -EIO; 244 dir_de = sysv_dotdot(old_inode, &dir_page); 245 if (!dir_de) 246 goto out_old; 247 } 248 249 if (new_inode) { 250 struct page * new_page; 251 struct sysv_dir_entry * new_de; 252 253 err = -ENOTEMPTY; 254 if (dir_de && !sysv_empty_dir(new_inode)) 255 goto out_dir; 256 257 err = -ENOENT; 258 new_de = sysv_find_entry(new_dentry, &new_page); 259 if (!new_de) 260 goto out_dir; 261 inc_count(old_inode); 262 sysv_set_link(new_de, new_page, old_inode); 263 new_inode->i_ctime = CURRENT_TIME_SEC; 264 if (dir_de) 265 new_inode->i_nlink--; 266 dec_count(new_inode); 267 } else { 268 if (dir_de) { 269 err = -EMLINK; 270 if (new_dir->i_nlink >= SYSV_SB(new_dir->i_sb)->s_link_max) 271 goto out_dir; 272 } 273 inc_count(old_inode); 274 err = sysv_add_link(new_dentry, old_inode); 275 if (err) { 276 dec_count(old_inode); 277 goto out_dir; 278 } 279 if (dir_de) 280 inc_count(new_dir); 281 } 282 283 sysv_delete_entry(old_de, old_page); 284 dec_count(old_inode); 285 286 if (dir_de) { 287 sysv_set_link(dir_de, dir_page, new_dir); 288 dec_count(old_dir); 289 } 290 return 0; 291 292 out_dir: 293 if (dir_de) { 294 kunmap(dir_page); 295 page_cache_release(dir_page); 296 } 297 out_old: 298 kunmap(old_page); 299 page_cache_release(old_page); 300 out: 301 return err; 302 } 303 304 /* 305 * directories can handle most operations... 306 */ 307 struct inode_operations sysv_dir_inode_operations = { 308 .create = sysv_create, 309 .lookup = sysv_lookup, 310 .link = sysv_link, 311 .unlink = sysv_unlink, 312 .symlink = sysv_symlink, 313 .mkdir = sysv_mkdir, 314 .rmdir = sysv_rmdir, 315 .mknod = sysv_mknod, 316 .rename = sysv_rename, 317 .getattr = sysv_getattr, 318 }; 319