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