1/* 2 * linux/fs/umsdos/namei.c 3 * 4 * Written 1993 by Jacques Gelinas 5 * Inspired from linux/fs/msdos/... by Werner Almesberger 6 * 7 * Maintain and access the --linux alternate directory file. 8 */ 9 /* 10 * You are in the maze of twisted functions - half of them shouldn't 11 * be here... 12 */ 13 14#include <linux/errno.h> 15#include <linux/kernel.h> 16#include <linux/sched.h> 17#include <linux/types.h> 18#include <linux/fcntl.h> 19#include <linux/stat.h> 20#include <linux/string.h> 21#include <linux/msdos_fs.h> 22#include <linux/umsdos_fs.h> 23#include <linux/slab.h> 24 25#define UMSDOS_DIR_LOCK 26 27#ifdef UMSDOS_DIR_LOCK 28 29static inline void u_sleep_on (struct inode *dir) 30{ 31 sleep_on (&dir->u.umsdos_i.dir_info.p); 32} 33 34static inline void u_wake_up (struct inode *dir) 35{ 36 wake_up (&dir->u.umsdos_i.dir_info.p); 37} 38 39/* 40 * Wait for creation exclusivity. 41 * Return 0 if the dir was already available. 42 * Return 1 if a wait was necessary. 43 * When 1 is return, it means a wait was done. It does not 44 * mean the directory is available. 45 */ 46static int umsdos_waitcreate (struct inode *dir) 47{ 48 int ret = 0; 49 50 if (dir->u.umsdos_i.dir_info.creating 51 && dir->u.umsdos_i.dir_info.pid != current->pid) { 52 PRINTK (("creating && dir_info.pid=%lu, current->pid=%u\n", dir->u.umsdos_i.dir_info.pid, current->pid)); 53 u_sleep_on (dir); 54 ret = 1; 55 } 56 return ret; 57} 58 59/* 60 * Wait for any lookup process to finish 61 */ 62static void umsdos_waitlookup (struct inode *dir) 63{ 64 while (dir->u.umsdos_i.dir_info.looking) { 65 u_sleep_on (dir); 66 } 67} 68 69/* 70 * Lock all other process out of this directory. 71 */ 72/* #Specification: file creation / not atomic 73 * File creation is a two step process. First we create (allocate) 74 * an entry in the EMD file and then (using the entry offset) we 75 * build a unique name for MSDOS. We create this name in the msdos 76 * space. 77 * 78 * We have to use semaphore (sleep_on/wake_up) to prevent lookup 79 * into a directory when we create a file or directory and to 80 * prevent creation while a lookup is going on. Since many lookup 81 * may happen at the same time, the semaphore is a counter. 82 * 83 * Only one creation is allowed at the same time. This protection 84 * may not be necessary. The problem arise mainly when a lookup 85 * or a readdir is done while a file is partially created. The 86 * lookup process see that as a "normal" problem and silently 87 * erase the file from the EMD file. Normal because a file 88 * may be erased during a MSDOS session, but not removed from 89 * the EMD file. 90 * 91 * The locking is done on a directory per directory basis. Each 92 * directory inode has its wait_queue. 93 * 94 * For some operation like hard link, things even get worse. Many 95 * creation must occur at once (atomic). To simplify the design 96 * a process is allowed to recursively lock the directory for 97 * creation. The pid of the locking process is kept along with 98 * a counter so a second level of locking is granted or not. 99 */ 100void umsdos_lockcreate (struct inode *dir) 101{ 102 /* 103 * Wait for any creation process to finish except 104 * if we (the process) own the lock 105 */ 106 while (umsdos_waitcreate (dir) != 0); 107 dir->u.umsdos_i.dir_info.creating++; 108 dir->u.umsdos_i.dir_info.pid = current->pid; 109 umsdos_waitlookup (dir); 110} 111 112/* 113 * Lock all other process out of those two directories. 114 */ 115static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2) 116{ 117 /* 118 * We must check that both directory are available before 119 * locking anyone of them. This is to avoid some deadlock. 120 * Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing 121 * this to me. 122 */ 123 while (1) { 124 if (umsdos_waitcreate (dir1) == 0 125 && umsdos_waitcreate (dir2) == 0) { 126 /* We own both now */ 127 dir1->u.umsdos_i.dir_info.creating++; 128 dir1->u.umsdos_i.dir_info.pid = current->pid; 129 dir2->u.umsdos_i.dir_info.creating++; 130 dir2->u.umsdos_i.dir_info.pid = current->pid; 131 break; 132 } 133 } 134 umsdos_waitlookup (dir1); 135 umsdos_waitlookup (dir2); 136} 137 138/* 139 * Wait until creation is finish in this directory. 140 */ 141void umsdos_startlookup (struct inode *dir) 142{ 143 while (umsdos_waitcreate (dir) != 0); 144 dir->u.umsdos_i.dir_info.looking++; 145} 146 147/* 148 * Unlock the directory. 149 */ 150void umsdos_unlockcreate (struct inode *dir) 151{ 152 dir->u.umsdos_i.dir_info.creating--; 153 if (dir->u.umsdos_i.dir_info.creating < 0) { 154 printk ("UMSDOS: dir->u.umsdos_i.dir_info.creating < 0: %d" 155 ,dir->u.umsdos_i.dir_info.creating); 156 } 157 u_wake_up (dir); 158} 159 160/* 161 * Tell directory lookup is over. 162 */ 163void umsdos_endlookup (struct inode *dir) 164{ 165 dir->u.umsdos_i.dir_info.looking--; 166 if (dir->u.umsdos_i.dir_info.looking < 0) { 167 printk ("UMSDOS: dir->u.umsdos_i.dir_info.looking < 0: %d" 168 ,dir->u.umsdos_i.dir_info.looking); 169 } 170 u_wake_up (dir); 171} 172 173#else 174static void umsdos_lockcreate (struct inode *dir) 175{ 176} 177static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2) 178{ 179} 180void umsdos_startlookup (struct inode *dir) 181{ 182} 183static void umsdos_unlockcreate (struct inode *dir) 184{ 185} 186void umsdos_endlookup (struct inode *dir) 187{ 188} 189 190#endif 191 192static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry, 193 int errcod) 194{ 195 int ret = 0; 196 197 if (umsdos_is_pseudodos (dir, dentry)) { 198 /* #Specification: pseudo root / any file creation /DOS 199 * The pseudo sub-directory /DOS can't be created! 200 * EEXIST is returned. 201 * 202 * The pseudo sub-directory /DOS can't be removed! 203 * EPERM is returned. 204 */ 205 ret = errcod; 206 } 207 return ret; 208} 209 210/* 211 * Add a new file (ordinary or special) into the alternate directory. 212 * The file is added to the real MSDOS directory. If successful, it 213 * is then added to the EMD file. 214 * 215 * Return the status of the operation. 0 mean success. 216 * 217 * #Specification: create / file exists in DOS 218 * Here is a situation: we are trying to create a file with 219 * UMSDOS. The file is unknown to UMSDOS but already 220 * exists in the DOS directory. 221 * 222 * Here is what we are NOT doing: 223 * 224 * We could silently assume that everything is fine 225 * and allows the creation to succeed. 226 * 227 * It is possible not all files in the partition 228 * are meant to be visible from linux. By trying to create 229 * those file in some directory, one user may get access 230 * to those file without proper permissions. Looks like 231 * a security hole to me. Off course sharing a file system 232 * with DOS is some kind of security hole :-) 233 * 234 * So ? 235 * 236 * We return EEXIST in this case. 237 * The same is true for directory creation. 238 */ 239static int umsdos_create_any (struct inode *dir, struct dentry *dentry, 240 int mode, int rdev, char flags) 241{ 242 struct dentry *fake; 243 struct inode *inode; 244 int ret; 245 struct umsdos_info info; 246 247 ret = umsdos_nevercreat (dir, dentry, -EEXIST); 248 if (ret) 249 goto out; 250 251 ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); 252 if (ret) 253 goto out; 254 255 info.entry.mode = mode; 256 info.entry.rdev = rdev; 257 info.entry.flags = flags; 258 info.entry.uid = current->fsuid; 259 info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 260 info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME; 261 info.entry.nlink = 1; 262 ret = umsdos_newentry (dentry->d_parent, &info); 263 if (ret) 264 goto out; 265 266 /* do a real lookup to get the short name dentry */ 267 fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); 268 ret = PTR_ERR(fake); 269 if (IS_ERR(fake)) 270 goto out_remove; 271 272 /* should not exist yet ... */ 273 ret = -EEXIST; 274 if (fake->d_inode) 275 goto out_remove_dput; 276 277 ret = msdos_create (dir, fake, S_IFREG | 0777); 278 if (ret) 279 goto out_remove_dput; 280 281 inode = fake->d_inode; 282 atomic_inc(&inode->i_count); 283 d_instantiate (dentry, inode); 284 dput(fake); 285 if (atomic_read(&inode->i_count) > 1) { 286 printk(KERN_WARNING 287 "umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n", 288 dentry->d_parent->d_name.name, dentry->d_name.name, 289 inode->i_ino, atomic_read(&inode->i_count)); 290 } 291 umsdos_lookup_patch_new(dentry, &info); 292 293out: 294 return ret; 295 296 /* Creation failed ... remove the EMD entry */ 297out_remove_dput: 298 dput(fake); 299out_remove: 300 if (ret == -EEXIST) 301 printk(KERN_WARNING "UMSDOS: out of sync, deleting %s/%s\n", 302 dentry->d_parent->d_name.name, info.fake.fname); 303 umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode)); 304 goto out; 305} 306 307/* 308 * Add a new file into the alternate directory. 309 * The file is added to the real MSDOS directory. If successful, it 310 * is then added to the EMD file. 311 * 312 * Return the status of the operation. 0 mean success. 313 */ 314int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode) 315{ 316 return umsdos_create_any (dir, dentry, mode, 0, 0); 317} 318 319 320/* 321 * Initialise the new_entry from the old for a rename operation. 322 * (Only useful for umsdos_rename_f() below). 323 */ 324static void umsdos_ren_init (struct umsdos_info *new_info, 325 struct umsdos_info *old_info) 326{ 327 new_info->entry.mode = old_info->entry.mode; 328 new_info->entry.rdev = old_info->entry.rdev; 329 new_info->entry.uid = old_info->entry.uid; 330 new_info->entry.gid = old_info->entry.gid; 331 new_info->entry.ctime = old_info->entry.ctime; 332 new_info->entry.atime = old_info->entry.atime; 333 new_info->entry.mtime = old_info->entry.mtime; 334 new_info->entry.flags = old_info->entry.flags; 335 new_info->entry.nlink = old_info->entry.nlink; 336} 337 338/* 339 * Rename a file (move) in the file system. 340 */ 341 342static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry, 343 struct inode *new_dir, struct dentry *new_dentry, 344 int flags) 345{ 346 struct inode *old_inode = old_dentry->d_inode; 347 struct dentry *old, *new, *old_emd; 348 int err, ret; 349 struct umsdos_info old_info; 350 struct umsdos_info new_info; 351 352 ret = -EPERM; 353 err = umsdos_parse (old_dentry->d_name.name, 354 old_dentry->d_name.len, &old_info); 355 if (err) 356 goto out; 357 err = umsdos_parse (new_dentry->d_name.name, 358 new_dentry->d_name.len, &new_info); 359 if (err) 360 goto out; 361 362 /* Get the EMD dentry for the old parent */ 363 old_emd = umsdos_get_emd_dentry(old_dentry->d_parent); 364 ret = PTR_ERR(old_emd); 365 if (IS_ERR(old_emd)) 366 goto out; 367 368 umsdos_lockcreate2 (old_dir, new_dir); 369 370 ret = umsdos_findentry(old_emd->d_parent, &old_info, 0); 371 if (ret) 372 goto out_unlock; 373 374 err = umsdos_findentry(new_dentry->d_parent, &new_info, 0); 375 if (err == 0) { 376 /* check whether it _really_ exists ... */ 377 ret = -EEXIST; 378 if (new_dentry->d_inode) 379 goto out_unlock; 380 381 /* bogus lookup? complain and fix up the EMD ... */ 382 printk(KERN_WARNING 383 "umsdos_rename_f: entry %s/%s exists, inode NULL??\n", 384 new_dentry->d_parent->d_name.name, new_info.entry.name); 385 err = umsdos_delentry(new_dentry->d_parent, &new_info, 386 S_ISDIR(new_info.entry.mode)); 387 } 388 389 umsdos_ren_init (&new_info, &old_info); 390 if (flags) 391 new_info.entry.flags = flags; 392 ret = umsdos_newentry (new_dentry->d_parent, &new_info); 393 if (ret) 394 goto out_unlock; 395 396 /* If we're moving a hardlink, drop it first */ 397 if (old_info.entry.flags & UMSDOS_HLINK) { 398 d_drop(old_dentry); 399 } 400 401 old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname, 402 old_info.fake.len); 403 ret = PTR_ERR(old); 404 if (IS_ERR(old)) 405 goto out_unlock; 406 /* make sure it's the same inode! */ 407 ret = -ENOENT; 408 /* 409 * note: for hardlinks they will be different! 410 * old_inode will contain inode of .LINKxxx file containing data, and 411 * old->d_inode will contain inode of file containing path to .LINKxxx file 412 */ 413 if (!(old_info.entry.flags & UMSDOS_HLINK)) { 414 if (old->d_inode != old_inode) 415 goto out_dput; 416 } 417 418 new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, 419 new_info.fake.len); 420 ret = PTR_ERR(new); 421 if (IS_ERR(new)) 422 goto out_dput; 423 424 /* Do the msdos-level rename */ 425 ret = msdos_rename (old_dir, old, new_dir, new); 426 427 dput(new); 428 429 /* If the rename failed, remove the new EMD entry */ 430 if (ret != 0) { 431 umsdos_delentry (new_dentry->d_parent, &new_info, 432 S_ISDIR (new_info.entry.mode)); 433 goto out_dput; 434 } 435 436 /* 437 * Rename successful ... remove the old name from the EMD. 438 * Note that we use the EMD parent here, as the old dentry 439 * may have moved to a new parent ... 440 */ 441 err = umsdos_delentry (old_emd->d_parent, &old_info, 442 S_ISDIR (old_info.entry.mode)); 443 if (err) { 444 /* Failed? Complain a bit, but don't fail the operation */ 445 printk(KERN_WARNING 446 "umsdos_rename_f: delentry %s/%s failed, error=%d\n", 447 old_emd->d_parent->d_name.name, old_info.entry.name, 448 err); 449 } 450 451 /* 452 * Update f_pos so notify_change will succeed 453 * if the file was already in use. 454 */ 455 umsdos_set_dirinfo_new(old_dentry, new_info.f_pos); 456 457 /* dput() the dentry if we haven't already */ 458out_dput: 459 dput(old); 460 461out_unlock: 462 dput(old_emd); 463 umsdos_unlockcreate (old_dir); 464 umsdos_unlockcreate (new_dir); 465 466out: 467 Printk ((" _ret=%d\n", ret)); 468 return ret; 469} 470 471/* 472 * Setup a Symbolic link or a (pseudo) hard link 473 * Return a negative error code or 0 if OK. 474 */ 475/* #Specification: symbolic links / strategy 476 * A symbolic link is simply a file which holds a path. It is 477 * implemented as a normal MSDOS file (not very space efficient :-() 478 * 479 * I see two different ways to do this: One is to place the link data 480 * in unused entries of the EMD file; the other is to have a separate 481 * file dedicated to hold all symbolic links data. 482 * 483 * Let's go for simplicity... 484 */ 485 486/* 487 * AV. Should be called with dir->i_sem down. 488 */ 489static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry, 490 const char *symname, int mode, char flags) 491{ 492 int ret, len; 493 494 ret = umsdos_create_any (dir, dentry, mode, 0, flags); 495 if (ret) { 496 printk(KERN_WARNING 497 "umsdos_symlink: create failed, ret=%d\n", ret); 498 goto out; 499 } 500 501 len = strlen (symname) + 1; 502 ret = block_symlink(dentry->d_inode, symname, len); 503 if (ret < 0) 504 goto out_unlink; 505out: 506 return ret; 507 508out_unlink: 509 printk(KERN_WARNING "umsdos_symlink: write failed, unlinking\n"); 510 UMSDOS_unlink (dir, dentry); 511 d_drop(dentry); 512 goto out; 513} 514 515/* 516 * Setup a Symbolic link. 517 * Return a negative error code or 0 if OK. 518 */ 519int UMSDOS_symlink ( struct inode *dir, struct dentry *dentry, 520 const char *symname) 521{ 522 return umsdos_symlink_x (dir, dentry, symname, S_IFLNK | 0777, 0); 523} 524 525/* 526 * Add a link to an inode in a directory 527 */ 528int UMSDOS_link (struct dentry *olddentry, struct inode *dir, 529 struct dentry *dentry) 530{ 531 struct inode *oldinode = olddentry->d_inode; 532 struct inode *olddir = olddentry->d_parent->d_inode; 533 struct dentry *temp; 534 char *path; 535 unsigned long buffer; 536 int ret; 537 struct umsdos_info old_info; 538 struct umsdos_info hid_info; 539 540#ifdef UMSDOS_DEBUG_VERBOSE 541printk("umsdos_link: new %s/%s -> %s/%s\n", 542dentry->d_parent->d_name.name, dentry->d_name.name, 543olddentry->d_parent->d_name.name, olddentry->d_name.name); 544#endif 545 546 ret = -EPERM; 547 if (S_ISDIR (oldinode->i_mode)) 548 goto out; 549 550 ret = umsdos_nevercreat (dir, dentry, -EPERM); 551 if (ret) 552 goto out; 553 554 ret = -ENOMEM; 555 buffer = get_free_page(GFP_KERNEL); 556 if (!buffer) 557 goto out; 558 559 /* 560 * Lock the link parent if it's not the same directory. 561 */ 562 ret = -EDEADLOCK; 563 if (olddir != dir) { 564 if (atomic_read(&olddir->i_sem.count) < 1) 565 goto out_free; 566 down(&olddir->i_sem); 567 } 568 569 /* 570 * Parse the name and get the visible directory entry. 571 */ 572 ret = umsdos_parse (olddentry->d_name.name, olddentry->d_name.len, 573 &old_info); 574 if (ret) 575 goto out_unlock; 576 ret = umsdos_findentry (olddentry->d_parent, &old_info, 1); 577 if (ret) { 578printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n", 579olddentry->d_parent->d_name.name, olddentry->d_name.name, ret); 580 goto out_unlock; 581 } 582 583 /* 584 * If the visible dentry is a pseudo-hardlink, the original 585 * file must be already hidden. 586 */ 587 if (!(old_info.entry.flags & UMSDOS_HLINK)) { 588 int err; 589 590 /* create a hidden link name */ 591 ret = umsdos_newhidden (olddentry->d_parent, &hid_info); 592 if (ret) { 593printk("umsdos_link: can't make hidden %s/%s, ret=%d\n", 594olddentry->d_parent->d_name.name, hid_info.entry.name, ret); 595 goto out_unlock; 596 } 597 598 /* 599 * Make a dentry and rename the original file ... 600 */ 601 temp = umsdos_lookup_dentry(olddentry->d_parent, 602 hid_info.entry.name, 603 hid_info.entry.name_len, 0); 604 ret = PTR_ERR(temp); 605 if (IS_ERR(temp)) { 606printk("umsdos_link: lookup %s/%s failed, ret=%d\n", 607dentry->d_parent->d_name.name, hid_info.entry.name, ret); 608 goto cleanup; 609 } 610 /* rename the link to the hidden location ... */ 611 ret = umsdos_rename_f(olddir, olddentry, olddir, temp, 612 UMSDOS_HIDDEN); 613 d_move(olddentry, temp); 614 dput(temp); 615 if (ret) { 616printk("umsdos_link: rename to %s/%s failed, ret=%d\n", 617temp->d_parent->d_name.name, temp->d_name.name, ret); 618 goto cleanup; 619 } 620 /* mark the inode as a hardlink */ 621 oldinode->u.umsdos_i.i_is_hlink = 1; 622 623 /* 624 * Capture the path to the hidden link. 625 */ 626 path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE); 627Printk(("umsdos_link: hidden link path=%s\n", path)); 628 629 /* 630 * Recreate a dentry for the original name and symlink it, 631 * then symlink the new dentry. Don't give up if one fails, 632 * or we'll lose the file completely! 633 * 634 * Note: this counts as the "original" reference, so we 635 * don't increment i_nlink for this one. 636 */ 637 temp = umsdos_lookup_dentry(olddentry->d_parent, 638 old_info.entry.name, 639 old_info.entry.name_len, 0); 640 ret = PTR_ERR(temp); 641 if (!IS_ERR(temp)) { 642 ret = umsdos_symlink_x (olddir, temp, path, 643 S_IFREG | 0777, UMSDOS_HLINK); 644 dput(temp); 645 } 646 647 /* This symlink increments i_nlink (see below.) */ 648 err = umsdos_symlink_x (dir, dentry, path, 649 S_IFREG | 0777, UMSDOS_HLINK); 650 /* fold the two errors */ 651 if (!ret) 652 ret = err; 653 goto out_unlock; 654 655 /* creation failed ... remove the link entry */ 656 cleanup: 657printk("umsdos_link: link failed, ret=%d, removing %s/%s\n", 658ret, olddentry->d_parent->d_name.name, hid_info.entry.name); 659 err = umsdos_delentry(olddentry->d_parent, &hid_info, 0); 660 goto out_unlock; 661 } 662 663Printk(("UMSDOS_link: %s/%s already hidden\n", 664olddentry->d_parent->d_name.name, olddentry->d_name.name)); 665 /* 666 * The original file is already hidden, and we need to get 667 * the dentry for its real name, not the visible name. 668 * N.B. make sure it's the hidden inode ... 669 */ 670 if (!oldinode->u.umsdos_i.i_is_hlink) 671 printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n", 672 olddentry->d_parent->d_name.name, 673 olddentry->d_name.name, oldinode->i_ino); 674 675 /* 676 * In order to get the correct (real) inode, we just drop 677 * the original dentry. 678 */ 679 d_drop(olddentry); 680Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n", 681olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname)); 682 683 /* Do a real lookup to get the short name dentry */ 684 temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, 685 old_info.fake.len); 686 ret = PTR_ERR(temp); 687 if (IS_ERR(temp)) 688 goto out_unlock; 689 690 /* now resolve the link ... */ 691 temp = umsdos_solve_hlink(temp); 692 ret = PTR_ERR(temp); 693 if (IS_ERR(temp)) 694 goto out_unlock; 695 path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE); 696 dput(temp); 697Printk(("umsdos_link: %s/%s already hidden, path=%s\n", 698olddentry->d_parent->d_name.name, olddentry->d_name.name, path)); 699 700 /* finally we can symlink it ... */ 701 ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK); 702 703out_unlock: 704 /* remain locked for the call to notify_change ... */ 705 if (ret == 0) { 706 struct iattr newattrs; 707 708 /* Do a real lookup to get the short name dentry */ 709 temp = umsdos_covered(olddentry->d_parent, 710 old_info.fake.fname, 711 old_info.fake.len); 712 ret = PTR_ERR(temp); 713 if (IS_ERR(temp)) 714 goto out_unlock2; 715 716 /* now resolve the link ... */ 717 temp = umsdos_solve_hlink(temp); 718 ret = PTR_ERR(temp); 719 if (IS_ERR(temp)) 720 goto out_unlock2; 721 722 723#ifdef UMSDOS_PARANOIA 724if (!oldinode->u.umsdos_i.i_is_hlink) 725printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n", 726olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino); 727#endif 728 temp->d_inode->i_nlink++; 729Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n", 730olddentry->d_parent->d_name.name, olddentry->d_name.name, 731oldinode->i_ino, oldinode->i_nlink)); 732 newattrs.ia_valid = 0; 733 ret = umsdos_notify_change_locked(temp, &newattrs); 734 if (ret == 0) 735 mark_inode_dirty(temp->d_inode); 736 dput(temp); 737out_unlock2: 738 if (ret == 0) 739 mark_inode_dirty(olddentry->d_inode); 740 } 741 if (olddir != dir) 742 up(&olddir->i_sem); 743 744out_free: 745 free_page(buffer); 746out: 747 Printk (("umsdos_link %d\n", ret)); 748 return ret; 749} 750 751 752/* 753 * Add a sub-directory in a directory 754 */ 755/* #Specification: mkdir / Directory already exist in DOS 756 * We do the same thing as for file creation. 757 * For all user it is an error. 758 */ 759/* #Specification: mkdir / umsdos directory / create EMD 760 * When we created a new sub-directory in a UMSDOS 761 * directory (one with full UMSDOS semantics), we 762 * create immediately an EMD file in the new 763 * sub-directory so it inherits UMSDOS semantics. 764 */ 765int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode) 766{ 767 struct dentry *temp; 768 struct inode *inode; 769 int ret, err; 770 struct umsdos_info info; 771 772 ret = umsdos_nevercreat (dir, dentry, -EEXIST); 773 if (ret) 774 goto out; 775 776 ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); 777 if (ret) 778 goto out; 779 780 info.entry.mode = mode | S_IFDIR; 781 info.entry.rdev = 0; 782 info.entry.uid = current->fsuid; 783 info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 784 info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME; 785 info.entry.flags = 0; 786 info.entry.nlink = 1; 787 ret = umsdos_newentry (dentry->d_parent, &info); 788 if (ret) 789 goto out; 790 791 /* lookup the short name dentry */ 792 temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); 793 ret = PTR_ERR(temp); 794 if (IS_ERR(temp)) 795 goto out_remove; 796 797 /* Make sure the short name doesn't exist */ 798 ret = -EEXIST; 799 if (temp->d_inode) { 800printk("umsdos_mkdir: short name %s/%s exists\n", 801dentry->d_parent->d_name.name, info.fake.fname); 802 goto out_remove_dput; 803 } 804 805 ret = msdos_mkdir (dir, temp, mode); 806 if (ret) 807 goto out_remove_dput; 808 809 /* 810 * Lock the inode to protect the EMD creation ... 811 */ 812 inode = temp->d_inode; 813 down(&inode->i_sem); 814 815 atomic_inc(&inode->i_count); 816 d_instantiate(dentry, inode); 817 818 /* N.B. this should have an option to create the EMD ... */ 819 umsdos_lookup_patch_new(dentry, &info); 820 821 /* 822 * Create the EMD file, and set up the dir so it is 823 * promoted to EMD with the EMD file invisible. 824 * 825 * N.B. error return if EMD fails? 826 */ 827 err = umsdos_make_emd(dentry); 828 umsdos_setup_dir(dentry); 829 830 up(&inode->i_sem); 831 dput(temp); 832 833out: 834 Printk(("umsdos_mkdir: %s/%s, ret=%d\n", 835 dentry->d_parent->d_name.name, dentry->d_name.name, ret)); 836 return ret; 837 838 /* an error occurred ... remove EMD entry. */ 839out_remove_dput: 840 dput(temp); 841out_remove: 842 umsdos_delentry (dentry->d_parent, &info, 1); 843 goto out; 844} 845 846/* 847 * Add a new device special file into a directory. 848 * 849 * #Specification: Special files / strategy 850 * Device special file, pipes, etc ... are created like normal 851 * file in the msdos file system. Of course they remain empty. 852 * 853 * One strategy was to create those files only in the EMD file 854 * since they were not important for MSDOS. The problem with 855 * that, is that there were not getting inode number allocated. 856 * The MSDOS filesystems is playing a nice game to fake inode 857 * number, so why not use it. 858 * 859 * The absence of inode number compatible with those allocated 860 * for ordinary files was causing major trouble with hard link 861 * in particular and other parts of the kernel I guess. 862 */ 863int UMSDOS_mknod (struct inode *dir, struct dentry *dentry, 864 int mode, int rdev) 865{ 866 return umsdos_create_any (dir, dentry, mode, rdev, 0); 867} 868 869/* 870 * Remove a sub-directory. 871 */ 872int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry) 873{ 874 struct dentry *temp; 875 int ret, err, empty; 876 struct umsdos_info info; 877 878 ret = umsdos_nevercreat (dir, dentry, -EPERM); 879 if (ret) 880 goto out; 881 882 ret = -EBUSY; 883 if (!d_unhashed(dentry)) 884 goto out; 885 886 /* check whether the EMD is empty */ 887 ret = -ENOTEMPTY; 888 empty = umsdos_isempty (dentry); 889 890 /* Have to remove the EMD file? */ 891 if (empty == 1) { 892 struct dentry *demd; 893 894 demd = umsdos_get_emd_dentry(dentry); 895 if (!IS_ERR(demd)) { 896 err = -ENOENT; 897 if (demd->d_inode) 898 err = msdos_unlink (dentry->d_inode, demd); 899Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err)); 900#ifdef UMSDOS_PARANOIA 901if (err) 902printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n", 903demd->d_parent->d_name.name, demd->d_name.name, err); 904#endif 905 if (!err) { 906 d_delete(demd); 907 ret = 0; 908 } 909 dput(demd); 910 } 911 } else if (empty == 2) 912 ret = 0; 913 if (ret) 914 goto out; 915 916 umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); 917 /* Call findentry to complete the mangling */ 918 umsdos_findentry (dentry->d_parent, &info, 2); 919 temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); 920 ret = PTR_ERR(temp); 921 if (IS_ERR(temp)) 922 goto out; 923 /* 924 * Attempt to remove the msdos name. 925 */ 926 ret = msdos_rmdir (dir, temp); 927 if (ret && ret != -ENOENT) 928 goto out_dput; 929 930 d_delete(temp); 931 /* OK so far ... remove the name from the EMD */ 932 ret = umsdos_delentry (dentry->d_parent, &info, 1); 933#ifdef UMSDOS_PARANOIA 934if (ret) 935printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret); 936#endif 937 938 /* dput() temp if we didn't do it above */ 939out_dput: 940 dput(temp); 941 942out: 943 Printk (("umsdos_rmdir %d\n", ret)); 944 return ret; 945} 946 947 948/* 949 * Remove a file from the directory. 950 * 951 * #Specification: hard link / deleting a link 952 * When we delete a file and this file is a link, 953 * we must subtract 1 from the nlink field of the 954 * hidden link. 955 * 956 * If the count goes to 0, we delete this hidden 957 * link too. 958 */ 959int UMSDOS_unlink (struct inode *dir, struct dentry *dentry) 960{ 961 struct dentry *temp, *link = NULL; 962 struct inode *inode; 963 int ret; 964 struct umsdos_info info; 965 966Printk(("UMSDOS_unlink: entering %s/%s\n", 967dentry->d_parent->d_name.name, dentry->d_name.name)); 968 969 ret = umsdos_nevercreat (dir, dentry, -EPERM); 970 if (ret) 971 goto out; 972 973 ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); 974 if (ret) 975 goto out; 976 977 umsdos_lockcreate (dir); 978 ret = umsdos_findentry (dentry->d_parent, &info, 1); 979 if (ret) { 980printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n", 981dentry->d_parent->d_name.name, dentry->d_name.name, ret); 982 goto out_unlock; 983 } 984 985Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname)); 986 987 /* 988 * Note! If this is a hardlink and the names are aliased, 989 * the short-name lookup will return the hardlink dentry. 990 * In order to get the correct (real) inode, we just drop 991 * the original dentry. 992 */ 993 if (info.entry.flags & UMSDOS_HLINK) { 994 d_drop(dentry); 995 } 996 997 /* Do a real lookup to get the short name dentry */ 998 temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); 999 ret = PTR_ERR(temp); 1000 if (IS_ERR(temp)) 1001 goto out_unlock; 1002 1003 /* 1004 * Resolve hardlinks now, but defer processing until later. 1005 */ 1006 if (info.entry.flags & UMSDOS_HLINK) { 1007 link = umsdos_solve_hlink(dget(temp)); 1008 } 1009 1010 /* Delete the EMD entry */ 1011 ret = umsdos_delentry (dentry->d_parent, &info, 0); 1012 if (ret && ret != -ENOENT) { 1013 printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n", 1014 info.entry.name, ret); 1015 goto out_dput; 1016 } 1017 1018 ret = msdos_unlink(dir, temp); 1019 if (!ret) 1020 d_delete(temp); 1021#ifdef UMSDOS_PARANOIA 1022if (ret) 1023printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n", 1024temp->d_parent->d_name.name, temp->d_name.name, ret); 1025#endif 1026 1027 /* dput() temp if we didn't do it above */ 1028out_dput: 1029 dput(temp); 1030 1031out_unlock: 1032 umsdos_unlockcreate (dir); 1033 1034 /* 1035 * Now check for deferred handling of a hardlink. 1036 */ 1037 if (!link) 1038 goto out; 1039 1040 if (IS_ERR(link)) { 1041printk("umsdos_unlink: failed to resolve %s/%s\n", 1042dentry->d_parent->d_name.name, dentry->d_name.name); 1043 if (!ret) 1044 ret = PTR_ERR(link); 1045 goto out; 1046 } 1047 1048Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n", 1049link->d_parent->d_name.name, link->d_name.name, ret)); 1050 1051 /* already have an error? */ 1052 if (ret) 1053 goto out_cleanup; 1054 1055 /* make sure the link exists ... */ 1056 inode = link->d_inode; 1057 if (!inode) { 1058 printk(KERN_WARNING "umsdos_unlink: hard link not found\n"); 1059 goto out_cleanup; 1060 } 1061 1062 /* 1063 * If this was the last linked reference, delete it now. 1064 * 1065 * N.B. Deadlock problem? We should be holding the lock 1066 * for the hardlink's parent, but another process might 1067 * be holding that lock waiting for us to finish ... 1068 */ 1069 if (inode->i_nlink <= 1) { 1070 ret = UMSDOS_unlink (link->d_parent->d_inode, link); 1071 if (ret) { 1072 printk(KERN_WARNING 1073 "umsdos_unlink: link removal failed, ret=%d\n", 1074 ret); 1075 } else 1076 d_delete(link); 1077 } else { 1078 struct iattr newattrs; 1079 inode->i_nlink--; 1080 newattrs.ia_valid = 0; 1081 ret = umsdos_notify_change_locked(link, &newattrs); 1082 if (!ret) 1083 mark_inode_dirty(link->d_inode); 1084 } 1085 1086out_cleanup: 1087 d_drop(link); 1088 dput(link); 1089 1090out: 1091 Printk (("umsdos_unlink %d\n", ret)); 1092 return ret; 1093} 1094 1095/* 1096 * Rename (move) a file. 1097 */ 1098int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry, 1099 struct inode *new_dir, struct dentry *new_dentry) 1100{ 1101 int ret; 1102 1103 ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST); 1104 if (ret) 1105 return ret; 1106 1107 /* 1108 * If the target already exists, delete it first. 1109 */ 1110 if (new_dentry->d_inode) { 1111 dget(new_dentry); 1112 if (S_ISDIR(old_dentry->d_inode->i_mode)) 1113 ret = UMSDOS_rmdir (new_dir, new_dentry); 1114 else 1115 ret = UMSDOS_unlink (new_dir, new_dentry); 1116 if (!ret) 1117 d_drop(new_dentry); 1118 dput(new_dentry); 1119 if (ret) 1120 return ret; 1121 } 1122 ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0); 1123 return ret; 1124} 1125