1 /* 2 * linux/fs/affs/namei.c 3 * 4 * (c) 1996 Hans-Joachim Widmaier - Rewritten 5 * 6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. 7 * 8 * (C) 1991 Linus Torvalds - minix filesystem 9 */ 10 11 #include "affs.h" 12 13 typedef int (*toupper_t)(int); 14 15 static int affs_toupper(int ch); 16 static int affs_hash_dentry(const struct dentry *, 17 const struct inode *, struct qstr *); 18 static int affs_compare_dentry(const struct dentry *parent, 19 const struct inode *pinode, 20 const struct dentry *dentry, const struct inode *inode, 21 unsigned int len, const char *str, const struct qstr *name); 22 static int affs_intl_toupper(int ch); 23 static int affs_intl_hash_dentry(const struct dentry *, 24 const struct inode *, struct qstr *); 25 static int affs_intl_compare_dentry(const struct dentry *parent, 26 const struct inode *pinode, 27 const struct dentry *dentry, const struct inode *inode, 28 unsigned int len, const char *str, const struct qstr *name); 29 30 const struct dentry_operations affs_dentry_operations = { 31 .d_hash = affs_hash_dentry, 32 .d_compare = affs_compare_dentry, 33 }; 34 35 const struct dentry_operations affs_intl_dentry_operations = { 36 .d_hash = affs_intl_hash_dentry, 37 .d_compare = affs_intl_compare_dentry, 38 }; 39 40 41 /* Simple toupper() for DOS\1 */ 42 43 static int 44 affs_toupper(int ch) 45 { 46 return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch; 47 } 48 49 /* International toupper() for DOS\3 ("international") */ 50 51 static int 52 affs_intl_toupper(int ch) 53 { 54 return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0 55 && ch <= 0xFE && ch != 0xF7) ? 56 ch - ('a' - 'A') : ch; 57 } 58 59 static inline toupper_t 60 affs_get_toupper(struct super_block *sb) 61 { 62 return AFFS_SB(sb)->s_flags & SF_INTL ? affs_intl_toupper : affs_toupper; 63 } 64 65 /* 66 * Note: the dentry argument is the parent dentry. 67 */ 68 static inline int 69 __affs_hash_dentry(struct qstr *qstr, toupper_t toupper) 70 { 71 const u8 *name = qstr->name; 72 unsigned long hash; 73 int i; 74 75 i = affs_check_name(qstr->name, qstr->len); 76 if (i) 77 return i; 78 79 hash = init_name_hash(); 80 i = min(qstr->len, 30u); 81 for (; i > 0; name++, i--) 82 hash = partial_name_hash(toupper(*name), hash); 83 qstr->hash = end_name_hash(hash); 84 85 return 0; 86 } 87 88 static int 89 affs_hash_dentry(const struct dentry *dentry, const struct inode *inode, 90 struct qstr *qstr) 91 { 92 return __affs_hash_dentry(qstr, affs_toupper); 93 } 94 static int 95 affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode, 96 struct qstr *qstr) 97 { 98 return __affs_hash_dentry(qstr, affs_intl_toupper); 99 } 100 101 static inline int __affs_compare_dentry(unsigned int len, 102 const char *str, const struct qstr *name, toupper_t toupper) 103 { 104 const u8 *aname = str; 105 const u8 *bname = name->name; 106 107 /* 108 * 'str' is the name of an already existing dentry, so the name 109 * must be valid. 'name' must be validated first. 110 */ 111 112 if (affs_check_name(name->name, name->len)) 113 return 1; 114 115 /* 116 * If the names are longer than the allowed 30 chars, 117 * the excess is ignored, so their length may differ. 118 */ 119 if (len >= 30) { 120 if (name->len < 30) 121 return 1; 122 len = 30; 123 } else if (len != name->len) 124 return 1; 125 126 for (; len > 0; len--) 127 if (toupper(*aname++) != toupper(*bname++)) 128 return 1; 129 130 return 0; 131 } 132 133 static int 134 affs_compare_dentry(const struct dentry *parent, const struct inode *pinode, 135 const struct dentry *dentry, const struct inode *inode, 136 unsigned int len, const char *str, const struct qstr *name) 137 { 138 return __affs_compare_dentry(len, str, name, affs_toupper); 139 } 140 static int 141 affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode, 142 const struct dentry *dentry, const struct inode *inode, 143 unsigned int len, const char *str, const struct qstr *name) 144 { 145 return __affs_compare_dentry(len, str, name, affs_intl_toupper); 146 } 147 148 /* 149 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure. 150 */ 151 152 static inline int 153 affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) 154 { 155 const u8 *name = dentry->d_name.name; 156 int len = dentry->d_name.len; 157 158 if (len >= 30) { 159 if (*name2 < 30) 160 return 0; 161 len = 30; 162 } else if (len != *name2) 163 return 0; 164 165 for (name2++; len > 0; len--) 166 if (toupper(*name++) != toupper(*name2++)) 167 return 0; 168 return 1; 169 } 170 171 int 172 affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) 173 { 174 toupper_t toupper = affs_get_toupper(sb); 175 int hash; 176 177 hash = len = min(len, 30u); 178 for (; len > 0; len--) 179 hash = (hash * 13 + toupper(*name++)) & 0x7ff; 180 181 return hash % AFFS_SB(sb)->s_hashsize; 182 } 183 184 static struct buffer_head * 185 affs_find_entry(struct inode *dir, struct dentry *dentry) 186 { 187 struct super_block *sb = dir->i_sb; 188 struct buffer_head *bh; 189 toupper_t toupper = affs_get_toupper(sb); 190 u32 key; 191 192 pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name); 193 194 bh = affs_bread(sb, dir->i_ino); 195 if (!bh) 196 return ERR_PTR(-EIO); 197 198 key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]); 199 200 for (;;) { 201 affs_brelse(bh); 202 if (key == 0) 203 return NULL; 204 bh = affs_bread(sb, key); 205 if (!bh) 206 return ERR_PTR(-EIO); 207 if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper)) 208 return bh; 209 key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); 210 } 211 } 212 213 struct dentry * 214 affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 215 { 216 struct super_block *sb = dir->i_sb; 217 struct buffer_head *bh; 218 struct inode *inode = NULL; 219 220 pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name); 221 222 affs_lock_dir(dir); 223 bh = affs_find_entry(dir, dentry); 224 affs_unlock_dir(dir); 225 if (IS_ERR(bh)) 226 return ERR_CAST(bh); 227 if (bh) { 228 u32 ino = bh->b_blocknr; 229 230 /* store the real header ino in d_fsdata for faster lookups */ 231 dentry->d_fsdata = (void *)(long)ino; 232 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 233 //link to dirs disabled 234 //case ST_LINKDIR: 235 case ST_LINKFILE: 236 ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original); 237 } 238 affs_brelse(bh); 239 inode = affs_iget(sb, ino); 240 if (IS_ERR(inode)) 241 return ERR_CAST(inode); 242 } 243 d_add(dentry, inode); 244 return NULL; 245 } 246 247 int 248 affs_unlink(struct inode *dir, struct dentry *dentry) 249 { 250 pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino, 251 dentry->d_inode->i_ino, 252 (int)dentry->d_name.len, dentry->d_name.name); 253 254 return affs_remove_header(dentry); 255 } 256 257 int 258 affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) 259 { 260 struct super_block *sb = dir->i_sb; 261 struct inode *inode; 262 int error; 263 264 pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,(int)dentry->d_name.len, 265 dentry->d_name.name,mode); 266 267 inode = affs_new_inode(dir); 268 if (!inode) 269 return -ENOSPC; 270 271 inode->i_mode = mode; 272 mode_to_prot(inode); 273 mark_inode_dirty(inode); 274 275 inode->i_op = &affs_file_inode_operations; 276 inode->i_fop = &affs_file_operations; 277 inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; 278 error = affs_add_entry(dir, inode, dentry, ST_FILE); 279 if (error) { 280 inode->i_nlink = 0; 281 iput(inode); 282 return error; 283 } 284 return 0; 285 } 286 287 int 288 affs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 289 { 290 struct inode *inode; 291 int error; 292 293 pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir->i_ino, 294 (int)dentry->d_name.len,dentry->d_name.name,mode); 295 296 inode = affs_new_inode(dir); 297 if (!inode) 298 return -ENOSPC; 299 300 inode->i_mode = S_IFDIR | mode; 301 mode_to_prot(inode); 302 303 inode->i_op = &affs_dir_inode_operations; 304 inode->i_fop = &affs_dir_operations; 305 306 error = affs_add_entry(dir, inode, dentry, ST_USERDIR); 307 if (error) { 308 inode->i_nlink = 0; 309 mark_inode_dirty(inode); 310 iput(inode); 311 return error; 312 } 313 return 0; 314 } 315 316 int 317 affs_rmdir(struct inode *dir, struct dentry *dentry) 318 { 319 pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino, 320 dentry->d_inode->i_ino, 321 (int)dentry->d_name.len, dentry->d_name.name); 322 323 return affs_remove_header(dentry); 324 } 325 326 int 327 affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 328 { 329 struct super_block *sb = dir->i_sb; 330 struct buffer_head *bh; 331 struct inode *inode; 332 char *p; 333 int i, maxlen, error; 334 char c, lc; 335 336 pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino, 337 (int)dentry->d_name.len,dentry->d_name.name,symname); 338 339 maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; 340 inode = affs_new_inode(dir); 341 if (!inode) 342 return -ENOSPC; 343 344 inode->i_op = &affs_symlink_inode_operations; 345 inode->i_data.a_ops = &affs_symlink_aops; 346 inode->i_mode = S_IFLNK | 0777; 347 mode_to_prot(inode); 348 349 error = -EIO; 350 bh = affs_bread(sb, inode->i_ino); 351 if (!bh) 352 goto err; 353 i = 0; 354 p = (char *)AFFS_HEAD(bh)->table; 355 lc = '/'; 356 if (*symname == '/') { 357 struct affs_sb_info *sbi = AFFS_SB(sb); 358 while (*symname == '/') 359 symname++; 360 spin_lock(&sbi->symlink_lock); 361 while (sbi->s_volume[i]) /* Cannot overflow */ 362 *p++ = sbi->s_volume[i++]; 363 spin_unlock(&sbi->symlink_lock); 364 } 365 while (i < maxlen && (c = *symname++)) { 366 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 367 *p++ = '/'; 368 i++; 369 symname += 2; 370 lc = '/'; 371 } else if (c == '.' && lc == '/' && *symname == '/') { 372 symname++; 373 lc = '/'; 374 } else { 375 *p++ = c; 376 lc = c; 377 i++; 378 } 379 if (lc == '/') 380 while (*symname == '/') 381 symname++; 382 } 383 *p = 0; 384 mark_buffer_dirty_inode(bh, inode); 385 affs_brelse(bh); 386 mark_inode_dirty(inode); 387 388 error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); 389 if (error) 390 goto err; 391 392 return 0; 393 394 err: 395 inode->i_nlink = 0; 396 mark_inode_dirty(inode); 397 iput(inode); 398 return error; 399 } 400 401 int 402 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 403 { 404 struct inode *inode = old_dentry->d_inode; 405 406 pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino, 407 (int)dentry->d_name.len,dentry->d_name.name); 408 409 return affs_add_entry(dir, inode, dentry, ST_LINKFILE); 410 } 411 412 int 413 affs_rename(struct inode *old_dir, struct dentry *old_dentry, 414 struct inode *new_dir, struct dentry *new_dentry) 415 { 416 struct super_block *sb = old_dir->i_sb; 417 struct buffer_head *bh = NULL; 418 int retval; 419 420 pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n", 421 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, 422 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); 423 424 retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len); 425 if (retval) 426 return retval; 427 428 /* Unlink destination if it already exists */ 429 if (new_dentry->d_inode) { 430 retval = affs_remove_header(new_dentry); 431 if (retval) 432 return retval; 433 } 434 435 bh = affs_bread(sb, old_dentry->d_inode->i_ino); 436 if (!bh) 437 return -EIO; 438 439 /* Remove header from its parent directory. */ 440 affs_lock_dir(old_dir); 441 retval = affs_remove_hash(old_dir, bh); 442 affs_unlock_dir(old_dir); 443 if (retval) 444 goto done; 445 446 /* And insert it into the new directory with the new name. */ 447 affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); 448 affs_fix_checksum(sb, bh); 449 affs_lock_dir(new_dir); 450 retval = affs_insert_hash(new_dir, bh); 451 affs_unlock_dir(new_dir); 452 /* TODO: move it back to old_dir, if error? */ 453 454 done: 455 mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); 456 affs_brelse(bh); 457 return retval; 458 } 459