diff options
-rw-r--r-- | sbin/fsck/Makefile | 9 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/0.t | 150 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/1.t | 83 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/2.t | 265 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/3.t | 452 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/4.t | 1424 | ||||
-rw-r--r-- | sbin/fsck/SMM.doc/Makefile | 7 | ||||
-rw-r--r-- | sbin/fsck/dir.c | 779 | ||||
-rw-r--r-- | sbin/fsck/fsck.8 | 321 | ||||
-rw-r--r-- | sbin/fsck/fsck.c | 540 | ||||
-rw-r--r-- | sbin/fsck/fsck.h | 305 | ||||
-rw-r--r-- | sbin/fsck/fsutil.c | 363 | ||||
-rw-r--r-- | sbin/fsck/fsutil.h | 62 | ||||
-rw-r--r-- | sbin/fsck/inode.c | 672 | ||||
-rw-r--r-- | sbin/fsck/main.c | 417 | ||||
-rw-r--r-- | sbin/fsck/pass1.c | 431 | ||||
-rw-r--r-- | sbin/fsck/pass1b.c | 107 | ||||
-rw-r--r-- | sbin/fsck/pass2.c | 486 | ||||
-rw-r--r-- | sbin/fsck/pass3.c | 118 | ||||
-rw-r--r-- | sbin/fsck/pass4.c | 145 | ||||
-rw-r--r-- | sbin/fsck/pass5.c | 427 | ||||
-rw-r--r-- | sbin/fsck/pathnames.h | 35 | ||||
-rw-r--r-- | sbin/fsck/preen.c | 332 | ||||
-rw-r--r-- | sbin/fsck/setup.c | 520 | ||||
-rw-r--r-- | sbin/fsck/utilities.c | 683 | ||||
-rw-r--r-- | sbin/fsdb/Makefile | 6 | ||||
-rw-r--r-- | sbin/quotacheck/Makefile | 5 | ||||
-rw-r--r-- | share/doc/smm/03.fsck/Makefile | 2 |
28 files changed, 1011 insertions, 8135 deletions
diff --git a/sbin/fsck/Makefile b/sbin/fsck/Makefile index 3155b1a..025f7bb 100644 --- a/sbin/fsck/Makefile +++ b/sbin/fsck/Makefile @@ -1,10 +1,9 @@ -# @(#)Makefile 8.2 (Berkeley) 4/27/95 +# $FreeBSD$ +# $NetBSD: Makefile,v 1.14 1996/09/27 22:38:37 christos Exp $ PROG= fsck +SRCS= fsck.c fsutil.c preen.c MAN8= fsck.8 -SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ - pass5.c preen.c setup.c utilities.c ffs_subr.c ffs_tables.c -CFLAGS+=-W -.PATH: ${.CURDIR}/../../sys/ufs/ffs +CFLAGS= .include <bsd.prog.mk> diff --git a/sbin/fsck/SMM.doc/0.t b/sbin/fsck/SMM.doc/0.t deleted file mode 100644 index 528dd96..0000000 --- a/sbin/fsck/SMM.doc/0.t +++ /dev/null @@ -1,150 +0,0 @@ -.\" Copyright (c) 1986, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)0.t 8.1 (Berkeley) 6/8/93 -.\" -.if n .ND -.TL -Fsck \- The UNIX\(dg File System Check Program -.EH 'SMM:3-%''The \s-2UNIX\s+2 File System Check Program' -.OH 'The \s-2UNIX\s+2 File System Check Program''SMM:3-%' -.AU -Marshall Kirk McKusick -.AI -Computer Systems Research Group -Computer Science Division -Department of Electrical Engineering and Computer Science -University of California, Berkeley -Berkeley, CA 94720 -.AU -T. J. Kowalski -.AI -Bell Laboratories -Murray Hill, New Jersey 07974 -.AB -.FS -\(dgUNIX is a trademark of Bell Laboratories. -.FE -.FS -This work was done under grants from -the National Science Foundation under grant MCS80-05144, -and the Defense Advance Research Projects Agency (DoD) under -Arpa Order No. 4031 monitored by Naval Electronic System Command under -Contract No. N00039-82-C-0235. -.FE -This document reflects the use of -.I fsck -with the 4.2BSD and 4.3BSD file system organization. This -is a revision of the -original paper written by -T. J. Kowalski. -.PP -File System Check Program (\fIfsck\fR) -is an interactive file system check and repair program. -.I Fsck -uses the redundant structural information in the -UNIX file system to perform several consistency checks. -If an inconsistency is detected, it is reported -to the operator, who may elect to fix or ignore -each inconsistency. -These inconsistencies result from the permanent interruption -of the file system updates, which are performed every -time a file is modified. -Unless there has been a hardware failure, -.I fsck -is able to repair corrupted file systems -using procedures based upon the order in which UNIX honors -these file system update requests. -.PP -The purpose of this document is to describe the normal updating -of the file system, -to discuss the possible causes of file system corruption, -and to present the corrective actions implemented -by -.I fsck. -Both the program and the interaction between the -program and the operator are described. -.sp 2 -.LP -Revised October 7, 1996 -.AE -.LP -.bp -.ce -.B "TABLE OF CONTENTS" -.LP -.sp 1 -.nf -.B "1. Introduction" -.LP -.sp .5v -.nf -.B "2. Overview of the file system -2.1. Superblock -2.2. Summary Information -2.3. Cylinder groups -2.4. Fragments -2.5. Updates to the file system -.LP -.sp .5v -.nf -.B "3. Fixing corrupted file systems -3.1. Detecting and correcting corruption -3.2. Super block checking -3.3. Free block checking -3.4. Checking the inode state -3.5. Inode links -3.6. Inode data size -3.7. Checking the data associated with an inode -3.8. File system connectivity -.LP -.sp .5v -.nf -.B Acknowledgements -.LP -.sp .5v -.nf -.B References -.LP -.sp .5v -.nf -.B "4. Appendix A -4.1. Conventions -4.2. Initialization -4.3. Phase 1 - Check Blocks and Sizes -4.4. Phase 1b - Rescan for more Dups -4.5. Phase 2 - Check Pathnames -4.6. Phase 3 - Check Connectivity -4.7. Phase 4 - Check Reference Counts -4.8. Phase 5 - Check Cyl groups -4.9. Cleanup -.ds RH Introduction -.bp diff --git a/sbin/fsck/SMM.doc/1.t b/sbin/fsck/SMM.doc/1.t deleted file mode 100644 index 4d2f535..0000000 --- a/sbin/fsck/SMM.doc/1.t +++ /dev/null @@ -1,83 +0,0 @@ -.\" Copyright (c) 1982, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)1.t 8.1 (Berkeley) 6/5/93 -.\" -.ds RH Introduction -.NH -Introduction -.PP -This document reflects the use of -.I fsck -with the 4.2BSD and 4.3BSD file system organization. This -is a revision of the -original paper written by -T. J. Kowalski. -.PP -When a UNIX -operating system is brought up, a consistency -check of the file systems should always be performed. -This precautionary measure helps to insure -a reliable environment for file storage on disk. -If an inconsistency is discovered, -corrective action must be taken. -.I Fsck -runs in two modes. -Normally it is run non-interactively by the system after -a normal boot. -When running in this mode, -it will only make changes to the file system that are known -to always be correct. -If an unexpected inconsistency is found -.I fsck -will exit with a non-zero exit status, -leaving the system running single-user. -Typically the operator then runs -.I fsck -interactively. -When running in this mode, -each problem is listed followed by a suggested corrective action. -The operator must decide whether or not the suggested correction -should be made. -.PP -The purpose of this memo is to dispel the -mystique surrounding -file system inconsistencies. -It first describes the updating of the file system -(the calm before the storm) and -then describes file system corruption (the storm). -Finally, -the set of deterministic corrective actions -used by -.I fsck -(the Coast Guard -to the rescue) is presented. -.ds RH Overview of the File System diff --git a/sbin/fsck/SMM.doc/2.t b/sbin/fsck/SMM.doc/2.t deleted file mode 100644 index 7d00cea..0000000 --- a/sbin/fsck/SMM.doc/2.t +++ /dev/null @@ -1,265 +0,0 @@ -.\" Copyright (c) 1982, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)2.t 8.1 (Berkeley) 6/5/93 -.\" -.ds RH Overview of the file system -.NH -Overview of the file system -.PP -The file system is discussed in detail in [Mckusick84]; -this section gives a brief overview. -.NH 2 -Superblock -.PP -A file system is described by its -.I "super-block" . -The super-block is built when the file system is created (\c -.I newfs (8)) -and never changes. -The super-block -contains the basic parameters of the file system, -such as the number of data blocks it contains -and a count of the maximum number of files. -Because the super-block contains critical data, -.I newfs -replicates it to protect against catastrophic loss. -The -.I "default super block" -always resides at a fixed offset from the beginning -of the file system's disk partition. -The -.I "redundant super blocks" -are not referenced unless a head crash -or other hard disk error causes the default super-block -to be unusable. -The redundant blocks are sprinkled throughout the disk partition. -.PP -Within the file system are files. -Certain files are distinguished as directories and contain collections -of pointers to files that may themselves be directories. -Every file has a descriptor associated with it called an -.I "inode". -The inode contains information describing ownership of the file, -time stamps indicating modification and access times for the file, -and an array of indices pointing to the data blocks for the file. -In this section, -we assume that the first 12 blocks -of the file are directly referenced by values stored -in the inode structure itself\(dg. -.FS -\(dgThe actual number may vary from system to system, but is usually in -the range 5-13. -.FE -The inode structure may also contain references to indirect blocks -containing further data block indices. -In a file system with a 4096 byte block size, a singly indirect -block contains 1024 further block addresses, -a doubly indirect block contains 1024 addresses of further single indirect -blocks, -and a triply indirect block contains 1024 addresses of further doubly indirect -blocks (the triple indirect block is never needed in practice). -.PP -In order to create files with up to -2\(ua32 bytes, -using only two levels of indirection, -the minimum size of a file system block is 4096 bytes. -The size of file system blocks can be any power of two -greater than or equal to 4096. -The block size of the file system is maintained in the super-block, -so it is possible for file systems of different block sizes -to be accessible simultaneously on the same system. -The block size must be decided when -.I newfs -creates the file system; -the block size cannot be subsequently -changed without rebuilding the file system. -.NH 2 -Summary information -.PP -Associated with the super block is non replicated -.I "summary information" . -The summary information changes -as the file system is modified. -The summary information contains -the number of blocks, fragments, inodes and directories in the file system. -.NH 2 -Cylinder groups -.PP -The file system partitions the disk into one or more areas called -.I "cylinder groups". -A cylinder group is comprised of one or more consecutive -cylinders on a disk. -Each cylinder group includes inode slots for files, a -.I "block map" -describing available blocks in the cylinder group, -and summary information describing the usage of data blocks -within the cylinder group. -A fixed number of inodes is allocated for each cylinder group -when the file system is created. -The current policy is to allocate one inode for each 2048 -bytes of disk space; -this is expected to be far more inodes than will ever be needed. -.PP -All the cylinder group bookkeeping information could be -placed at the beginning of each cylinder group. -However if this approach were used, -all the redundant information would be on the top platter. -A single hardware failure that destroyed the top platter -could cause the loss of all copies of the redundant super-blocks. -Thus the cylinder group bookkeeping information -begins at a floating offset from the beginning of the cylinder group. -The offset for -the -.I "i+1" st -cylinder group is about one track further -from the beginning of the cylinder group -than it was for the -.I "i" th -cylinder group. -In this way, -the redundant -information spirals down into the pack; -any single track, cylinder, -or platter can be lost without losing all copies of the super-blocks. -Except for the first cylinder group, -the space between the beginning of the cylinder group -and the beginning of the cylinder group information stores data. -.NH 2 -Fragments -.PP -To avoid waste in storing small files, -the file system space allocator divides a single -file system block into one or more -.I "fragments". -The fragmentation of the file system is specified -when the file system is created; -each file system block can be optionally broken into -2, 4, or 8 addressable fragments. -The lower bound on the size of these fragments is constrained -by the disk sector size; -typically 512 bytes is the lower bound on fragment size. -The block map associated with each cylinder group -records the space availability at the fragment level. -Aligned fragments are examined -to determine block availability. -.PP -On a file system with a block size of 4096 bytes -and a fragment size of 1024 bytes, -a file is represented by zero or more 4096 byte blocks of data, -and possibly a single fragmented block. -If a file system block must be fragmented to obtain -space for a small amount of data, -the remainder of the block is made available for allocation -to other files. -For example, -consider an 11000 byte file stored on -a 4096/1024 byte file system. -This file uses two full size blocks and a 3072 byte fragment. -If no fragments with at least 3072 bytes -are available when the file is created, -a full size block is split yielding the necessary 3072 byte -fragment and an unused 1024 byte fragment. -This remaining fragment can be allocated to another file, as needed. -.NH 2 -Updates to the file system -.PP -Every working day hundreds of files -are created, modified, and removed. -Every time a file is modified, -the operating system performs a -series of file system updates. -These updates, when written on disk, yield a consistent file system. -The file system stages -all modifications of critical information; -modification can -either be completed or cleanly backed out after a crash. -Knowing the information that is first written to the file system, -deterministic procedures can be developed to -repair a corrupted file system. -To understand this process, -the order that the update -requests were being honored must first be understood. -.PP -When a user program does an operation to change the file system, -such as a -.I write , -the data to be written is copied into an internal -.I "in-core" -buffer in the kernel. -Normally, the disk update is handled asynchronously; -the user process is allowed to proceed even though -the data has not yet been written to the disk. -The data, -along with the inode information reflecting the change, -is eventually written out to disk. -The real disk write may not happen until long after the -.I write -system call has returned. -Thus at any given time, the file system, -as it resides on the disk, -lags the state of the file system represented by the in-core information. -.PP -The disk information is updated to reflect the in-core information -when the buffer is required for another use, -when a -.I sync (2) -is done (at 30 second intervals) by -.I "/etc/update" "(8)," -or by manual operator intervention with the -.I sync (8) -command. -If the system is halted without writing out the in-core information, -the file system on the disk will be in an inconsistent state. -.PP -If all updates are done asynchronously, several serious -inconsistencies can arise. -One inconsistency is that a block may be claimed by two inodes. -Such an inconsistency can occur when the system is halted before -the pointer to the block in the old inode has been cleared -in the copy of the old inode on the disk, -and after the pointer to the block in the new inode has been written out -to the copy of the new inode on the disk. -Here, -there is no deterministic method for deciding -which inode should really claim the block. -A similar problem can arise with a multiply claimed inode. -.PP -The problem with asynchronous inode updates -can be avoided by doing all inode deallocations synchronously. -Consequently, -inodes and indirect blocks are written to the disk synchronously -(\fIi.e.\fP the process blocks until the information is -really written to disk) -when they are being deallocated. -Similarly inodes are kept consistent by synchronously -deleting, adding, or changing directory entries. -.ds RH Fixing corrupted file systems diff --git a/sbin/fsck/SMM.doc/3.t b/sbin/fsck/SMM.doc/3.t deleted file mode 100644 index bb6f05b..0000000 --- a/sbin/fsck/SMM.doc/3.t +++ /dev/null @@ -1,452 +0,0 @@ -.\" Copyright (c) 1982, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)3.t 8.1 (Berkeley) 6/5/93 -.\" -.ds RH Fixing corrupted file systems -.NH -Fixing corrupted file systems -.PP -A file system -can become corrupted in several ways. -The most common of these ways are -improper shutdown procedures -and hardware failures. -.PP -File systems may become corrupted during an -.I "unclean halt" . -This happens when proper shutdown -procedures are not observed, -physically write-protecting a mounted file system, -or a mounted file system is taken off-line. -The most common operator procedural failure is forgetting to -.I sync -the system before halting the CPU. -.PP -File systems may become further corrupted if proper startup -procedures are not observed, e.g., -not checking a file system for inconsistencies, -and not repairing inconsistencies. -Allowing a corrupted file system to be used (and, thus, to be modified -further) can be disastrous. -.PP -Any piece of hardware can fail at any time. -Failures -can be as subtle as a bad block -on a disk pack, or as blatant as a non-functional disk-controller. -.NH 2 -Detecting and correcting corruption -.PP -Normally -.I fsck -is run non-interactively. -In this mode it will only fix -corruptions that are expected to occur from an unclean halt. -These actions are a proper subset of the actions that -.I fsck -will take when it is running interactively. -Throughout this paper we assume that -.I fsck -is being run interactively, -and all possible errors can be encountered. -When an inconsistency is discovered in this mode, -.I fsck -reports the inconsistency for the operator to -chose a corrective action. -.PP -A quiescent\(dd -.FS -\(dd I.e., unmounted and not being written on. -.FE -file system may be checked for structural integrity -by performing consistency checks on the -redundant data intrinsic to a file system. -The redundant data is either read from -the file system, -or computed from other known values. -The file system -.B must -be in a quiescent state when -.I fsck -is run, -since -.I fsck -is a multi-pass program. -.PP -In the following sections, -we discuss methods to discover inconsistencies -and possible corrective actions -for the cylinder group blocks, the inodes, the indirect blocks, and -the data blocks containing directory entries. -.NH 2 -Super-block checking -.PP -The most commonly corrupted item in a file system -is the summary information -associated with the super-block. -The summary information is prone to corruption -because it is modified with every change to the file -system's blocks or inodes, -and is usually corrupted -after an unclean halt. -.PP -The super-block is checked for inconsistencies -involving file-system size, number of inodes, -free-block count, and the free-inode count. -The file-system size must be larger than the -number of blocks used by the super-block -and the number of blocks used by the list of inodes. -The file-system size and layout information -are the most critical pieces of information for -.I fsck . -While there is no way to actually check these sizes, -since they are statically determined by -.I newfs , -.I fsck -can check that these sizes are within reasonable bounds. -All other file system checks require that these sizes be correct. -If -.I fsck -detects corruption in the static parameters of the default super-block, -.I fsck -requests the operator to specify the location of an alternate super-block. -.NH 2 -Free block checking -.PP -.I Fsck -checks that all the blocks -marked as free in the cylinder group block maps -are not claimed by any files. -When all the blocks have been initially accounted for, -.I fsck -checks that -the number of free blocks -plus the number of blocks claimed by the inodes -equals the total number of blocks in the file system. -.PP -If anything is wrong with the block allocation maps, -.I fsck -will rebuild them, -based on the list it has computed of allocated blocks. -.PP -The summary information associated with the super-block -counts the total number of free blocks within the file system. -.I Fsck -compares this count to the -number of free blocks it found within the file system. -If the two counts do not agree, then -.I fsck -replaces the incorrect count in the summary information -by the actual free-block count. -.PP -The summary information -counts the total number of free inodes within the file system. -.I Fsck -compares this count to the number -of free inodes it found within the file system. -If the two counts do not agree, then -.I fsck -replaces the incorrect count in the -summary information by the actual free-inode count. -.NH 2 -Checking the inode state -.PP -An individual inode is not as likely to be corrupted as -the allocation information. -However, because of the great number of active inodes, -a few of the inodes are usually corrupted. -.PP -The list of inodes in the file system -is checked sequentially starting with inode 2 -(inode 0 marks unused inodes; -inode 1 is saved for future generations) -and progressing through the last inode in the file system. -The state of each inode is checked for -inconsistencies involving format and type, -link count, -duplicate blocks, -bad blocks, -and inode size. -.PP -Each inode contains a mode word. -This mode word describes the type and state of the inode. -Inodes must be one of six types: -regular inode, directory inode, symbolic link inode, -special block inode, special character inode, or socket inode. -Inodes may be found in one of three allocation states: -unallocated, allocated, and neither unallocated nor allocated. -This last state suggests an incorrectly formated inode. -An inode can get in this state if -bad data is written into the inode list. -The only possible corrective action is for -.I fsck -is to clear the inode. -.NH 2 -Inode links -.PP -Each inode counts the -total number of directory entries -linked to the inode. -.I Fsck -verifies the link count of each inode -by starting at the root of the file system, -and descending through the directory structure. -The actual link count for each inode -is calculated during the descent. -.PP -If the stored link count is non-zero and the actual -link count is zero, -then no directory entry appears for the inode. -If this happens, -.I fsck -will place the disconnected file in the -.I lost+found -directory. -If the stored and actual link counts are non-zero and unequal, -a directory entry may have been added or removed without the inode being -updated. -If this happens, -.I fsck -replaces the incorrect stored link count by the actual link count. -.PP -Each inode contains a list, -or pointers to -lists (indirect blocks), -of all the blocks claimed by the inode. -Since indirect blocks are owned by an inode, -inconsistencies in indirect blocks directly -affect the inode that owns it. -.PP -.I Fsck -compares each block number claimed by an inode -against a list of already allocated blocks. -If another inode already claims a block number, -then the block number is added to a list of -.I "duplicate blocks" . -Otherwise, the list of allocated blocks -is updated to include the block number. -.PP -If there are any duplicate blocks, -.I fsck -will perform a partial second -pass over the inode list -to find the inode of the duplicated block. -The second pass is needed, -since without examining the files associated with -these inodes for correct content, -not enough information is available -to determine which inode is corrupted and should be cleared. -If this condition does arise -(only hardware failure will cause it), -then the inode with the earliest -modify time is usually incorrect, -and should be cleared. -If this happens, -.I fsck -prompts the operator to clear both inodes. -The operator must decide which one should be kept -and which one should be cleared. -.PP -.I Fsck -checks the range of each block number claimed by an inode. -If the block number is -lower than the first data block in the file system, -or greater than the last data block, -then the block number is a -.I "bad block number" . -Many bad blocks in an inode are usually caused by -an indirect block that was not written to the file system, -a condition which can only occur if there has been a hardware failure. -If an inode contains bad block numbers, -.I fsck -prompts the operator to clear it. -.NH 2 -Inode data size -.PP -Each inode contains a count of the number of data blocks -that it contains. -The number of actual data blocks -is the sum of the allocated data blocks -and the indirect blocks. -.I Fsck -computes the actual number of data blocks -and compares that block count against -the actual number of blocks the inode claims. -If an inode contains an incorrect count -.I fsck -prompts the operator to fix it. -.PP -Each inode contains a thirty-two bit size field. -The size is the number of data bytes -in the file associated with the inode. -The consistency of the byte size field is roughly checked -by computing from the size field the maximum number of blocks -that should be associated with the inode, -and comparing that expected block count against -the actual number of blocks the inode claims. -.NH 2 -Checking the data associated with an inode -.PP -An inode can directly or indirectly -reference three kinds of data blocks. -All referenced blocks must be the same kind. -The three types of data blocks are: -plain data blocks, symbolic link data blocks, and directory data blocks. -Plain data blocks -contain the information stored in a file; -symbolic link data blocks -contain the path name stored in a link. -Directory data blocks contain directory entries. -.I Fsck -can only check the validity of directory data blocks. -.PP -Each directory data block is checked for -several types of inconsistencies. -These inconsistencies include -directory inode numbers pointing to unallocated inodes, -directory inode numbers that are greater than -the number of inodes in the file system, -incorrect directory inode numbers for ``\fB.\fP'' and ``\fB..\fP'', -and directories that are not attached to the file system. -If the inode number in a directory data block -references an unallocated inode, -then -.I fsck -will remove that directory entry. -Again, -this condition can only arise when there has been a hardware failure. -.PP -.I Fsck -also checks for directories with unallocated blocks (holes). -Such directories should never be created. -When found, -.I fsck -will prompt the user to adjust the length of the offending directory -which is done by shortening the size of the directory to the end of the -last allocated block preceeding the hole. -Unfortunately, this means that another Phase 1 run has to be done. -.I Fsck -will remind the user to rerun fsck after repairing a -directory containing an unallocated block. -.PP -If a directory entry inode number references -outside the inode list, then -.I fsck -will remove that directory entry. -This condition occurs if bad data is written into a directory data block. -.PP -The directory inode number entry for ``\fB.\fP'' -must be the first entry in the directory data block. -The inode number for ``\fB.\fP'' -must reference itself; -e.g., it must equal the inode number -for the directory data block. -The directory inode number entry -for ``\fB..\fP'' must be -the second entry in the directory data block. -Its value must equal the inode number for the -parent of the directory entry -(or the inode number of the directory -data block if the directory is the -root directory). -If the directory inode numbers are -incorrect, -.I fsck -will replace them with the correct values. -If there are multiple hard links to a directory, -the first one encountered is considered the real parent -to which ``\fB..\fP'' should point; -\fIfsck\fP recommends deletion for the subsequently discovered names. -.NH 2 -File system connectivity -.PP -.I Fsck -checks the general connectivity of the file system. -If directories are not linked into the file system, then -.I fsck -links the directory back into the file system in the -.I lost+found -directory. -This condition only occurs when there has been a hardware failure. -.ds RH "References" -.SH -\s+2Acknowledgements\s0 -.PP -I thank Bill Joy, Sam Leffler, Robert Elz and Dennis Ritchie -for their suggestions and help in implementing the new file system. -Thanks also to Robert Henry for his editorial input to -get this document together. -Finally we thank our sponsors, -the National Science Foundation under grant MCS80-05144, -and the Defense Advance Research Projects Agency (DoD) under -Arpa Order No. 4031 monitored by Naval Electronic System Command under -Contract No. N00039-82-C-0235. (Kirk McKusick, July 1983) -.PP -I would like to thank Larry A. Wehr for advice that lead -to the first version of -.I fsck -and Rick B. Brandt for adapting -.I fsck -to -UNIX/TS. (T. Kowalski, July 1979) -.sp 2 -.SH -\s+2References\s0 -.LP -.IP [Dolotta78] 20 -Dolotta, T. A., and Olsson, S. B. eds., -.I "UNIX User's Manual, Edition 1.1\^" , -January 1978. -.IP [Joy83] 20 -Joy, W., Cooper, E., Fabry, R., Leffler, S., McKusick, M., and Mosher, D. -4.2BSD System Manual, -.I "University of California at Berkeley" , -.I "Computer Systems Research Group Technical Report" -#4, 1982. -.IP [McKusick84] 20 -McKusick, M., Joy, W., Leffler, S., and Fabry, R. -A Fast File System for UNIX, -\fIACM Transactions on Computer Systems 2\fP, 3. -pp. 181-197, August 1984. -.IP [Ritchie78] 20 -Ritchie, D. M., and Thompson, K., -The UNIX Time-Sharing System, -.I "The Bell System Technical Journal" -.B 57 , -6 (July-August 1978, Part 2), pp. 1905-29. -.IP [Thompson78] 20 -Thompson, K., -UNIX Implementation, -.I "The Bell System Technical Journal\^" -.B 57 , -6 (July-August 1978, Part 2), pp. 1931-46. -.ds RH Appendix A \- Fsck Error Conditions -.bp diff --git a/sbin/fsck/SMM.doc/4.t b/sbin/fsck/SMM.doc/4.t deleted file mode 100644 index 5ea8179..0000000 --- a/sbin/fsck/SMM.doc/4.t +++ /dev/null @@ -1,1424 +0,0 @@ -.\" Copyright (c) 1982, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)4.t 8.1 (Berkeley) 6/5/93 -.\" -.ds RH Appendix A \- Fsck Error Conditions -.NH -Appendix A \- Fsck Error Conditions -.NH 2 -Conventions -.PP -.I Fsck -is -a multi-pass file system check program. -Each file system pass invokes a different Phase of the -.I fsck -program. -After the initial setup, -.I fsck -performs successive Phases over each file system, -checking blocks and sizes, -path-names, -connectivity, -reference counts, -and the map of free blocks, -(possibly rebuilding it), -and performs some cleanup. -.LP -Normally -.I fsck -is run non-interactively to -.I preen -the file systems after an unclean halt. -While preen'ing a file system, -it will only fix corruptions that are expected -to occur from an unclean halt. -These actions are a proper subset of the actions that -.I fsck -will take when it is running interactively. -Throughout this appendix many errors have several options -that the operator can take. -When an inconsistency is detected, -.I fsck -reports the error condition to the operator. -If a response is required, -.I fsck -prints a prompt message and -waits for a response. -When preen'ing most errors are fatal. -For those that are expected, -the response taken is noted. -This appendix explains the meaning of each error condition, -the possible responses, and the related error conditions. -.LP -The error conditions are organized by the -.I Phase -of the -.I fsck -program in which they can occur. -The error conditions that may occur -in more than one Phase -will be discussed in initialization. -.NH 2 -Initialization -.PP -Before a file system check can be performed, certain -tables have to be set up and certain files opened. -This section concerns itself with the opening of files and -the initialization of tables. -This section lists error conditions resulting from -command line options, -memory requests, -opening of files, -status of files, -file system size checks, -and creation of the scratch file. -All the initialization errors are fatal -when the file system is being preen'ed. -.sp -.LP -.B "\fIC\fP option?" -.br -\fIC\fP is not a legal option to -.I fsck ; -legal options are \-b, \-c, \-y, \-n, and \-p. -.I Fsck -terminates on this error condition. -See the -.I fsck (8) -manual entry for further detail. -.sp -.LP -.B "cannot alloc NNN bytes for blockmap" -.br -.B "cannot alloc NNN bytes for freemap" -.br -.B "cannot alloc NNN bytes for statemap" -.br -.B "cannot alloc NNN bytes for lncntp" -.br -.I Fsck 's -request for memory for its virtual -memory tables failed. -This should never happen. -.I Fsck -terminates on this error condition. -See a guru. -.sp -.LP -.B "Can't open checklist file: \fIF\fP" -.br -The file system checklist file -\fIF\fP (usually -.I /etc/fstab ) -can not be opened for reading. -.I Fsck -terminates on this error condition. -Check access modes of \fIF\fP. -.sp -.LP -.B "Can't stat root" -.br -.I Fsck 's -request for statistics about the root directory ``/'' failed. -This should never happen. -.I Fsck -terminates on this error condition. -See a guru. -.sp -.LP -.B "Can't stat \fIF\fP" -.br -.B "Can't make sense out of name \fIF\fP" -.br -.I Fsck 's -request for statistics about the file system \fIF\fP failed. -When running manually, -it ignores this file system -and continues checking the next file system given. -Check access modes of \fIF\fP. -.sp -.LP -.B "Can't open \fIF\fP" -.br -.I Fsck 's -request attempt to open the file system \fIF\fP failed. -When running manually, it ignores this file system -and continues checking the next file system given. -Check access modes of \fIF\fP. -.sp -.LP -.B "\fIF\fP: (NO WRITE)" -.br -Either the \-n flag was specified or -.I fsck 's -attempt to open the file system \fIF\fP for writing failed. -When running manually, -all the diagnostics are printed out, -but no modifications are attempted to fix them. -.sp -.LP -.B "file is not a block or character device; OK" -.br -You have given -.I fsck -a regular file name by mistake. -Check the type of the file specified. -.LP -Possible responses to the OK prompt are: -.IP YES -ignore this error condition. -.IP NO -ignore this file system and continues checking -the next file system given. -.sp -.LP -.B "UNDEFINED OPTIMIZATION IN SUPERBLOCK (SET TO DEFAULT)" -.br -The superblock optimization parameter is neither OPT_TIME -nor OPT_SPACE. -.LP -Possible responses to the SET TO DEFAULT prompt are: -.IP YES -The superblock is set to request optimization to minimize -running time of the system. -(If optimization to minimize disk space utilization is -desired, it can be set using \fItunefs\fP(8).) -.IP NO -ignore this error condition. -.sp -.LP -.B "IMPOSSIBLE MINFREE=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)" -.br -The superblock minimum space percentage is greater than 99% -or less then 0%. -.LP -Possible responses to the SET TO DEFAULT prompt are: -.IP YES -The minfree parameter is set to 10%. -(If some other percentage is desired, -it can be set using \fItunefs\fP(8).) -.IP NO -ignore this error condition. -.sp -.LP -.B "IMPOSSIBLE INTERLEAVE=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)" -.br -The file system interleave is less than or equal to zero. -.LP -Possible responses to the SET TO DEFAULT prompt are: -.IP YES -The interleave parameter is set to 1. -.IP NO -ignore this error condition. -.sp -.LP -.B "IMPOSSIBLE NPSECT=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)" -.br -The number of physical sectors per track is less than the number -of usable sectors per track. -.LP -Possible responses to the SET TO DEFAULT prompt are: -.IP YES -The npsect parameter is set to the number of usable sectors per track. -.IP NO -ignore this error condition. -.sp -.LP -One of the following messages will appear: -.br -.B "MAGIC NUMBER WRONG" -.br -.B "NCG OUT OF RANGE" -.br -.B "CPG OUT OF RANGE" -.br -.B "NCYL DOES NOT JIVE WITH NCG*CPG" -.br -.B "SIZE PREPOSTEROUSLY LARGE" -.br -.B "TRASHED VALUES IN SUPER BLOCK" -.br -and will be followed by the message: -.br -.B "\fIF\fP: BAD SUPER BLOCK: \fIB\fP" -.br -.B "USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE" -.br -.B "SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8)." -.br -The super block has been corrupted. -An alternative super block must be selected from among those -listed by -.I newfs -(8) when the file system was created. -For file systems with a blocksize less than 32K, -specifying \-b 32 is a good first choice. -.sp -.LP -.B "INTERNAL INCONSISTENCY: \fIM\fP" -.br -.I Fsck 's -has had an internal panic, whose message is specified as \fIM\fP. -This should never happen. -See a guru. -.sp -.LP -.B "CAN NOT SEEK: BLK \fIB\fP (CONTINUE)" -.br -.I Fsck 's -request for moving to a specified block number \fIB\fP in -the file system failed. -This should never happen. -See a guru. -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -attempt to continue to run the file system check. -Often, -however the problem will persist. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -If the block was part of the virtual memory buffer -cache, -.I fsck -will terminate with the message ``Fatal I/O error''. -.IP NO -terminate the program. -.sp -.LP -.B "CAN NOT READ: BLK \fIB\fP (CONTINUE)" -.br -.I Fsck 's -request for reading a specified block number \fIB\fP in -the file system failed. -This should never happen. -See a guru. -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -attempt to continue to run the file system check. -It will retry the read and print out the message: -.br -.B "THE FOLLOWING SECTORS COULD NOT BE READ: \fIN\fP" -.br -where \fIN\fP indicates the sectors that could not be read. -If -.I fsck -ever tries to write back one of the blocks on which the read failed -it will print the message: -.br -.B "WRITING ZERO'ED BLOCK \fIN\fP TO DISK" -.br -where \fIN\fP indicates the sector that was written with zero's. -If the disk is experiencing hardware problems, the problem will persist. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -If the block was part of the virtual memory buffer -cache, -.I fsck -will terminate with the message ``Fatal I/O error''. -.IP NO -terminate the program. -.sp -.LP -.B "CAN NOT WRITE: BLK \fIB\fP (CONTINUE)" -.br -.I Fsck 's -request for writing a specified block number \fIB\fP -in the file system failed. -The disk is write-protected; -check the write protect lock on the drive. -If that is not the problem, see a guru. -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -attempt to continue to run the file system check. -The write operation will be retried with the failed blocks -indicated by the message: -.br -.B "THE FOLLOWING SECTORS COULD NOT BE WRITTEN: \fIN\fP" -.br -where \fIN\fP indicates the sectors that could not be written. -If the disk is experiencing hardware problems, the problem will persist. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -If the block was part of the virtual memory buffer -cache, -.I fsck -will terminate with the message ``Fatal I/O error''. -.IP NO -terminate the program. -.sp -.LP -.B "bad inode number DDD to ginode" -.br -An internal error has attempted to read non-existent inode \fIDDD\fP. -This error causes -.I fsck -to exit. -See a guru. -.NH 2 -Phase 1 \- Check Blocks and Sizes -.PP -This phase concerns itself with -the inode list. -This section lists error conditions resulting from -checking inode types, -setting up the zero-link-count table, -examining inode block numbers for bad or duplicate blocks, -checking inode size, -and checking inode format. -All errors in this phase except -.B "INCORRECT BLOCK COUNT" -and -.B "PARTIALLY TRUNCATED INODE" -are fatal if the file system is being preen'ed. -.sp -.LP -.B "UNKNOWN FILE TYPE I=\fII\fP (CLEAR)" -.br -The mode word of the inode \fII\fP indicates that the inode is not a -special block inode, special character inode, socket inode, regular inode, -symbolic link, or directory inode. -.LP -Possible responses to the CLEAR prompt are: -.IP YES -de-allocate inode \fII\fP by zeroing its contents. -This will always invoke the UNALLOCATED error condition in Phase 2 -for each directory entry pointing to this inode. -.IP NO -ignore this error condition. -.sp -.LP -.B "PARTIALLY TRUNCATED INODE I=\fII\fP (SALVAGE)" -.br -.I Fsck -has found inode \fII\fP whose size is shorter than the number of -blocks allocated to it. -This condition should only occur if the system crashes while in the -midst of truncating a file. -When preen'ing the file system, -.I fsck -completes the truncation to the specified size. -.LP -Possible responses to SALVAGE are: -.IP YES -complete the truncation to the size specified in the inode. -.IP NO -ignore this error condition. -.sp -.LP -.B "LINK COUNT TABLE OVERFLOW (CONTINUE)" -.br -An internal table for -.I fsck -containing allocated inodes with a link count of -zero cannot allocate more memory. -Increase the virtual memory for -.I fsck . -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -continue with the program. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -If another allocated inode with a zero link count is found, -this error condition is repeated. -.IP NO -terminate the program. -.sp -.LP -.B "\fIB\fP BAD I=\fII\fP" -.br -Inode \fII\fP contains block number \fIB\fP with a number -lower than the number of the first data block in the file system or -greater than the number of the last block -in the file system. -This error condition may invoke the -.B "EXCESSIVE BAD BLKS" -error condition in Phase 1 (see next paragraph) if -inode \fII\fP has too many block numbers outside the file system range. -This error condition will always invoke the -.B "BAD/DUP" -error condition in Phase 2 and Phase 4. -.sp -.LP -.B "EXCESSIVE BAD BLKS I=\fII\fP (CONTINUE)" -.br -There is more than a tolerable number (usually 10) of blocks with a number -lower than the number of the first data block in the file system or greater than -the number of last block in the file system associated with inode \fII\fP. -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -ignore the rest of the blocks in this inode -and continue checking with the next inode in the file system. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -.IP NO -terminate the program. -.sp -.LP -.B "BAD STATE DDD TO BLKERR" -.br -An internal error has scrambled -.I fsck 's -state map to have the impossible value \fIDDD\fP. -.I Fsck -exits immediately. -See a guru. -.sp -.LP -.B "\fIB\fP DUP I=\fII\fP" -.br -Inode \fII\fP contains block number \fIB\fP that is already claimed by -another inode. -This error condition may invoke the -.B "EXCESSIVE DUP BLKS" -error condition in Phase 1 if -inode \fII\fP has too many block numbers claimed by other inodes. -This error condition will always invoke Phase 1b and the -.B "BAD/DUP" -error condition in Phase 2 and Phase 4. -.sp -.LP -.B "EXCESSIVE DUP BLKS I=\fII\fP (CONTINUE)" -.br -There is more than a tolerable number (usually 10) of blocks claimed by other -inodes. -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -ignore the rest of the blocks in this inode -and continue checking with the next inode in the file system. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -.IP NO -terminate the program. -.sp -.LP -.B "DUP TABLE OVERFLOW (CONTINUE)" -.br -An internal table in -.I fsck -containing duplicate block numbers cannot allocate any more space. -Increase the amount of virtual memory available to -.I fsck . -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -continue with the program. -This error condition will not allow a complete check of the file system. -A second run of -.I fsck -should be made to re-check this file system. -If another duplicate block is found, this error condition will repeat. -.IP NO -terminate the program. -.sp -.LP -.B "PARTIALLY ALLOCATED INODE I=\fII\fP (CLEAR)" -.br -Inode \fII\fP is neither allocated nor unallocated. -.LP -Possible responses to the CLEAR prompt are: -.IP YES -de-allocate inode \fII\fP by zeroing its contents. -.IP NO -ignore this error condition. -.sp -.LP -.B "INCORRECT BLOCK COUNT I=\fII\fP (\fIX\fP should be \fIY\fP) (CORRECT)" -.br -The block count for inode \fII\fP is \fIX\fP blocks, -but should be \fIY\fP blocks. -When preen'ing the count is corrected. -.LP -Possible responses to the CORRECT prompt are: -.IP YES -replace the block count of inode \fII\fP with \fIY\fP. -.IP NO -ignore this error condition. -.NH 2 -Phase 1B: Rescan for More Dups -.PP -When a duplicate block is found in the file system, the file system is -rescanned to find the inode that previously claimed that block. -This section lists the error condition when the duplicate block is found. -.sp -.LP -.B "\fIB\fP DUP I=\fII\fP" -.br -Inode \fII\fP contains block number \fIB\fP that -is already claimed by another inode. -This error condition will always invoke the -.B "BAD/DUP" -error condition in Phase 2. -You can determine which inodes have overlapping blocks by examining -this error condition and the DUP error condition in Phase 1. -.NH 2 -Phase 2 \- Check Pathnames -.PP -This phase concerns itself with removing directory entries -pointing to -error conditioned inodes -from Phase 1 and Phase 1b. -This section lists error conditions resulting from -root inode mode and status, -directory inode pointers in range, -and directory entries pointing to bad inodes, -and directory integrity checks. -All errors in this phase are fatal if the file system is being preen'ed, -except for directories not being a multiple of the blocks size -and extraneous hard links. -.sp -.LP -.B "ROOT INODE UNALLOCATED (ALLOCATE)" -.br -The root inode (usually inode number 2) has no allocate mode bits. -This should never happen. -.LP -Possible responses to the ALLOCATE prompt are: -.IP YES -allocate inode 2 as the root inode. -The files and directories usually found in the root will be recovered -in Phase 3 and put into -.I lost+found . -If the attempt to allocate the root fails, -.I fsck -will exit with the message: -.br -.B "CANNOT ALLOCATE ROOT INODE" . -.IP NO -.I fsck -will exit. -.sp -.LP -.B "ROOT INODE NOT DIRECTORY (REALLOCATE)" -.br -The root inode (usually inode number 2) -is not directory inode type. -.LP -Possible responses to the REALLOCATE prompt are: -.IP YES -clear the existing contents of the root inode -and reallocate it. -The files and directories usually found in the root will be recovered -in Phase 3 and put into -.I lost+found . -If the attempt to allocate the root fails, -.I fsck -will exit with the message: -.br -.B "CANNOT ALLOCATE ROOT INODE" . -.IP NO -.I fsck -will then prompt with -.B "FIX" -.LP -Possible responses to the FIX prompt are: -.IP YES -replace the root inode's type to be a directory. -If the root inode's data blocks are not directory blocks, -many error conditions will be produced. -.IP NO -terminate the program. -.sp -.LP -.B "DUPS/BAD IN ROOT INODE (REALLOCATE)" -.br -Phase 1 or Phase 1b have found duplicate blocks -or bad blocks in the root inode (usually inode number 2) for the file system. -.LP -Possible responses to the REALLOCATE prompt are: -.IP YES -clear the existing contents of the root inode -and reallocate it. -The files and directories usually found in the root will be recovered -in Phase 3 and put into -.I lost+found . -If the attempt to allocate the root fails, -.I fsck -will exit with the message: -.br -.B "CANNOT ALLOCATE ROOT INODE" . -.IP NO -.I fsck -will then prompt with -.B "CONTINUE" . -.LP -Possible responses to the CONTINUE prompt are: -.IP YES -ignore the -.B "DUPS/BAD" -error condition in the root inode and -attempt to continue to run the file system check. -If the root inode is not correct, -then this may result in many other error conditions. -.IP NO -terminate the program. -.sp -.LP -.B "NAME TOO LONG \fIF\fP" -.br -An excessively long path name has been found. -This usually indicates loops in the file system name space. -This can occur if the super user has made circular links to directories. -The offending links must be removed (by a guru). -.sp -.LP -.B "I OUT OF RANGE I=\fII\fP NAME=\fIF\fP (REMOVE)" -.br -A directory entry \fIF\fP has an inode number \fII\fP that is greater than -the end of the inode list. -.LP -Possible responses to the REMOVE prompt are: -.IP YES -the directory entry \fIF\fP is removed. -.IP NO -ignore this error condition. -.sp -.LP -.B "UNALLOCATED I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP \fItype\fP=\fIF\fP (REMOVE)" -.br -A directory or file entry \fIF\fP points to an unallocated inode \fII\fP. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP, -and name \fIF\fP are printed. -.LP -Possible responses to the REMOVE prompt are: -.IP YES -the directory entry \fIF\fP is removed. -.IP NO -ignore this error condition. -.sp -.LP -.B "DUP/BAD I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP \fItype\fP=\fIF\fP (REMOVE)" -.br -Phase 1 or Phase 1b have found duplicate blocks or bad blocks -associated with directory or file entry \fIF\fP, inode \fII\fP. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP, -and directory name \fIF\fP are printed. -.LP -Possible responses to the REMOVE prompt are: -.IP YES -the directory entry \fIF\fP is removed. -.IP NO -ignore this error condition. -.sp -.LP -.B "ZERO LENGTH DIRECTORY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (REMOVE)" -.br -A directory entry \fIF\fP has a size \fIS\fP that is zero. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP, -and directory name \fIF\fP are printed. -.LP -Possible responses to the REMOVE prompt are: -.IP YES -the directory entry \fIF\fP is removed; -this will always invoke the BAD/DUP error condition in Phase 4. -.IP NO -ignore this error condition. -.sp -.LP -.B "DIRECTORY TOO SHORT I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fIF\fP has been found whose size \fIS\fP -is less than the minimum size directory. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP, -and directory name \fIF\fP are printed. -.LP -Possible responses to the FIX prompt are: -.IP YES -increase the size of the directory to the minimum directory size. -.IP NO -ignore this directory. -.sp -.LP -.B "DIRECTORY \fIF\fP LENGTH \fIS\fP NOT MULTIPLE OF \fIB\fP (ADJUST) -.br -A directory \fIF\fP has been found with size \fIS\fP that is not -a multiple of the directory blocksize \fIB\fP. -.LP -Possible responses to the ADJUST prompt are: -.IP YES -the length is rounded up to the appropriate block size. -This error can occur on 4.2BSD file systems. -Thus when preen'ing the file system only a warning is printed -and the directory is adjusted. -.IP NO -ignore the error condition. -.sp -.LP -.B "DIRECTORY CORRUPTED I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (SALVAGE)" -.br -A directory with an inconsistent internal state has been found. -.LP -Possible responses to the FIX prompt are: -.IP YES -throw away all entries up to the next directory boundary (usually 512-byte) -boundary. -This drastic action can throw away up to 42 entries, -and should be taken only after other recovery efforts have failed. -.IP NO -skip up to the next directory boundary and resume reading, -but do not modify the directory. -.sp -.LP -.B "BAD INODE NUMBER FOR `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found whose inode number for `.' does -does not equal \fII\fP. -.LP -Possible responses to the FIX prompt are: -.IP YES -change the inode number for `.' to be equal to \fII\fP. -.IP NO -leave the inode number for `.' unchanged. -.sp -.LP -.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found whose first entry is unallocated. -.LP -Possible responses to the FIX prompt are: -.IP YES -build an entry for `.' with inode number equal to \fII\fP. -.IP NO -leave the directory unchanged. -.sp -.LP -.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP" -.br -.B "CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS \fIF\fP" -.br -A directory \fII\fP has been found whose first entry is \fIF\fP. -.I Fsck -cannot resolve this problem. -The file system should be mounted and the offending entry \fIF\fP -moved elsewhere. -The file system should then be unmounted and -.I fsck -should be run again. -.sp -.LP -.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP" -.br -.B "CANNOT FIX, INSUFFICIENT SPACE TO ADD `.'" -.br -A directory \fII\fP has been found whose first entry is not `.'. -.I Fsck -cannot resolve this problem as it should never happen. -See a guru. -.sp -.LP -.B "EXTRA `.' ENTRY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found that has more than one entry for `.'. -.LP -Possible responses to the FIX prompt are: -.IP YES -remove the extra entry for `.'. -.IP NO -leave the directory unchanged. -.sp -.LP -.B "BAD INODE NUMBER FOR `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found whose inode number for `..' does -does not equal the parent of \fII\fP. -.LP -Possible responses to the FIX prompt are: -.IP YES -change the inode number for `..' to be equal to the parent of \fII\fP -(``\fB..\fP'' in the root inode points to itself). -.IP NO -leave the inode number for `..' unchanged. -.sp -.LP -.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found whose second entry is unallocated. -.LP -Possible responses to the FIX prompt are: -.IP YES -build an entry for `..' with inode number equal to the parent of \fII\fP -(``\fB..\fP'' in the root inode points to itself). -.IP NO -leave the directory unchanged. -.sp -.LP -.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP" -.br -.B "CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS \fIF\fP" -.br -A directory \fII\fP has been found whose second entry is \fIF\fP. -.I Fsck -cannot resolve this problem. -The file system should be mounted and the offending entry \fIF\fP -moved elsewhere. -The file system should then be unmounted and -.I fsck -should be run again. -.sp -.LP -.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP" -.br -.B "CANNOT FIX, INSUFFICIENT SPACE TO ADD `..'" -.br -A directory \fII\fP has been found whose second entry is not `..'. -.I Fsck -cannot resolve this problem. -The file system should be mounted and the second entry in the directory -moved elsewhere. -The file system should then be unmounted and -.I fsck -should be run again. -.sp -.LP -.B "EXTRA `..' ENTRY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)" -.br -A directory \fII\fP has been found that has more than one entry for `..'. -.LP -Possible responses to the FIX prompt are: -.IP YES -remove the extra entry for `..'. -.IP NO -leave the directory unchanged. -.sp -.LP -.B "\fIN\fP IS AN EXTRANEOUS HARD LINK TO A DIRECTORY \fID\fP (REMOVE) -.br -.I Fsck -has found a hard link, \fIN\fP, to a directory, \fID\fP. -When preen'ing the extraneous links are ignored. -.LP -Possible responses to the REMOVE prompt are: -.IP YES -delete the extraneous entry, \fIN\fP. -.IP NO -ignore the error condition. -.sp -.LP -.B "BAD INODE \fIS\fP TO DESCEND" -.br -An internal error has caused an impossible state \fIS\fP to be passed to the -routine that descends the file system directory structure. -.I Fsck -exits. -See a guru. -.sp -.LP -.B "BAD RETURN STATE \fIS\fP FROM DESCEND" -.br -An internal error has caused an impossible state \fIS\fP to be returned -from the routine that descends the file system directory structure. -.I Fsck -exits. -See a guru. -.sp -.LP -.B "BAD STATE \fIS\fP FOR ROOT INODE" -.br -An internal error has caused an impossible state \fIS\fP to be assigned -to the root inode. -.I Fsck -exits. -See a guru. -.NH 2 -Phase 3 \- Check Connectivity -.PP -This phase concerns itself with the directory connectivity seen in -Phase 2. -This section lists error conditions resulting from -unreferenced directories, -and missing or full -.I lost+found -directories. -.sp -.LP -.B "UNREF DIR I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (RECONNECT)" -.br -The directory inode \fII\fP was not connected to a directory entry -when the file system was traversed. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and -modify time \fIT\fP of directory inode \fII\fP are printed. -When preen'ing, the directory is reconnected if its size is non-zero, -otherwise it is cleared. -.LP -Possible responses to the RECONNECT prompt are: -.IP YES -reconnect directory inode \fII\fP to the file system in the -directory for lost files (usually \fIlost+found\fP). -This may invoke the -.I lost+found -error condition in Phase 3 -if there are problems connecting directory inode \fII\fP to \fIlost+found\fP. -This may also invoke the CONNECTED error condition in Phase 3 if the link -was successful. -.IP NO -ignore this error condition. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "NO lost+found DIRECTORY (CREATE)" -.br -There is no -.I lost+found -directory in the root directory of the file system; -When preen'ing -.I fsck -tries to create a \fIlost+found\fP directory. -.LP -Possible responses to the CREATE prompt are: -.IP YES -create a \fIlost+found\fP directory in the root of the file system. -This may raise the message: -.br -.B "NO SPACE LEFT IN / (EXPAND)" -.br -See below for the possible responses. -Inability to create a \fIlost+found\fP directory generates the message: -.br -.B "SORRY. CANNOT CREATE lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "lost+found IS NOT A DIRECTORY (REALLOCATE)" -.br -The entry for -.I lost+found -is not a directory. -.LP -Possible responses to the REALLOCATE prompt are: -.IP YES -allocate a directory inode, and change \fIlost+found\fP to reference it. -The previous inode reference by the \fIlost+found\fP name is not cleared. -Thus it will either be reclaimed as an UNREF'ed inode or have its -link count ADJUST'ed later in this Phase. -Inability to create a \fIlost+found\fP directory generates the message: -.br -.B "SORRY. CANNOT CREATE lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "NO SPACE LEFT IN /lost+found (EXPAND)" -.br -There is no space to add another entry to the -.I lost+found -directory in the root directory -of the file system. -When preen'ing the -.I lost+found -directory is expanded. -.LP -Possible responses to the EXPAND prompt are: -.IP YES -the -.I lost+found -directory is expanded to make room for the new entry. -If the attempted expansion fails -.I fsck -prints the message: -.br -.B "SORRY. NO SPACE IN lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -Clean out unnecessary entries in -.I lost+found . -This error is fatal if the file system is being preen'ed. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "DIR I=\fII1\fP CONNECTED. PARENT WAS I=\fII2\fP" -.br -This is an advisory message indicating a directory inode \fII1\fP was -successfully connected to the -.I lost+found -directory. -The parent inode \fII2\fP of the directory inode \fII1\fP is -replaced by the inode number of the -.I lost+found -directory. -.sp -.LP -.B "DIRECTORY \fIF\fP LENGTH \fIS\fP NOT MULTIPLE OF \fIB\fP (ADJUST) -.br -A directory \fIF\fP has been found with size \fIS\fP that is not -a multiple of the directory blocksize \fIB\fP -(this can reoccur in Phase 3 if it is not adjusted in Phase 2). -.LP -Possible responses to the ADJUST prompt are: -.IP YES -the length is rounded up to the appropriate block size. -This error can occur on 4.2BSD file systems. -Thus when preen'ing the file system only a warning is printed -and the directory is adjusted. -.IP NO -ignore the error condition. -.sp -.LP -.B "BAD INODE \fIS\fP TO DESCEND" -.br -An internal error has caused an impossible state \fIS\fP to be passed to the -routine that descends the file system directory structure. -.I Fsck -exits. -See a guru. -.NH 2 -Phase 4 \- Check Reference Counts -.PP -This phase concerns itself with the link count information -seen in Phase 2 and Phase 3. -This section lists error conditions resulting from -unreferenced files, -missing or full -.I lost+found -directory, -incorrect link counts for files, directories, symbolic links, or special files, -unreferenced files, symbolic links, and directories, -and bad or duplicate blocks in files, symbolic links, and directories. -All errors in this phase are correctable if the file system is being preen'ed -except running out of space in the \fIlost+found\fP directory. -.sp -.LP -.B "UNREF FILE I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (RECONNECT)" -.br -Inode \fII\fP was not connected to a directory entry -when the file system was traversed. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and -modify time \fIT\fP of inode \fII\fP are printed. -When preen'ing the file is cleared if either its size or its -link count is zero, -otherwise it is reconnected. -.LP -Possible responses to the RECONNECT prompt are: -.IP YES -reconnect inode \fII\fP to the file system in the directory for -lost files (usually \fIlost+found\fP). -This may invoke the -.I lost+found -error condition in Phase 4 -if there are problems connecting inode \fII\fP to -.I lost+found . -.IP NO -ignore this error condition. -This will always invoke the CLEAR error condition in Phase 4. -.sp -.LP -.B "(CLEAR)" -.br -The inode mentioned in the immediately previous error condition can not be -reconnected. -This cannot occur if the file system is being preen'ed, -since lack of space to reconnect files is a fatal error. -.LP -Possible responses to the CLEAR prompt are: -.IP YES -de-allocate the inode mentioned in the immediately previous error condition by zeroing its contents. -.IP NO -ignore this error condition. -.sp -.LP -.B "NO lost+found DIRECTORY (CREATE)" -.br -There is no -.I lost+found -directory in the root directory of the file system; -When preen'ing -.I fsck -tries to create a \fIlost+found\fP directory. -.LP -Possible responses to the CREATE prompt are: -.IP YES -create a \fIlost+found\fP directory in the root of the file system. -This may raise the message: -.br -.B "NO SPACE LEFT IN / (EXPAND)" -.br -See below for the possible responses. -Inability to create a \fIlost+found\fP directory generates the message: -.br -.B "SORRY. CANNOT CREATE lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "lost+found IS NOT A DIRECTORY (REALLOCATE)" -.br -The entry for -.I lost+found -is not a directory. -.LP -Possible responses to the REALLOCATE prompt are: -.IP YES -allocate a directory inode, and change \fIlost+found\fP to reference it. -The previous inode reference by the \fIlost+found\fP name is not cleared. -Thus it will either be reclaimed as an UNREF'ed inode or have its -link count ADJUST'ed later in this Phase. -Inability to create a \fIlost+found\fP directory generates the message: -.br -.B "SORRY. CANNOT CREATE lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "NO SPACE LEFT IN /lost+found (EXPAND)" -.br -There is no space to add another entry to the -.I lost+found -directory in the root directory -of the file system. -When preen'ing the -.I lost+found -directory is expanded. -.LP -Possible responses to the EXPAND prompt are: -.IP YES -the -.I lost+found -directory is expanded to make room for the new entry. -If the attempted expansion fails -.I fsck -prints the message: -.br -.B "SORRY. NO SPACE IN lost+found DIRECTORY" -.br -and aborts the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -Clean out unnecessary entries in -.I lost+found . -This error is fatal if the file system is being preen'ed. -.IP NO -abort the attempt to linkup the lost inode. -This will always invoke the UNREF error condition in Phase 4. -.sp -.LP -.B "LINK COUNT \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP COUNT=\fIX\fP SHOULD BE \fIY\fP (ADJUST)" -.br -The link count for inode \fII\fP, -is \fIX\fP but should be \fIY\fP. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and modify time \fIT\fP -are printed. -When preen'ing the link count is adjusted unless the number of references -is increasing, a condition that should never occur unless precipitated -by a hardware failure. -When the number of references is increasing under preen mode, -.I fsck -exits with the message: -.br -.B "LINK COUNT INCREASING" -.LP -Possible responses to the ADJUST prompt are: -.IP YES -replace the link count of file inode \fII\fP with \fIY\fP. -.IP NO -ignore this error condition. -.sp -.LP -.B "UNREF \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (CLEAR)" -.br -Inode \fII\fP, was not connected to a directory entry when the -file system was traversed. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, -and modify time \fIT\fP of inode \fII\fP -are printed. -When preen'ing, -this is a file that was not connected because its size or link count was zero, -hence it is cleared. -.LP -Possible responses to the CLEAR prompt are: -.IP YES -de-allocate inode \fII\fP by zeroing its contents. -.IP NO -ignore this error condition. -.sp -.LP -.B "BAD/DUP \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (CLEAR)" -.br -Phase 1 or Phase 1b have found duplicate blocks -or bad blocks associated with -inode \fII\fP. -The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, -and modify time \fIT\fP of inode \fII\fP -are printed. -This error cannot arise when the file system is being preen'ed, -as it would have caused a fatal error earlier. -.LP -Possible responses to the CLEAR prompt are: -.IP YES -de-allocate inode \fII\fP by zeroing its contents. -.IP NO -ignore this error condition. -.NH 2 -Phase 5 - Check Cyl groups -.PP -This phase concerns itself with the free-block and used-inode maps. -This section lists error conditions resulting from -allocated blocks in the free-block maps, -free blocks missing from free-block maps, -and the total free-block count incorrect. -It also lists error conditions resulting from -free inodes in the used-inode maps, -allocated inodes missing from used-inode maps, -and the total used-inode count incorrect. -.sp -.LP -.B "CG \fIC\fP: BAD MAGIC NUMBER" -.br -The magic number of cylinder group \fIC\fP is wrong. -This usually indicates that the cylinder group maps have been destroyed. -When running manually the cylinder group is marked as needing -to be reconstructed. -This error is fatal if the file system is being preen'ed. -.sp -.LP -.B "BLK(S) MISSING IN BIT MAPS (SALVAGE)" -.br -A cylinder group block map is missing some free blocks. -During preen'ing the maps are reconstructed. -.LP -Possible responses to the SALVAGE prompt are: -.IP YES -reconstruct the free block map. -.IP NO -ignore this error condition. -.sp -.LP -.B "SUMMARY INFORMATION BAD (SALVAGE)" -.br -The summary information was found to be incorrect. -When preen'ing, -the summary information is recomputed. -.LP -Possible responses to the SALVAGE prompt are: -.IP YES -reconstruct the summary information. -.IP NO -ignore this error condition. -.sp -.LP -.B "FREE BLK COUNT(S) WRONG IN SUPERBLOCK (SALVAGE)" -.br -The superblock free block information was found to be incorrect. -When preen'ing, -the superblock free block information is recomputed. -.LP -Possible responses to the SALVAGE prompt are: -.IP YES -reconstruct the superblock free block information. -.IP NO -ignore this error condition. -.NH 2 -Cleanup -.PP -Once a file system has been checked, a few cleanup functions are performed. -This section lists advisory messages about -the file system -and modify status of the file system. -.sp -.LP -.B "\fIV\fP files, \fIW\fP used, \fIX\fP free (\fIY\fP frags, \fIZ\fP blocks)" -.br -This is an advisory message indicating that -the file system checked contained -\fIV\fP files using -\fIW\fP fragment sized blocks leaving -\fIX\fP fragment sized blocks free in the file system. -The numbers in parenthesis breaks the free count down into -\fIY\fP free fragments and -\fIZ\fP free full sized blocks. -.sp -.LP -.B "***** REBOOT UNIX *****" -.br -This is an advisory message indicating that -the root file system has been modified by -.I fsck. -If UNIX is not rebooted immediately, -the work done by -.I fsck -may be undone by the in-core copies of tables -UNIX keeps. -When preen'ing, -.I fsck -will exit with a code of 4. -The standard auto-reboot script distributed with 4.3BSD -interprets an exit code of 4 by issuing a reboot system call. -.sp -.LP -.B "***** FILE SYSTEM WAS MODIFIED *****" -.br -This is an advisory message indicating that -the current file system was modified by -.I fsck. -If this file system is mounted or is the current root file system, -.I fsck -should be halted and UNIX rebooted. -If UNIX is not rebooted immediately, -the work done by -.I fsck -may be undone by the in-core copies of tables -UNIX keeps. diff --git a/sbin/fsck/SMM.doc/Makefile b/sbin/fsck/SMM.doc/Makefile deleted file mode 100644 index 26823bc..0000000 --- a/sbin/fsck/SMM.doc/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# @(#)Makefile 8.1 (Berkeley) 6/8/93 - -DIR= smm/03.fsck -SRCS= 0.t 1.t 2.t 3.t 4.t -MACROS= -ms - -.include <bsd.doc.mk> diff --git a/sbin/fsck/dir.c b/sbin/fsck/dir.c deleted file mode 100644 index 5def8b2..0000000 --- a/sbin/fsck/dir.c +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -char *lfname = "lost+found"; -int lfmode = 01777; -struct dirtemplate emptydir = { 0, DIRBLKSIZ }; -struct dirtemplate dirhead = { - 0, 12, DT_DIR, 1, ".", - 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." -}; -struct odirtemplate odirhead = { - 0, 12, 1, ".", - 0, DIRBLKSIZ - 12, 2, ".." -}; - -static int chgino __P((struct inodesc *)); -static int dircheck __P((struct inodesc *, struct direct *)); -static int expanddir __P((struct dinode *dp, char *name)); -static void freedir __P((ino_t ino, ino_t parent)); -static struct direct *fsck_readdir __P((struct inodesc *)); -static struct bufarea *getdirblk __P((ufs_daddr_t blkno, long size)); -static int lftempname __P((char *bufp, ino_t ino)); -static int mkentry __P((struct inodesc *)); - -/* - * Propagate connected state through the tree. - */ -void -propagate() -{ - register struct inoinfo **inpp, *inp; - struct inoinfo **inpend; - long change; - - inpend = &inpsort[inplast]; - do { - change = 0; - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_parent == 0) - continue; - if (inoinfo(inp->i_parent)->ino_state == DFOUND && - inoinfo(inp->i_number)->ino_state == DSTATE) { - inoinfo(inp->i_number)->ino_state = DFOUND; - change++; - } - } - } while (change > 0); -} - -/* - * Scan each entry in a directory block. - */ -int -dirscan(idesc) - register struct inodesc *idesc; -{ - register struct direct *dp; - register struct bufarea *bp; - int dsize, n; - long blksiz; - char dbuf[DIRBLKSIZ]; - - if (idesc->id_type != DATA) - errx(EEXIT, "wrong type to dirscan %d", idesc->id_type); - if (idesc->id_entryno == 0 && - (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) - idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); - blksiz = idesc->id_numfrags * sblock.fs_fsize; - if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { - idesc->id_filesize -= blksiz; - return (SKIP); - } - idesc->id_loc = 0; - for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { - dsize = dp->d_reclen; - if (dsize > sizeof(dbuf)) - dsize = sizeof(dbuf); - memmove(dbuf, dp, (size_t)dsize); -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt) { - struct direct *tdp = (struct direct *)dbuf; - u_char tmp; - - tmp = tdp->d_namlen; - tdp->d_namlen = tdp->d_type; - tdp->d_type = tmp; - } -# endif - idesc->id_dirp = (struct direct *)dbuf; - if ((n = (*idesc->id_func)(idesc)) & ALTERED) { -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt && !doinglevel2) { - struct direct *tdp; - u_char tmp; - - tdp = (struct direct *)dbuf; - tmp = tdp->d_namlen; - tdp->d_namlen = tdp->d_type; - tdp->d_type = tmp; - } -# endif - bp = getdirblk(idesc->id_blkno, blksiz); - memmove(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf, - (size_t)dsize); - dirty(bp); - sbdirty(); - } - if (n & STOP) - return (n); - } - return (idesc->id_filesize > 0 ? KEEPON : STOP); -} - -/* - * get next entry in a directory. - */ -static struct direct * -fsck_readdir(idesc) - register struct inodesc *idesc; -{ - register struct direct *dp, *ndp; - register struct bufarea *bp; - long size, blksiz, fix, dploc; - - blksiz = idesc->id_numfrags * sblock.fs_fsize; - bp = getdirblk(idesc->id_blkno, blksiz); - if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && - idesc->id_loc < blksiz) { - dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - if (dircheck(idesc, dp)) - goto dpok; - if (idesc->id_fix == IGNORE) - return (0); - fix = dofix(idesc, "DIRECTORY CORRUPTED"); - bp = getdirblk(idesc->id_blkno, blksiz); - dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - dp->d_reclen = DIRBLKSIZ; - dp->d_ino = 0; - dp->d_type = 0; - dp->d_namlen = 0; - dp->d_name[0] = '\0'; - if (fix) - dirty(bp); - idesc->id_loc += DIRBLKSIZ; - idesc->id_filesize -= DIRBLKSIZ; - return (dp); - } -dpok: - if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) - return NULL; - dploc = idesc->id_loc; - dp = (struct direct *)(bp->b_un.b_buf + dploc); - idesc->id_loc += dp->d_reclen; - idesc->id_filesize -= dp->d_reclen; - if ((idesc->id_loc % DIRBLKSIZ) == 0) - return (dp); - ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && - dircheck(idesc, ndp) == 0) { - size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); - idesc->id_loc += size; - idesc->id_filesize -= size; - if (idesc->id_fix == IGNORE) - return (0); - fix = dofix(idesc, "DIRECTORY CORRUPTED"); - bp = getdirblk(idesc->id_blkno, blksiz); - dp = (struct direct *)(bp->b_un.b_buf + dploc); - dp->d_reclen += size; - if (fix) - dirty(bp); - } - return (dp); -} - -/* - * Verify that a directory entry is valid. - * This is a superset of the checks made in the kernel. - */ -static int -dircheck(idesc, dp) - struct inodesc *idesc; - register struct direct *dp; -{ - register int size; - register char *cp; - u_char namlen, type; - int spaceleft; - - spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); - if (dp->d_reclen == 0 || - dp->d_reclen > spaceleft || - (dp->d_reclen & 0x3) != 0) - goto bad; - if (dp->d_ino == 0) - return (1); - size = DIRSIZ(!newinofmt, dp); -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt) { - type = dp->d_namlen; - namlen = dp->d_type; - } else { - namlen = dp->d_namlen; - type = dp->d_type; - } -# else - namlen = dp->d_namlen; - type = dp->d_type; -# endif - if (dp->d_reclen < size || - idesc->id_filesize < size || - namlen > MAXNAMLEN || - type > 15) - goto bad; - for (cp = dp->d_name, size = 0; size < namlen; size++) - if (*cp == '\0' || (*cp++ == '/')) - goto bad; - if (*cp != '\0') - goto bad; - return (1); -bad: - if (debug) - printf("Bad dir: ino %d reclen %d namlen %d type %d name %s\n", - dp->d_ino, dp->d_reclen, dp->d_namlen, dp->d_type, - dp->d_name); - return (0); -} - -void -direrror(ino, errmesg) - ino_t ino; - char *errmesg; -{ - - fileerror(ino, ino, errmesg); -} - -void -fileerror(cwd, ino, errmesg) - ino_t cwd, ino; - char *errmesg; -{ - register struct dinode *dp; - char pathbuf[MAXPATHLEN + 1]; - - pwarn("%s ", errmesg); - pinode(ino); - printf("\n"); - getpathname(pathbuf, cwd, ino); - if (ino < ROOTINO || ino > maxino) { - pfatal("NAME=%s\n", pathbuf); - return; - } - dp = ginode(ino); - if (ftypeok(dp)) - pfatal("%s=%s\n", - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); - else - pfatal("NAME=%s\n", pathbuf); -} - -void -adjust(idesc, lcnt) - register struct inodesc *idesc; - int lcnt; -{ - struct dinode *dp; - int saveresolved; - - dp = ginode(idesc->id_number); - if (dp->di_nlink == lcnt) { - /* - * If we have not hit any unresolved problems, are running - * in preen mode, and are on a filesystem using soft updates, - * then just toss any partially allocated files. - */ - if (resolved && preen && usedsoftdep) { - clri(idesc, "UNREF", 1); - return; - } else { - /* - * The filesystem can be marked clean even if - * a file is not linked up, but is cleared. - * Hence, resolved should not be cleared when - * linkup is answered no, but clri is answered yes. - */ - saveresolved = resolved; - if (linkup(idesc->id_number, (ino_t)0, NULL) == 0) { - resolved = saveresolved; - clri(idesc, "UNREF", 0); - return; - } - /* - * Account for the new reference created by linkup(). - */ - dp = ginode(idesc->id_number); - lcnt--; - } - } - if (lcnt != 0) { - pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : - ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE")); - pinode(idesc->id_number); - printf(" COUNT %d SHOULD BE %d", - dp->di_nlink, dp->di_nlink - lcnt); - if (preen || usedsoftdep) { - if (lcnt < 0) { - printf("\n"); - pfatal("LINK COUNT INCREASING"); - } - if (preen) - printf(" (ADJUSTED)\n"); - } - if (preen || reply("ADJUST") == 1) { - dp->di_nlink -= lcnt; - inodirty(); - } - } -} - -static int -mkentry(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - struct direct newent; - int newlen, oldlen; - - newent.d_namlen = strlen(idesc->id_name); - newlen = DIRSIZ(0, &newent); - if (dirp->d_ino != 0) - oldlen = DIRSIZ(0, dirp); - else - oldlen = 0; - if (dirp->d_reclen - oldlen < newlen) - return (KEEPON); - newent.d_reclen = dirp->d_reclen - oldlen; - dirp->d_reclen = oldlen; - dirp = (struct direct *)(((char *)dirp) + oldlen); - dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ - dirp->d_reclen = newent.d_reclen; - if (newinofmt) - dirp->d_type = inoinfo(idesc->id_parent)->ino_type; - else - dirp->d_type = 0; - dirp->d_namlen = newent.d_namlen; - memmove(dirp->d_name, idesc->id_name, (size_t)newent.d_namlen + 1); -# if (BYTE_ORDER == LITTLE_ENDIAN) - /* - * If the entry was split, dirscan() will only reverse the byte - * order of the original entry, and not the new one, before - * writing it back out. So, we reverse the byte order here if - * necessary. - */ - if (oldlen != 0 && !newinofmt && !doinglevel2) { - u_char tmp; - - tmp = dirp->d_namlen; - dirp->d_namlen = dirp->d_type; - dirp->d_type = tmp; - } -# endif - return (ALTERED|STOP); -} - -static int -chgino(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (memcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) - return (KEEPON); - dirp->d_ino = idesc->id_parent; - if (newinofmt) - dirp->d_type = inoinfo(idesc->id_parent)->ino_type; - else - dirp->d_type = 0; - return (ALTERED|STOP); -} - -int -linkup(orphan, parentdir, name) - ino_t orphan; - ino_t parentdir; - char *name; -{ - register struct dinode *dp; - int lostdir; - ino_t oldlfdir; - struct inodesc idesc; - char tempname[BUFSIZ]; - - memset(&idesc, 0, sizeof(struct inodesc)); - dp = ginode(orphan); - lostdir = (dp->di_mode & IFMT) == IFDIR; - pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); - pinode(orphan); - if (preen && dp->di_size == 0) - return (0); - if (preen) - printf(" (RECONNECTED)\n"); - else - if (reply("RECONNECT") == 0) - return (0); - if (lfdir == 0) { - dp = ginode(ROOTINO); - idesc.id_name = lfname; - idesc.id_type = DATA; - idesc.id_func = findino; - idesc.id_number = ROOTINO; - if ((ckinode(dp, &idesc) & FOUND) != 0) { - lfdir = idesc.id_parent; - } else { - pwarn("NO lost+found DIRECTORY"); - if (preen || reply("CREATE")) { - lfdir = allocdir(ROOTINO, (ino_t)0, lfmode); - if (lfdir != 0) { - if (makeentry(ROOTINO, lfdir, lfname) != 0) { - numdirs++; - if (preen) - printf(" (CREATED)\n"); - } else { - freedir(lfdir, ROOTINO); - lfdir = 0; - if (preen) - printf("\n"); - } - } - } - } - if (lfdir == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); - printf("\n\n"); - return (0); - } - } - dp = ginode(lfdir); - if ((dp->di_mode & IFMT) != IFDIR) { - pfatal("lost+found IS NOT A DIRECTORY"); - if (reply("REALLOCATE") == 0) - return (0); - oldlfdir = lfdir; - if ((lfdir = allocdir(ROOTINO, (ino_t)0, lfmode)) == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); - return (0); - } - if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); - return (0); - } - inodirty(); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - idesc.id_number = oldlfdir; - adjust(&idesc, inoinfo(oldlfdir)->ino_linkcnt + 1); - inoinfo(oldlfdir)->ino_linkcnt = 0; - dp = ginode(lfdir); - } - if (inoinfo(lfdir)->ino_state != DFOUND) { - pfatal("SORRY. NO lost+found DIRECTORY\n\n"); - return (0); - } - (void)lftempname(tempname, orphan); - if (makeentry(lfdir, orphan, (name ? name : tempname)) == 0) { - pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); - printf("\n\n"); - return (0); - } - inoinfo(orphan)->ino_linkcnt--; - if (lostdir) { - if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 && - parentdir != (ino_t)-1) - (void)makeentry(orphan, lfdir, ".."); - dp = ginode(lfdir); - dp->di_nlink++; - inodirty(); - inoinfo(lfdir)->ino_linkcnt++; - pwarn("DIR I=%lu CONNECTED. ", orphan); - if (parentdir != (ino_t)-1) { - printf("PARENT WAS I=%lu\n", (u_long)parentdir); - /* - * The parent directory, because of the ordering - * guarantees, has had the link count incremented - * for the child, but no entry was made. This - * fixes the parent link count so that fsck does - * not need to be rerun. - */ - inoinfo(parentdir)->ino_linkcnt++; - } - if (preen == 0) - printf("\n"); - } - return (1); -} - -/* - * fix an entry in a directory. - */ -int -changeino(dir, name, newnum) - ino_t dir; - char *name; - ino_t newnum; -{ - struct inodesc idesc; - - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_func = chgino; - idesc.id_number = dir; - idesc.id_fix = DONTKNOW; - idesc.id_name = name; - idesc.id_parent = newnum; /* new value for name */ - return (ckinode(ginode(dir), &idesc)); -} - -/* - * make an entry in a directory - */ -int -makeentry(parent, ino, name) - ino_t parent, ino; - char *name; -{ - struct dinode *dp; - struct inodesc idesc; - char pathbuf[MAXPATHLEN + 1]; - - if (parent < ROOTINO || parent >= maxino || - ino < ROOTINO || ino >= maxino) - return (0); - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_func = mkentry; - idesc.id_number = parent; - idesc.id_parent = ino; /* this is the inode to enter */ - idesc.id_fix = DONTKNOW; - idesc.id_name = name; - dp = ginode(parent); - if (dp->di_size % DIRBLKSIZ) { - dp->di_size = roundup(dp->di_size, DIRBLKSIZ); - inodirty(); - } - if ((ckinode(dp, &idesc) & ALTERED) != 0) - return (1); - getpathname(pathbuf, parent, parent); - dp = ginode(parent); - if (expanddir(dp, pathbuf) == 0) - return (0); - return (ckinode(dp, &idesc) & ALTERED); -} - -/* - * Attempt to expand the size of a directory - */ -static int -expanddir(dp, name) - register struct dinode *dp; - char *name; -{ - ufs_daddr_t lastbn, newblk; - register struct bufarea *bp; - char *cp, firstblk[DIRBLKSIZ]; - - lastbn = lblkno(&sblock, dp->di_size); - if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0) - return (0); - if ((newblk = allocblk(sblock.fs_frag)) == 0) - return (0); - dp->di_db[lastbn + 1] = dp->di_db[lastbn]; - dp->di_db[lastbn] = newblk; - dp->di_size += sblock.fs_bsize; - dp->di_blocks += btodb(sblock.fs_bsize); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); - if (bp->b_errs) - goto bad; - memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ); - bp = getdirblk(newblk, sblock.fs_bsize); - if (bp->b_errs) - goto bad; - memmove(bp->b_un.b_buf, firstblk, DIRBLKSIZ); - for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; - cp < &bp->b_un.b_buf[sblock.fs_bsize]; - cp += DIRBLKSIZ) - memmove(cp, &emptydir, sizeof emptydir); - dirty(bp); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); - if (bp->b_errs) - goto bad; - memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir); - pwarn("NO SPACE LEFT IN %s", name); - if (preen) - printf(" (EXPANDED)\n"); - else if (reply("EXPAND") == 0) - goto bad; - dirty(bp); - inodirty(); - return (1); -bad: - dp->di_db[lastbn] = dp->di_db[lastbn + 1]; - dp->di_db[lastbn + 1] = 0; - dp->di_size -= sblock.fs_bsize; - dp->di_blocks -= btodb(sblock.fs_bsize); - freeblk(newblk, sblock.fs_frag); - return (0); -} - -/* - * allocate a new directory - */ -ino_t -allocdir(parent, request, mode) - ino_t parent, request; - int mode; -{ - ino_t ino; - char *cp; - struct dinode *dp; - struct bufarea *bp; - struct inoinfo *inp; - struct dirtemplate *dirp; - - ino = allocino(request, IFDIR|mode); - if (newinofmt) - dirp = &dirhead; - else - dirp = (struct dirtemplate *)&odirhead; - dirp->dot_ino = ino; - dirp->dotdot_ino = parent; - dp = ginode(ino); - bp = getdirblk(dp->di_db[0], sblock.fs_fsize); - if (bp->b_errs) { - freeino(ino); - return (0); - } - memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate)); - for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; - cp < &bp->b_un.b_buf[sblock.fs_fsize]; - cp += DIRBLKSIZ) - memmove(cp, &emptydir, sizeof emptydir); - dirty(bp); - dp->di_nlink = 2; - inodirty(); - if (ino == ROOTINO) { - inoinfo(ino)->ino_linkcnt = dp->di_nlink; - cacheino(dp, ino); - return(ino); - } - if (inoinfo(parent)->ino_state != DSTATE && - inoinfo(parent)->ino_state != DFOUND) { - freeino(ino); - return (0); - } - cacheino(dp, ino); - inp = getinoinfo(ino); - inp->i_parent = parent; - inp->i_dotdot = parent; - inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; - if (inoinfo(ino)->ino_state == DSTATE) { - inoinfo(ino)->ino_linkcnt = dp->di_nlink; - inoinfo(parent)->ino_linkcnt++; - } - dp = ginode(parent); - dp->di_nlink++; - inodirty(); - return (ino); -} - -/* - * free a directory inode - */ -static void -freedir(ino, parent) - ino_t ino, parent; -{ - struct dinode *dp; - - if (ino != parent) { - dp = ginode(parent); - dp->di_nlink--; - inodirty(); - } - freeino(ino); -} - -/* - * generate a temporary name for the lost+found directory. - */ -static int -lftempname(bufp, ino) - char *bufp; - ino_t ino; -{ - register ino_t in; - register char *cp; - int namlen; - - cp = bufp + 2; - for (in = maxino; in > 0; in /= 10) - cp++; - *--cp = 0; - namlen = cp - bufp; - in = ino; - while (cp > bufp) { - *--cp = (in % 10) + '0'; - in /= 10; - } - *cp = '#'; - return (namlen); -} - -/* - * Get a directory block. - * Insure that it is held until another is requested. - */ -static struct bufarea * -getdirblk(blkno, size) - ufs_daddr_t blkno; - long size; -{ - - if (pdirbp != 0) - pdirbp->b_flags &= ~B_INUSE; - pdirbp = getdatablk(blkno, size); - return (pdirbp); -} diff --git a/sbin/fsck/fsck.8 b/sbin/fsck/fsck.8 deleted file mode 100644 index 59d7fa8..0000000 --- a/sbin/fsck/fsck.8 +++ /dev/null @@ -1,321 +0,0 @@ -.\" -.\" Copyright (c) 1980, 1989, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95 -.\" $FreeBSD$ -.\" -.Dd November 15, 1996 -.Dt FSCK 8 -.Os BSD 4 -.Sh NAME -.Nm fsck -.Nd filesystem consistency check and interactive repair -.Sh SYNOPSIS -.Nm fsck -.Fl p -.Op Fl f -.Op Fl m Ar mode -.Op Ar filesystem -.Ar ... -.Nm fsck -.Op Fl ny -.Op Fl b Ar block# -.Op Fl c Ar level -.Op Fl l Ar maxparallel -.Op Fl m Ar mode -.Op Ar filesystem -.Ar ... -.Sh DESCRIPTION -The first form of -.Nm -preens a standard set of filesystems or the specified filesystems. -It is normally used in the script -.Pa /etc/rc -during automatic reboot. -Here -.Nm -reads the table -.Pa /etc/fstab -to determine which filesystems to check. -Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro'' -and that have non-zero pass number are checked. -Filesystems with pass number 1 (normally just the root filesystem) -are checked one at a time. -When pass 1 completes, all remaining filesystems are checked, -running one process per disk drive. -The disk drive containing each filesystem is inferred from the longest prefix -of the device name that ends in a digit; the remaining characters are assumed -to be the partition designator. -.Pp -In "preen" mode the clean flag of each filesystem's superblock is examined -and only those filesystems that -are not marked clean are checked. -Filesystems are marked clean when they are unmounted, -when they have been mounted read-only, or when -.Nm -runs on them successfully. -If the -.Fl f -option is specified, the filesystems -will be checked regardless of the state of their clean flag. -.Pp -The kernel takes care that only a restricted class of innocuous filesystem -inconsistencies can happen unless hardware or software failures intervene. -These are limited to the following: -.Pp -.Bl -item -compact -offset indent -.It -Unreferenced inodes -.It -Link counts in inodes too large -.It -Missing blocks in the free map -.It -Blocks in the free map also in files -.It -Counts in the super-block wrong -.El -.Pp -These are the only inconsistencies that -.Nm -with the -.Fl p -option will correct; if it encounters other inconsistencies, it exits -with an abnormal return status and an automatic reboot will then fail. -For each corrected inconsistency one or more lines will be printed -identifying the filesystem on which the correction will take place, -and the nature of the correction. After successfully correcting a filesystem, -.Nm -will print the number of files on that filesystem, -the number of used and free blocks, -and the percentage of fragmentation. -.Pp -If sent a -.Dv QUIT -signal, -.Nm -will finish the filesystem checks, then exit with an abnormal -return status that causes an automatic reboot to fail. -This is useful when you want to finish the filesystem checks during an -automatic reboot, -but do not want the machine to come up multiuser after the checks complete. -.Pp -Without the -.Fl p -option, -.Nm -audits and interactively repairs inconsistent conditions for filesystems. -If the filesystem is inconsistent the operator is prompted for concurrence -before each correction is attempted. -It should be noted that some of the corrective actions which are not -correctable under the -.Fl p -option will result in some loss of data. -The amount and severity of data lost may be determined from the diagnostic -output. -The default action for each consistency correction -is to wait for the operator to respond -.Li yes -or -.Li no . -If the operator does not have write permission on the filesystem -.Nm -will default to a -.Fl n -action. -.Pp -.Nm Fsck -has more consistency checks than -its predecessors -.Em check , dcheck , fcheck , -and -.Em icheck -combined. -.Pp -The following flags are interpreted by -.Nm Ns . -.Bl -tag -width indent -.It Fl b -Use the block specified immediately after the flag as -the super block for the filesystem. Block 32 is usually -an alternate super block. -.It Fl c -Convert the filesystem to the specified level. -Note that the level of a filesystem can only be raised. -.Bl -tag -width indent -There are currently four levels defined: -.It 0 -The filesystem is in the old (static table) format. -.It 1 -The filesystem is in the new (dynamic table) format. -.It 2 -The filesystem supports 32-bit uid's and gid's, -short symbolic links are stored in the inode, -and directories have an added field showing the file type. -.It 3 -If maxcontig is greater than one, -build the free segment maps to aid in finding contiguous sets of blocks. -If maxcontig is equal to one, delete any existing segment maps. -.El -.Pp -In interactive mode, -.Nm -will list the conversion to be made -and ask whether the conversion should be done. -If a negative answer is given, -no further operations are done on the filesystem. -In preen mode, -the conversion is listed and done if -possible without user interaction. -Conversion in preen mode is best used when all the filesystems -are being converted at once. -The format of a filesystem can be determined from the -first line of output from -.Xr dumpfs 8 . -.It Fl f -Force -.Nm fsck -to check -.Sq clean -filesystems when preening. -.It Fl l -Limit the number of parallel checks to the number specified in the following -argument. -By default, the limit is the number of disks, running one process per disk. -If a smaller limit is given, the disks are checked round-robin, one filesystem -at a time. -.It Fl m -Use the mode specified in octal immediately after the flag as the -permission bits to use when creating the -.Pa lost+found -directory rather than the default 1777. -In particular, systems that do not wish to have lost files accessible -by all users on the system should use a more restrictive -set of permissions such as 700. -.It Fl n -Assume a no response to all questions asked by -.Nm -except for -.Ql CONTINUE? , -which is assumed to be affirmative; -do not open the filesystem for writing. -.It Fl p -Preen filesystems (see above). -.It Fl y -Assume a yes response to all questions asked by -.Nm Ns ; -this should be used with great caution as this is a free license -to continue after essentially unlimited trouble has been encountered. -.El -.Pp -If no filesystems are given to -.Nm -then a default list of filesystems is read from -the file -.Pa /etc/fstab . -.Pp -.Bl -enum -indent indent -compact -Inconsistencies checked are as follows: -.It -Blocks claimed by more than one inode or the free map. -.It -Blocks claimed by an inode outside the range of the filesystem. -.It -Incorrect link counts. -.It -Size checks: -.Bl -item -indent indent -compact -.It -Directory size not a multiple of DIRBLKSIZ. -.It -Partially truncated file. -.El -.It -Bad inode format. -.It -Blocks not accounted for anywhere. -.It -Directory checks: -.Bl -item -indent indent -compact -.It -File pointing to unallocated inode. -.It -Inode number out of range. -.It -Directories with unallocated blocks (holes). -.It -Dot or dot-dot not the first two entries of a directory -or having the wrong inode number. -.El -.It -Super Block checks: -.Bl -item -indent indent -compact -.It -More blocks for inodes than there are in the filesystem. -.It -Bad free block map format. -.It -Total free block and/or free inode count incorrect. -.El -.El -.Pp -Orphaned files and directories (allocated but unreferenced) are, -with the operator's concurrence, reconnected by -placing them in the -.Pa lost+found -directory. -The name assigned is the inode number. -If the -.Pa lost+found -directory does not exist, it is created. -If there is insufficient space its size is increased. -.Pp -Because of inconsistencies between the block device and the buffer cache, -the raw device should always be used. -.Sh FILES -.Bl -tag -width /etc/fstab -compact -.It Pa /etc/fstab -contains default list of filesystems to check. -.El -.Sh DIAGNOSTICS -The diagnostics produced by -.Nm -are fully enumerated and explained in Appendix A of -.Rs -.%T "Fsck \- The UNIX File System Check Program" -.Re -.Sh SEE ALSO -.Xr fs 5 , -.Xr fstab 5 , -.Xr fsdb 8 , -.Xr newfs 8 , -.Xr reboot 8 diff --git a/sbin/fsck/fsck.c b/sbin/fsck/fsck.c new file mode 100644 index 0000000..4bc24ac --- /dev/null +++ b/sbin/fsck/fsck.c @@ -0,0 +1,540 @@ +/* $NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * Copyright (c) 1980, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: @(#)mount.c 8.19 (Berkeley) 4/19/94 + * From: NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp + * $FreeBSD$ + * + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $"); +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/mount.h> +#include <sys/queue.h> +#include <sys/wait.h> +#define FSTYPENAMES +#define DKTYPENAMES +#include <sys/disklabel.h> +#include <sys/ioctl.h> + +#include <err.h> +#include <errno.h> +#include <fstab.h> +#include <fcntl.h> +#include <paths.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "pathnames.h" +#include "fsutil.h" + +static enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST; + +TAILQ_HEAD(fstypelist, entry) opthead, selhead; + +struct entry { + char *type; + char *options; + TAILQ_ENTRY(entry) entries; +}; + +static int maxrun = 0; +static char *options = NULL; +static int flags = 0; + +int main __P((int, char *[])); + +static int checkfs __P((const char *, const char *, const char *, void *, + pid_t *)); +static int selected __P((const char *)); +static void addoption __P((char *)); +static const char *getoptions __P((const char *)); +static void addentry __P((struct fstypelist *, const char *, const char *)); +static void maketypelist __P((char *)); +static void catopt __P((char **, const char *)); +static void mangle __P((char *, int *, const char ***, int *)); +static const char *getfslab __P((const char *)); +static void usage __P((void)); +static void *isok __P((struct fstab *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct fstab *fs; + int i, rval = 0; + const char *vfstype = NULL; + char globopt[3]; + + globopt[0] = '-'; + globopt[2] = '\0'; + + TAILQ_INIT(&selhead); + TAILQ_INIT(&opthead); + + while ((i = getopt(argc, argv, "dvpfnyl:t:T:")) != -1) + switch (i) { + case 'd': + flags |= CHECK_DEBUG; + break; + + case 'v': + flags |= CHECK_VERBOSE; + break; + + case 'p': + flags |= CHECK_PREEN; + /*FALLTHROUGH*/ + case 'n': + case 'f': + case 'y': + globopt[1] = i; + catopt(&options, globopt); + break; + + case 'l': + maxrun = atoi(optarg); + break; + + case 'T': + if (*optarg) + addoption(optarg); + break; + + case 't': + if (selhead.tqh_first != NULL) + errx(1, "only one -t option may be specified."); + + maketypelist(optarg); + vfstype = optarg; + break; + + case '?': + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return checkfstab(flags, maxrun, isok, checkfs); + +#define BADTYPE(type) \ + (strcmp(type, FSTAB_RO) && \ + strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) + + + for (; argc--; argv++) { + const char *spec, *type, *cp; + char device[MAXPATHLEN]; + + spec = *argv; + cp = strrchr(spec, '/'); + if (cp == 0) { + (void)snprintf(device, sizeof(device), "%s%s", + _PATH_DEV, spec); + spec = device; + } + if ((fs = getfsfile(spec)) == NULL && + (fs = getfsspec(spec)) == NULL) { + if (vfstype == NULL) + vfstype = getfslab(spec); + type = vfstype; + } + else { + spec = fs->fs_spec; + type = fs->fs_vfstype; + if (BADTYPE(fs->fs_type)) + errx(1, "%s has unknown file system type.", + spec); + } + + rval |= checkfs(type, devcheck(spec), *argv, NULL, NULL); + } + + return rval; +} + + +static void * +isok(fs) + struct fstab *fs; +{ + if (fs->fs_passno == 0) + return NULL; + + if (BADTYPE(fs->fs_type)) + return NULL; + + if (!selected(fs->fs_vfstype)) + return NULL; + + return fs; +} + + +static int +checkfs(pvfstype, spec, mntpt, auxarg, pidp) + const char *pvfstype, *spec, *mntpt; + void *auxarg; + pid_t *pidp; +{ + /* List of directories containing fsck_xxx subcommands. */ + static const char *edirs[] = { + _PATH_SBIN, + _PATH_USRSBIN, + NULL + }; + const char **argv, **edir; + pid_t pid; + int argc, i, status, maxargc; + char *optbuf, execname[MAXPATHLEN + 1], execbase[MAXPATHLEN]; + char *vfstype = NULL; + const char *extra = NULL; + +#ifdef __GNUC__ + /* Avoid vfork clobbering */ + (void) &optbuf; + (void) &vfstype; +#endif + /* + * We convert the vfstype to lowercase and any spaces to underscores + * to not confuse the issue + */ + vfstype = strdup(pvfstype); + if (vfstype == NULL) + perror("strdup(pvfstype)"); + for (i = 0; i < strlen(vfstype); i++) { + vfstype[i] = tolower(vfstype[i]); + if (vfstype[i] == ' ') + vfstype[i] = '_'; + } + + extra = getoptions(vfstype); + optbuf = NULL; + if (options) + catopt(&optbuf, options); + if (extra) + catopt(&optbuf, extra); + + maxargc = 64; + argv = emalloc(sizeof(char *) * maxargc); + + (void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype); + argc = 0; + argv[argc++] = execbase; + if (optbuf) + mangle(optbuf, &argc, &argv, &maxargc); + argv[argc++] = spec; + argv[argc] = NULL; + + if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) { + (void)printf("start %s %swait", mntpt, + pidp ? "no" : ""); + for (i = 0; i < argc; i++) + (void)printf(" %s", argv[i]); + (void)printf("\n"); + } + + switch (pid = vfork()) { + case -1: /* Error. */ + warn("vfork"); + if (optbuf) + free(optbuf); + free(vfstype); + return (1); + + case 0: /* Child. */ + if (flags & CHECK_DEBUG) + _exit(0); + + /* Go find an executable. */ + edir = edirs; + do { + (void)snprintf(execname, + sizeof(execname), "%s/%s", *edir, execbase); + execv(execname, (char * const *)argv); + if (errno != ENOENT) { + if (spec) + warn("exec %s for %s", execname, spec); + else + warn("exec %s", execname); + } + } while (*++edir != NULL); + + if (errno == ENOENT) { + if (spec) + warn("exec %s for %s", execname, spec); + else + warn("exec %s", execname); + } + _exit(1); + /* NOTREACHED */ + + default: /* Parent. */ + if (optbuf) + free(optbuf); + + free(vfstype); + + if (pidp) { + *pidp = pid; + return 0; + } + + if (waitpid(pid, &status, 0) < 0) { + warn("waitpid"); + return (1); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + return (WEXITSTATUS(status)); + } + else if (WIFSIGNALED(status)) { + warnx("%s: %s", spec, strsignal(WTERMSIG(status))); + return (1); + } + break; + } + + return (0); +} + + +static int +selected(type) + const char *type; +{ + struct entry *e; + + /* If no type specified, it's always selected. */ + for (e = selhead.tqh_first; e != NULL; e = e->entries.tqe_next) + if (!strncmp(e->type, type, MFSNAMELEN)) + return which == IN_LIST ? 1 : 0; + + return which == IN_LIST ? 0 : 1; +} + + +static const char * +getoptions(type) + const char *type; +{ + struct entry *e; + + for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next) + if (!strncmp(e->type, type, MFSNAMELEN)) + return e->options; + return ""; +} + + +static void +addoption(optstr) + char *optstr; +{ + char *newoptions; + struct entry *e; + + if ((newoptions = strchr(optstr, ':')) == NULL) + errx(1, "Invalid option string"); + + *newoptions++ = '\0'; + + for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next) + if (!strncmp(e->type, optstr, MFSNAMELEN)) { + catopt(&e->options, newoptions); + return; + } + addentry(&opthead, optstr, newoptions); +} + + +static void +addentry(list, type, opts) + struct fstypelist *list; + const char *type; + const char *opts; +{ + struct entry *e; + + e = emalloc(sizeof(struct entry)); + e->type = estrdup(type); + e->options = estrdup(opts); + TAILQ_INSERT_TAIL(list, e, entries); +} + + +static void +maketypelist(fslist) + char *fslist; +{ + char *ptr; + + if ((fslist == NULL) || (fslist[0] == '\0')) + errx(1, "empty type list"); + + if (fslist[0] == 'n' && fslist[1] == 'o') { + fslist += 2; + which = NOT_IN_LIST; + } + else + which = IN_LIST; + + while ((ptr = strsep(&fslist, ",")) != NULL) + addentry(&selhead, ptr, ""); + +} + + +static void +catopt(sp, o) + char **sp; + const char *o; +{ + char *s; + size_t i, j; + + s = *sp; + if (s) { + i = strlen(s); + j = i + 1 + strlen(o) + 1; + s = erealloc(s, j); + (void)snprintf(s + i, j, ",%s", o); + } else + s = estrdup(o); + *sp = s; +} + + +static void +mangle(options, argcp, argvp, maxargcp) + char *options; + int *argcp, *maxargcp; + const char ***argvp; +{ + char *p, *s; + int argc, maxargc; + const char **argv; + + argc = *argcp; + argv = *argvp; + maxargc = *maxargcp; + + for (s = options; (p = strsep(&s, ",")) != NULL;) { + /* Always leave space for one more argument and the NULL. */ + if (argc >= maxargc - 3) { + maxargc <<= 1; + argv = erealloc(argv, maxargc * sizeof(char *)); + } + if (*p != '\0') { + if (*p == '-') { + argv[argc++] = p; + p = strchr(p, '='); + if (p) { + *p = '\0'; + argv[argc++] = p+1; + } + } else { + argv[argc++] = "-o"; + argv[argc++] = p; + } + } + } + + *argcp = argc; + *argvp = argv; + *maxargcp = maxargc; +} + + +const static char * +getfslab(str) + const char *str; +{ + struct disklabel dl; + int fd; + char p; + const char *vfstype; + u_char t; + + /* deduce the filesystem type from the disk label */ + if ((fd = open(str, O_RDONLY)) == -1) + err(1, "cannot open `%s'", str); + + if (ioctl(fd, DIOCGDINFO, &dl) == -1) + err(1, "cannot get disklabel for `%s'", str); + + (void) close(fd); + + p = str[strlen(str) - 1]; + + if ((p - 'a') >= dl.d_npartitions) + errx(1, "partition `%s' is not defined on disk", str); + + if ((t = dl.d_partitions[p - 'a'].p_fstype) >= FSMAXTYPES) + errx(1, "partition `%s' is not of a legal vfstype", + str); + + if ((vfstype = fstypenames[t]) == NULL) + errx(1, "vfstype `%s' on partition `%s' is not supported", + fstypenames[t], str); + + return vfstype; +} + + +static void +usage() +{ + extern char *__progname; + static const char common[] = + "[-dpvlyn] [-T fstype:fsoptions] [-t fstype]"; + + (void)fprintf(stderr, "Usage: %s %s [special|node]...\n", + __progname, common); + exit(1); +} diff --git a/sbin/fsck/fsck.h b/sbin/fsck/fsck.h deleted file mode 100644 index f0280fe..0000000 --- a/sbin/fsck/fsck.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)fsck.h 8.4 (Berkeley) 5/9/95 - * $FreeBSD$ - */ - -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> - -#define MAXDUP 10 /* limit on dup blks (per inode) */ -#define MAXBAD 10 /* limit on bad blks (per inode) */ -#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ -#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ - -/* - * Each inode on the filesystem is described by the following structure. - * The linkcnt is initially set to the value in the inode. Each time it - * is found during the descent in passes 2, 3, and 4 the count is - * decremented. Any inodes whose count is non-zero after pass 4 needs to - * have its link count adjusted by the value remaining in ino_linkcnt. - */ -struct inostat { - char ino_state; /* state of inode, see below */ - char ino_type; /* type of inode */ - short ino_linkcnt; /* number of links not found */ -}; -/* - * Inode states. - */ -#define USTATE 01 /* inode not allocated */ -#define FSTATE 02 /* inode is file */ -#define DSTATE 03 /* inode is directory */ -#define DFOUND 04 /* directory found during descent */ -#define DCLEAR 05 /* directory is to be cleared */ -#define FCLEAR 06 /* file is to be cleared */ -/* - * Inode state information is contained on per cylinder group lists - * which are described by the following structure. - */ -struct inostatlist { - long il_numalloced; /* number of inodes allocated in this cg */ - struct inostat *il_stat;/* inostat info for this cylinder group */ -} *inostathead; - -/* - * buffer cache structure. - */ -struct bufarea { - struct bufarea *b_next; /* free list queue */ - struct bufarea *b_prev; /* free list queue */ - ufs_daddr_t b_bno; - int b_size; - int b_errs; - int b_flags; - union { - char *b_buf; /* buffer space */ - ufs_daddr_t *b_indir; /* indirect block */ - struct fs *b_fs; /* super block */ - struct cg *b_cg; /* cylinder group */ - struct dinode *b_dinode; /* inode block */ - } b_un; - char b_dirty; -}; - -#define B_INUSE 1 - -#define MINBUFS 5 /* minimum number of buffers required */ -struct bufarea bufhead; /* head of list of other blks in filesys */ -struct bufarea sblk; /* file system superblock */ -struct bufarea cgblk; /* cylinder group blocks */ -struct bufarea *pdirbp; /* current directory contents */ -struct bufarea *pbp; /* current inode block */ - -#define dirty(bp) (bp)->b_dirty = 1 -#define initbarea(bp) \ - (bp)->b_dirty = 0; \ - (bp)->b_bno = (ufs_daddr_t)-1; \ - (bp)->b_flags = 0; - -#define sbdirty() sblk.b_dirty = 1 -#define cgdirty() cgblk.b_dirty = 1 -#define sblock (*sblk.b_un.b_fs) -#define cgrp (*cgblk.b_un.b_cg) - -enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; -ino_t cursnapshot; - -struct inodesc { - enum fixstate id_fix; /* policy on fixing errors */ - int (*id_func)(); /* function to be applied to blocks of inode */ - ino_t id_number; /* inode number described */ - ino_t id_parent; /* for DATA nodes, their parent */ - int id_lbn; /* logical block number of current block */ - ufs_daddr_t id_blkno; /* current block number being examined */ - int id_numfrags; /* number of frags contained in block */ - quad_t id_filesize; /* for DATA nodes, the size of the directory */ - int id_loc; /* for DATA nodes, current location in dir */ - int id_entryno; /* for DATA nodes, current entry number */ - struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ - char *id_name; /* for DATA nodes, name to find or enter */ - char id_type; /* type of descriptor, DATA or ADDR */ -}; -/* file types */ -#define DATA 1 /* a directory */ -#define SNAP 2 /* a snapshot */ -#define ADDR 3 /* anything but a directory or a snapshot */ - -/* - * Linked list of duplicate blocks. - * - * The list is composed of two parts. The first part of the - * list (from duplist through the node pointed to by muldup) - * contains a single copy of each duplicate block that has been - * found. The second part of the list (from muldup to the end) - * contains duplicate blocks that have been found more than once. - * To check if a block has been found as a duplicate it is only - * necessary to search from duplist through muldup. To find the - * total number of times that a block has been found as a duplicate - * the entire list must be searched for occurences of the block - * in question. The following diagram shows a sample list where - * w (found twice), x (found once), y (found three times), and z - * (found once) are duplicate block numbers: - * - * w -> y -> x -> z -> y -> w -> y - * ^ ^ - * | | - * duplist muldup - */ -struct dups { - struct dups *next; - ufs_daddr_t dup; -}; -struct dups *duplist; /* head of dup list */ -struct dups *muldup; /* end of unique duplicate dup block numbers */ - -/* - * Linked list of inodes with zero link counts. - */ -struct zlncnt { - struct zlncnt *next; - ino_t zlncnt; -}; -struct zlncnt *zlnhead; /* head of zero link count list */ - -/* - * Inode cache data structures. - */ -struct inoinfo { - struct inoinfo *i_nexthash; /* next entry in hash chain */ - ino_t i_number; /* inode number of this entry */ - ino_t i_parent; /* inode number of parent */ - ino_t i_dotdot; /* inode number of `..' */ - size_t i_isize; /* size of inode */ - u_int i_numblks; /* size of block array in bytes */ - ufs_daddr_t i_blks[1]; /* actually longer */ -} **inphead, **inpsort; -long numdirs, dirhash, listmax, inplast; -long countdirs; /* number of directories we actually found */ - -char *cdevname; /* name of device being checked */ -long dev_bsize; /* computed value of DEV_BSIZE */ -long secsize; /* actual disk sector size */ -char fflag; /* force check, ignore clean flag */ -char nflag; /* assume a no response */ -char yflag; /* assume a yes response */ -int bflag; /* location of alternate super block */ -int debug; /* output debugging info */ -int cvtlevel; /* convert to newer file system format */ -int doinglevel1; /* converting to new cylinder group format */ -int doinglevel2; /* converting to new inode format */ -int newinofmt; /* filesystem has new inode format */ -char usedsoftdep; /* just fix soft dependency inconsistencies */ -char preen; /* just fix normal inconsistencies */ -char rerun; /* rerun fsck. Only used in non-preen mode */ -int returntosingle; /* 1 => return to single user mode on exit */ -char resolved; /* cleared if unresolved changes => not clean */ -char havesb; /* superblock has been read */ -int fsmodified; /* 1 => write done to file system */ -int fsreadfd; /* file descriptor for reading file system */ -int fswritefd; /* file descriptor for writing file system */ - -ufs_daddr_t maxfsblock; /* number of blocks in the file system */ -char *blockmap; /* ptr to primary blk allocation map */ -ino_t maxino; /* number of inodes in file system */ - -ino_t lfdir; /* lost & found directory inode number */ -char *lfname; /* lost & found directory name */ -int lfmode; /* lost & found directory creation mode */ - -ufs_daddr_t n_blks; /* number of blocks in use */ -ufs_daddr_t n_files; /* number of files in use */ - -#define clearinode(dp) (*(dp) = zino) -struct dinode zino; - -#define setbmap(blkno) setbit(blockmap, blkno) -#define testbmap(blkno) isset(blockmap, blkno) -#define clrbmap(blkno) clrbit(blockmap, blkno) - -#define STOP 0x01 -#define SKIP 0x02 -#define KEEPON 0x04 -#define ALTERED 0x08 -#define FOUND 0x10 - -#define EEXIT 8 /* Standard error exit. */ - -struct fstab; - - -void adjust __P((struct inodesc *, int lcnt)); -ufs_daddr_t allocblk __P((long frags)); -ino_t allocdir __P((ino_t parent, ino_t request, int mode)); -ino_t allocino __P((ino_t request, int type)); -void blkerror __P((ino_t ino, char *type, ufs_daddr_t blk)); -char *blockcheck __P((char *name)); -int bread __P((int fd, char *buf, ufs_daddr_t blk, long size)); -void bufinit __P((void)); -void bwrite __P((int fd, char *buf, ufs_daddr_t blk, long size)); -void cacheino __P((struct dinode *dp, ino_t inumber)); -void catch __P((int)); -void catchquit __P((int)); -int changeino __P((ino_t dir, char *name, ino_t newnum)); -int checkfstab __P((int preen, int maxrun, - int (*docheck)(struct fstab *), - int (*chkit)(char *, char *, long, int))); -int chkrange __P((ufs_daddr_t blk, int cnt)); -void ckfini __P((int markclean)); -int ckinode __P((struct dinode *dp, struct inodesc *)); -void clri __P((struct inodesc *, char *type, int flag)); -int clearentry __P((struct inodesc *)); -void direrror __P((ino_t ino, char *errmesg)); -int dirscan __P((struct inodesc *)); -int dofix __P((struct inodesc *, char *msg)); -void ffs_clrblock __P((struct fs *, u_char *, ufs_daddr_t)); -void ffs_fragacct __P((struct fs *, int, int32_t [], int)); -int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t)); -void ffs_setblock __P((struct fs *, u_char *, ufs_daddr_t)); -void fileerror __P((ino_t cwd, ino_t ino, char *errmesg)); -int findino __P((struct inodesc *)); -int findname __P((struct inodesc *)); -void flush __P((int fd, struct bufarea *bp)); -void freeblk __P((ufs_daddr_t blkno, long frags)); -void freeino __P((ino_t ino)); -void freeinodebuf __P((void)); -int ftypeok __P((struct dinode *dp)); -void getblk __P((struct bufarea *bp, ufs_daddr_t blk, long size)); -struct bufarea *getdatablk __P((ufs_daddr_t blkno, long size)); -struct inoinfo *getinoinfo __P((ino_t inumber)); -struct dinode *getnextinode __P((ino_t inumber)); -void getpathname __P((char *namebuf, ino_t curdir, ino_t ino)); -struct dinode *ginode __P((ino_t inumber)); -void inocleanup __P((void)); -void inodirty __P((void)); -struct inostat *inoinfo __P((ino_t inum)); -int linkup __P((ino_t orphan, ino_t parentdir, char *name)); -int makeentry __P((ino_t parent, ino_t ino, char *name)); -void panic __P((const char *fmt, ...)); -void pass1 __P((void)); -void pass1b __P((void)); -int pass1check __P((struct inodesc *)); -void pass2 __P((void)); -void pass3 __P((void)); -void pass4 __P((void)); -int pass4check __P((struct inodesc *)); -void pass5 __P((void)); -void pfatal __P((const char *fmt, ...)); -void pinode __P((ino_t ino)); -void propagate __P((void)); -void pwarn __P((const char *fmt, ...)); -int reply __P((char *question)); -void setinodebuf __P((ino_t)); -int setup __P((char *dev)); -void voidquit __P((int)); diff --git a/sbin/fsck/fsutil.c b/sbin/fsck/fsutil.c new file mode 100644 index 0000000..f83c936 --- /dev/null +++ b/sbin/fsck/fsutil.c @@ -0,0 +1,363 @@ +/* $NetBSD: fsutil.c,v 1.7 1998/07/30 17:41:03 thorpej Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: fsutil.c,v 1.7 1998/07/30 17:41:03 thorpej Exp $"); +#endif /* not lint */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <errno.h> +#include <fstab.h> +#include <err.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include "fsutil.h" + +static const char *dev = NULL; +static int hot = 0; +static int preen = 0; + +extern char *__progname; + +static void vmsg __P((int, const char *, va_list)); + +void +setcdevname(cd, pr) + const char *cd; + int pr; +{ + dev = cd; + preen = pr; +} + +const char * +cdevname() +{ + return dev; +} + +int +hotroot() +{ + return hot; +} + +/*VARARGS*/ +void +#if __STDC__ +errexit(const char *fmt, ...) +#else +errexit(va_alist) + va_dcl +#endif +{ + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + const char *fmt; + + va_start(ap); + fmt = va_arg(ap, const char *); +#endif + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + exit(8); +} + +static void +vmsg(fatal, fmt, ap) + int fatal; + const char *fmt; + va_list ap; +{ + if (!fatal && preen) + (void) printf("%s: ", dev); + + (void) vprintf(fmt, ap); + + if (fatal && preen) + (void) printf("\n"); + + if (fatal && preen) { + (void) printf( + "%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n", + dev, __progname); + exit(8); + } +} + +/*VARARGS*/ +void +#if __STDC__ +pfatal(const char *fmt, ...) +#else +pfatal(va_alist) + va_dcl +#endif +{ + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + const char *fmt; + + va_start(ap); + fmt = va_arg(ap, const char *); +#endif + vmsg(1, fmt, ap); + va_end(ap); +} + +/*VARARGS*/ +void +#if __STDC__ +pwarn(const char *fmt, ...) +#else +pwarn(va_alist) + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + const char *fmt; + + va_start(ap); + fmt = va_arg(ap, const char *); +#endif + vmsg(0, fmt, ap); + va_end(ap); +} + +void +perror(s) + const char *s; +{ + pfatal("%s (%s)", s, strerror(errno)); +} + +void +#if __STDC__ +panic(const char *fmt, ...) +#else +panic(va_alist) + va_dcl +#endif +{ + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + const char *fmt; + + va_start(ap); + fmt = va_arg(ap, const char *); +#endif + vmsg(1, fmt, ap); + va_end(ap); + exit(8); +} + +const char * +unrawname(name) + const char *name; +{ + static char unrawbuf[32]; + const char *dp; + struct stat stb; + + if ((dp = strrchr(name, '/')) == 0) + return (name); + if (stat(name, &stb) < 0) + return (name); + if (!S_ISCHR(stb.st_mode)) + return (name); + if (dp[1] != 'r') + return (name); + (void)snprintf(unrawbuf, 32, "%.*s/%s", (int)(dp - name), name, dp + 2); + return (unrawbuf); +} + +const char * +rawname(name) + const char *name; +{ + static char rawbuf[32]; + const char *dp; + + if ((dp = strrchr(name, '/')) == 0) + return (0); + (void)snprintf(rawbuf, 32, "%.*s/r%s", (int)(dp - name), name, dp + 1); + return (rawbuf); +} + +const char * +devcheck(origname) + const char *origname; +{ + struct stat stslash, stchar; + + if (stat("/", &stslash) < 0) { + perror("/"); + printf("Can't stat root\n"); + return (origname); + } + if (stat(origname, &stchar) < 0) { + perror(origname); + printf("Can't stat %s\n", origname); + return (origname); + } + if (!S_ISCHR(stchar.st_mode)) { + perror(origname); + printf("%s is not a char device\n", origname); + } + return (origname); +} + +#if 0 +/* + * XXX this code is from NetBSD, but fails in FreeBSD because we + * don't have blockdevs. I don't think its needed. + */ +const char * +blockcheck(origname) + const char *origname; +{ + struct stat stslash, stblock, stchar; + const char *newname, *raw; + struct fstab *fsp; + int retried = 0; + + hot = 0; + if (stat("/", &stslash) < 0) { + perror("/"); + printf("Can't stat root\n"); + return (origname); + } + newname = origname; +retry: + if (stat(newname, &stblock) < 0) { + perror(newname); + printf("Can't stat %s\n", newname); + return (origname); + } + if (S_ISBLK(stblock.st_mode)) { + if (stslash.st_dev == stblock.st_rdev) + hot++; + raw = rawname(newname); + if (stat(raw, &stchar) < 0) { + perror(raw); + printf("Can't stat %s\n", raw); + return (origname); + } + if (S_ISCHR(stchar.st_mode)) { + return (raw); + } else { + printf("%s is not a character device\n", raw); + return (origname); + } + } else if (S_ISCHR(stblock.st_mode) && !retried) { + newname = unrawname(newname); + retried++; + goto retry; + } else if ((fsp = getfsfile(newname)) != 0 && !retried) { + newname = fsp->fs_spec; + retried++; + goto retry; + } + /* + * Not a block or character device, just return name and + * let the user decide whether to use it. + */ + return (origname); +} +#endif + + +void * +emalloc(s) + size_t s; +{ + void *p; + + p = malloc(s); + if (p == NULL) + err(1, "malloc failed"); + return (p); +} + + +void * +erealloc(p, s) + void *p; + size_t s; +{ + void *q; + + q = realloc(p, s); + if (q == NULL) + err(1, "realloc failed"); + return (q); +} + + +char * +estrdup(s) + const char *s; +{ + char *p; + + p = strdup(s); + if (p == NULL) + err(1, "strdup failed"); + return (p); +} diff --git a/sbin/fsck/fsutil.h b/sbin/fsck/fsutil.h new file mode 100644 index 0000000..98c4506 --- /dev/null +++ b/sbin/fsck/fsutil.h @@ -0,0 +1,62 @@ +/* $NetBSD: fsutil.h,v 1.4 1998/07/26 20:02:36 mycroft Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +void perror __P((const char *)); +void errexit __P((const char *, ...)) + __attribute__((__noreturn__,__format__(__printf__,1,2))); +void pfatal __P((const char *, ...)) + __attribute__((__format__(__printf__,1,2))); +void pwarn __P((const char *, ...)) + __attribute__((__format__(__printf__,1,2))); +void panic __P((const char *, ...)) + __attribute__((__noreturn__,__format__(__printf__,1,2))); +const char *rawname __P((const char *)); +const char *unrawname __P((const char *)); +#if 0 +const char *blockcheck __P((const char *)); +#endif +const char *devcheck __P((const char *)); +const char *cdevname __P((void)); +void setcdevname __P((const char *, int)); +int hotroot __P((void)); +void *emalloc __P((size_t)); +void *erealloc __P((void *, size_t)); +char *estrdup __P((const char *)); + +#define CHECK_PREEN 1 +#define CHECK_VERBOSE 2 +#define CHECK_DEBUG 4 + +struct fstab; +int checkfstab __P((int, int, void *(*)(struct fstab *), + int (*) (const char *, const char *, const char *, void *, pid_t *))); diff --git a/sbin/fsck/inode.c b/sbin/fsck/inode.c deleted file mode 100644 index 8b2f14b..0000000 --- a/sbin/fsck/inode.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <pwd.h> -#include <string.h> - -#include "fsck.h" - -static ino_t startinum; - -static int iblock __P((struct inodesc *, long ilevel, quad_t isize)); - -int -ckinode(dp, idesc) - struct dinode *dp; - register struct inodesc *idesc; -{ - ufs_daddr_t *ap; - int ret; - long n, ndb, offset; - struct dinode dino; - quad_t remsize, sizepb; - mode_t mode; - char pathbuf[MAXPATHLEN + 1]; - - if (idesc->id_fix != IGNORE) - idesc->id_fix = DONTKNOW; - idesc->id_lbn = -1; - idesc->id_entryno = 0; - idesc->id_filesize = dp->di_size; - mode = dp->di_mode & IFMT; - if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && - dp->di_size < (unsigned)sblock.fs_maxsymlinklen)) - return (KEEPON); - dino = *dp; - ndb = howmany(dino.di_size, sblock.fs_bsize); - for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { - idesc->id_lbn++; - if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) - idesc->id_numfrags = - numfrags(&sblock, fragroundup(&sblock, offset)); - else - idesc->id_numfrags = sblock.fs_frag; - if (*ap == 0) { - if (idesc->id_type == DATA && ndb >= 0) { - /* An empty block in a directory XXX */ - getpathname(pathbuf, idesc->id_number, - idesc->id_number); - pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", - pathbuf); - if (reply("ADJUST LENGTH") == 1) { - dp = ginode(idesc->id_number); - dp->di_size = (ap - &dino.di_db[0]) * - sblock.fs_bsize; - printf( - "YOU MUST RERUN FSCK AFTERWARDS\n"); - rerun = 1; - inodirty(); - - } - } - continue; - } - idesc->id_blkno = *ap; - if (idesc->id_type != DATA) - ret = (*idesc->id_func)(idesc); - else - ret = dirscan(idesc); - if (ret & STOP) - return (ret); - } - idesc->id_numfrags = sblock.fs_frag; - remsize = dino.di_size - sblock.fs_bsize * NDADDR; - sizepb = sblock.fs_bsize; - for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { - sizepb *= NINDIR(&sblock); - if (*ap) { - idesc->id_blkno = *ap; - ret = iblock(idesc, n, remsize); - if (ret & STOP) - return (ret); - } else { - idesc->id_lbn += sizepb / sblock.fs_bsize; - if (idesc->id_type == DATA && remsize > 0) { - /* An empty block in a directory XXX */ - getpathname(pathbuf, idesc->id_number, - idesc->id_number); - pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", - pathbuf); - if (reply("ADJUST LENGTH") == 1) { - dp = ginode(idesc->id_number); - dp->di_size -= remsize; - remsize = 0; - printf( - "YOU MUST RERUN FSCK AFTERWARDS\n"); - rerun = 1; - inodirty(); - break; - } - } - } - remsize -= sizepb; - } - return (KEEPON); -} - -static int -iblock(idesc, ilevel, isize) - struct inodesc *idesc; - long ilevel; - quad_t isize; -{ - ufs_daddr_t *ap; - ufs_daddr_t *aplim; - struct bufarea *bp; - int i, n, (*func)(), nif; - quad_t sizepb; - char buf[BUFSIZ]; - char pathbuf[MAXPATHLEN + 1]; - struct dinode *dp; - - if (idesc->id_type != DATA) { - func = idesc->id_func; - if (((n = (*func)(idesc)) & KEEPON) == 0) - return (n); - } else - func = dirscan; - if (chkrange(idesc->id_blkno, idesc->id_numfrags)) - return (SKIP); - bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); - ilevel--; - for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) - sizepb *= NINDIR(&sblock); - nif = howmany(isize , sizepb); - if (nif > NINDIR(&sblock)) - nif = NINDIR(&sblock); - if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { - aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; - for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { - if (*ap == 0) - continue; - (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", - (u_long)idesc->id_number); - if (dofix(idesc, buf)) { - *ap = 0; - dirty(bp); - } - } - flush(fswritefd, bp); - } - aplim = &bp->b_un.b_indir[nif]; - for (ap = bp->b_un.b_indir; ap < aplim; ap++) { - if (ilevel == 0) - idesc->id_lbn++; - if (*ap) { - idesc->id_blkno = *ap; - if (ilevel == 0) - n = (*func)(idesc); - else - n = iblock(idesc, ilevel, isize); - if (n & STOP) { - bp->b_flags &= ~B_INUSE; - return (n); - } - } else { - if (idesc->id_type == DATA && isize > 0) { - /* An empty block in a directory XXX */ - getpathname(pathbuf, idesc->id_number, - idesc->id_number); - pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", - pathbuf); - if (reply("ADJUST LENGTH") == 1) { - dp = ginode(idesc->id_number); - dp->di_size -= isize; - isize = 0; - printf( - "YOU MUST RERUN FSCK AFTERWARDS\n"); - rerun = 1; - inodirty(); - bp->b_flags &= ~B_INUSE; - return(STOP); - } - } - } - isize -= sizepb; - } - bp->b_flags &= ~B_INUSE; - return (KEEPON); -} - -/* - * Check that a block in a legal block number. - * Return 0 if in range, 1 if out of range. - */ -int -chkrange(blk, cnt) - ufs_daddr_t blk; - int cnt; -{ - register int c; - - if (cnt <= 0 || blk <= 0 || blk > maxfsblock || - cnt - 1 > maxfsblock - blk) - return (1); - if (cnt > sblock.fs_frag || - fragnum(&sblock, blk) + cnt > sblock.fs_frag) { - if (debug) - printf("bad size: blk %ld, offset %ld, size %ld\n", - blk, fragnum(&sblock, blk), cnt); - return (1); - } - c = dtog(&sblock, blk); - if (blk < cgdmin(&sblock, c)) { - if ((blk + cnt) > cgsblock(&sblock, c)) { - if (debug) { - printf("blk %ld < cgdmin %ld;", - (long)blk, (long)cgdmin(&sblock, c)); - printf(" blk + cnt %ld > cgsbase %ld\n", - (long)(blk + cnt), - (long)cgsblock(&sblock, c)); - } - return (1); - } - } else { - if ((blk + cnt) > cgbase(&sblock, c+1)) { - if (debug) { - printf("blk %ld >= cgdmin %ld;", - (long)blk, (long)cgdmin(&sblock, c)); - printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", - (long)(blk + cnt), (long)sblock.fs_fpg); - } - return (1); - } - } - return (0); -} - -/* - * General purpose interface for reading inodes. - */ -struct dinode * -ginode(inumber) - ino_t inumber; -{ - ufs_daddr_t iblk; - - if (inumber < ROOTINO || inumber > maxino) - errx(EEXIT, "bad inode number %d to ginode", inumber); - if (startinum == 0 || - inumber < startinum || inumber >= startinum + INOPB(&sblock)) { - iblk = ino_to_fsba(&sblock, inumber); - if (pbp != 0) - pbp->b_flags &= ~B_INUSE; - pbp = getdatablk(iblk, sblock.fs_bsize); - startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); - } - return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); -} - -/* - * Special purpose version of ginode used to optimize first pass - * over all the inodes in numerical order. - */ -ino_t nextino, lastinum, lastvalidinum; -long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; -struct dinode *inodebuf; - -struct dinode * -getnextinode(inumber) - ino_t inumber; -{ - long size; - ufs_daddr_t dblk; - static struct dinode *dp; - - if (inumber != nextino++ || inumber > lastvalidinum) - errx(EEXIT, "bad inode number %d to nextinode", inumber); - if (inumber >= lastinum) { - readcnt++; - dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); - if (readcnt % readpercg == 0) { - size = partialsize; - lastinum += partialcnt; - } else { - size = inobufsize; - lastinum += fullcnt; - } - /* - * If bread returns an error, it will already have zeroed - * out the buffer, so we do not need to do so here. - */ - (void)bread(fsreadfd, (char *)inodebuf, dblk, size); - dp = inodebuf; - } - return (dp++); -} - -void -setinodebuf(inum) - ino_t inum; -{ - - if (inum % sblock.fs_ipg != 0) - errx(EEXIT, "bad inode number %d to setinodebuf", inum); - lastvalidinum = inum + sblock.fs_ipg - 1; - startinum = 0; - nextino = inum; - lastinum = inum; - readcnt = 0; - if (inodebuf != NULL) - return; - inobufsize = blkroundup(&sblock, INOBUFSIZE); - fullcnt = inobufsize / sizeof(struct dinode); - readpercg = sblock.fs_ipg / fullcnt; - partialcnt = sblock.fs_ipg % fullcnt; - partialsize = partialcnt * sizeof(struct dinode); - if (partialcnt != 0) { - readpercg++; - } else { - partialcnt = fullcnt; - partialsize = inobufsize; - } - if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) - errx(EEXIT, "cannot allocate space for inode buffer"); -} - -void -freeinodebuf() -{ - - if (inodebuf != NULL) - free((char *)inodebuf); - inodebuf = NULL; -} - -/* - * Routines to maintain information about directory inodes. - * This is built during the first pass and used during the - * second and third passes. - * - * Enter inodes into the cache. - */ -void -cacheino(dp, inumber) - register struct dinode *dp; - ino_t inumber; -{ - register struct inoinfo *inp; - struct inoinfo **inpp; - int blks; - - blks = howmany(dp->di_size, sblock.fs_bsize); - if (blks > NDADDR) - blks = NDADDR + NIADDR; - inp = (struct inoinfo *) - malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); - if (inp == NULL) - errx(EEXIT, "cannot increase directory list"); - inpp = &inphead[inumber % dirhash]; - inp->i_nexthash = *inpp; - *inpp = inp; - inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; - inp->i_dotdot = (ino_t)0; - inp->i_number = inumber; - inp->i_isize = dp->di_size; - inp->i_numblks = blks * sizeof(ufs_daddr_t); - memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); - if (inplast == listmax) { - listmax += 100; - inpsort = (struct inoinfo **)realloc((char *)inpsort, - (unsigned)listmax * sizeof(struct inoinfo *)); - if (inpsort == NULL) - errx(EEXIT, "cannot increase directory list"); - } - inpsort[inplast++] = inp; -} - -/* - * Look up an inode cache structure. - */ -struct inoinfo * -getinoinfo(inumber) - ino_t inumber; -{ - register struct inoinfo *inp; - - for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { - if (inp->i_number != inumber) - continue; - return (inp); - } - errx(EEXIT, "cannot find inode %d", inumber); - return ((struct inoinfo *)0); -} - -/* - * Clean up all the inode cache structure. - */ -void -inocleanup() -{ - register struct inoinfo **inpp; - - if (inphead == NULL) - return; - for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) - free((char *)(*inpp)); - free((char *)inphead); - free((char *)inpsort); - inphead = inpsort = NULL; -} - -void -inodirty() -{ - - dirty(pbp); -} - -void -clri(idesc, type, flag) - register struct inodesc *idesc; - char *type; - int flag; -{ - register struct dinode *dp; - - dp = ginode(idesc->id_number); - if (flag == 1) { - pwarn("%s %s", type, - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); - pinode(idesc->id_number); - } - if (preen || reply("CLEAR") == 1) { - if (preen) - printf(" (CLEARED)\n"); - n_files--; - (void)ckinode(dp, idesc); - clearinode(dp); - inoinfo(idesc->id_number)->ino_state = USTATE; - inodirty(); - } -} - -int -findname(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { - idesc->id_entryno++; - return (KEEPON); - } - memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); - return (STOP|FOUND); -} - -int -findino(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (dirp->d_ino == 0) - return (KEEPON); - if (strcmp(dirp->d_name, idesc->id_name) == 0 && - dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { - idesc->id_parent = dirp->d_ino; - return (STOP|FOUND); - } - return (KEEPON); -} - -int -clearentry(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { - idesc->id_entryno++; - return (KEEPON); - } - dirp->d_ino = 0; - return (STOP|FOUND|ALTERED); -} - -void -pinode(ino) - ino_t ino; -{ - register struct dinode *dp; - register char *p; - struct passwd *pw; - time_t t; - - printf(" I=%lu ", (u_long)ino); - if (ino < ROOTINO || ino > maxino) - return; - dp = ginode(ino); - printf(" OWNER="); - if ((pw = getpwuid((int)dp->di_uid)) != 0) - printf("%s ", pw->pw_name); - else - printf("%u ", (unsigned)dp->di_uid); - printf("MODE=%o\n", dp->di_mode); - if (preen) - printf("%s: ", cdevname); - printf("SIZE=%qu ", dp->di_size); - t = dp->di_mtime; - p = ctime(&t); - printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); -} - -void -blkerror(ino, type, blk) - ino_t ino; - char *type; - ufs_daddr_t blk; -{ - - pfatal("%ld %s I=%lu", blk, type, ino); - printf("\n"); - switch (inoinfo(ino)->ino_state) { - - case FSTATE: - inoinfo(ino)->ino_state = FCLEAR; - return; - - case DSTATE: - inoinfo(ino)->ino_state = DCLEAR; - return; - - case FCLEAR: - case DCLEAR: - return; - - default: - errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state); - /* NOTREACHED */ - } -} - -/* - * allocate an unused inode - */ -ino_t -allocino(request, type) - ino_t request; - int type; -{ - register ino_t ino; - register struct dinode *dp; - struct cg *cgp = &cgrp; - int cg; - - if (request == 0) - request = ROOTINO; - else if (inoinfo(request)->ino_state != USTATE) - return (0); - for (ino = request; ino < maxino; ino++) - if (inoinfo(ino)->ino_state == USTATE) - break; - if (ino == maxino) - return (0); - cg = ino_to_cg(&sblock, ino); - getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); - if (!cg_chkmagic(cgp)) - pfatal("CG %d: BAD MAGIC NUMBER\n", cg); - setbit(cg_inosused(cgp), ino % sblock.fs_ipg); - cgp->cg_cs.cs_nifree--; - switch (type & IFMT) { - case IFDIR: - inoinfo(ino)->ino_state = DSTATE; - cgp->cg_cs.cs_ndir++; - break; - case IFREG: - case IFLNK: - inoinfo(ino)->ino_state = FSTATE; - break; - default: - return (0); - } - cgdirty(); - dp = ginode(ino); - dp->di_db[0] = allocblk((long)1); - if (dp->di_db[0] == 0) { - inoinfo(ino)->ino_state = USTATE; - return (0); - } - dp->di_mode = type; - dp->di_flags = 0; - dp->di_atime = time(NULL); - dp->di_mtime = dp->di_ctime = dp->di_atime; - dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; - dp->di_size = sblock.fs_fsize; - dp->di_blocks = btodb(sblock.fs_fsize); - n_files++; - inodirty(); - if (newinofmt) - inoinfo(ino)->ino_type = IFTODT(type); - return (ino); -} - -/* - * deallocate an inode - */ -void -freeino(ino) - ino_t ino; -{ - struct inodesc idesc; - struct dinode *dp; - - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - idesc.id_number = ino; - dp = ginode(ino); - (void)ckinode(dp, &idesc); - clearinode(dp); - inodirty(); - inoinfo(ino)->ino_state = USTATE; - n_files--; -} diff --git a/sbin/fsck/main.c b/sbin/fsck/main.c deleted file mode 100644 index 6463990..0000000 --- a/sbin/fsck/main.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1980, 1986, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/mount.h> -#include <sys/resource.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/ufsmount.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <errno.h> -#include <fstab.h> -#include <paths.h> - -#include "fsck.h" - -static int argtoi __P((int flag, char *req, char *str, int base)); -static int docheck __P((struct fstab *fsp)); -static int checkfilesys __P((char *filesys, char *mntpt, long auxdata, - int child)); -static struct statfs *getmntpt __P((const char *)); -int main __P((int argc, char *argv[])); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int ch; - int ret, maxrun = 0; - struct rlimit rlimit; - - sync(); - while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != -1) { - switch (ch) { - case 'p': - preen++; - break; - - case 'b': - bflag = argtoi('b', "number", optarg, 10); - printf("Alternate super block location: %d\n", bflag); - break; - - case 'c': - cvtlevel = argtoi('c', "conversion level", optarg, 10); - break; - - case 'd': - debug++; - break; - - case 'f': - fflag++; - break; - - case 'l': - maxrun = argtoi('l', "number", optarg, 10); - break; - - case 'm': - lfmode = argtoi('m', "mode", optarg, 8); - if (lfmode &~ 07777) - errx(EEXIT, "bad mode to -m: %o", lfmode); - printf("** lost+found creation mode %o\n", lfmode); - break; - - case 'n': - case 'N': - nflag++; - yflag = 0; - break; - - case 'y': - case 'Y': - yflag++; - nflag = 0; - break; - - default: - errx(EEXIT, "%c option?", ch); - } - } - argc -= optind; - argv += optind; - if (signal(SIGINT, SIG_IGN) != SIG_IGN) - (void)signal(SIGINT, catch); - if (preen) - (void)signal(SIGQUIT, catchquit); - /* - * Push up our allowed memory limit so we can cope - * with huge filesystems. - */ - if (getrlimit(RLIMIT_DATA, &rlimit) == 0) { - rlimit.rlim_cur = rlimit.rlim_max; - (void)setrlimit(RLIMIT_DATA, &rlimit); - } - if (argc) { - while (argc-- > 0) { - char *path = blockcheck(*argv); - - if (path == NULL) - pfatal("Can't check %s\n", *argv); - else - (void)checkfilesys(path, 0, 0L, 0); - ++argv; - } - exit(0); - } - ret = checkfstab(preen, maxrun, docheck, checkfilesys); - if (returntosingle) - exit(2); - exit(ret); -} - -static int -argtoi(flag, req, str, base) - int flag; - char *req, *str; - int base; -{ - char *cp; - int ret; - - ret = (int)strtol(str, &cp, base); - if (cp == str || *cp) - errx(EEXIT, "-%c flag requires a %s", flag, req); - return (ret); -} - -/* - * Determine whether a filesystem should be checked. - */ -static int -docheck(fsp) - register struct fstab *fsp; -{ - - if (strcmp(fsp->fs_vfstype, "ufs") || - (strcmp(fsp->fs_type, FSTAB_RW) && - strcmp(fsp->fs_type, FSTAB_RO)) || - fsp->fs_passno == 0) - return (0); - return (1); -} - -/* - * Check the specified filesystem. - */ -/* ARGSUSED */ -static int -checkfilesys(filesys, mntpt, auxdata, child) - char *filesys, *mntpt; - long auxdata; - int child; -{ - ufs_daddr_t n_ffree, n_bfree; - struct dups *dp; - struct statfs *mntbuf; - struct zlncnt *zlnp; - int cylno; - - if (preen && child) - (void)signal(SIGQUIT, voidquit); - cdevname = filesys; - if (debug && preen) - pwarn("starting\n"); - switch (setup(filesys)) { - case 0: - if (preen) - pfatal("CAN'T CHECK FILE SYSTEM."); - return (0); - case -1: - pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree + - sblock.fs_frag * sblock.fs_cstotal.cs_nbfree); - printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", - sblock.fs_cstotal.cs_nffree, sblock.fs_cstotal.cs_nbfree, - sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize); - return (0); - } - - /* - * Get the mount point information of the filesystem, if - * it is available. - */ - mntbuf = getmntpt(filesys); - - /* - * Cleared if any questions answered no. Used to decide if - * the superblock should be marked clean. - */ - resolved = 1; - /* - * 1: scan inodes tallying blocks used - */ - if (preen == 0) { - printf("** Last Mounted on %s\n", sblock.fs_fsmnt); - if (mntbuf != NULL && mntbuf->f_flags & MNT_ROOTFS) - printf("** Root file system\n"); - printf("** Phase 1 - Check Blocks and Sizes\n"); - } - pass1(); - - /* - * 1b: locate first references to duplicates, if any - */ - if (duplist) { - if (preen || usedsoftdep) - pfatal("INTERNAL ERROR: dups with -p"); - printf("** Phase 1b - Rescan For More DUPS\n"); - pass1b(); - } - - /* - * 2: traverse directories from root to mark all connected directories - */ - if (preen == 0) - printf("** Phase 2 - Check Pathnames\n"); - pass2(); - - /* - * 3: scan inodes looking for disconnected directories - */ - if (preen == 0) - printf("** Phase 3 - Check Connectivity\n"); - pass3(); - - /* - * 4: scan inodes looking for disconnected files; check reference counts - */ - if (preen == 0) - printf("** Phase 4 - Check Reference Counts\n"); - pass4(); - - /* - * 5: check and repair resource counts in cylinder groups - */ - if (preen == 0) - printf("** Phase 5 - Check Cyl groups\n"); - pass5(); - - /* - * print out summary statistics - */ - n_ffree = sblock.fs_cstotal.cs_nffree; - n_bfree = sblock.fs_cstotal.cs_nbfree; - pwarn("%ld files, %ld used, %ld free ", - n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); - printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", - n_ffree, n_bfree, n_ffree * 100.0 / sblock.fs_dsize); - if (debug && - (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) - printf("%d files missing\n", n_files); - if (debug) { - n_blks += sblock.fs_ncg * - (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); - n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); - n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); - if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) - printf("%d blocks missing\n", n_blks); - if (duplist != NULL) { - printf("The following duplicate blocks remain:"); - for (dp = duplist; dp; dp = dp->next) - printf(" %d,", dp->dup); - printf("\n"); - } - if (zlnhead != NULL) { - printf("The following zero link count inodes remain:"); - for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) - printf(" %u,", zlnp->zlncnt); - printf("\n"); - } - } - zlnhead = (struct zlncnt *)0; - duplist = (struct dups *)0; - muldup = (struct dups *)0; - inocleanup(); - if (fsmodified) { - sblock.fs_time = time(NULL); - sbdirty(); - } - if (cvtlevel && sblk.b_dirty) { - /* - * Write out the duplicate super blocks - */ - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) - bwrite(fswritefd, (char *)&sblock, - fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); - } - if (rerun) - resolved = 0; - - /* - * Check to see if the filesystem is mounted read-write. - */ - if (mntbuf != NULL && (mntbuf->f_flags & MNT_RDONLY) == 0) - resolved = 0; - ckfini(resolved); - - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) - if (inostathead[cylno].il_stat != NULL) - free((char *)inostathead[cylno].il_stat); - free((char *)inostathead); - inostathead = NULL; - if (fsmodified && !preen) - printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - if (rerun) - printf("\n***** PLEASE RERUN FSCK *****\n"); - if (mntbuf != NULL) { - struct ufs_args args; - int ret; - /* - * We modified a mounted filesystem. Do a mount update on - * it unless it is read-write, so we can continue using it - * as safely as possible. - */ - if (mntbuf->f_flags & MNT_RDONLY) { - args.fspec = 0; - args.export.ex_flags = 0; - args.export.ex_root = 0; - ret = mount("ufs", mntbuf->f_mntonname, - mntbuf->f_flags | MNT_UPDATE | MNT_RELOAD, &args); - if (ret == 0) - return (0); - pwarn("mount reload of '%s' failed: %s\n\n", - mntbuf->f_mntonname, strerror(errno)); - } - if (!fsmodified) - return (0); - if (!preen) - printf("\n***** REBOOT NOW *****\n"); - sync(); - return (4); - } - return (0); -} - -/* - * Get the directory that the device is mounted on. - */ -static struct statfs * -getmntpt(name) - const char *name; -{ - struct stat devstat, mntdevstat; - char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; - char *devname; - struct statfs *mntbuf; - int i, mntsize; - - if (stat(name, &devstat) != 0 || - !(S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))) - return (NULL); - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - for (i = 0; i < mntsize; i++) { - if (strcmp(mntbuf[i].f_fstypename, "ufs") != 0) - continue; - devname = mntbuf[i].f_mntfromname; - if (*devname != '/') { - strcpy(device, _PATH_DEV); - strcat(device, devname); - devname = device; - } - if (stat(devname, &mntdevstat) == 0 && - mntdevstat.st_rdev == devstat.st_rdev) - return (&mntbuf[i]); - } - return (NULL); -} diff --git a/sbin/fsck/pass1.c b/sbin/fsck/pass1.c deleted file mode 100644 index fcd596b..0000000 --- a/sbin/fsck/pass1.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -static ufs_daddr_t badblk; -static ufs_daddr_t dupblk; -static ino_t lastino; /* last inode in use */ - -static void checkinode __P((ino_t inumber, struct inodesc *)); - -void -pass1() -{ - u_int8_t *cp; - ino_t inumber; - int c, i, cgd, inosused; - struct inostat *info; - struct inodesc idesc; - - /* - * Set file system reserved blocks in used block map. - */ - for (c = 0; c < sblock.fs_ncg; c++) { - cgd = cgdmin(&sblock, c); - if (c == 0) { - i = cgbase(&sblock, c); - cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); - } else - i = cgsblock(&sblock, c); - for (; i < cgd; i++) - setbmap(i); - } - /* - * Find all allocated blocks. - */ - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_func = pass1check; - n_files = n_blks = 0; - for (c = 0; c < sblock.fs_ncg; c++) { - inumber = c * sblock.fs_ipg; - setinodebuf(inumber); - inosused = sblock.fs_ipg; - /* - * If we are using soft updates, then we can trust the - * cylinder group inode allocation maps to tell us which - * inodes are allocated. We will scan the used inode map - * to find the inodes that are really in use, and then - * read only those inodes in from disk. - */ - if (preen && usedsoftdep) { - getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); - if (!cg_chkmagic(&cgrp)) - pfatal("CG %d: BAD MAGIC NUMBER\n", c); - cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY]; - for ( ; inosused > 0; inosused -= NBBY, cp--) { - if (*cp == 0) - continue; - for (i = 1 << (NBBY - 1); i > 0; i >>= 1) { - if (*cp & i) - break; - inosused--; - } - break; - } - if (inosused < 0) - inosused = 0; - } - /* - * Allocate inoinfo structures for the allocated inodes. - */ - inostathead[c].il_numalloced = inosused; - if (inosused == 0) { - inostathead[c].il_stat = 0; - continue; - } - info = calloc((unsigned)inosused, sizeof(struct inostat)); - if (info == NULL) - pfatal("cannot alloc %u bytes for inoinfo\n", - (unsigned)(sizeof(struct inostat) * inosused)); - inostathead[c].il_stat = info; - /* - * Scan the allocated inodes. - */ - for (i = 0; i < inosused; i++, inumber++) { - if (inumber < ROOTINO) { - (void)getnextinode(inumber); - continue; - } - checkinode(inumber, &idesc); - } - lastino += 1; - if (inosused < sblock.fs_ipg || inumber == lastino) - continue; - /* - * If we were not able to determine in advance which inodes - * were in use, then reduce the size of the inoinfo structure - * to the size necessary to describe the inodes that we - * really found. - */ - inosused = lastino - (c * sblock.fs_ipg); - if (inosused < 0) - inosused = 0; - inostathead[c].il_numalloced = inosused; - if (inosused == 0) { - free(inostathead[c].il_stat); - inostathead[c].il_stat = 0; - continue; - } - info = calloc((unsigned)inosused, sizeof(struct inostat)); - if (info == NULL) - pfatal("cannot alloc %u bytes for inoinfo\n", - (unsigned)(sizeof(struct inostat) * inosused)); - memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); - free(inostathead[c].il_stat); - inostathead[c].il_stat = info; - } - freeinodebuf(); -} - -static void -checkinode(inumber, idesc) - ino_t inumber; - register struct inodesc *idesc; -{ - register struct dinode *dp; - struct zlncnt *zlnp; - int ndb, j; - mode_t mode; - char *symbuf; - - dp = getnextinode(inumber); - mode = dp->di_mode & IFMT; - if (mode == 0) { - if (memcmp(dp->di_db, zino.di_db, - NDADDR * sizeof(ufs_daddr_t)) || - memcmp(dp->di_ib, zino.di_ib, - NIADDR * sizeof(ufs_daddr_t)) || - dp->di_mode || dp->di_size) { - pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); - if (reply("CLEAR") == 1) { - dp = ginode(inumber); - clearinode(dp); - inodirty(); - } - } - inoinfo(inumber)->ino_state = USTATE; - return; - } - lastino = inumber; - if (/* dp->di_size < 0 || */ - dp->di_size + sblock.fs_bsize - 1 < dp->di_size || - (mode == IFDIR && dp->di_size > MAXDIRSIZE)) { - if (debug) - printf("bad size %qu:", dp->di_size); - goto unknown; - } - if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { - dp = ginode(inumber); - dp->di_size = sblock.fs_fsize; - dp->di_mode = IFREG|0600; - inodirty(); - } - if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || - mode == IFSOCK) && dp->di_size != 0) { - if (debug) - printf("bad special-file size %qu:", dp->di_size); - goto unknown; - } - ndb = howmany(dp->di_size, sblock.fs_bsize); - if (ndb < 0) { - if (debug) - printf("bad size %qu ndb %d:", - dp->di_size, ndb); - goto unknown; - } - if (mode == IFBLK || mode == IFCHR) - ndb++; - if (mode == IFLNK) { - if (doinglevel2 && - dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && - dp->di_blocks != 0) { - symbuf = alloca(secsize); - if (bread(fsreadfd, symbuf, - fsbtodb(&sblock, dp->di_db[0]), - (long)secsize) != 0) - errx(EEXIT, "cannot read symlink"); - if (debug) { - symbuf[dp->di_size] = 0; - printf("convert symlink %lu(%s) of size %ld\n", - (u_long)inumber, symbuf, (long)dp->di_size); - } - dp = ginode(inumber); - memmove(dp->di_shortlink, symbuf, (long)dp->di_size); - dp->di_blocks = 0; - inodirty(); - } - /* - * Fake ndb value so direct/indirect block checks below - * will detect any garbage after symlink string. - */ - if (dp->di_size < sblock.fs_maxsymlinklen) { - ndb = howmany(dp->di_size, sizeof(ufs_daddr_t)); - if (ndb > NDADDR) { - j = ndb - NDADDR; - for (ndb = 1; j > 1; j--) - ndb *= NINDIR(&sblock); - ndb += NDADDR; - } - } - } - for (j = ndb; j < NDADDR; j++) - if (dp->di_db[j] != 0) { - if (debug) - printf("bad direct addr: %ld\n", - (long)dp->di_db[j]); - goto unknown; - } - for (j = 0, ndb -= NDADDR; ndb > 0; j++) - ndb /= NINDIR(&sblock); - for (; j < NIADDR; j++) - if (dp->di_ib[j] != 0) { - if (debug) - printf("bad indirect addr: %ld\n", - (long)dp->di_ib[j]); - goto unknown; - } - if (ftypeok(dp) == 0) - goto unknown; - n_files++; - inoinfo(inumber)->ino_linkcnt = dp->di_nlink; - if (dp->di_nlink <= 0) { - zlnp = (struct zlncnt *)malloc(sizeof *zlnp); - if (zlnp == NULL) { - pfatal("LINK COUNT TABLE OVERFLOW"); - if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - } else { - zlnp->zlncnt = inumber; - zlnp->next = zlnhead; - zlnhead = zlnp; - } - } - if (mode == IFDIR) { - if (dp->di_size == 0) - inoinfo(inumber)->ino_state = DCLEAR; - else - inoinfo(inumber)->ino_state = DSTATE; - cacheino(dp, inumber); - countdirs++; - } else - inoinfo(inumber)->ino_state = FSTATE; - inoinfo(inumber)->ino_type = IFTODT(mode); - if (doinglevel2 && - (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { - dp = ginode(inumber); - dp->di_uid = dp->di_ouid; - dp->di_ouid = -1; - dp->di_gid = dp->di_ogid; - dp->di_ogid = -1; - inodirty(); - } - badblk = dupblk = 0; - idesc->id_number = inumber; - if (dp->di_flags & SF_SNAPSHOT) - idesc->id_type = SNAP; - else - idesc->id_type = ADDR; - (void)ckinode(dp, idesc); - idesc->id_entryno *= btodb(sblock.fs_fsize); - if (dp->di_blocks != idesc->id_entryno) { - pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", - inumber, dp->di_blocks, idesc->id_entryno); - if (preen) - printf(" (CORRECTED)\n"); - else if (reply("CORRECT") == 0) - return; - dp = ginode(inumber); - dp->di_blocks = idesc->id_entryno; - inodirty(); - } - return; -unknown: - pfatal("UNKNOWN FILE TYPE I=%lu", inumber); - inoinfo(inumber)->ino_state = FCLEAR; - if (reply("CLEAR") == 1) { - inoinfo(inumber)->ino_state = USTATE; - dp = ginode(inumber); - clearinode(dp); - inodirty(); - } -} - -int -pass1check(idesc) - register struct inodesc *idesc; -{ - int res = KEEPON; - int anyout, nfrags; - ufs_daddr_t blkno = idesc->id_blkno; - register struct dups *dlp; - struct dups *new; - - if (idesc->id_type == SNAP) { - if (blkno == BLK_NOCOPY) - return (KEEPON); - if (idesc->id_number == cursnapshot) { - if (blkno == blkstofrags(&sblock, idesc->id_lbn)) - return (KEEPON); - if (blkno == BLK_SNAP) { - blkno = blkstofrags(&sblock, idesc->id_lbn); - idesc->id_entryno -= idesc->id_numfrags; - } - } else { - if (blkno == BLK_SNAP) - return (KEEPON); - } - } - if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { - blkerror(idesc->id_number, "BAD", blkno); - if (badblk++ >= MAXBAD) { - pwarn("EXCESSIVE BAD BLKS I=%lu", - idesc->id_number); - if (preen) - printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - return (STOP); - } - } - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (anyout && chkrange(blkno, 1)) { - res = SKIP; - } else if (!testbmap(blkno)) { - n_blks++; - setbmap(blkno); - } else { - blkerror(idesc->id_number, "DUP", blkno); - if (dupblk++ >= MAXDUP) { - pwarn("EXCESSIVE DUP BLKS I=%lu", - idesc->id_number); - if (preen) - printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - return (STOP); - } - new = (struct dups *)malloc(sizeof(struct dups)); - if (new == NULL) { - pfatal("DUP TABLE OVERFLOW."); - if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - return (STOP); - } - new->dup = blkno; - if (muldup == 0) { - duplist = muldup = new; - new->next = 0; - } else { - new->next = muldup->next; - muldup->next = new; - } - for (dlp = duplist; dlp != muldup; dlp = dlp->next) - if (dlp->dup == blkno) - break; - if (dlp == muldup && dlp->dup != blkno) - muldup = new; - } - /* - * count the number of blocks found in id_entryno - */ - idesc->id_entryno++; - } - return (res); -} diff --git a/sbin/fsck/pass1b.c b/sbin/fsck/pass1b.c deleted file mode 100644 index 7ef662f..0000000 --- a/sbin/fsck/pass1b.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass1b.c 8.4 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ffs/fs.h> - -#include <string.h> - -#include "fsck.h" - -static struct dups *duphead; -static int pass1bcheck __P((struct inodesc *)); - -void -pass1b() -{ - register int c, i; - register struct dinode *dp; - struct inodesc idesc; - ino_t inumber; - - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass1bcheck; - duphead = duplist; - inumber = 0; - for (c = 0; c < sblock.fs_ncg; c++) { - for (i = 0; i < sblock.fs_ipg; i++, inumber++) { - if (inumber < ROOTINO) - continue; - dp = ginode(inumber); - if (dp == NULL) - continue; - idesc.id_number = inumber; - if (inoinfo(inumber)->ino_state != USTATE && - (ckinode(dp, &idesc) & STOP)) - return; - } - } -} - -static int -pass1bcheck(idesc) - register struct inodesc *idesc; -{ - register struct dups *dlp; - int nfrags, res = KEEPON; - ufs_daddr_t blkno = idesc->id_blkno; - - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (chkrange(blkno, 1)) - res = SKIP; - for (dlp = duphead; dlp; dlp = dlp->next) { - if (dlp->dup == blkno) { - blkerror(idesc->id_number, "DUP", blkno); - dlp->dup = duphead->dup; - duphead->dup = blkno; - duphead = duphead->next; - } - if (dlp == muldup) - break; - } - if (muldup == 0 || duphead == muldup->next) - return (STOP); - } - return (res); -} diff --git a/sbin/fsck/pass2.c b/sbin/fsck/pass2.c deleted file mode 100644 index 088ecff..0000000 --- a/sbin/fsck/pass2.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -#define MINDIRSIZE (sizeof (struct dirtemplate)) - -static int blksort __P((const void *, const void *)); -static int pass2check __P((struct inodesc *)); - -void -pass2() -{ - register struct dinode *dp; - register struct inoinfo **inpp, *inp; - struct inoinfo **inpend; - struct inodesc curino; - struct dinode dino; - char pathbuf[MAXPATHLEN + 1]; - - switch (inoinfo(ROOTINO)->ino_state) { - - case USTATE: - pfatal("ROOT INODE UNALLOCATED"); - if (reply("ALLOCATE") == 0) { - ckfini(0); - exit(EEXIT); - } - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); - break; - - case DCLEAR: - pfatal("DUPS/BAD IN ROOT INODE"); - if (reply("REALLOCATE")) { - freeino(ROOTINO); - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); - break; - } - if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - break; - - case FSTATE: - case FCLEAR: - pfatal("ROOT INODE NOT DIRECTORY"); - if (reply("REALLOCATE")) { - freeino(ROOTINO); - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); - break; - } - if (reply("FIX") == 0) { - ckfini(0); - exit(EEXIT); - } - dp = ginode(ROOTINO); - dp->di_mode &= ~IFMT; - dp->di_mode |= IFDIR; - inodirty(); - break; - - case DSTATE: - break; - - default: - errx(EEXIT, "BAD STATE %d FOR ROOT INODE", - inoinfo(ROOTINO)->ino_state); - } - inoinfo(ROOTINO)->ino_state = DFOUND; - if (newinofmt) { - inoinfo(WINO)->ino_state = FSTATE; - inoinfo(WINO)->ino_type = DT_WHT; - } - /* - * Sort the directory list into disk block order. - */ - qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); - /* - * Check the integrity of each directory. - */ - memset(&curino, 0, sizeof(struct inodesc)); - curino.id_type = DATA; - curino.id_func = pass2check; - dp = &dino; - inpend = &inpsort[inplast]; - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_isize == 0) - continue; - if (inp->i_isize < MINDIRSIZE) { - direrror(inp->i_number, "DIRECTORY TOO SHORT"); - inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); - if (reply("FIX") == 1) { - dp = ginode(inp->i_number); - dp->di_size = inp->i_isize; - inodirty(); - dp = &dino; - } - } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { - getpathname(pathbuf, inp->i_number, inp->i_number); - if (usedsoftdep) - pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d", - "DIRECTORY", pathbuf, inp->i_isize, - DIRBLKSIZ); - else - pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d", - "DIRECTORY", pathbuf, inp->i_isize, - DIRBLKSIZ); - if (preen) - printf(" (ADJUSTED)\n"); - inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); - if (preen || reply("ADJUST") == 1) { - dp = ginode(inp->i_number); - dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); - inodirty(); - dp = &dino; - } - } - memset(&dino, 0, sizeof(struct dinode)); - dino.di_mode = IFDIR; - dp->di_size = inp->i_isize; - memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks); - curino.id_number = inp->i_number; - curino.id_parent = inp->i_parent; - (void)ckinode(dp, &curino); - } - /* - * Now that the parents of all directories have been found, - * make another pass to verify the value of `..' - */ - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_parent == 0 || inp->i_isize == 0) - continue; - if (inoinfo(inp->i_parent)->ino_state == DFOUND && - inoinfo(inp->i_number)->ino_state == DSTATE) - inoinfo(inp->i_number)->ino_state = DFOUND; - if (inp->i_dotdot == inp->i_parent || - inp->i_dotdot == (ino_t)-1) - continue; - if (inp->i_dotdot == 0) { - inp->i_dotdot = inp->i_parent; - fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); - if (reply("FIX") == 0) - continue; - (void)makeentry(inp->i_number, inp->i_parent, ".."); - inoinfo(inp->i_parent)->ino_linkcnt--; - continue; - } - fileerror(inp->i_parent, inp->i_number, - "BAD INODE NUMBER FOR '..'"); - if (reply("FIX") == 0) - continue; - inoinfo(inp->i_dotdot)->ino_linkcnt++; - inoinfo(inp->i_parent)->ino_linkcnt--; - inp->i_dotdot = inp->i_parent; - (void)changeino(inp->i_number, "..", inp->i_parent); - } - /* - * Mark all the directories that can be found from the root. - */ - propagate(); -} - -static int -pass2check(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - register struct inoinfo *inp; - int n, entrysize, ret = 0; - struct dinode *dp; - char *errmsg; - struct direct proto; - char namebuf[MAXPATHLEN + 1]; - char pathbuf[MAXPATHLEN + 1]; - - /* - * If converting, set directory entry type. - */ - if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) { - dirp->d_type = inoinfo(dirp->d_ino)->ino_type; - ret |= ALTERED; - } - /* - * check for "." - */ - if (idesc->id_entryno != 0) - goto chk1; - if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { - if (dirp->d_ino != idesc->id_number) { - direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); - dirp->d_ino = idesc->id_number; - if (reply("FIX") == 1) - ret |= ALTERED; - } - if (newinofmt && dirp->d_type != DT_DIR) { - direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); - dirp->d_type = DT_DIR; - if (reply("FIX") == 1) - ret |= ALTERED; - } - goto chk1; - } - direrror(idesc->id_number, "MISSING '.'"); - proto.d_ino = idesc->id_number; - if (newinofmt) - proto.d_type = DT_DIR; - else - proto.d_type = 0; - proto.d_namlen = 1; - (void)strcpy(proto.d_name, "."); -# if BYTE_ORDER == LITTLE_ENDIAN - if (!newinofmt) { - u_char tmp; - - tmp = proto.d_type; - proto.d_type = proto.d_namlen; - proto.d_namlen = tmp; - } -# endif - entrysize = DIRSIZ(0, &proto); - if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { - pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", - dirp->d_name); - } else if (dirp->d_reclen < entrysize) { - pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); - } else if (dirp->d_reclen < 2 * entrysize) { - proto.d_reclen = dirp->d_reclen; - memmove(dirp, &proto, (size_t)entrysize); - if (reply("FIX") == 1) - ret |= ALTERED; - } else { - n = dirp->d_reclen - entrysize; - proto.d_reclen = entrysize; - memmove(dirp, &proto, (size_t)entrysize); - idesc->id_entryno++; - inoinfo(dirp->d_ino)->ino_linkcnt--; - dirp = (struct direct *)((char *)(dirp) + entrysize); - memset(dirp, 0, (size_t)n); - dirp->d_reclen = n; - if (reply("FIX") == 1) - ret |= ALTERED; - } -chk1: - if (idesc->id_entryno > 1) - goto chk2; - inp = getinoinfo(idesc->id_number); - proto.d_ino = inp->i_parent; - if (newinofmt) - proto.d_type = DT_DIR; - else - proto.d_type = 0; - proto.d_namlen = 2; - (void)strcpy(proto.d_name, ".."); -# if BYTE_ORDER == LITTLE_ENDIAN - if (!newinofmt) { - u_char tmp; - - tmp = proto.d_type; - proto.d_type = proto.d_namlen; - proto.d_namlen = tmp; - } -# endif - entrysize = DIRSIZ(0, &proto); - if (idesc->id_entryno == 0) { - n = DIRSIZ(0, dirp); - if (dirp->d_reclen < n + entrysize) - goto chk2; - proto.d_reclen = dirp->d_reclen - n; - dirp->d_reclen = n; - idesc->id_entryno++; - inoinfo(dirp->d_ino)->ino_linkcnt--; - dirp = (struct direct *)((char *)(dirp) + n); - memset(dirp, 0, (size_t)proto.d_reclen); - dirp->d_reclen = proto.d_reclen; - } - if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { - inp->i_dotdot = dirp->d_ino; - if (newinofmt && dirp->d_type != DT_DIR) { - direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); - dirp->d_type = DT_DIR; - if (reply("FIX") == 1) - ret |= ALTERED; - } - goto chk2; - } - if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", - dirp->d_name); - inp->i_dotdot = (ino_t)-1; - } else if (dirp->d_reclen < entrysize) { - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); - inp->i_dotdot = (ino_t)-1; - } else if (inp->i_parent != 0) { - /* - * We know the parent, so fix now. - */ - inp->i_dotdot = inp->i_parent; - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - proto.d_reclen = dirp->d_reclen; - memmove(dirp, &proto, (size_t)entrysize); - if (reply("FIX") == 1) - ret |= ALTERED; - } - idesc->id_entryno++; - if (dirp->d_ino != 0) - inoinfo(dirp->d_ino)->ino_linkcnt--; - return (ret|KEEPON); -chk2: - if (dirp->d_ino == 0) - return (ret|KEEPON); - if (dirp->d_namlen <= 2 && - dirp->d_name[0] == '.' && - idesc->id_entryno >= 2) { - if (dirp->d_namlen == 1) { - direrror(idesc->id_number, "EXTRA '.' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) - ret |= ALTERED; - return (KEEPON | ret); - } - if (dirp->d_name[1] == '.') { - direrror(idesc->id_number, "EXTRA '..' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) - ret |= ALTERED; - return (KEEPON | ret); - } - } - idesc->id_entryno++; - n = 0; - if (dirp->d_ino > maxino) { - fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); - n = reply("REMOVE"); - } else if (newinofmt && - ((dirp->d_ino == WINO && dirp->d_type != DT_WHT) || - (dirp->d_ino != WINO && dirp->d_type == DT_WHT))) { - fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); - dirp->d_ino = WINO; - dirp->d_type = DT_WHT; - if (reply("FIX") == 1) - ret |= ALTERED; - } else { -again: - switch (inoinfo(dirp->d_ino)->ino_state) { - case USTATE: - if (idesc->id_entryno <= 2) - break; - fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); - n = reply("REMOVE"); - break; - - case DCLEAR: - case FCLEAR: - if (idesc->id_entryno <= 2) - break; - if (inoinfo(dirp->d_ino)->ino_state == FCLEAR) - errmsg = "DUP/BAD"; - else if (!preen && !usedsoftdep) - errmsg = "ZERO LENGTH DIRECTORY"; - else { - n = 1; - break; - } - fileerror(idesc->id_number, dirp->d_ino, errmsg); - if ((n = reply("REMOVE")) == 1) - break; - dp = ginode(dirp->d_ino); - inoinfo(dirp->d_ino)->ino_state = - (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; - inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink; - goto again; - - case DSTATE: - if (inoinfo(idesc->id_number)->ino_state == DFOUND) - inoinfo(dirp->d_ino)->ino_state = DFOUND; - /* fall through */ - - case DFOUND: - inp = getinoinfo(dirp->d_ino); - if (inp->i_parent != 0 && idesc->id_entryno > 2) { - getpathname(pathbuf, idesc->id_number, - idesc->id_number); - getpathname(namebuf, dirp->d_ino, dirp->d_ino); - pwarn("%s %s %s\n", pathbuf, - "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", - namebuf); - if (preen) { - printf(" (REMOVED)\n"); - n = 1; - break; - } - if ((n = reply("REMOVE")) == 1) - break; - } - if (idesc->id_entryno > 2) - inp->i_parent = idesc->id_number; - /* fall through */ - - case FSTATE: - if (newinofmt && - dirp->d_type != inoinfo(dirp->d_ino)->ino_type) { - fileerror(idesc->id_number, dirp->d_ino, - "BAD TYPE VALUE"); - dirp->d_type = inoinfo(dirp->d_ino)->ino_type; - if (reply("FIX") == 1) - ret |= ALTERED; - } - inoinfo(dirp->d_ino)->ino_linkcnt--; - break; - - default: - errx(EEXIT, "BAD STATE %d FOR INODE I=%d", - inoinfo(dirp->d_ino)->ino_state, dirp->d_ino); - } - } - if (n == 0) - return (ret|KEEPON); - dirp->d_ino = 0; - return (ret|KEEPON|ALTERED); -} - -/* - * Routine to sort disk blocks. - */ -static int -blksort(arg1, arg2) - const void *arg1, *arg2; -{ - - return ((*(struct inoinfo **)arg1)->i_blks[0] - - (*(struct inoinfo **)arg2)->i_blks[0]); -} diff --git a/sbin/fsck/pass3.c b/sbin/fsck/pass3.c deleted file mode 100644 index 80e38e9..0000000 --- a/sbin/fsck/pass3.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass3.c 8.2 (Berkeley) 4/27/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> - -#include <string.h> - -#include "fsck.h" - -void -pass3() -{ - struct inoinfo *inp; - int loopcnt, inpindex, state; - ino_t orphan; - struct inodesc idesc; - char namebuf[MAXNAMLEN+1]; - - for (inpindex = inplast - 1; inpindex >= 0; inpindex--) { - inp = inpsort[inpindex]; - state = inoinfo(inp->i_number)->ino_state; - if (inp->i_number == ROOTINO || - (inp->i_parent != 0 && state != DSTATE)) - continue; - if (state == DCLEAR) - continue; - /* - * If we are running with soft updates and we come - * across unreferenced directories, we just leave - * them in DSTATE which will cause them to be pitched - * in pass 4. - */ - if (preen && resolved && usedsoftdep && state == DSTATE) { - if (inp->i_dotdot >= ROOTINO) - inoinfo(inp->i_dotdot)->ino_linkcnt++; - continue; - } - for (loopcnt = 0; ; loopcnt++) { - orphan = inp->i_number; - if (inp->i_parent == 0 || - inoinfo(inp->i_parent)->ino_state != DSTATE || - loopcnt > countdirs) - break; - inp = getinoinfo(inp->i_parent); - } - if (loopcnt <= countdirs) { - if (linkup(orphan, inp->i_dotdot, NULL)) { - inp->i_parent = inp->i_dotdot = lfdir; - inoinfo(lfdir)->ino_linkcnt--; - } - inoinfo(orphan)->ino_state = DFOUND; - propagate(); - continue; - } - pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu", orphan); - if (reply("RECONNECT") == 0) - continue; - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_number = inp->i_parent; - idesc.id_parent = orphan; - idesc.id_func = findname; - idesc.id_name = namebuf; - if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0) - pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY"); - if (linkup(orphan, inp->i_parent, namebuf)) { - idesc.id_func = clearentry; - if (ckinode(ginode(inp->i_parent), &idesc) & FOUND) - inoinfo(orphan)->ino_linkcnt++; - inp->i_parent = inp->i_dotdot = lfdir; - inoinfo(lfdir)->ino_linkcnt--; - } - inoinfo(orphan)->ino_state = DFOUND; - propagate(); - } -} diff --git a/sbin/fsck/pass4.c b/sbin/fsck/pass4.c deleted file mode 100644 index 0012c50..0000000 --- a/sbin/fsck/pass4.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -void -pass4() -{ - register ino_t inumber; - register struct zlncnt *zlnp; - struct dinode *dp; - struct inodesc idesc; - int i, n, cg; - - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - for (cg = 0; cg < sblock.fs_ncg; cg++) { - inumber = cg * sblock.fs_ipg; - for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) { - if (inumber < ROOTINO) - continue; - idesc.id_number = inumber; - switch (inoinfo(inumber)->ino_state) { - - case FSTATE: - case DFOUND: - n = inoinfo(inumber)->ino_linkcnt; - if (n) { - adjust(&idesc, (short)n); - break; - } - for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) { - if (zlnp->zlncnt == inumber) { - zlnp->zlncnt = zlnhead->zlncnt; - zlnp = zlnhead; - zlnhead = zlnhead->next; - free((char *)zlnp); - clri(&idesc, "UNREF", 1); - break; - } - } - break; - - case DSTATE: - clri(&idesc, "UNREF", 1); - break; - - case DCLEAR: - dp = ginode(inumber); - if (dp->di_size == 0) { - clri(&idesc, "ZERO LENGTH", 1); - break; - } - /* fall through */ - case FCLEAR: - clri(&idesc, "BAD/DUP", 1); - break; - - case USTATE: - break; - - default: - errx(EEXIT, "BAD STATE %d FOR INODE I=%d", - inoinfo(inumber)->ino_state, inumber); - } - } - } -} - -int -pass4check(idesc) - register struct inodesc *idesc; -{ - register struct dups *dlp; - int nfrags, res = KEEPON; - ufs_daddr_t blkno = idesc->id_blkno; - - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (chkrange(blkno, 1)) { - res = SKIP; - } else if (testbmap(blkno)) { - for (dlp = duplist; dlp; dlp = dlp->next) { - if (dlp->dup != blkno) - continue; - dlp->dup = duplist->dup; - dlp = duplist; - duplist = duplist->next; - free((char *)dlp); - break; - } - if (dlp == 0) { - clrbmap(blkno); - n_blks--; - } - } - } - return (res); -} diff --git a/sbin/fsck/pass5.c b/sbin/fsck/pass5.c deleted file mode 100644 index e395625..0000000 --- a/sbin/fsck/pass5.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -void -pass5() -{ - int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0; - int inomapsize, blkmapsize, astart, aend, ustart, uend; - struct fs *fs = &sblock; - struct cg *cg = &cgrp; - ufs_daddr_t dbase, dmax; - ufs_daddr_t d; - long i, j, k, l, m, n; - struct csum *cs; - struct csum cstotal; - struct inodesc idesc[3]; - char buf[MAXBSIZE]; - register struct cg *newcg = (struct cg *)buf; - struct ocg *ocg = (struct ocg *)buf; - - inoinfo(WINO)->ino_state = USTATE; - memset(newcg, 0, (size_t)fs->fs_cgsize); - newcg->cg_niblk = fs->fs_ipg; - if (cvtlevel >= 3) { - if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { - if (preen) - pwarn("DELETING CLUSTERING MAPS\n"); - if (preen || reply("DELETE CLUSTERING MAPS")) { - fs->fs_contigsumsize = 0; - doinglevel1 = 1; - sbdirty(); - } - } - if (fs->fs_maxcontig > 1) { - char *doit = 0; - - if (fs->fs_contigsumsize < 1) { - doit = "CREAT"; - } else if (fs->fs_contigsumsize < fs->fs_maxcontig && - fs->fs_contigsumsize < FS_MAXCONTIG) { - doit = "EXPAND"; - } - if (doit) { - i = fs->fs_contigsumsize; - fs->fs_contigsumsize = - MIN(fs->fs_maxcontig, FS_MAXCONTIG); - if (CGSIZE(fs) > fs->fs_bsize) { - pwarn("CANNOT %s CLUSTER MAPS\n", doit); - fs->fs_contigsumsize = i; - } else if (preen || - reply("CREATE CLUSTER MAPS")) { - if (preen) - pwarn("%sING CLUSTER MAPS\n", - doit); - fs->fs_cgsize = - fragroundup(fs, CGSIZE(fs)); - doinglevel1 = 1; - sbdirty(); - } - } - } - } - switch ((int)fs->fs_postblformat) { - - case FS_42POSTBLFMT: - basesize = (char *)(&ocg->cg_btot[0]) - - (char *)(&ocg->cg_firstfield); - sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]); - mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - - (u_char *)&ocg->cg_iused[0]; - blkmapsize = howmany(fs->fs_fpg, NBBY); - inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0]; - ocg->cg_magic = CG_MAGIC; - savednrpos = fs->fs_nrpos; - fs->fs_nrpos = 8; - break; - - case FS_DYNAMICPOSTBLFMT: - newcg->cg_btotoff = - &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); - newcg->cg_boff = - newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t); - newcg->cg_iusedoff = newcg->cg_boff + - fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t); - newcg->cg_freeoff = - newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); - inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff; - newcg->cg_nextfreeoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); - blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff; - if (fs->fs_contigsumsize > 0) { - newcg->cg_clustersumoff = newcg->cg_nextfreeoff - - sizeof(u_int32_t); - newcg->cg_clustersumoff = - roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); - newcg->cg_clusteroff = newcg->cg_clustersumoff + - (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); - newcg->cg_nextfreeoff = newcg->cg_clusteroff + - howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY); - } - newcg->cg_magic = CG_MAGIC; - basesize = &newcg->cg_space[0] - - (u_char *)(&newcg->cg_firstfield); - sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; - mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; - break; - - default: - inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */ - errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d", - fs->fs_postblformat); - } - memset(&idesc[0], 0, sizeof idesc); - for (i = 0; i < 3; i++) { - idesc[i].id_type = ADDR; - if (doinglevel2) - idesc[i].id_fix = FIX; - } - memset(&cstotal, 0, sizeof(struct csum)); - j = blknum(fs, fs->fs_size + fs->fs_frag - 1); - for (i = fs->fs_size; i < j; i++) - setbmap(i); - for (c = 0; c < fs->fs_ncg; c++) { - getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); - if (!cg_chkmagic(cg)) - pfatal("CG %d: BAD MAGIC NUMBER\n", c); - dbase = cgbase(fs, c); - dmax = dbase + fs->fs_fpg; - if (dmax > fs->fs_size) - dmax = fs->fs_size; - newcg->cg_time = cg->cg_time; - newcg->cg_cgx = c; - if (c == fs->fs_ncg - 1) - newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg; - else - newcg->cg_ncyl = fs->fs_cpg; - newcg->cg_ndblk = dmax - dbase; - if (fs->fs_contigsumsize > 0) - newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; - newcg->cg_cs.cs_ndir = 0; - newcg->cg_cs.cs_nffree = 0; - newcg->cg_cs.cs_nbfree = 0; - newcg->cg_cs.cs_nifree = fs->fs_ipg; - if (cg->cg_rotor < newcg->cg_ndblk) - newcg->cg_rotor = cg->cg_rotor; - else - newcg->cg_rotor = 0; - if (cg->cg_frotor < newcg->cg_ndblk) - newcg->cg_frotor = cg->cg_frotor; - else - newcg->cg_frotor = 0; - if (cg->cg_irotor < newcg->cg_niblk) - newcg->cg_irotor = cg->cg_irotor; - else - newcg->cg_irotor = 0; - memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); - memset(&cg_blktot(newcg)[0], 0, - (size_t)(sumsize + mapsize)); - if (fs->fs_postblformat == FS_42POSTBLFMT) - ocg->cg_magic = CG_MAGIC; - j = fs->fs_ipg * c; - for (i = 0; i < inostathead[c].il_numalloced; j++, i++) { - switch (inoinfo(j)->ino_state) { - - case USTATE: - break; - - case DSTATE: - case DCLEAR: - case DFOUND: - newcg->cg_cs.cs_ndir++; - /* fall through */ - - case FSTATE: - case FCLEAR: - newcg->cg_cs.cs_nifree--; - setbit(cg_inosused(newcg), i); - break; - - default: - if (j < ROOTINO) - break; - errx(EEXIT, "BAD STATE %d FOR INODE I=%ld", - inoinfo(j)->ino_state, j); - } - } - if (c == 0) - for (i = 0; i < ROOTINO; i++) { - setbit(cg_inosused(newcg), i); - newcg->cg_cs.cs_nifree--; - } - for (i = 0, d = dbase; - d < dmax; - d += fs->fs_frag, i += fs->fs_frag) { - frags = 0; - for (j = 0; j < fs->fs_frag; j++) { - if (testbmap(d + j)) - continue; - setbit(cg_blksfree(newcg), i + j); - frags++; - } - if (frags == fs->fs_frag) { - newcg->cg_cs.cs_nbfree++; - j = cbtocylno(fs, i); - cg_blktot(newcg)[j]++; - cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++; - if (fs->fs_contigsumsize > 0) - setbit(cg_clustersfree(newcg), - i / fs->fs_frag); - } else if (frags > 0) { - newcg->cg_cs.cs_nffree += frags; - blk = blkmap(fs, cg_blksfree(newcg), i); - ffs_fragacct(fs, blk, newcg->cg_frsum, 1); - } - } - if (fs->fs_contigsumsize > 0) { - int32_t *sump = cg_clustersum(newcg); - u_char *mapp = cg_clustersfree(newcg); - int map = *mapp++; - int bit = 1; - int run = 0; - - for (i = 0; i < newcg->cg_nclusterblks; i++) { - if ((map & bit) != 0) { - run++; - } else if (run != 0) { - if (run > fs->fs_contigsumsize) - run = fs->fs_contigsumsize; - sump[run]++; - run = 0; - } - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - if (run != 0) { - if (run > fs->fs_contigsumsize) - run = fs->fs_contigsumsize; - sump[run]++; - } - } - cstotal.cs_nffree += newcg->cg_cs.cs_nffree; - cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; - cstotal.cs_nifree += newcg->cg_cs.cs_nifree; - cstotal.cs_ndir += newcg->cg_cs.cs_ndir; - cs = &fs->fs_cs(fs, c); - if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 && - dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { - memmove(cs, &newcg->cg_cs, sizeof *cs); - sbdirty(); - } - if (doinglevel1) { - memmove(cg, newcg, (size_t)fs->fs_cgsize); - cgdirty(); - continue; - } - if ((memcmp(newcg, cg, basesize) != 0 || - memcmp(&cg_blktot(newcg)[0], - &cg_blktot(cg)[0], sumsize) != 0) && - dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { - memmove(cg, newcg, (size_t)basesize); - memmove(&cg_blktot(cg)[0], - &cg_blktot(newcg)[0], (size_t)sumsize); - cgdirty(); - } - if (debug) { - for (i = 0; i < inomapsize; i++) { - j = cg_inosused(newcg)[i]; - k = cg_inosused(cg)[i]; - if (j == k) - continue; - for (m = 0, l = 1; m < NBBY; m++, l <<= 1) { - if ((j & l) == (k & l)) - continue; - n = c * fs->fs_ipg + i * NBBY + m; - if ((j & l) != 0) - pwarn("%s INODE %d MARKED %s\n", - "ALLOCATED", n, "FREE"); - else - pwarn("%s INODE %d MARKED %s\n", - "UNALLOCATED", n, "USED"); - } - } - astart = ustart = -1; - for (i = 0; i < blkmapsize; i++) { - j = cg_blksfree(cg)[i]; - k = cg_blksfree(newcg)[i]; - if (j == k) - continue; - for (m = 0, l = 1; m < NBBY; m++, l <<= 1) { - if ((j & l) == (k & l)) - continue; - n = c * fs->fs_fpg + i * NBBY + m; - if ((j & l) != 0) { - if (astart == -1) { - astart = aend = n; - continue; - } - if (aend + 1 == n) { - aend = n; - continue; - } - pwarn("%s FRAGS %d-%d %s\n", - "ALLOCATED", astart, aend, - "MARKED FREE"); - astart = aend = n; - } else { - if (ustart == -1) { - ustart = uend = n; - continue; - } - if (uend + 1 == n) { - uend = n; - continue; - } - pwarn("%s FRAGS %d-%d %s\n", - "UNALLOCATED", ustart, uend, - "MARKED USED"); - ustart = uend = n; - } - } - } - if (astart != -1) - pwarn("%s FRAGS %d-%d %s\n", - "ALLOCATED", astart, aend, - "MARKED FREE"); - if (ustart != -1) - pwarn("%s FRAGS %d-%d %s\n", - "UNALLOCATED", ustart, uend, - "MARKED USED"); - } - if (usedsoftdep) { - for (i = 0; i < inomapsize; i++) { - j = cg_inosused(newcg)[i]; - if ((cg_inosused(cg)[i] & j) == j) - continue; - for (k = 0; k < NBBY; k++) { - if ((j & (1 << k)) == 0) - continue; - if (cg_inosused(cg)[i] & (1 << k)) - continue; - pwarn("ALLOCATED INODE %d MARKED FREE\n", - c * fs->fs_ipg + i * NBBY + k); - } - } - for (i = 0; i < blkmapsize; i++) { - j = cg_blksfree(cg)[i]; - if ((cg_blksfree(newcg)[i] & j) == j) - continue; - for (k = 0; k < NBBY; k++) { - if ((j & (1 << k)) == 0) - continue; - if (cg_blksfree(newcg)[i] & (1 << k)) - continue; - pwarn("ALLOCATED FRAG %d MARKED FREE\n", - c * fs->fs_fpg + i * NBBY + k); - } - } - } - if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 && - dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { - memmove(cg_inosused(cg), cg_inosused(newcg), - (size_t)mapsize); - cgdirty(); - } - } - if (fs->fs_postblformat == FS_42POSTBLFMT) - fs->fs_nrpos = savednrpos; - if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0 - && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { - memmove(&fs->fs_cstotal, &cstotal, sizeof *cs); - fs->fs_ronly = 0; - fs->fs_fmod = 0; - sbdirty(); - } -} diff --git a/sbin/fsck/pathnames.h b/sbin/fsck/pathnames.h new file mode 100644 index 0000000..5f3166e --- /dev/null +++ b/sbin/fsck/pathnames.h @@ -0,0 +1,35 @@ +/* $NetBSD: pathnames.h,v 1.1 1996/09/11 20:27:15 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define _PATH_SBIN "/sbin" +#define _PATH_USRSBIN "/usr/sbin" diff --git a/sbin/fsck/preen.c b/sbin/fsck/preen.c deleted file mode 100644 index e43aada..0000000 --- a/sbin/fsck/preen.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#include <ufs/ufs/dinode.h> - -#include <ctype.h> -#include <errno.h> -#include <fstab.h> -#include <string.h> - -#include "fsck.h" - -struct part { - struct part *next; /* forward link of partitions on disk */ - char *name; /* device name */ - char *fsname; /* mounted filesystem name */ - long auxdata; /* auxillary data for application */ -} *badlist, **badnext = &badlist; - -struct disk { - char *name; /* disk base name */ - struct disk *next; /* forward link for list of disks */ - struct part *part; /* head of list of partitions on disk */ - int pid; /* If != 0, pid of proc working on */ -} *disks; - -int nrun, ndisks; - -static void addpart __P((char *name, char *fsname, long auxdata)); -static struct disk *finddisk __P((char *name)); -static int startdisk __P((struct disk *dk, - int (*checkit)(char *, char *, long, int))); - -int -checkfstab(preen, maxrun, docheck, chkit) - int preen; - int maxrun; - int (*docheck)(struct fstab *); - int (*chkit)(char *, char *, long, int); -{ - register struct fstab *fsp; - register struct disk *dk, *nextdisk; - register struct part *pt; - int ret, pid, retcode, passno, sumstatus, status; - long auxdata; - char *name; - - sumstatus = 0; - for (passno = 1; passno <= 2; passno++) { - if (setfsent() == 0) { - fprintf(stderr, "Can't open checklist file: %s\n", - _PATH_FSTAB); - return (8); - } - while ((fsp = getfsent()) != 0) { - if ((auxdata = (*docheck)(fsp)) == 0) - continue; - if (preen == 0 || - (passno == 1 && fsp->fs_passno == 1)) { - if ((name = blockcheck(fsp->fs_spec)) != 0) { - if ((sumstatus = (*chkit)(name, - fsp->fs_file, auxdata, 0)) != 0) - return (sumstatus); - } else if (preen) - return (8); - } else if (passno == 2 && fsp->fs_passno > 1) { - if ((name = blockcheck(fsp->fs_spec)) == NULL) { - fprintf(stderr, "BAD DISK NAME %s\n", - fsp->fs_spec); - sumstatus |= 8; - continue; - } - addpart(name, fsp->fs_file, auxdata); - } - } - if (preen == 0) - return (0); - } - if (preen) { - if (maxrun == 0) - maxrun = ndisks; - if (maxrun > ndisks) - maxrun = ndisks; - nextdisk = disks; - for (passno = 0; passno < maxrun; ++passno) { - while ((ret = startdisk(nextdisk, chkit)) && nrun > 0) - sleep(10); - if (ret) - return (ret); - nextdisk = nextdisk->next; - } - while ((pid = wait(&status)) != -1) { - for (dk = disks; dk; dk = dk->next) - if (dk->pid == pid) - break; - if (dk == 0) { - printf("Unknown pid %d\n", pid); - continue; - } - if (WIFEXITED(status)) - retcode = WEXITSTATUS(status); - else - retcode = 0; - if (WIFSIGNALED(status)) { - printf("%s (%s): EXITED WITH SIGNAL %d\n", - dk->part->name, dk->part->fsname, - WTERMSIG(status)); - retcode = 8; - } - if (retcode != 0) { - sumstatus |= retcode; - *badnext = dk->part; - badnext = &dk->part->next; - dk->part = dk->part->next; - *badnext = NULL; - } else - dk->part = dk->part->next; - dk->pid = 0; - nrun--; - if (dk->part == NULL) - ndisks--; - - if (nextdisk == NULL) { - if (dk->part) { - while ((ret = startdisk(dk, chkit)) && - nrun > 0) - sleep(10); - if (ret) - return (ret); - } - } else if (nrun < maxrun && nrun < ndisks) { - for ( ;; ) { - if ((nextdisk = nextdisk->next) == NULL) - nextdisk = disks; - if (nextdisk->part != NULL && - nextdisk->pid == 0) - break; - } - while ((ret = startdisk(nextdisk, chkit)) && - nrun > 0) - sleep(10); - if (ret) - return (ret); - } - } - } - if (sumstatus) { - if (badlist == 0) - return (sumstatus); - fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", - badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); - for (pt = badlist; pt; pt = pt->next) - fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, - pt->next ? ", " : "\n"); - return (sumstatus); - } - (void)endfsent(); - return (0); -} - -static struct disk * -finddisk(name) - char *name; -{ - register struct disk *dk, **dkp; - register char *p; - size_t len; - - p = strrchr(name, '/'); - p = p == NULL ? name : p + 1; - while (*p != '\0' && !isdigit((u_char)*p)) - p++; - while (isdigit((u_char)*p)) - p++; - len = (size_t)(p - name); - for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { - if (strncmp(dk->name, name, len) == 0 && - dk->name[len] == 0) - return (dk); - } - if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - dk = *dkp; - if ((dk->name = malloc(len + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strncpy(dk->name, name, len); - dk->name[len] = '\0'; - dk->part = NULL; - dk->next = NULL; - dk->pid = 0; - ndisks++; - return (dk); -} - -static void -addpart(name, fsname, auxdata) - char *name, *fsname; - long auxdata; -{ - struct disk *dk = finddisk(name); - register struct part *pt, **ppt = &dk->part; - - for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) - if (strcmp(pt->name, name) == 0) { - printf("%s in fstab more than once!\n", name); - return; - } - if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - pt = *ppt; - if ((pt->name = malloc(strlen(name) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->name, name); - if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->fsname, fsname); - pt->next = NULL; - pt->auxdata = auxdata; -} - -static int -startdisk(dk, checkit) - register struct disk *dk; - int (*checkit)(char *, char *, long, int); -{ - register struct part *pt = dk->part; - - dk->pid = fork(); - if (dk->pid < 0) { - perror("fork"); - return (8); - } - if (dk->pid == 0) - exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); - nrun++; - return (0); -} - -char * -blockcheck(origname) - char *origname; -{ - struct stat stslash, stblock, stchar; - char *newname, *raw; - struct fstab *fsinfo; - int retried = 0, len; - - newname = origname; -retry: - if (stat(newname, &stblock) < 0) { - printf("Can't stat %s: %s\n", newname, strerror(errno)); - return (origname); - } - switch(stblock.st_mode & S_IFMT) { - case S_IFCHR: - case S_IFBLK: - return(newname); - case S_IFDIR: - if (retried) - break; - - len = strlen(origname) - 1; - if (len > 0 && origname[len] == '/') - /* remove trailing slash */ - origname[len] = '\0'; - if ((fsinfo = getfsfile(origname)) == NULL) { - printf("Can't resolve %s to character special device", - origname); - return (0); - } - newname = fsinfo->fs_spec; - retried++; - goto retry; - } - /* - * Not a block or character device, just return name and - * let the user decide whether to use it. - */ - return (origname); -} diff --git a/sbin/fsck/setup.c b/sbin/fsck/setup.c deleted file mode 100644 index 6c4098c..0000000 --- a/sbin/fsck/setup.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#define DKTYPENAMES -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/disklabel.h> -#include <sys/file.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ffs/fs.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <string.h> - -#include "fsck.h" - -struct bufarea asblk; -#define altsblock (*asblk.b_un.b_fs) -#define POWEROF2(num) (((num) & ((num) - 1)) == 0) - -static void badsb __P((int listerr, char *s)); -static int calcsb __P((char *dev, int devfd, struct fs *fs)); -static struct disklabel *getdisklabel __P((char *s, int fd)); -static int readsb __P((int listerr)); - -/* - * Read in a superblock finding an alternate if necessary. - * Return 1 if successful, 0 if unsuccessful, -1 if filesystem - * is already clean (preen mode only). - */ -int -setup(dev) - char *dev; -{ - long cg, size, asked, i, j; - long skipclean, bmapsize; - struct disklabel *lp; - off_t sizepb; - struct stat statb; - struct fs proto; - - havesb = 0; - fswritefd = -1; - cursnapshot = 0; - skipclean = fflag ? 0 : preen; - if (stat(dev, &statb) < 0) { - printf("Can't stat %s: %s\n", dev, strerror(errno)); - return (0); - } - if ((statb.st_mode & S_IFMT) != S_IFCHR && - (statb.st_mode & S_IFMT) != S_IFBLK) { - if ((statb.st_flags & SF_SNAPSHOT) != 0) { - cursnapshot = statb.st_ino; - } else { - pfatal("%s is not a disk device", dev); - if (reply("CONTINUE") == 0) - return (0); - } - } - if ((fsreadfd = open(dev, O_RDONLY)) < 0) { - printf("Can't open %s: %s\n", dev, strerror(errno)); - return (0); - } - if (preen == 0) - printf("** %s", dev); - if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { - fswritefd = -1; - if (preen) - pfatal("NO WRITE ACCESS"); - printf(" (NO WRITE)"); - } - if (preen == 0) - printf("\n"); - fsmodified = 0; - lfdir = 0; - initbarea(&sblk); - initbarea(&asblk); - sblk.b_un.b_buf = malloc(SBSIZE); - asblk.b_un.b_buf = malloc(SBSIZE); - if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) - errx(EEXIT, "cannot allocate space for superblock"); - if ((lp = getdisklabel(NULL, fsreadfd))) - dev_bsize = secsize = lp->d_secsize; - else - dev_bsize = secsize = DEV_BSIZE; - /* - * Read in the superblock, looking for alternates if necessary - */ - if (readsb(1) == 0) { - skipclean = 0; - if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) - return(0); - if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) - return (0); - for (cg = 0; cg < proto.fs_ncg; cg++) { - bflag = fsbtodb(&proto, cgsblock(&proto, cg)); - if (readsb(0) != 0) - break; - } - if (cg >= proto.fs_ncg) { - printf("%s %s\n%s %s\n%s %s\n", - "SEARCH FOR ALTERNATE SUPER-BLOCK", - "FAILED. YOU MUST USE THE", - "-b OPTION TO FSCK TO SPECIFY THE", - "LOCATION OF AN ALTERNATE", - "SUPER-BLOCK TO SUPPLY NEEDED", - "INFORMATION; SEE fsck(8)."); - bflag = 0; - return(0); - } - pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); - bflag = 0; - } - if (skipclean && sblock.fs_clean) { - pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); - return (-1); - } - maxfsblock = sblock.fs_size; - maxino = sblock.fs_ncg * sblock.fs_ipg; - /* - * Check and potentially fix certain fields in the super block. - */ - if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { - pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); - if (reply("SET TO DEFAULT") == 1) { - sblock.fs_optim = FS_OPTTIME; - sbdirty(); - } - } - if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { - pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", - sblock.fs_minfree); - if (reply("SET TO DEFAULT") == 1) { - sblock.fs_minfree = 10; - sbdirty(); - } - } - if (sblock.fs_interleave < 1 || - sblock.fs_interleave > sblock.fs_nsect) { - pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK", - sblock.fs_interleave); - sblock.fs_interleave = 1; - if (preen) - printf(" (FIXED)\n"); - if (preen || reply("SET TO DEFAULT") == 1) { - sbdirty(); - dirty(&asblk); - } - } - if (sblock.fs_npsect < sblock.fs_nsect || - sblock.fs_npsect > sblock.fs_nsect*2) { - pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK", - sblock.fs_npsect); - sblock.fs_npsect = sblock.fs_nsect; - if (preen) - printf(" (FIXED)\n"); - if (preen || reply("SET TO DEFAULT") == 1) { - sbdirty(); - dirty(&asblk); - } - } - if (sblock.fs_inodefmt >= FS_44INODEFMT) { - newinofmt = 1; - } else { - sblock.fs_qbmask = ~sblock.fs_bmask; - sblock.fs_qfmask = ~sblock.fs_fmask; - newinofmt = 0; - } - /* - * Convert to new inode format. - */ - if (cvtlevel >= 2 && sblock.fs_inodefmt < FS_44INODEFMT) { - if (preen) - pwarn("CONVERTING TO NEW INODE FORMAT\n"); - else if (!reply("CONVERT TO NEW INODE FORMAT")) - return(0); - doinglevel2++; - sblock.fs_inodefmt = FS_44INODEFMT; - sizepb = sblock.fs_bsize; - sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; - for (i = 0; i < NIADDR; i++) { - sizepb *= NINDIR(&sblock); - sblock.fs_maxfilesize += sizepb; - } - sblock.fs_maxsymlinklen = MAXSYMLINKLEN; - sblock.fs_qbmask = ~sblock.fs_bmask; - sblock.fs_qfmask = ~sblock.fs_fmask; - sbdirty(); - dirty(&asblk); - } - /* - * Convert to new cylinder group format. - */ - if (cvtlevel >= 1 && sblock.fs_postblformat == FS_42POSTBLFMT) { - if (preen) - pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n"); - else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT")) - return(0); - doinglevel1++; - sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; - sblock.fs_nrpos = 8; - sblock.fs_postbloff = - (char *)(&sblock.fs_opostbl[0][0]) - - (char *)(&sblock.fs_firstfield); - sblock.fs_rotbloff = &sblock.fs_space[0] - - (u_char *)(&sblock.fs_firstfield); - sblock.fs_cgsize = - fragroundup(&sblock, CGSIZE(&sblock)); - sbdirty(); - dirty(&asblk); - } - if (asblk.b_dirty && !bflag) { - memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize); - flush(fswritefd, &asblk); - } - /* - * read in the summary info. - */ - asked = 0; - for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - size = sblock.fs_cssize - i < sblock.fs_bsize ? - sblock.fs_cssize - i : sblock.fs_bsize; - sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size); - if (bread(fsreadfd, (char *)sblock.fs_csp[j], - fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), - size) != 0 && !asked) { - pfatal("BAD SUMMARY INFORMATION"); - if (reply("CONTINUE") == 0) { - ckfini(0); - exit(EEXIT); - } - asked++; - } - } - /* - * allocate and initialize the necessary maps - */ - bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short)); - blockmap = calloc((unsigned)bmapsize, sizeof (char)); - if (blockmap == NULL) { - printf("cannot alloc %u bytes for blockmap\n", - (unsigned)bmapsize); - goto badsb; - } - inostathead = calloc((unsigned)(sblock.fs_ncg), - sizeof(struct inostatlist)); - if (inostathead == NULL) { - printf("cannot alloc %u bytes for inostathead\n", - (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg))); - goto badsb; - } - numdirs = sblock.fs_cstotal.cs_ndir; - dirhash = numdirs; - if (numdirs == 0) { - printf("numdirs is zero, try using an alternate superblock\n"); - goto badsb; - } - inplast = 0; - listmax = numdirs + 10; - inpsort = (struct inoinfo **)calloc((unsigned)listmax, - sizeof(struct inoinfo *)); - inphead = (struct inoinfo **)calloc((unsigned)numdirs, - sizeof(struct inoinfo *)); - if (inpsort == NULL || inphead == NULL) { - printf("cannot alloc %u bytes for inphead\n", - (unsigned)numdirs * sizeof(struct inoinfo *)); - goto badsb; - } - bufinit(); - if (sblock.fs_flags & FS_DOSOFTDEP) - usedsoftdep = 1; - else - usedsoftdep = 0; - return (1); - -badsb: - ckfini(0); - return (0); -} - -/* - * Read in the super block and its summary info. - */ -static int -readsb(listerr) - int listerr; -{ - ufs_daddr_t super = bflag ? bflag : SBOFF / dev_bsize; - - if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0) - return (0); - sblk.b_bno = super; - sblk.b_size = SBSIZE; - /* - * run a few consistency checks of the super block - */ - if (sblock.fs_magic != FS_MAGIC) - { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); } - if (sblock.fs_ncg < 1) - { badsb(listerr, "NCG OUT OF RANGE"); return (0); } - if (sblock.fs_cpg < 1) - { badsb(listerr, "CPG OUT OF RANGE"); return (0); } - if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || - (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) - { badsb(listerr, "NCYL LESS THAN NCG*CPG"); return (0); } - if (sblock.fs_sbsize > SBSIZE) - { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } - /* - * Compute block size that the filesystem is based on, - * according to fsbtodb, and adjust superblock block number - * so we can tell if this is an alternate later. - */ - super *= dev_bsize; - dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); - sblk.b_bno = super / dev_bsize; - if (bflag) { - havesb = 1; - return (1); - } - /* - * Set all possible fields that could differ, then do check - * of whole super block against an alternate super block. - * When an alternate super-block is specified this check is skipped. - */ - getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); - if (asblk.b_errs) - return (0); - altsblock.fs_firstfield = sblock.fs_firstfield; - altsblock.fs_unused_1 = sblock.fs_unused_1; - altsblock.fs_time = sblock.fs_time; - altsblock.fs_cstotal = sblock.fs_cstotal; - altsblock.fs_cgrotor = sblock.fs_cgrotor; - altsblock.fs_fmod = sblock.fs_fmod; - altsblock.fs_clean = sblock.fs_clean; - altsblock.fs_ronly = sblock.fs_ronly; - altsblock.fs_flags = sblock.fs_flags; - altsblock.fs_maxcontig = sblock.fs_maxcontig; - altsblock.fs_minfree = sblock.fs_minfree; - altsblock.fs_optim = sblock.fs_optim; - altsblock.fs_rotdelay = sblock.fs_rotdelay; - altsblock.fs_maxbpg = sblock.fs_maxbpg; - memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp); - altsblock.fs_maxcluster = sblock.fs_maxcluster; - memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt); - memmove(altsblock.fs_snapinum, sblock.fs_snapinum, - sizeof sblock.fs_snapinum); - memmove(altsblock.fs_sparecon, - sblock.fs_sparecon, sizeof sblock.fs_sparecon); - /* - * The following should not have to be copied. - */ - altsblock.fs_fsbtodb = sblock.fs_fsbtodb; - altsblock.fs_interleave = sblock.fs_interleave; - altsblock.fs_npsect = sblock.fs_npsect; - altsblock.fs_nrpos = sblock.fs_nrpos; - altsblock.fs_state = sblock.fs_state; - altsblock.fs_qbmask = sblock.fs_qbmask; - altsblock.fs_qfmask = sblock.fs_qfmask; - altsblock.fs_state = sblock.fs_state; - altsblock.fs_maxfilesize = sblock.fs_maxfilesize; - if (memcmp(&sblock, &altsblock, (int)sblock.fs_sbsize)) { - if (debug) { - long *nlp, *olp, *endlp; - - printf("superblock mismatches\n"); - nlp = (long *)&altsblock; - olp = (long *)&sblock; - endlp = olp + (sblock.fs_sbsize / sizeof *olp); - for ( ; olp < endlp; olp++, nlp++) { - if (*olp == *nlp) - continue; - printf( - "offset %d, original %ld, alternate %ld\n", - olp - (long *)&sblock, *olp, *nlp); - } - } - badsb(listerr, - "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); - return (0); - } - havesb = 1; - return (1); -} - -static void -badsb(listerr, s) - int listerr; - char *s; -{ - - if (!listerr) - return; - if (preen) - printf("%s: ", cdevname); - pfatal("BAD SUPER BLOCK: %s\n", s); -} - -/* - * Calculate a prototype superblock based on information in the disk label. - * When done the cgsblock macro can be calculated and the fs_ncg field - * can be used. Do NOT attempt to use other macros without verifying that - * their needed information is available! - */ -static int -calcsb(dev, devfd, fs) - char *dev; - int devfd; - register struct fs *fs; -{ - register struct disklabel *lp; - register struct partition *pp; - register char *cp; - int i; - - cp = strchr(dev, '\0') - 1; - if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { - pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); - return (0); - } - lp = getdisklabel(dev, devfd); - if (isdigit(*cp)) - pp = &lp->d_partitions[0]; - else - pp = &lp->d_partitions[*cp - 'a']; - if (pp->p_fstype != FS_BSDFFS) { - pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", - dev, pp->p_fstype < FSMAXTYPES ? - fstypenames[pp->p_fstype] : "unknown"); - return (0); - } - if (pp->p_fsize == 0 || pp->p_frag == 0 || - pp->p_cpg == 0 || pp->p_size == 0) { - pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n", - dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype], - pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size); - return (0); - } - memset(fs, 0, sizeof(struct fs)); - fs->fs_fsize = pp->p_fsize; - fs->fs_frag = pp->p_frag; - fs->fs_cpg = pp->p_cpg; - fs->fs_size = pp->p_size; - fs->fs_ntrak = lp->d_ntracks; - fs->fs_nsect = lp->d_nsectors; - fs->fs_spc = lp->d_secpercyl; - fs->fs_nspf = fs->fs_fsize / lp->d_secsize; - fs->fs_sblkno = roundup( - howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), - fs->fs_frag); - fs->fs_cgmask = 0xffffffff; - for (i = fs->fs_ntrak; i > 1; i >>= 1) - fs->fs_cgmask <<= 1; - if (!POWEROF2(fs->fs_ntrak)) - fs->fs_cgmask <<= 1; - fs->fs_cgoffset = roundup( - howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag); - fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs); - fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg); - for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1) - fs->fs_fsbtodb++; - dev_bsize = lp->d_secsize; - return (1); -} - -static struct disklabel * -getdisklabel(s, fd) - char *s; - int fd; -{ - static struct disklabel lab; - - if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { - if (s == NULL) - return ((struct disklabel *)NULL); - pwarn("ioctl (GCINFO): %s\n", strerror(errno)); - errx(EEXIT, "%s: can't read disk label", s); - } - return (&lab); -} diff --git a/sbin/fsck/utilities.c b/sbin/fsck/utilities.c deleted file mode 100644 index 0ccd9bb..0000000 --- a/sbin/fsck/utilities.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> -#include <ufs/ffs/fs.h> - -#include <err.h> -#include <string.h> - -#include "fsck.h" - -long diskreads, totalreads; /* Disk cache statistics */ - -static void rwerror __P((char *mesg, ufs_daddr_t blk)); - -int -ftypeok(dp) - struct dinode *dp; -{ - switch (dp->di_mode & IFMT) { - - case IFDIR: - case IFREG: - case IFBLK: - case IFCHR: - case IFLNK: - case IFSOCK: - case IFIFO: - return (1); - - default: - if (debug) - printf("bad file type 0%o\n", dp->di_mode); - return (0); - } -} - -int -reply(question) - char *question; -{ - int persevere; - char c; - - if (preen) - pfatal("INTERNAL ERROR: GOT TO reply()"); - persevere = !strcmp(question, "CONTINUE"); - printf("\n"); - if (!persevere && (nflag || fswritefd < 0)) { - printf("%s? no\n\n", question); - resolved = 0; - return (0); - } - if (yflag || (persevere && nflag)) { - printf("%s? yes\n\n", question); - return (1); - } - do { - printf("%s? [yn] ", question); - (void) fflush(stdout); - c = getc(stdin); - while (c != '\n' && getc(stdin) != '\n') { - if (feof(stdin)) { - resolved = 0; - return (0); - } - } - } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); - printf("\n"); - if (c == 'y' || c == 'Y') - return (1); - resolved = 0; - return (0); -} - -/* - * Look up state information for an inode. - */ -struct inostat * -inoinfo(inum) - ino_t inum; -{ - static struct inostat unallocated = { USTATE, 0, 0 }; - struct inostatlist *ilp; - int iloff; - - if (inum > maxino) - errx(EEXIT, "inoinfo: inumber %d out of range", inum); - ilp = &inostathead[inum / sblock.fs_ipg]; - iloff = inum % sblock.fs_ipg; - if (iloff >= ilp->il_numalloced) - return (&unallocated); - return (&ilp->il_stat[iloff]); -} - -/* - * Malloc buffers and set up cache. - */ -void -bufinit() -{ - register struct bufarea *bp; - long bufcnt, i; - char *bufp; - - pbp = pdirbp = (struct bufarea *)0; - bufp = malloc((unsigned int)sblock.fs_bsize); - if (bufp == 0) - errx(EEXIT, "cannot allocate buffer pool"); - cgblk.b_un.b_buf = bufp; - initbarea(&cgblk); - bufhead.b_next = bufhead.b_prev = &bufhead; - bufcnt = MAXBUFSPACE / sblock.fs_bsize; - if (bufcnt < MINBUFS) - bufcnt = MINBUFS; - for (i = 0; i < bufcnt; i++) { - bp = (struct bufarea *)malloc(sizeof(struct bufarea)); - bufp = malloc((unsigned int)sblock.fs_bsize); - if (bp == NULL || bufp == NULL) { - if (i >= MINBUFS) - break; - errx(EEXIT, "cannot allocate buffer pool"); - } - bp->b_un.b_buf = bufp; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; - initbarea(bp); - } - bufhead.b_size = i; /* save number of buffers */ -} - -/* - * Manage a cache of directory blocks. - */ -struct bufarea * -getdatablk(blkno, size) - ufs_daddr_t blkno; - long size; -{ - register struct bufarea *bp; - - for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) - if (bp->b_bno == fsbtodb(&sblock, blkno)) - goto foundit; - for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) - if ((bp->b_flags & B_INUSE) == 0) - break; - if (bp == &bufhead) - errx(EEXIT, "deadlocked buffer pool"); - getblk(bp, blkno, size); - /* fall through */ -foundit: - totalreads++; - bp->b_prev->b_next = bp->b_next; - bp->b_next->b_prev = bp->b_prev; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; - bp->b_flags |= B_INUSE; - return (bp); -} - -void -getblk(bp, blk, size) - register struct bufarea *bp; - ufs_daddr_t blk; - long size; -{ - ufs_daddr_t dblk; - - dblk = fsbtodb(&sblock, blk); - if (bp->b_bno != dblk) { - flush(fswritefd, bp); - diskreads++; - bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); - bp->b_bno = dblk; - bp->b_size = size; - } -} - -void -flush(fd, bp) - int fd; - register struct bufarea *bp; -{ - register int i, j; - - if (!bp->b_dirty) - return; - if (bp->b_errs != 0) - pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", - (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", - bp->b_bno); - bp->b_dirty = 0; - bp->b_errs = 0; - bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); - if (bp != &sblk) - return; - for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - bwrite(fswritefd, (char *)sblock.fs_csp[j], - fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), - sblock.fs_cssize - i < sblock.fs_bsize ? - sblock.fs_cssize - i : sblock.fs_bsize); - } -} - -static void -rwerror(mesg, blk) - char *mesg; - ufs_daddr_t blk; -{ - - if (preen == 0) - printf("\n"); - pfatal("CANNOT %s: BLK %ld", mesg, blk); - if (reply("CONTINUE") == 0) - exit(EEXIT); -} - -void -ckfini(markclean) - int markclean; -{ - register struct bufarea *bp, *nbp; - int ofsmodified, cnt = 0; - - if (fswritefd < 0) { - (void)close(fsreadfd); - return; - } - flush(fswritefd, &sblk); - if (havesb && sblk.b_bno != SBOFF / dev_bsize && - !preen && reply("UPDATE STANDARD SUPERBLOCK")) { - sblk.b_bno = SBOFF / dev_bsize; - sbdirty(); - flush(fswritefd, &sblk); - } - flush(fswritefd, &cgblk); - free(cgblk.b_un.b_buf); - for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { - cnt++; - flush(fswritefd, bp); - nbp = bp->b_prev; - free(bp->b_un.b_buf); - free((char *)bp); - } - if (bufhead.b_size != cnt) - errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt); - pbp = pdirbp = (struct bufarea *)0; - if (sblock.fs_clean != markclean) { - sblock.fs_clean = markclean; - sbdirty(); - ofsmodified = fsmodified; - flush(fswritefd, &sblk); - fsmodified = ofsmodified; - if (!preen) { - printf("\n***** FILE SYSTEM MARKED %s *****\n", - markclean ? "CLEAN" : "DIRTY"); - if (!markclean) - rerun = 1; - } - } else if (!preen && !markclean) { - printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); - rerun = 1; - } - if (debug) - printf("cache missed %ld of %ld (%d%%)\n", diskreads, - totalreads, (int)(diskreads * 100 / totalreads)); - (void)close(fsreadfd); - (void)close(fswritefd); -} - -int -bread(fd, buf, blk, size) - int fd; - char *buf; - ufs_daddr_t blk; - long size; -{ - char *cp; - int i, errs; - off_t offset; - - offset = blk; - offset *= dev_bsize; - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - else if (read(fd, buf, (int)size) == size) - return (0); - rwerror("READ", blk); - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - errs = 0; - memset(buf, 0, (size_t)size); - printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); - for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { - if (read(fd, cp, (int)secsize) != secsize) { - (void)lseek(fd, offset + i + secsize, 0); - if (secsize != dev_bsize && dev_bsize != 1) - printf(" %ld (%ld),", - (blk * dev_bsize + i) / secsize, - blk + i / dev_bsize); - else - printf(" %ld,", blk + i / dev_bsize); - errs++; - } - } - printf("\n"); - if (errs) - resolved = 0; - return (errs); -} - -void -bwrite(fd, buf, blk, size) - int fd; - char *buf; - ufs_daddr_t blk; - long size; -{ - int i; - char *cp; - off_t offset; - - if (fd < 0) - return; - offset = blk; - offset *= dev_bsize; - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - else if (write(fd, buf, (int)size) == size) { - fsmodified = 1; - return; - } - resolved = 0; - rwerror("WRITE", blk); - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); - for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) - if (write(fd, cp, (int)dev_bsize) != dev_bsize) { - (void)lseek(fd, offset + i + dev_bsize, 0); - printf(" %ld,", blk + i / dev_bsize); - } - printf("\n"); - return; -} - -/* - * allocate a data block with the specified number of fragments - */ -ufs_daddr_t -allocblk(frags) - long frags; -{ - int i, j, k, cg, baseblk; - struct cg *cgp = &cgrp; - - if (frags <= 0 || frags > sblock.fs_frag) - return (0); - for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { - for (j = 0; j <= sblock.fs_frag - frags; j++) { - if (testbmap(i + j)) - continue; - for (k = 1; k < frags; k++) - if (testbmap(i + j + k)) - break; - if (k < frags) { - j += k; - continue; - } - cg = dtog(&sblock, i + j); - getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); - if (!cg_chkmagic(cgp)) - pfatal("CG %d: BAD MAGIC NUMBER\n", cg); - baseblk = dtogd(&sblock, i + j); - for (k = 0; k < frags; k++) { - setbmap(i + j + k); - clrbit(cg_blksfree(cgp), baseblk + k); - } - n_blks += frags; - if (frags == sblock.fs_frag) - cgp->cg_cs.cs_nbfree--; - else - cgp->cg_cs.cs_nffree -= frags; - cgdirty(); - return (i + j); - } - } - return (0); -} - -/* - * Free a previously allocated block - */ -void -freeblk(blkno, frags) - ufs_daddr_t blkno; - long frags; -{ - struct inodesc idesc; - - idesc.id_blkno = blkno; - idesc.id_numfrags = frags; - (void)pass4check(&idesc); -} - -/* - * Find a pathname - */ -void -getpathname(namebuf, curdir, ino) - char *namebuf; - ino_t curdir, ino; -{ - int len; - register char *cp; - struct inodesc idesc; - static int busy = 0; - - if (curdir == ino && ino == ROOTINO) { - (void)strcpy(namebuf, "/"); - return; - } - if (busy || - (inoinfo(curdir)->ino_state != DSTATE && - inoinfo(curdir)->ino_state != DFOUND)) { - (void)strcpy(namebuf, "?"); - return; - } - busy = 1; - memset(&idesc, 0, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_fix = IGNORE; - cp = &namebuf[MAXPATHLEN - 1]; - *cp = '\0'; - if (curdir != ino) { - idesc.id_parent = curdir; - goto namelookup; - } - while (ino != ROOTINO) { - idesc.id_number = ino; - idesc.id_func = findino; - idesc.id_name = ".."; - if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) - break; - namelookup: - idesc.id_number = idesc.id_parent; - idesc.id_parent = ino; - idesc.id_func = findname; - idesc.id_name = namebuf; - if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) - break; - len = strlen(namebuf); - cp -= len; - memmove(cp, namebuf, (size_t)len); - *--cp = '/'; - if (cp < &namebuf[MAXNAMLEN]) - break; - ino = idesc.id_number; - } - busy = 0; - if (ino != ROOTINO) - *--cp = '?'; - memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); -} - -void -catch(sig) - int sig; -{ - if (!doinglevel2) - ckfini(0); - exit(12); -} - -/* - * When preening, allow a single quit to signal - * a special exit after filesystem checks complete - * so that reboot sequence may be interrupted. - */ -void -catchquit(sig) - int sig; -{ - printf("returning to single-user after filesystem check\n"); - returntosingle = 1; - (void)signal(SIGQUIT, SIG_DFL); -} - -/* - * Ignore a single quit signal; wait and flush just in case. - * Used by child processes in preen. - */ -void -voidquit(sig) - int sig; -{ - - sleep(1); - (void)signal(SIGQUIT, SIG_IGN); - (void)signal(SIGQUIT, SIG_DFL); -} - -/* - * determine whether an inode should be fixed. - */ -int -dofix(idesc, msg) - register struct inodesc *idesc; - char *msg; -{ - - switch (idesc->id_fix) { - - case DONTKNOW: - if (idesc->id_type == DATA) - direrror(idesc->id_number, msg); - else - pwarn("%s", msg); - if (preen) { - printf(" (SALVAGED)\n"); - idesc->id_fix = FIX; - return (ALTERED); - } - if (reply("SALVAGE") == 0) { - idesc->id_fix = NOFIX; - return (0); - } - idesc->id_fix = FIX; - return (ALTERED); - - case FIX: - return (ALTERED); - - case NOFIX: - case IGNORE: - return (0); - - default: - errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); - } - /* NOTREACHED */ - return (0); -} - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -/* - * An unexpected inconsistency occured. - * Die if preening or filesystem is running with soft dependency protocol, - * otherwise just print message and continue. - */ -void -#if __STDC__ -pfatal(const char *fmt, ...) -#else -pfatal(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - va_list ap; -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - if (!preen) { - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - if (usedsoftdep) - (void)fprintf(stderr, - "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); - return; - } - if (cdevname == NULL) - cdevname = "fsck"; - (void)fprintf(stderr, "%s: ", cdevname); - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, - "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", - cdevname, usedsoftdep ? " SOFT UPDATE " : " "); - ckfini(0); - exit(EEXIT); -} - -/* - * Pwarn just prints a message when not preening or running soft dependency - * protocol, or a warning (preceded by filename) when preening. - */ -void -#if __STDC__ -pwarn(const char *fmt, ...) -#else -pwarn(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - va_list ap; -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - if (preen) - (void)fprintf(stderr, "%s: ", cdevname); - (void)vfprintf(stderr, fmt, ap); - va_end(ap); -} - -/* - * Stub for routines from kernel. - */ -void -#if __STDC__ -panic(const char *fmt, ...) -#else -panic(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - va_list ap; -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - pfatal("INTERNAL INCONSISTENCY:"); - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - exit(EEXIT); -} diff --git a/sbin/fsdb/Makefile b/sbin/fsdb/Makefile index ef842c9..972bf8e 100644 --- a/sbin/fsdb/Makefile +++ b/sbin/fsdb/Makefile @@ -5,11 +5,11 @@ PROG= fsdb MAN8= fsdb.8 SRCS= fsdb.c fsdbutil.c \ - dir.c inode.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ + dir.c fsutil.c inode.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ pass5.c preen.c setup.c utilities.c ffs_subr.c ffs_tables.c -CFLAGS+= -I${.CURDIR}/../fsck +CFLAGS+= -I${.CURDIR}/../fsck_ffs LDADD+= -ledit -ltermcap DPADD+= ${LIBEDIT} ${LIBTERMCAP} -.PATH: ${.CURDIR}/../fsck ${.CURDIR}/../../sys/ufs/ffs +.PATH: ${.CURDIR}/../fsck_ffs ${.CURDIR}/../../sys/ufs/ffs .include <bsd.prog.mk> diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile index 7f929c8..7240fb9 100644 --- a/sbin/quotacheck/Makefile +++ b/sbin/quotacheck/Makefile @@ -1,8 +1,9 @@ +# $FreeBSD$ # @(#)Makefile 8.1 (Berkeley) 6/5/93 PROG= quotacheck -SRCS= quotacheck.c preen.c +SRCS= quotacheck.c preen.c utilities.c MAN8= quotacheck.8 -.PATH: ${.CURDIR}/../fsck +.PATH: ${.CURDIR}/../fsck_ffs .include <bsd.prog.mk> diff --git a/share/doc/smm/03.fsck/Makefile b/share/doc/smm/03.fsck/Makefile index 60fe632..fbdc009 100644 --- a/share/doc/smm/03.fsck/Makefile +++ b/share/doc/smm/03.fsck/Makefile @@ -4,6 +4,6 @@ VOLUME= smm/03.fsck SRCS= 0.t 1.t 2.t 3.t 4.t MACROS= -ms -SRCDIR= ${.CURDIR}/../../../../sbin/fsck/SMM.doc +SRCDIR= ${.CURDIR}/../../../../sbin/fsck_ffs/SMM.doc .include <bsd.doc.mk> |