1/* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 19 unchanged lines hidden (view full) --- 28 */ 29 30#if 0 31#ifndef lint 32static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95"; 33#endif /* not lint */ 34#endif 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sbin/fsck_ffs/pass2.c 202109 2010-01-11 20:05:38Z mckusick $"); |
37 38#include <sys/param.h> |
39#include <sys/sysctl.h> |
40 41#include <ufs/ufs/dinode.h> 42#include <ufs/ufs/dir.h> 43#include <ufs/ffs/fs.h> 44 45#include <err.h> |
46#include <errno.h> |
47#include <stdint.h> 48#include <string.h> 49 50#include "fsck.h" 51 52#define MINDIRSIZE (sizeof (struct dirtemplate)) 53 54static int fix_extraneous(struct inoinfo *, struct inodesc *); --- 156 unchanged lines hidden (view full) --- 211 inp->i_dotdot = inp->i_parent; 212 fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); 213 if (reply("FIX") == 0) 214 continue; 215 (void)makeentry(inp->i_number, inp->i_parent, ".."); 216 inoinfo(inp->i_parent)->ino_linkcnt--; 217 continue; 218 } |
219 /* 220 * Here we have: 221 * inp->i_number is directory with bad ".." in it. 222 * inp->i_dotdot is current value of "..". 223 * inp->i_parent is directory to which ".." should point. 224 */ 225 getpathname(pathbuf, inp->i_parent, inp->i_number); 226 printf("BAD INODE NUMBER FOR '..' in DIR I=%d (%s)\n", 227 inp->i_number, pathbuf); 228 getpathname(pathbuf, inp->i_dotdot, inp->i_dotdot); 229 printf("CURRENTLY POINTS TO I=%d (%s), ", inp->i_dotdot, 230 pathbuf); 231 getpathname(pathbuf, inp->i_parent, inp->i_parent); 232 printf("SHOULD POINT TO I=%d (%s)", inp->i_parent, pathbuf); 233 if (cursnapshot != 0) { 234 /* 235 * We need to: 236 * setcwd(inp->i_number); 237 * setdotdot(inp->i_dotdot, inp->i_parent); 238 */ 239 cmd.value = inp->i_number; 240 if (sysctlbyname("vfs.ffs.setcwd", 0, 0, 241 &cmd, sizeof cmd) == -1) { 242 /* kernel lacks support for these functions */ 243 printf(" (IGNORED)\n"); 244 continue; 245 } 246 cmd.value = inp->i_dotdot; /* verify same value */ 247 cmd.size = inp->i_parent; /* new parent */ 248 if (sysctlbyname("vfs.ffs.setdotdot", 0, 0, 249 &cmd, sizeof cmd) == -1) { 250 printf(" (FIX FAILED: %s)\n", strerror(errno)); 251 continue; 252 } 253 printf(" (FIXED)\n"); 254 inoinfo(inp->i_parent)->ino_linkcnt--; 255 inp->i_dotdot = inp->i_parent; |
256 continue; |
257 } 258 if (preen) 259 printf(" (FIXED)\n"); 260 else if (reply("FIX") == 0) 261 continue; |
262 inoinfo(inp->i_dotdot)->ino_linkcnt++; 263 inoinfo(inp->i_parent)->ino_linkcnt--; 264 inp->i_dotdot = inp->i_parent; 265 (void)changeino(inp->i_number, "..", inp->i_parent); 266 } 267 /* 268 * Mark all the directories that can be found from the root. 269 */ --- 216 unchanged lines hidden (view full) --- 486 return (ret|KEEPON); 487 dirp->d_ino = 0; 488 return (ret|KEEPON|ALTERED); 489} 490 491static int 492fix_extraneous(struct inoinfo *inp, struct inodesc *idesc) 493{ |
494 char *cp; |
495 struct inodesc dotdesc; 496 char oldname[MAXPATHLEN + 1]; 497 char newname[MAXPATHLEN + 1]; 498 499 /* 500 * If we have not yet found "..", look it up now so we know 501 * which inode the directory itself believes is its parent. 502 */ --- 25 unchanged lines hidden (view full) --- 528 idesc->id_number == inp->i_parent || /* Case 2 */ 529 inp->i_dotdot != idesc->id_number || /* Case 3 */ 530 inp->i_dotdot == inp->i_parent) { /* Case 4 */ 531 getpathname(newname, idesc->id_number, idesc->id_number); 532 if (strcmp(newname, "/") != 0) 533 strcat (newname, "/"); 534 strcat(newname, idesc->id_dirp->d_name); 535 getpathname(oldname, inp->i_number, inp->i_number); |
536 pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s", |
537 newname, oldname); 538 if (cursnapshot != 0) { 539 /* 540 * We need to 541 * setcwd(idesc->id_number); 542 * unlink(idesc->id_dirp->d_name); 543 */ |
544 cmd.value = idesc->id_number; 545 if (sysctlbyname("vfs.ffs.setcwd", 0, 0, 546 &cmd, sizeof cmd) == -1) { 547 printf(" (IGNORED)\n"); 548 return (0); 549 } 550 cmd.value = (int)idesc->id_dirp->d_name; 551 cmd.size = inp->i_number; /* verify same name */ 552 if (sysctlbyname("vfs.ffs.unlink", 0, 0, 553 &cmd, sizeof cmd) == -1) { 554 printf(" (UNLINK FAILED: %s)\n", 555 strerror(errno)); 556 return (0); 557 } 558 printf(" (REMOVED)\n"); |
559 return (0); 560 } 561 if (preen) { 562 printf(" (REMOVED)\n"); 563 return (1); 564 } 565 return (reply("REMOVE")); 566 } 567 /* 568 * None of the first four cases above, so must be case (5). 569 * Eliminate the old name and make the new the name the parent. 570 */ 571 getpathname(oldname, inp->i_parent, inp->i_number); 572 getpathname(newname, inp->i_number, inp->i_number); |
573 pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s", oldname, |
574 newname); 575 if (cursnapshot != 0) { 576 /* 577 * We need to 578 * setcwd(inp->i_parent); 579 * unlink(last component of oldname pathname); 580 */ |
581 cmd.value = inp->i_parent; 582 if (sysctlbyname("vfs.ffs.setcwd", 0, 0, 583 &cmd, sizeof cmd) == -1) { 584 printf(" (IGNORED)\n"); 585 return (0); 586 } 587 if ((cp = rindex(oldname, '/')) == NULL) { 588 printf(" (IGNORED)\n"); 589 return (0); 590 } 591 cmd.value = (int)(cp + 1); 592 cmd.size = inp->i_number; /* verify same name */ 593 if (sysctlbyname("vfs.ffs.unlink", 0, 0, 594 &cmd, sizeof cmd) == -1) { 595 printf(" (UNLINK FAILED: %s)\n", 596 strerror(errno)); 597 return (0); 598 } 599 printf(" (REMOVED)\n"); 600 inp->i_parent = idesc->id_number; /* reparent to correct dir */ |
601 return (0); 602 } 603 if (!preen && !reply("REMOVE")) 604 return (0); 605 memset(&dotdesc, 0, sizeof(struct inodesc)); 606 dotdesc.id_type = DATA; 607 dotdesc.id_number = inp->i_parent; /* directory in which name appears */ 608 dotdesc.id_parent = inp->i_number; /* inode number in entry to delete */ --- 29 unchanged lines hidden --- |