clang-format
This commit is contained in:
@@ -58,268 +58,241 @@
|
||||
* instead of the first entry we recursively find. Beware of course
|
||||
* that the .. entry might not point to anywhere valid at all...
|
||||
*/
|
||||
static
|
||||
int
|
||||
pass2_dir(uint32_t ino, uint32_t parentino, const char *pathsofar)
|
||||
{
|
||||
struct sfs_dinode sfi;
|
||||
struct sfs_direntry *direntries;
|
||||
int *sortvector;
|
||||
uint32_t dirsize, ndirentries, maxdirentries, subdircount, i;
|
||||
int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0;
|
||||
static int pass2_dir(uint32_t ino, uint32_t parentino, const char *pathsofar) {
|
||||
struct sfs_dinode sfi;
|
||||
struct sfs_direntry *direntries;
|
||||
int *sortvector;
|
||||
uint32_t dirsize, ndirentries, maxdirentries, subdircount, i;
|
||||
int ichanged = 0, dchanged = 0, dotseen = 0, dotdotseen = 0;
|
||||
|
||||
if (inode_visitdir(ino)) {
|
||||
/* crosslinked dir; tell parent to remove the entry */
|
||||
return 1;
|
||||
}
|
||||
if (inode_visitdir(ino)) {
|
||||
/* crosslinked dir; tell parent to remove the entry */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Load the inode. */
|
||||
sfs_readinode(ino, &sfi);
|
||||
/* Load the inode. */
|
||||
sfs_readinode(ino, &sfi);
|
||||
|
||||
/*
|
||||
* Load the directory. If there is any leftover room in the
|
||||
* last block, allocate space for it in case we want to insert
|
||||
* entries.
|
||||
*/
|
||||
/*
|
||||
* Load the directory. If there is any leftover room in the
|
||||
* last block, allocate space for it in case we want to insert
|
||||
* entries.
|
||||
*/
|
||||
|
||||
ndirentries = sfi.sfi_size/sizeof(struct sfs_direntry);
|
||||
maxdirentries = SFS_ROUNDUP(ndirentries,
|
||||
SFS_BLOCKSIZE/sizeof(struct sfs_direntry));
|
||||
dirsize = maxdirentries * sizeof(struct sfs_direntry);
|
||||
direntries = domalloc(dirsize);
|
||||
ndirentries = sfi.sfi_size / sizeof(struct sfs_direntry);
|
||||
maxdirentries =
|
||||
SFS_ROUNDUP(ndirentries, SFS_BLOCKSIZE / sizeof(struct sfs_direntry));
|
||||
dirsize = maxdirentries * sizeof(struct sfs_direntry);
|
||||
direntries = domalloc(dirsize);
|
||||
|
||||
sortvector = domalloc(ndirentries * sizeof(int));
|
||||
sortvector = domalloc(ndirentries * sizeof(int));
|
||||
|
||||
sfs_readdir(&sfi, direntries, ndirentries);
|
||||
for (i=ndirentries; i<maxdirentries; i++) {
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name));
|
||||
}
|
||||
sfs_readdir(&sfi, direntries, ndirentries);
|
||||
for (i = ndirentries; i < maxdirentries; i++) {
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort by name and check for duplicate names.
|
||||
*/
|
||||
/*
|
||||
* Sort by name and check for duplicate names.
|
||||
*/
|
||||
|
||||
sfsdir_sort(direntries, ndirentries, sortvector);
|
||||
sfsdir_sort(direntries, ndirentries, sortvector);
|
||||
|
||||
/* don't use ndirentries-1 here, in case ndirentries == 0 */
|
||||
for (i=0; i+1<ndirentries; i++) {
|
||||
struct sfs_direntry *d1 = &direntries[sortvector[i]];
|
||||
struct sfs_direntry *d2 = &direntries[sortvector[i+1]];
|
||||
assert(d1 != d2);
|
||||
/* don't use ndirentries-1 here, in case ndirentries == 0 */
|
||||
for (i = 0; i + 1 < ndirentries; i++) {
|
||||
struct sfs_direntry *d1 = &direntries[sortvector[i]];
|
||||
struct sfs_direntry *d2 = &direntries[sortvector[i + 1]];
|
||||
assert(d1 != d2);
|
||||
|
||||
if (d1->sfd_ino == SFS_NOINO || d2->sfd_ino == SFS_NOINO) {
|
||||
/* sfsdir_sort puts these last */
|
||||
continue;
|
||||
}
|
||||
if (d1->sfd_ino == SFS_NOINO || d2->sfd_ino == SFS_NOINO) {
|
||||
/* sfsdir_sort puts these last */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(d1->sfd_name, d2->sfd_name)) {
|
||||
if (d1->sfd_ino == d2->sfd_ino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Duplicate entries for "
|
||||
"%s (merged)",
|
||||
pathsofar, d1->sfd_name);
|
||||
d1->sfd_ino = SFS_NOINO;
|
||||
d1->sfd_name[0] = 0;
|
||||
}
|
||||
else {
|
||||
/* XXX: what if FSCK.n.m already exists? */
|
||||
snprintf(d1->sfd_name, sizeof(d1->sfd_name),
|
||||
"FSCK.%lu.%lu",
|
||||
(unsigned long) d1->sfd_ino,
|
||||
(unsigned long) uniqueid());
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Duplicate names %s "
|
||||
"(one renamed: %s)",
|
||||
pathsofar, d2->sfd_name, d1->sfd_name);
|
||||
}
|
||||
dchanged = 1;
|
||||
}
|
||||
}
|
||||
if (!strcmp(d1->sfd_name, d2->sfd_name)) {
|
||||
if (d1->sfd_ino == d2->sfd_ino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Duplicate entries for "
|
||||
"%s (merged)",
|
||||
pathsofar, d1->sfd_name);
|
||||
d1->sfd_ino = SFS_NOINO;
|
||||
d1->sfd_name[0] = 0;
|
||||
} else {
|
||||
/* XXX: what if FSCK.n.m already exists? */
|
||||
snprintf(d1->sfd_name, sizeof(d1->sfd_name), "FSCK.%lu.%lu",
|
||||
(unsigned long)d1->sfd_ino, (unsigned long)uniqueid());
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Duplicate names %s "
|
||||
"(one renamed: %s)",
|
||||
pathsofar, d2->sfd_name, d1->sfd_name);
|
||||
}
|
||||
dchanged = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the . and .. entries.
|
||||
*/
|
||||
/*
|
||||
* Look for the . and .. entries.
|
||||
*/
|
||||
|
||||
for (i=0; i<ndirentries; i++) {
|
||||
if (!strcmp(direntries[i].sfd_name, ".")) {
|
||||
if (direntries[i].sfd_ino != ino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Incorrect `.' entry "
|
||||
"(fixed)", pathsofar);
|
||||
direntries[i].sfd_ino = ino;
|
||||
dchanged = 1;
|
||||
}
|
||||
/* duplicates are checked above -> only one . here */
|
||||
assert(dotseen==0);
|
||||
dotseen = 1;
|
||||
}
|
||||
else if (!strcmp(direntries[i].sfd_name, "..")) {
|
||||
if (direntries[i].sfd_ino != parentino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Incorrect `..' entry "
|
||||
"(fixed)", pathsofar);
|
||||
direntries[i].sfd_ino = parentino;
|
||||
dchanged = 1;
|
||||
}
|
||||
/* duplicates are checked above -> only one .. here */
|
||||
assert(dotdotseen==0);
|
||||
dotdotseen = 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ndirentries; i++) {
|
||||
if (!strcmp(direntries[i].sfd_name, ".")) {
|
||||
if (direntries[i].sfd_ino != ino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Incorrect `.' entry "
|
||||
"(fixed)",
|
||||
pathsofar);
|
||||
direntries[i].sfd_ino = ino;
|
||||
dchanged = 1;
|
||||
}
|
||||
/* duplicates are checked above -> only one . here */
|
||||
assert(dotseen == 0);
|
||||
dotseen = 1;
|
||||
} else if (!strcmp(direntries[i].sfd_name, "..")) {
|
||||
if (direntries[i].sfd_ino != parentino) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Incorrect `..' entry "
|
||||
"(fixed)",
|
||||
pathsofar);
|
||||
direntries[i].sfd_ino = parentino;
|
||||
dchanged = 1;
|
||||
}
|
||||
/* duplicates are checked above -> only one .. here */
|
||||
assert(dotdotseen == 0);
|
||||
dotdotseen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no . entry, try to insert one.
|
||||
*/
|
||||
/*
|
||||
* If no . entry, try to insert one.
|
||||
*/
|
||||
|
||||
if (!dotseen) {
|
||||
if (sfsdir_tryadd(direntries, ndirentries, ".", ino)==0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `.' entry (added)",
|
||||
pathsofar);
|
||||
dchanged = 1;
|
||||
}
|
||||
else if (sfsdir_tryadd(direntries, maxdirentries, ".",
|
||||
ino)==0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `.' entry (added)",
|
||||
pathsofar);
|
||||
ndirentries++;
|
||||
dchanged = 1;
|
||||
sfi.sfi_size += sizeof(struct sfs_direntry);
|
||||
ichanged = 1;
|
||||
}
|
||||
else {
|
||||
setbadness(EXIT_UNRECOV);
|
||||
warnx("Directory %s: No `.' entry (NOT FIXED)",
|
||||
pathsofar);
|
||||
}
|
||||
}
|
||||
if (!dotseen) {
|
||||
if (sfsdir_tryadd(direntries, ndirentries, ".", ino) == 0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `.' entry (added)", pathsofar);
|
||||
dchanged = 1;
|
||||
} else if (sfsdir_tryadd(direntries, maxdirentries, ".", ino) == 0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `.' entry (added)", pathsofar);
|
||||
ndirentries++;
|
||||
dchanged = 1;
|
||||
sfi.sfi_size += sizeof(struct sfs_direntry);
|
||||
ichanged = 1;
|
||||
} else {
|
||||
setbadness(EXIT_UNRECOV);
|
||||
warnx("Directory %s: No `.' entry (NOT FIXED)", pathsofar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no .. entry, try to insert one.
|
||||
*/
|
||||
/*
|
||||
* If no .. entry, try to insert one.
|
||||
*/
|
||||
|
||||
if (!dotdotseen) {
|
||||
if (sfsdir_tryadd(direntries, ndirentries, "..",
|
||||
parentino)==0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `..' entry (added)",
|
||||
pathsofar);
|
||||
dchanged = 1;
|
||||
}
|
||||
else if (sfsdir_tryadd(direntries, maxdirentries, "..",
|
||||
parentino)==0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `..' entry (added)",
|
||||
pathsofar);
|
||||
ndirentries++;
|
||||
dchanged = 1;
|
||||
sfi.sfi_size += sizeof(struct sfs_direntry);
|
||||
ichanged = 1;
|
||||
}
|
||||
else {
|
||||
setbadness(EXIT_UNRECOV);
|
||||
warnx("Directory %s: No `..' entry (NOT FIXED)",
|
||||
pathsofar);
|
||||
}
|
||||
}
|
||||
if (!dotdotseen) {
|
||||
if (sfsdir_tryadd(direntries, ndirentries, "..", parentino) == 0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `..' entry (added)", pathsofar);
|
||||
dchanged = 1;
|
||||
} else if (sfsdir_tryadd(direntries, maxdirentries, "..", parentino) == 0) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: No `..' entry (added)", pathsofar);
|
||||
ndirentries++;
|
||||
dchanged = 1;
|
||||
sfi.sfi_size += sizeof(struct sfs_direntry);
|
||||
ichanged = 1;
|
||||
} else {
|
||||
setbadness(EXIT_UNRECOV);
|
||||
warnx("Directory %s: No `..' entry (NOT FIXED)", pathsofar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now load each inode in the directory.
|
||||
*
|
||||
* For regular files, count the number of links we see; for
|
||||
* directories, recurse. Count the number of subdirs seen
|
||||
* so we can correct our own link count if necessary.
|
||||
*/
|
||||
/*
|
||||
* Now load each inode in the directory.
|
||||
*
|
||||
* For regular files, count the number of links we see; for
|
||||
* directories, recurse. Count the number of subdirs seen
|
||||
* so we can correct our own link count if necessary.
|
||||
*/
|
||||
|
||||
subdircount=0;
|
||||
for (i=0; i<ndirentries; i++) {
|
||||
if (direntries[i].sfd_ino == SFS_NOINO) {
|
||||
/* nothing */
|
||||
}
|
||||
else if (!strcmp(direntries[i].sfd_name, ".")) {
|
||||
/* nothing */
|
||||
}
|
||||
else if (!strcmp(direntries[i].sfd_name, "..")) {
|
||||
/* nothing */
|
||||
}
|
||||
else {
|
||||
char path[strlen(pathsofar)+SFS_NAMELEN+1];
|
||||
struct sfs_dinode subsfi;
|
||||
subdircount = 0;
|
||||
for (i = 0; i < ndirentries; i++) {
|
||||
if (direntries[i].sfd_ino == SFS_NOINO) {
|
||||
/* nothing */
|
||||
} else if (!strcmp(direntries[i].sfd_name, ".")) {
|
||||
/* nothing */
|
||||
} else if (!strcmp(direntries[i].sfd_name, "..")) {
|
||||
/* nothing */
|
||||
} else {
|
||||
char path[strlen(pathsofar) + SFS_NAMELEN + 1];
|
||||
struct sfs_dinode subsfi;
|
||||
|
||||
sfs_readinode(direntries[i].sfd_ino, &subsfi);
|
||||
snprintf(path, sizeof(path), "%s/%s",
|
||||
pathsofar, direntries[i].sfd_name);
|
||||
sfs_readinode(direntries[i].sfd_ino, &subsfi);
|
||||
snprintf(path, sizeof(path), "%s/%s", pathsofar, direntries[i].sfd_name);
|
||||
|
||||
switch (subsfi.sfi_type) {
|
||||
case SFS_TYPE_FILE:
|
||||
inode_addlink(direntries[i].sfd_ino);
|
||||
break;
|
||||
case SFS_TYPE_DIR:
|
||||
if (pass2_dir(direntries[i].sfd_ino,
|
||||
ino,
|
||||
path)) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Crosslink to "
|
||||
"other directory (removed)",
|
||||
path);
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
direntries[i].sfd_name[0] = 0;
|
||||
dchanged = 1;
|
||||
}
|
||||
else {
|
||||
subdircount++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Object %s: Invalid inode type %u "
|
||||
"(removed)", path, subsfi.sfi_type);
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
direntries[i].sfd_name[0] = 0;
|
||||
dchanged = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (subsfi.sfi_type) {
|
||||
case SFS_TYPE_FILE:
|
||||
inode_addlink(direntries[i].sfd_ino);
|
||||
break;
|
||||
case SFS_TYPE_DIR:
|
||||
if (pass2_dir(direntries[i].sfd_ino, ino, path)) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Crosslink to "
|
||||
"other directory (removed)",
|
||||
path);
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
direntries[i].sfd_name[0] = 0;
|
||||
dchanged = 1;
|
||||
} else {
|
||||
subdircount++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Object %s: Invalid inode type %u "
|
||||
"(removed)",
|
||||
path, subsfi.sfi_type);
|
||||
direntries[i].sfd_ino = SFS_NOINO;
|
||||
direntries[i].sfd_name[0] = 0;
|
||||
dchanged = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the link count if needed.
|
||||
*/
|
||||
/*
|
||||
* Fix up the link count if needed.
|
||||
*/
|
||||
|
||||
if (sfi.sfi_linkcount != subdircount+2) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Link count %lu should be %lu (fixed)",
|
||||
pathsofar, (unsigned long) sfi.sfi_linkcount,
|
||||
(unsigned long) subdircount+2);
|
||||
sfi.sfi_linkcount = subdircount+2;
|
||||
ichanged = 1;
|
||||
}
|
||||
if (sfi.sfi_linkcount != subdircount + 2) {
|
||||
setbadness(EXIT_RECOV);
|
||||
warnx("Directory %s: Link count %lu should be %lu (fixed)", pathsofar,
|
||||
(unsigned long)sfi.sfi_linkcount, (unsigned long)subdircount + 2);
|
||||
sfi.sfi_linkcount = subdircount + 2;
|
||||
ichanged = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write back anything that changed, clean up, and return.
|
||||
*/
|
||||
/*
|
||||
* Write back anything that changed, clean up, and return.
|
||||
*/
|
||||
|
||||
if (dchanged) {
|
||||
sfs_writedir(&sfi, direntries, ndirentries);
|
||||
}
|
||||
if (dchanged) {
|
||||
sfs_writedir(&sfi, direntries, ndirentries);
|
||||
}
|
||||
|
||||
if (ichanged) {
|
||||
sfs_writeinode(ino, &sfi);
|
||||
}
|
||||
if (ichanged) {
|
||||
sfs_writeinode(ino, &sfi);
|
||||
}
|
||||
|
||||
free(direntries);
|
||||
free(sortvector);
|
||||
free(direntries);
|
||||
free(sortvector);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
pass2(void)
|
||||
{
|
||||
char path[SFS_VOLNAME_SIZE + 2];
|
||||
void pass2(void) {
|
||||
char path[SFS_VOLNAME_SIZE + 2];
|
||||
|
||||
snprintf(path, sizeof(path), "%s:", sb_volname());
|
||||
pass2_dir(SFS_ROOTDIR_INO, SFS_ROOTDIR_INO, path);
|
||||
snprintf(path, sizeof(path), "%s:", sb_volname());
|
||||
pass2_dir(SFS_ROOTDIR_INO, SFS_ROOTDIR_INO, path);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user