From f7fa9f7edc626c0c42e63f1143cc6ff1d25f80c7 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 19:29:25 +0000 Subject: entered into RCS --- bsdfsck/preen.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 bsdfsck/preen.c (limited to 'bsdfsck') diff --git a/bsdfsck/preen.c b/bsdfsck/preen.c new file mode 100644 index 00000000..7893a5e1 --- /dev/null +++ b/bsdfsck/preen.c @@ -0,0 +1,355 @@ +/* + * 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 +/*static char sccsid[] = "from: @(#)preen.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: preen.c,v 1.1 1994/08/23 19:29:25 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +char *rawname(), *unrawname(), *blockcheck(); + +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; +char hotroot; + +checkfstab(preen, maxrun, docheck, chkit) + int preen, maxrun; + int (*docheck)(), (*chkit)(); +{ + 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)) { + if (sumstatus = (*chkit)(name, + fsp->fs_file, auxdata, 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); +} + +struct disk * +finddisk(name) + char *name; +{ + register struct disk *dk, **dkp; + register char *p; + size_t len; + + for (p = name + strlen(name) - 1; p >= name; --p) + if (isdigit(*p)) { + len = p - name + 1; + break; + } + if (p < name) + len = strlen(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); +} + +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; +} + +startdisk(dk, checkit) + register struct disk *dk; + int (*checkit)(); +{ + 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(name) + char *name; +{ + struct stat stslash, stblock, stchar; + char *raw; + int retried = 0; + + hotroot = 0; + if (stat("/", &stslash) < 0) { + perror("/"); + printf("Can't stat root\n"); + return (0); + } +retry: + if (stat(name, &stblock) < 0) { + perror(name); + printf("Can't stat %s\n", name); + return (0); + } + if ((stblock.st_mode & S_IFMT) == S_IFBLK) { + if (stslash.st_dev == stblock.st_rdev) + hotroot++; + raw = rawname(name); + if (stat(raw, &stchar) < 0) { + perror(raw); + printf("Can't stat %s\n", raw); + return (name); + } + if ((stchar.st_mode & S_IFMT) == S_IFCHR) { + return (raw); + } else { + printf("%s is not a character device\n", raw); + return (name); + } + } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { + name = unrawname(name); + retried++; + goto retry; + } + printf("Can't make sense out of name %s\n", name); + return (0); +} + +char * +unrawname(name) + char *name; +{ + char *dp; + struct stat stb; + + if ((dp = rindex(name, '/')) == 0) + return (name); + if (stat(name, &stb) < 0) + return (name); + if ((stb.st_mode & S_IFMT) != S_IFCHR) + return (name); + if (dp[1] != 'r') + return (name); + (void)strcpy(&dp[1], &dp[2]); + return (name); +} + +char * +rawname(name) + char *name; +{ + static char rawbuf[32]; + char *dp; + + if ((dp = rindex(name, '/')) == 0) + return (0); + *dp = 0; + (void)strcpy(rawbuf, name); + *dp = '/'; + (void)strcat(rawbuf, "/r"); + (void)strcat(rawbuf, &dp[1]); + return (rawbuf); +} -- cgit v1.2.3 From 212103a299c805c1568811847ef52ad1636d81bd Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 19:30:43 +0000 Subject: Initial revision --- bsdfsck/Makefile | 14 + bsdfsck/dir.c | 689 +++++++++++++++++++++++++++++ bsdfsck/inode.c | 549 +++++++++++++++++++++++ bsdfsck/main.c | 319 +++++++++++++ bsdfsck/pass1.c | 324 ++++++++++++++ bsdfsck/pass1b.c | 100 +++++ bsdfsck/pass2.c | 431 ++++++++++++++++++ bsdfsck/pass3.c | 72 +++ bsdfsck/pass4.c | 134 ++++++ bsdfsck/pass5.c | 320 ++++++++++++++ bsdfsck/setup.c | 467 +++++++++++++++++++ bsdfsck/utilities.c | 567 ++++++++++++++++++++++++ ufs-utils/Makefile | 15 + ufs-utils/mkfs.c | 1229 +++++++++++++++++++++++++++++++++++++++++++++++++++ ufs-utils/newfs.c | 679 ++++++++++++++++++++++++++++ 15 files changed, 5909 insertions(+) create mode 100644 bsdfsck/Makefile create mode 100644 bsdfsck/dir.c create mode 100644 bsdfsck/inode.c create mode 100644 bsdfsck/main.c create mode 100644 bsdfsck/pass1.c create mode 100644 bsdfsck/pass1b.c create mode 100644 bsdfsck/pass2.c create mode 100644 bsdfsck/pass3.c create mode 100644 bsdfsck/pass4.c create mode 100644 bsdfsck/pass5.c create mode 100644 bsdfsck/setup.c create mode 100644 bsdfsck/utilities.c create mode 100644 ufs-utils/Makefile create mode 100644 ufs-utils/mkfs.c create mode 100644 ufs-utils/newfs.c (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile new file mode 100644 index 00000000..b1e25a2f --- /dev/null +++ b/bsdfsck/Makefile @@ -0,0 +1,14 @@ +# from: @(#)Makefile 8.1 (Berkeley) 6/5/93 +# $Id: Makefile,v 1.1 1994/08/23 19:29:26 mib Exp $ + +PROG= fsck +MAN8= fsck.0 +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 +.PATH: ${.CURDIR}/../../sys/ufs/ffs + +.if make(install) +SUBDIR+= SMM.doc +.endif + +.include diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c new file mode 100644 index 00000000..e086439e --- /dev/null +++ b/bsdfsck/dir.c @@ -0,0 +1,689 @@ +/* + * 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 char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: dir.c,v 1.1 1994/08/23 19:29:21 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#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, ".." +}; + +struct direct *fsck_readdir(); +struct bufarea *getdirblk(); + +/* + * Propagate connected state through the tree. + */ +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 (statemap[inp->i_parent] == DFOUND && + statemap[inp->i_number] == DSTATE) { + statemap[inp->i_number] = DFOUND; + change++; + } + } + } while (change > 0); +} + +/* + * Scan each entry in a directory block. + */ +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) + errexit("wrong type to dirscan %d\n", 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; + bcopy((char *)dp, dbuf, (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); + bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize, + (size_t)dsize); + dirty(bp); + sbdirty(); + } + if (n & STOP) + return (n); + } + return (idesc->id_filesize > 0 ? KEEPON : STOP); +} + +/* + * get next entry in a directory. + */ +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; + 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; + 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. + */ +dircheck(idesc, dp) + struct inodesc *idesc; + register struct direct *dp; +{ + register int size; + register char *cp; + u_char namlen, type; + int spaceleft; + + size = DIRSIZ(!newinofmt, dp); + spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); +# 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_ino < maxino && + dp->d_reclen != 0 && + dp->d_reclen <= spaceleft && + (dp->d_reclen & 0x3) == 0 && + dp->d_reclen >= size && + idesc->id_filesize >= size && + namlen <= MAXNAMLEN && + type <= 15) { + if (dp->d_ino == 0) + return (1); + for (cp = dp->d_name, size = 0; size < namlen; size++) + if (*cp == 0 || (*cp++ == '/')) + return (0); + if (*cp == 0) + return (1); + } + return (0); +} + +direrror(ino, errmesg) + ino_t ino; + char *errmesg; +{ + + fileerror(ino, ino, errmesg); +} + +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); +} + +adjust(idesc, lcnt) + register struct inodesc *idesc; + short lcnt; +{ + register struct dinode *dp; + + dp = ginode(idesc->id_number); + if (dp->di_nlink == lcnt) { + if (linkup(idesc->id_number, (ino_t)0) == 0) + clri(idesc, "UNREF", 0); + } else { + 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) { + if (lcnt < 0) { + printf("\n"); + pfatal("LINK COUNT INCREASING"); + } + printf(" (ADJUSTED)\n"); + } + if (preen || reply("ADJUST") == 1) { + dp->di_nlink -= lcnt; + inodirty(); + } + } +} + +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 */ + if (newinofmt) { + dirp->d_type = typemap[idesc->id_parent]; + dirp->d_namlen = newent.d_namlen; + } else { +# if (BYTE_ORDER == LITTLE_ENDIAN) + dirp->d_type = newent.d_namlen; + dirp->d_namlen = 0; +# else + dirp->d_type = 0; + dirp->d_namlen = newent.d_namlen; +# endif + } + dirp->d_reclen = newent.d_reclen; + bcopy(idesc->id_name, dirp->d_name, (size_t)newent.d_namlen + 1); + return (ALTERED|STOP); +} + +chgino(idesc) + struct inodesc *idesc; +{ + register struct direct *dirp = idesc->id_dirp; + + if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) + return (KEEPON); + dirp->d_ino = idesc->id_parent; + if (newinofmt) + dirp->d_type = typemap[idesc->id_parent]; + else + dirp->d_type = 0; + return (ALTERED|STOP); +} + +linkup(orphan, parentdir) + ino_t orphan; + ino_t parentdir; +{ + register struct dinode *dp; + int lostdir; + ino_t oldlfdir; + struct inodesc idesc; + char tempname[BUFSIZ]; + extern int pass4check(); + + bzero((char *)&idesc, 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) { + 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, lncntp[oldlfdir] + 1); + lncntp[oldlfdir] = 0; + dp = ginode(lfdir); + } + if (statemap[lfdir] != DFOUND) { + pfatal("SORRY. NO lost+found DIRECTORY\n\n"); + return (0); + } + (void)lftempname(tempname, orphan); + if (makeentry(lfdir, orphan, tempname) == 0) { + pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); + printf("\n\n"); + return (0); + } + lncntp[orphan]--; + if (lostdir) { + if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 && + parentdir != (ino_t)-1) + (void)makeentry(orphan, lfdir, ".."); + dp = ginode(lfdir); + dp->di_nlink++; + inodirty(); + lncntp[lfdir]++; + pwarn("DIR I=%lu CONNECTED. ", orphan); + if (parentdir != (ino_t)-1) + printf("PARENT WAS I=%lu\n", parentdir); + if (preen == 0) + printf("\n"); + } + return (1); +} + +/* + * fix an entry in a directory. + */ +changeino(dir, name, newnum) + ino_t dir; + char *name; + ino_t newnum; +{ + struct inodesc idesc; + + bzero((char *)&idesc, 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 + */ +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); + bzero((char *)&idesc, 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 + */ +expanddir(dp, name) + register struct dinode *dp; + char *name; +{ + 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; + bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ); + bp = getdirblk(newblk, sblock.fs_bsize); + if (bp->b_errs) + goto bad; + bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ); + for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; + cp < &bp->b_un.b_buf[sblock.fs_bsize]; + cp += DIRBLKSIZ) + bcopy((char *)&emptydir, cp, sizeof emptydir); + dirty(bp); + bp = getdirblk(dp->di_db[lastbn + 1], + (long)dblksize(&sblock, dp, lastbn + 1)); + if (bp->b_errs) + goto bad; + bcopy((char *)&emptydir, bp->b_un.b_buf, 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 + */ +allocdir(parent, request, mode) + ino_t parent, request; + int mode; +{ + ino_t ino; + char *cp; + struct dinode *dp; + register struct bufarea *bp; + 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); + } + bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate)); + for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; + cp < &bp->b_un.b_buf[sblock.fs_fsize]; + cp += DIRBLKSIZ) + bcopy((char *)&emptydir, cp, sizeof emptydir); + dirty(bp); + dp->di_nlink = 2; + inodirty(); + if (ino == ROOTINO) { + lncntp[ino] = dp->di_nlink; + cacheino(dp, ino); + return(ino); + } + if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { + freeino(ino); + return (0); + } + cacheino(dp, ino); + statemap[ino] = statemap[parent]; + if (statemap[ino] == DSTATE) { + lncntp[ino] = dp->di_nlink; + lncntp[parent]++; + } + dp = ginode(parent); + dp->di_nlink++; + inodirty(); + return (ino); +} + +/* + * free a directory inode + */ +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. + */ +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. + */ +struct bufarea * +getdirblk(blkno, size) + daddr_t blkno; + long size; +{ + + if (pdirbp != 0) + pdirbp->b_flags &= ~B_INUSE; + pdirbp = getdatablk(blkno, size); + return (pdirbp); +} diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c new file mode 100644 index 00000000..10a01afa --- /dev/null +++ b/bsdfsck/inode.c @@ -0,0 +1,549 @@ +/* + * 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 char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ +static char *rcsid = "$Id: inode.c,v 1.1 1994/08/23 19:29:21 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#ifndef SMALL +#include +#endif +#include +#include +#include "fsck.h" + +static ino_t startinum; + +ckinode(dp, idesc) + struct dinode *dp; + register struct inodesc *idesc; +{ + register daddr_t *ap; + long ret, n, ndb, offset; + struct dinode dino; + quad_t remsize, sizepb; + mode_t mode; + + if (idesc->id_fix != IGNORE) + idesc->id_fix = DONTKNOW; + 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 < sblock.fs_maxsymlinklen || + (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) + return (KEEPON); + dino = *dp; + ndb = howmany(dino.di_size, sblock.fs_bsize); + for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { + 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) + continue; + idesc->id_blkno = *ap; + if (idesc->id_type == ADDR) + 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++) { + if (*ap) { + idesc->id_blkno = *ap; + ret = iblock(idesc, n, remsize); + if (ret & STOP) + return (ret); + } + sizepb *= NINDIR(&sblock); + remsize -= sizepb; + } + return (KEEPON); +} + +iblock(idesc, ilevel, isize) + struct inodesc *idesc; + long ilevel; + quad_t isize; +{ + register daddr_t *ap; + register daddr_t *aplim; + register struct bufarea *bp; + int i, n, (*func)(), nif; + quad_t sizepb; + char buf[BUFSIZ]; + extern int dirscan(), pass1check(); + + if (idesc->id_type == ADDR) { + 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", + 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 (*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); + } + } + 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. + */ +chkrange(blk, cnt) + daddr_t blk; + int cnt; +{ + register int c; + + if ((unsigned)(blk + cnt) > maxfsblock) + return (1); + c = dtog(&sblock, blk); + if (blk < cgdmin(&sblock, c)) { + if ((blk + cnt) > cgsblock(&sblock, c)) { + if (debug) { + printf("blk %ld < cgdmin %ld;", + blk, cgdmin(&sblock, c)); + printf(" blk + cnt %ld > cgsbase %ld\n", + blk + cnt, cgsblock(&sblock, c)); + } + return (1); + } + } else { + if ((blk + cnt) > cgbase(&sblock, c+1)) { + if (debug) { + printf("blk %ld >= cgdmin %ld;", + blk, cgdmin(&sblock, c)); + printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", + blk+cnt, sblock.fs_fpg); + } + return (1); + } + } + return (0); +} + +/* + * General purpose interface for reading inodes. + */ +struct dinode * +ginode(inumber) + ino_t inumber; +{ + daddr_t iblk; + + if (inumber < ROOTINO || inumber > maxino) + errexit("bad inode number %d to ginode\n", 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; +long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; +struct dinode *inodebuf; + +struct dinode * +getnextinode(inumber) + ino_t inumber; +{ + long size; + daddr_t dblk; + static struct dinode *dp; + + if (inumber != nextino++ || inumber > maxino) + errexit("bad inode number %d to nextinode\n", 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; + } + (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ + dp = inodebuf; + } + return (dp++); +} + +resetinodebuf() +{ + + startinum = 0; + nextino = 0; + lastinum = 0; + readcnt = 0; + 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 == NULL && + (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) + errexit("Cannot allocate space for inode buffer\n"); + while (nextino < ROOTINO) + (void)getnextinode(nextino); +} + +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. + */ +cacheino(dp, inumber) + register struct dinode *dp; + ino_t inumber; +{ + register struct inoinfo *inp; + struct inoinfo **inpp; + unsigned 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(daddr_t)); + if (inp == NULL) + return; + inpp = &inphead[inumber % numdirs]; + inp->i_nexthash = *inpp; + *inpp = inp; + inp->i_parent = (ino_t)0; + inp->i_dotdot = (ino_t)0; + inp->i_number = inumber; + inp->i_isize = dp->di_size; + inp->i_numblks = blks * sizeof(daddr_t); + bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[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) + errexit("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 % numdirs]; inp; inp = inp->i_nexthash) { + if (inp->i_number != inumber) + continue; + return (inp); + } + errexit("cannot find inode %d\n", inumber); + return ((struct inoinfo *)0); +} + +/* + * Clean up all the inode cache structure. + */ +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; +} + +inodirty() +{ + + dirty(pbp); +} + +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); + statemap[idesc->id_number] = USTATE; + inodirty(); + } +} + +findname(idesc) + struct inodesc *idesc; +{ + register struct direct *dirp = idesc->id_dirp; + + if (dirp->d_ino != idesc->id_parent) + return (KEEPON); + bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1); + return (STOP|FOUND); +} + +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); +} + +pinode(ino) + ino_t ino; +{ + register struct dinode *dp; + register char *p; + struct passwd *pw; + char *ctime(); + + printf(" I=%lu ", ino); + if (ino < ROOTINO || ino > maxino) + return; + dp = ginode(ino); + printf(" OWNER="); +#ifndef SMALL + if ((pw = getpwuid((int)dp->di_uid)) != 0) + printf("%s ", pw->pw_name); + else +#endif + printf("%u ", (unsigned)dp->di_uid); + printf("MODE=%o\n", dp->di_mode); + if (preen) + printf("%s: ", cdevname); + printf("SIZE=%qu ", dp->di_size); + p = ctime(&dp->di_mtime.ts_sec); + printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); +} + +blkerror(ino, type, blk) + ino_t ino; + char *type; + daddr_t blk; +{ + + pfatal("%ld %s I=%lu", blk, type, ino); + printf("\n"); + switch (statemap[ino]) { + + case FSTATE: + statemap[ino] = FCLEAR; + return; + + case DSTATE: + statemap[ino] = DCLEAR; + return; + + case FCLEAR: + case DCLEAR: + return; + + default: + errexit("BAD STATE %d TO BLKERR", statemap[ino]); + /* NOTREACHED */ + } +} + +/* + * allocate an unused inode + */ +ino_t +allocino(request, type) + ino_t request; + int type; +{ + register ino_t ino; + register struct dinode *dp; + + if (request == 0) + request = ROOTINO; + else if (statemap[request] != USTATE) + return (0); + for (ino = request; ino < maxino; ino++) + if (statemap[ino] == USTATE) + break; + if (ino == maxino) + return (0); + switch (type & IFMT) { + case IFDIR: + statemap[ino] = DSTATE; + break; + case IFREG: + case IFLNK: + statemap[ino] = FSTATE; + break; + default: + return (0); + } + dp = ginode(ino); + dp->di_db[0] = allocblk((long)1); + if (dp->di_db[0] == 0) { + statemap[ino] = USTATE; + return (0); + } + dp->di_mode = type; + (void)time(&dp->di_atime.ts_sec); + dp->di_mtime = dp->di_ctime = dp->di_atime; + dp->di_size = sblock.fs_fsize; + dp->di_blocks = btodb(sblock.fs_fsize); + n_files++; + inodirty(); + if (newinofmt) + typemap[ino] = IFTODT(type); + return (ino); +} + +/* + * deallocate an inode + */ +freeino(ino) + ino_t ino; +{ + struct inodesc idesc; + extern int pass4check(); + struct dinode *dp; + + bzero((char *)&idesc, 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(); + statemap[ino] = USTATE; + n_files--; +} diff --git a/bsdfsck/main.c b/bsdfsck/main.c new file mode 100644 index 00000000..e8f952a1 --- /dev/null +++ b/bsdfsck/main.c @@ -0,0 +1,319 @@ +/* + * 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 char copyright[] = +"@(#) Copyright (c) 1980, 1986, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/ +static char *rcsid = "$Id: main.c,v 1.1 1994/08/23 19:29:22 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +void catch(), catchquit(), voidquit(); +int returntosingle; + +main(argc, argv) + int argc; + char *argv[]; +{ + int ch; + int ret, maxrun = 0; + extern int docheck(), checkfilesys(); + extern char *optarg, *blockcheck(); + extern int optind; + + sync(); + while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) { + 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 'l': + maxrun = argtoi('l', "number", optarg, 10); + break; + + case 'm': + lfmode = argtoi('m', "mode", optarg, 8); + if (lfmode &~ 07777) + errexit("bad mode to -m: %o\n", 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: + errexit("%c option?\n", ch); + } + } + argc -= optind; + argv += optind; + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + (void)signal(SIGINT, catch); + if (preen) + (void)signal(SIGQUIT, catchquit); + if (argc) { + while (argc-- > 0) + (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); + exit(0); + } + ret = checkfstab(preen, maxrun, docheck, checkfilesys); + if (returntosingle) + exit(2); + exit(ret); +} + +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) + errexit("-%c flag requires a %s\n", flag, req); + return (ret); +} + +/* + * Determine whether a filesystem should be checked. + */ +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 */ +checkfilesys(filesys, mntpt, auxdata, child) + char *filesys, *mntpt; + long auxdata; +{ + daddr_t n_ffree, n_bfree; + struct dups *dp; + struct zlncnt *zlnp; + int cylno; + + if (preen && child) + (void)signal(SIGQUIT, voidquit); + cdevname = filesys; + if (debug && preen) + pwarn("starting\n"); + if (setup(filesys) == 0) { + if (preen) + pfatal("CAN'T CHECK FILE SYSTEM."); + return (0); + } + /* + * 1: scan inodes tallying blocks used + */ + if (preen == 0) { + printf("** Last Mounted on %s\n", sblock.fs_fsmnt); + if (hotroot) + 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) + 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("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", + n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, + ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); + if (debug && + (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) + printf("%ld 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("%ld blocks missing\n", n_blks); + if (duplist != NULL) { + printf("The following duplicate blocks remain:"); + for (dp = duplist; dp; dp = dp->next) + printf(" %ld,", dp->dup); + printf("\n"); + } + if (zlnhead != NULL) { + printf("The following zero link count inodes remain:"); + for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) + printf(" %lu,", zlnp->zlncnt); + printf("\n"); + } + } + zlnhead = (struct zlncnt *)0; + duplist = (struct dups *)0; + muldup = (struct dups *)0; + inocleanup(); + if (fsmodified) { + (void)time(&sblock.fs_time); + 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); + } + ckfini(); + free(blockmap); + free(statemap); + free((char *)lncntp); + if (!fsmodified) + return (0); + if (!preen) + printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + if (hotroot) { + struct statfs stfs_buf; + /* + * We modified the root. Do a mount update on + * it, unless it is read-write, so we can continue. + */ + if (statfs("/", &stfs_buf) == 0) { + long flags = stfs_buf.f_flags; + struct ufs_args args; + int ret; + + if (flags & MNT_RDONLY) { + args.fspec = 0; + args.export.ex_flags = 0; + args.export.ex_root = 0; + flags |= MNT_UPDATE | MNT_RELOAD; + ret = mount(MOUNT_UFS, "/", flags, &args); + if (ret == 0) + return(0); + } + } + if (!preen) + printf("\n***** REBOOT NOW *****\n"); + sync(); + return (4); + } + return (0); +} diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c new file mode 100644 index 00000000..cc15c199 --- /dev/null +++ b/bsdfsck/pass1.c @@ -0,0 +1,324 @@ +/* + * 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 char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: pass1.c,v 1.1 1994/08/23 19:29:23 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +static daddr_t badblk; +static daddr_t dupblk; +int pass1check(); +struct dinode *getnextinode(); + +pass1() +{ + ino_t inumber; + int c, i, cgd; + 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. + */ + bzero((char *)&idesc, sizeof(struct inodesc)); + idesc.id_type = ADDR; + idesc.id_func = pass1check; + inumber = 0; + n_files = n_blks = 0; + resetinodebuf(); + for (c = 0; c < sblock.fs_ncg; c++) { + for (i = 0; i < sblock.fs_ipg; i++, inumber++) { + if (inumber < ROOTINO) + continue; + checkinode(inumber, &idesc); + } + } + freeinodebuf(); +} + +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 (bcmp((char *)dp->di_db, (char *)zino.di_db, + NDADDR * sizeof(daddr_t)) || + bcmp((char *)dp->di_ib, (char *)zino.di_ib, + NIADDR * sizeof(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(); + } + } + statemap[inumber] = USTATE; + return; + } + lastino = inumber; + if (/* dp->di_size < 0 || */ + dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { + 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(); + } + 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) { + /* + * Note that the old fastlink format always had di_blocks set + * to 0. Other than that we no longer use the `spare' field + * (which is now the extended uid) for sanity checking, the + * new format is the same as the old. We simply ignore the + * conversion altogether. - mycroft, 19MAY1994 + */ + 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) + errexit("cannot read symlink"); + if (debug) { + symbuf[dp->di_size] = 0; + printf("convert symlink %d(%s) of size %d\n", + inumber, symbuf, (long)dp->di_size); + } + dp = ginode(inumber); + bcopy(symbuf, (caddr_t)dp->di_shortlink, + (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 || + (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)) { + ndb = howmany(dp->di_size, sizeof(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", 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", + dp->di_ib[j]); + goto unknown; + } + if (ftypeok(dp) == 0) + goto unknown; + n_files++; + lncntp[inumber] = 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) + errexit(""); + } else { + zlnp->zlncnt = inumber; + zlnp->next = zlnhead; + zlnhead = zlnp; + } + } + if (mode == IFDIR) { + if (dp->di_size == 0) + statemap[inumber] = DCLEAR; + else + statemap[inumber] = DSTATE; + cacheino(dp, inumber); + } else + statemap[inumber] = FSTATE; + typemap[inumber] = 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; + (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); + statemap[inumber] = FCLEAR; + if (reply("CLEAR") == 1) { + statemap[inumber] = USTATE; + dp = ginode(inumber); + clearinode(dp); + inodirty(); + } +} + +pass1check(idesc) + register struct inodesc *idesc; +{ + int res = KEEPON; + int anyout, nfrags; + daddr_t blkno = idesc->id_blkno; + register struct dups *dlp; + struct dups *new; + + 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) + errexit(""); + 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) + errexit(""); + return (STOP); + } + new = (struct dups *)malloc(sizeof(struct dups)); + if (new == NULL) { + pfatal("DUP TABLE OVERFLOW."); + if (reply("CONTINUE") == 0) + errexit(""); + 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/bsdfsck/pass1b.c b/bsdfsck/pass1b.c new file mode 100644 index 00000000..d40e2254 --- /dev/null +++ b/bsdfsck/pass1b.c @@ -0,0 +1,100 @@ +/* + * 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 char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: pass1b.c,v 1.1 1994/08/23 19:29:23 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include "fsck.h" + +int pass1bcheck(); +static struct dups *duphead; + +pass1b() +{ + register int c, i; + register struct dinode *dp; + struct inodesc idesc; + ino_t inumber; + + bzero((char *)&idesc, 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 (statemap[inumber] != USTATE && + (ckinode(dp, &idesc) & STOP)) + return; + } + } +} + +pass1bcheck(idesc) + register struct inodesc *idesc; +{ + register struct dups *dlp; + int nfrags, res = KEEPON; + 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/bsdfsck/pass2.c b/bsdfsck/pass2.c new file mode 100644 index 00000000..df3af93c --- /dev/null +++ b/bsdfsck/pass2.c @@ -0,0 +1,431 @@ +/* + * 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 char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/ +static char *rcsid = "$Id: pass2.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +#define MINDIRSIZE (sizeof (struct dirtemplate)) + +int pass2check(), blksort(); + +pass2() +{ + register struct dinode *dp; + register struct inoinfo **inpp, *inp; + struct inoinfo **inpend; + struct inodesc curino; + struct dinode dino; + char pathbuf[MAXPATHLEN + 1]; + + switch (statemap[ROOTINO]) { + + case USTATE: + pfatal("ROOT INODE UNALLOCATED"); + if (reply("ALLOCATE") == 0) + errexit(""); + if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) + errexit("CANNOT ALLOCATE ROOT INODE\n"); + break; + + case DCLEAR: + pfatal("DUPS/BAD IN ROOT INODE"); + if (reply("REALLOCATE")) { + freeino(ROOTINO); + if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) + errexit("CANNOT ALLOCATE ROOT INODE\n"); + break; + } + if (reply("CONTINUE") == 0) + errexit(""); + break; + + case FSTATE: + case FCLEAR: + pfatal("ROOT INODE NOT DIRECTORY"); + if (reply("REALLOCATE")) { + freeino(ROOTINO); + if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) + errexit("CANNOT ALLOCATE ROOT INODE\n"); + break; + } + if (reply("FIX") == 0) + errexit(""); + dp = ginode(ROOTINO); + dp->di_mode &= ~IFMT; + dp->di_mode |= IFDIR; + inodirty(); + break; + + case DSTATE: + break; + + default: + errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]); + } + statemap[ROOTINO] = DFOUND; + /* + * Sort the directory list into disk block order. + */ + qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); + /* + * Check the integrity of each directory. + */ + bzero((char *)&curino, 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); + pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", + 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; + } + } + bzero((char *)&dino, sizeof(struct dinode)); + dino.di_mode = IFDIR; + dp->di_size = inp->i_isize; + bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[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 (statemap[inp->i_parent] == DFOUND && + statemap[inp->i_number] == DSTATE) + statemap[inp->i_number] = 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, ".."); + lncntp[inp->i_parent]--; + continue; + } + fileerror(inp->i_parent, inp->i_number, + "BAD INODE NUMBER FOR '..'"); + if (reply("FIX") == 0) + continue; + lncntp[inp->i_dotdot]++; + lncntp[inp->i_parent]--; + 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(); +} + +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 = typemap[dirp->d_ino]; + 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, "."); + 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; + bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); + if (reply("FIX") == 1) + ret |= ALTERED; + } else { + n = dirp->d_reclen - entrysize; + proto.d_reclen = entrysize; + bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); + idesc->id_entryno++; + lncntp[dirp->d_ino]--; + dirp = (struct direct *)((char *)(dirp) + entrysize); + bzero((char *)dirp, (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, ".."); + 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++; + lncntp[dirp->d_ino]--; + dirp = (struct direct *)((char *)(dirp) + n); + bzero((char *)dirp, (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; + bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); + if (reply("FIX") == 1) + ret |= ALTERED; + } + idesc->id_entryno++; + if (dirp->d_ino != 0) + lncntp[dirp->d_ino]--; + 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 { +again: + switch (statemap[dirp->d_ino]) { + 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 (statemap[dirp->d_ino] == FCLEAR) + errmsg = "DUP/BAD"; + else if (!preen) + 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); + statemap[dirp->d_ino] = + (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; + lncntp[dirp->d_ino] = dp->di_nlink; + goto again; + + case DSTATE: + if (statemap[idesc->id_number] == DFOUND) + statemap[dirp->d_ino] = 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(" (IGNORED)\n"); + else 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 != typemap[dirp->d_ino]) { + fileerror(idesc->id_number, dirp->d_ino, + "BAD TYPE VALUE"); + dirp->d_type = typemap[dirp->d_ino]; + if (reply("FIX") == 1) + ret |= ALTERED; + } + lncntp[dirp->d_ino]--; + break; + + default: + errexit("BAD STATE %d FOR INODE I=%d", + statemap[dirp->d_ino], dirp->d_ino); + } + } + if (n == 0) + return (ret|KEEPON); + dirp->d_ino = 0; + return (ret|KEEPON|ALTERED); +} + +/* + * Routine to sort disk blocks. + */ +blksort(inpp1, inpp2) + struct inoinfo **inpp1, **inpp2; +{ + + return ((*inpp1)->i_blks[0] - (*inpp2)->i_blks[0]); +} diff --git a/bsdfsck/pass3.c b/bsdfsck/pass3.c new file mode 100644 index 00000000..12c40700 --- /dev/null +++ b/bsdfsck/pass3.c @@ -0,0 +1,72 @@ +/* + * 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 char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: pass3.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "fsck.h" + +pass3() +{ + register struct inoinfo **inpp, *inp; + ino_t orphan; + int loopcnt; + + for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) { + inp = *inpp; + if (inp->i_number == ROOTINO || + !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE)) + continue; + if (statemap[inp->i_number] == DCLEAR) + continue; + for (loopcnt = 0; ; loopcnt++) { + orphan = inp->i_number; + if (inp->i_parent == 0 || + statemap[inp->i_parent] != DSTATE || + loopcnt > numdirs) + break; + inp = getinoinfo(inp->i_parent); + } + (void)linkup(orphan, inp->i_dotdot); + inp->i_parent = inp->i_dotdot = lfdir; + lncntp[lfdir]--; + statemap[orphan] = DFOUND; + propagate(); + } +} diff --git a/bsdfsck/pass4.c b/bsdfsck/pass4.c new file mode 100644 index 00000000..b7623f4e --- /dev/null +++ b/bsdfsck/pass4.c @@ -0,0 +1,134 @@ +/* + * 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 char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: pass4.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +int pass4check(); + +pass4() +{ + register ino_t inumber; + register struct zlncnt *zlnp; + struct dinode *dp; + struct inodesc idesc; + int n; + + bzero((char *)&idesc, sizeof(struct inodesc)); + idesc.id_type = ADDR; + idesc.id_func = pass4check; + for (inumber = ROOTINO; inumber <= lastino; inumber++) { + idesc.id_number = inumber; + switch (statemap[inumber]) { + + case FSTATE: + case DFOUND: + n = lncntp[inumber]; + if (n) + adjust(&idesc, (short)n); + else { + 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: + errexit("BAD STATE %d FOR INODE I=%d", + statemap[inumber], inumber); + } + } +} + +pass4check(idesc) + register struct inodesc *idesc; +{ + register struct dups *dlp; + int nfrags, res = KEEPON; + 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/bsdfsck/pass5.c b/bsdfsck/pass5.c new file mode 100644 index 00000000..66e9efea --- /dev/null +++ b/bsdfsck/pass5.c @@ -0,0 +1,320 @@ +/* + * 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 char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/ +static char *rcsid = "$Id: pass5.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include "fsck.h" + +pass5() +{ + int c, blk, frags, basesize, sumsize, mapsize, savednrpos; + register struct fs *fs = &sblock; + register struct cg *cg = &cgrp; + daddr_t dbase, dmax; + register daddr_t d; + register long i, j; + 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; + + bzero((char *)newcg, (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_link); + sumsize = &ocg->cg_iused[0] - (char *)(&ocg->cg_btot[0]); + mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - + (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_link); + newcg->cg_boff = + newcg->cg_btotoff + fs->fs_cpg * sizeof(long); + newcg->cg_iusedoff = newcg->cg_boff + + fs->fs_cpg * fs->fs_nrpos * sizeof(short); + newcg->cg_freeoff = + newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); + if (fs->fs_contigsumsize <= 0) { + newcg->cg_nextfreeoff = newcg->cg_freeoff + + howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); + } else { + newcg->cg_clustersumoff = newcg->cg_freeoff + + howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) - + sizeof(long); + newcg->cg_clustersumoff = + roundup(newcg->cg_clustersumoff, sizeof(long)); + newcg->cg_clusteroff = newcg->cg_clustersumoff + + (fs->fs_contigsumsize + 1) * sizeof(long); + 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_link); + sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; + mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; + break; + + default: + errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n", + fs->fs_postblformat); + } + bzero((char *)&idesc[0], sizeof idesc); + for (i = 0; i < 3; i++) { + idesc[i].id_type = ADDR; + if (doinglevel2) + idesc[i].id_fix = FIX; + } + bzero((char *)&cstotal, 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; + bzero((char *)&newcg->cg_frsum[0], sizeof newcg->cg_frsum); + bzero((char *)&cg_blktot(newcg)[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 < fs->fs_ipg; j++, i++) { + switch (statemap[j]) { + + 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; + errexit("BAD STATE %d FOR INODE I=%d", + statemap[j], 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) { + long *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 (bcmp((char *)&newcg->cg_cs, (char *)cs, sizeof *cs) != 0 && + dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { + bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs); + sbdirty(); + } + if (doinglevel1) { + bcopy((char *)newcg, (char *)cg, (size_t)fs->fs_cgsize); + cgdirty(); + continue; + } + if (bcmp(cg_inosused(newcg), + cg_inosused(cg), mapsize) != 0 && + dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { + bcopy(cg_inosused(newcg), cg_inosused(cg), + (size_t)mapsize); + cgdirty(); + } + if ((bcmp((char *)newcg, (char *)cg, basesize) != 0 || + bcmp((char *)&cg_blktot(newcg)[0], + (char *)&cg_blktot(cg)[0], sumsize) != 0) && + dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { + bcopy((char *)newcg, (char *)cg, (size_t)basesize); + bcopy((char *)&cg_blktot(newcg)[0], + (char *)&cg_blktot(cg)[0], (size_t)sumsize); + cgdirty(); + } + } + if (fs->fs_postblformat == FS_42POSTBLFMT) + fs->fs_nrpos = savednrpos; + if (bcmp((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs) != 0 + && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { + bcopy((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs); + fs->fs_ronly = 0; + fs->fs_fmod = 0; + sbdirty(); + } +} diff --git a/bsdfsck/setup.c b/bsdfsck/setup.c new file mode 100644 index 00000000..475192cb --- /dev/null +++ b/bsdfsck/setup.c @@ -0,0 +1,467 @@ +/* + * 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 char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/ +static char *rcsid = "$Id: setup.c,v 1.1 1994/08/23 19:29:25 mib Exp $"; +#endif /* not lint */ + +#define DKTYPENAMES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +struct bufarea asblk; +#define altsblock (*asblk.b_un.b_fs) +#define POWEROF2(num) (((num) & ((num) - 1)) == 0) + +struct disklabel *getdisklabel(); + +setup(dev) + char *dev; +{ + long cg, size, asked, i, j; + long bmapsize; + struct disklabel *lp; + off_t sizepb; + struct stat statb; + struct fs proto; + + havesb = 0; + fswritefd = -1; + 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) { + pfatal("%s is not a character 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) + errexit("cannot allocate space for superblock\n"); + if (lp = getdisklabel((char *)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) { + 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)."); + return(0); + } + pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); + } + 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_link); + sblock.fs_rotbloff = &sblock.fs_space[0] - + (u_char *)(&sblock.fs_link); + sblock.fs_cgsize = + fragroundup(&sblock, CGSIZE(&sblock)); + sbdirty(); + dirty(&asblk); + } + if (asblk.b_dirty && !bflag) { + bcopy((char *)&sblock, (char *)&altsblock, + (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) + errexit(""); + 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; + } + statemap = calloc((unsigned)(maxino + 1), sizeof(char)); + if (statemap == NULL) { + printf("cannot alloc %u bytes for statemap\n", + (unsigned)(maxino + 1)); + goto badsb; + } + typemap = calloc((unsigned)(maxino + 1), sizeof(char)); + if (typemap == NULL) { + printf("cannot alloc %u bytes for typemap\n", + (unsigned)(maxino + 1)); + goto badsb; + } + lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short)); + if (lncntp == NULL) { + printf("cannot alloc %u bytes for lncntp\n", + (unsigned)(maxino + 1) * sizeof(short)); + goto badsb; + } + numdirs = sblock.fs_cstotal.cs_ndir; + 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(); + return (1); + +badsb: + ckfini(); + return (0); +} + +/* + * Read in the super block and its summary info. + */ +readsb(listerr) + int listerr; +{ + 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_link = sblock.fs_link; + altsblock.fs_rlink = sblock.fs_rlink; + 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; + bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp, + sizeof sblock.fs_csp); + bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt, + sizeof sblock.fs_fsmnt); + bcopy((char *)sblock.fs_sparecon, (char *)altsblock.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_qbmask = sblock.fs_qbmask; + altsblock.fs_qfmask = sblock.fs_qfmask; + altsblock.fs_state = sblock.fs_state; + altsblock.fs_maxfilesize = sblock.fs_maxfilesize; + if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) { + badsb(listerr, + "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); + return (0); + } + havesb = 1; + return (1); +} + +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! + */ +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 = index(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); + } + bzero((char *)fs, 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); +} + +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)); + errexit("%s: can't read disk label\n", s); + } + return (&lab); +} diff --git a/bsdfsck/utilities.c b/bsdfsck/utilities.c new file mode 100644 index 00000000..5c31061c --- /dev/null +++ b/bsdfsck/utilities.c @@ -0,0 +1,567 @@ +/* + * 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 char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/ +static char *rcsid = "$Id: utilities.c,v 1.1 1994/08/23 19:29:26 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsck.h" + +long diskreads, totalreads; /* Disk cache statistics */ + +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); + } +} + +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); + 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)) + return (0); + } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); + printf("\n"); + if (c == 'y' || c == 'Y') + return (1); + return (0); +} + +/* + * Malloc buffers and set up cache. + */ +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) + errexit("cannot allocate buffer pool\n"); + 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; + errexit("cannot allocate buffer pool\n"); + } + 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) + 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) + errexit("deadlocked buffer pool\n"); + 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; + daddr_t blk; + long size; +{ + 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; + } +} + +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); + } +} + +rwerror(mesg, blk) + char *mesg; + daddr_t blk; +{ + + if (preen == 0) + printf("\n"); + pfatal("CANNOT %s: BLK %ld", mesg, blk); + if (reply("CONTINUE") == 0) + errexit("Program terminated\n"); +} + +ckfini() +{ + register struct bufarea *bp, *nbp; + int 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) + errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt); + pbp = pdirbp = (struct bufarea *)0; + if (debug) + printf("cache missed %ld of %ld (%d%%)\n", diskreads, + totalreads, (int)(diskreads * 100 / totalreads)); + (void)close(fsreadfd); + (void)close(fswritefd); +} + +bread(fd, buf, blk, size) + int fd; + char *buf; + 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; + bzero(buf, (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"); + return (errs); +} + +bwrite(fd, buf, blk, size) + int fd; + char *buf; + 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; + } + 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 + */ +allocblk(frags) + long frags; +{ + register int i, j, k; + + 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; + } + for (k = 0; k < frags; k++) + setbmap(i + j + k); + n_blks += frags; + return (i + j); + } + } + return (0); +} + +/* + * Free a previously allocated block + */ +freeblk(blkno, frags) + daddr_t blkno; + long frags; +{ + struct inodesc idesc; + + idesc.id_blkno = blkno; + idesc.id_numfrags = frags; + (void)pass4check(&idesc); +} + +/* + * Find a pathname + */ +getpathname(namebuf, curdir, ino) + char *namebuf; + ino_t curdir, ino; +{ + int len; + register char *cp; + struct inodesc idesc; + static int busy = 0; + extern int findname(); + + if (curdir == ino && ino == ROOTINO) { + (void)strcpy(namebuf, "/"); + return; + } + if (busy || + (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { + (void)strcpy(namebuf, "?"); + return; + } + busy = 1; + bzero((char *)&idesc, 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; + bcopy(namebuf, cp, (size_t)len); + *--cp = '/'; + if (cp < &namebuf[MAXNAMLEN]) + break; + ino = idesc.id_number; + } + busy = 0; + if (ino != ROOTINO) + *--cp = '?'; + bcopy(cp, namebuf, (size_t)(&namebuf[MAXPATHLEN] - cp)); +} + +void +catch() +{ + if (!doinglevel2) + ckfini(); + 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() +{ + extern returntosingle; + + 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() +{ + + sleep(1); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGQUIT, SIG_DFL); +} + +/* + * determine whether an inode should be fixed. + */ +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(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: + errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); + } + /* NOTREACHED */ +} + +/* VARARGS1 */ +errexit(s1, s2, s3, s4) + char *s1; +{ + printf(s1, s2, s3, s4); + exit(8); +} + +/* + * An unexpected inconsistency occured. + * Die if preening, otherwise just print message and continue. + */ +/* VARARGS1 */ +pfatal(s, a1, a2, a3) + char *s; +{ + + if (preen) { + printf("%s: ", cdevname); + printf(s, a1, a2, a3); + printf("\n"); + printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", + cdevname); + exit(8); + } + printf(s, a1, a2, a3); +} + +/* + * Pwarn just prints a message when not preening, + * or a warning (preceded by filename) when preening. + */ +/* VARARGS1 */ +pwarn(s, a1, a2, a3, a4, a5, a6) + char *s; +{ + + if (preen) + printf("%s: ", cdevname); + printf(s, a1, a2, a3, a4, a5, a6); +} + +#ifndef lint +/* + * Stub for routines from kernel. + */ +panic(s) + char *s; +{ + + pfatal("INTERNAL INCONSISTENCY:"); + errexit(s); +} +#endif diff --git a/ufs-utils/Makefile b/ufs-utils/Makefile new file mode 100644 index 00000000..4cc571a1 --- /dev/null +++ b/ufs-utils/Makefile @@ -0,0 +1,15 @@ +# from: @(#)Makefile 8.2 (Berkeley) 3/27/94 +# $Id: Makefile,v 1.1 1994/08/23 19:30:43 mib Exp $ + +PROG= newfs +SRCS= dkcksum.c getmntopts.c newfs.c mkfs.c +MAN8= newfs.0 + +MOUNT= ${.CURDIR}/../mount +CFLAGS+=-DMFS -I${MOUNT} +.PATH: ${MOUNT} ${.CURDIR}/../disklabel + +LINKS= ${BINDIR}/newfs ${BINDIR}/mount_mfs +MLINKS= newfs.8 mount_mfs.8 newfs.8 mfs.8 + +.include diff --git a/ufs-utils/mkfs.c b/ufs-utils/mkfs.c new file mode 100644 index 00000000..d35dd10b --- /dev/null +++ b/ufs-utils/mkfs.c @@ -0,0 +1,1229 @@ +/* + * Copyright (c) 1980, 1989, 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 char sccsid[] = "from: @(#)mkfs.c 8.3 (Berkeley) 2/3/94";*/ +static char *rcsid = "$Id: mkfs.c,v 1.1 1994/08/23 19:30:42 mib Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef STANDALONE +#include +#include +#endif + +/* + * make file system for cylinder-group style file systems + */ + +/* + * We limit the size of the inode map to be no more than a + * third of the cylinder group space, since we must leave at + * least an equal amount of space for the block map. + * + * N.B.: MAXIPG must be a multiple of INOPB(fs). + */ +#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) + +#define UMASK 0755 +#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) +#define POWEROF2(num) (((num) & ((num) - 1)) == 0) + +/* + * variables set up by front end. + */ +extern int mfs; /* run as the memory based filesystem */ +extern int Nflag; /* run mkfs without writing file system */ +extern int Oflag; /* format as an 4.3BSD file system */ +extern int fssize; /* file system size */ +extern int ntracks; /* # tracks/cylinder */ +extern int nsectors; /* # sectors/track */ +extern int nphyssectors; /* # sectors/track including spares */ +extern int secpercyl; /* sectors per cylinder */ +extern int sectorsize; /* bytes/sector */ +extern int rpm; /* revolutions/minute of drive */ +extern int interleave; /* hardware sector interleave */ +extern int trackskew; /* sector 0 skew, per track */ +extern int headswitch; /* head switch time, usec */ +extern int trackseek; /* track-to-track seek, usec */ +extern int fsize; /* fragment size */ +extern int bsize; /* block size */ +extern int cpg; /* cylinders/cylinder group */ +extern int cpgflg; /* cylinders/cylinder group flag was given */ +extern int minfree; /* free space threshold */ +extern int opt; /* optimization preference (space or time) */ +extern int density; /* number of bytes per inode */ +extern int maxcontig; /* max contiguous blocks to allocate */ +extern int rotdelay; /* rotational delay between blocks */ +extern int maxbpg; /* maximum blocks per file in a cyl group */ +extern int nrpos; /* # of distinguished rotational positions */ +extern int bbsize; /* boot block size */ +extern int sbsize; /* superblock size */ +extern u_long memleft; /* virtual memory available */ +extern caddr_t membase; /* start address of memory based filesystem */ +extern caddr_t malloc(), calloc(); + +union { + struct fs fs; + char pad[SBSIZE]; +} fsun; +#define sblock fsun.fs +struct csum *fscs; + +union { + struct cg cg; + char pad[MAXBSIZE]; +} cgun; +#define acg cgun.cg + +struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; + +int fsi, fso; +daddr_t alloc(); + +mkfs(pp, fsys, fi, fo) + struct partition *pp; + char *fsys; + int fi, fo; +{ + register long i, mincpc, mincpg, inospercg; + long cylno, rpos, blk, j, warn = 0; + long used, mincpgcnt, bpcg; + long mapcramped, inodecramped; + long postblsize, rotblsize, totalsbsize; + int ppid, status; + time_t utime; + quad_t sizepb; + void started(); + +#ifndef STANDALONE + time(&utime); +#endif + if (mfs) { + ppid = getpid(); + (void) signal(SIGUSR1, started); + if (i = fork()) { + if (i == -1) { + perror("mfs"); + exit(10); + } + if (waitpid(i, &status, 0) != -1 && WIFEXITED(status)) + exit(WEXITSTATUS(status)); + exit(11); + /* NOTREACHED */ + } + (void)malloc(0); + if (fssize * sectorsize > memleft) + fssize = (memleft - 16384) / sectorsize; + if ((membase = malloc(fssize * sectorsize)) == 0) + exit(12); + } + fsi = fi; + fso = fo; + if (Oflag) { + sblock.fs_inodefmt = FS_42INODEFMT; + sblock.fs_maxsymlinklen = 0; + } else { + sblock.fs_inodefmt = FS_44INODEFMT; + sblock.fs_maxsymlinklen = MAXSYMLINKLEN; + } + /* + * Validate the given file system size. + * Verify that its last block can actually be accessed. + */ + if (fssize <= 0) + printf("preposterous size %d\n", fssize), exit(13); + wtfs(fssize - 1, sectorsize, (char *)&sblock); + /* + * collect and verify the sector and track info + */ + sblock.fs_nsect = nsectors; + sblock.fs_ntrak = ntracks; + if (sblock.fs_ntrak <= 0) + printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14); + if (sblock.fs_nsect <= 0) + printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); + /* + * collect and verify the block and fragment sizes + */ + sblock.fs_bsize = bsize; + sblock.fs_fsize = fsize; + if (!POWEROF2(sblock.fs_bsize)) { + printf("block size must be a power of 2, not %d\n", + sblock.fs_bsize); + exit(16); + } + if (!POWEROF2(sblock.fs_fsize)) { + printf("fragment size must be a power of 2, not %d\n", + sblock.fs_fsize); + exit(17); + } + if (sblock.fs_fsize < sectorsize) { + printf("fragment size %d is too small, minimum is %d\n", + sblock.fs_fsize, sectorsize); + exit(18); + } + if (sblock.fs_bsize < MINBSIZE) { + printf("block size %d is too small, minimum is %d\n", + sblock.fs_bsize, MINBSIZE); + exit(19); + } + if (sblock.fs_bsize < sblock.fs_fsize) { + printf("block size (%d) cannot be smaller than fragment size (%d)\n", + sblock.fs_bsize, sblock.fs_fsize); + exit(20); + } + sblock.fs_bmask = ~(sblock.fs_bsize - 1); + sblock.fs_fmask = ~(sblock.fs_fsize - 1); + sblock.fs_qbmask = ~sblock.fs_bmask; + sblock.fs_qfmask = ~sblock.fs_fmask; + for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) + sblock.fs_bshift++; + for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) + sblock.fs_fshift++; + sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); + for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) + sblock.fs_fragshift++; + if (sblock.fs_frag > MAXFRAG) { + printf("fragment size %d is too small, minimum with block size %d is %d\n", + sblock.fs_fsize, sblock.fs_bsize, + sblock.fs_bsize / MAXFRAG); + exit(21); + } + sblock.fs_nrpos = nrpos; + sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); + sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); + sblock.fs_nspf = sblock.fs_fsize / sectorsize; + for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) + sblock.fs_fsbtodb++; + sblock.fs_sblkno = + roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); + sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + + roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); + sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; + sblock.fs_cgoffset = roundup( + howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); + for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) + sblock.fs_cgmask <<= 1; + if (!POWEROF2(sblock.fs_ntrak)) + sblock.fs_cgmask <<= 1; + sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; + for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { + sizepb *= NINDIR(&sblock); + sblock.fs_maxfilesize += sizepb; + } + /* + * Validate specified/determined secpercyl + * and calculate minimum cylinders per group. + */ + sblock.fs_spc = secpercyl; + for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; + sblock.fs_cpc > 1 && (i & 1) == 0; + sblock.fs_cpc >>= 1, i >>= 1) + /* void */; + mincpc = sblock.fs_cpc; + bpcg = sblock.fs_spc * sectorsize; + inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); + if (inospercg > MAXIPG(&sblock)) + inospercg = MAXIPG(&sblock); + used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); + mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, + sblock.fs_spc); + mincpg = roundup(mincpgcnt, mincpc); + /* + * Ensure that cylinder group with mincpg has enough space + * for block maps. + */ + sblock.fs_cpg = mincpg; + sblock.fs_ipg = inospercg; + if (maxcontig > 1) + sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); + mapcramped = 0; + while (CGSIZE(&sblock) > sblock.fs_bsize) { + mapcramped = 1; + if (sblock.fs_bsize < MAXBSIZE) { + sblock.fs_bsize <<= 1; + if ((i & 1) == 0) { + i >>= 1; + } else { + sblock.fs_cpc <<= 1; + mincpc <<= 1; + mincpg = roundup(mincpgcnt, mincpc); + sblock.fs_cpg = mincpg; + } + sblock.fs_frag <<= 1; + sblock.fs_fragshift += 1; + if (sblock.fs_frag <= MAXFRAG) + continue; + } + if (sblock.fs_fsize == sblock.fs_bsize) { + printf("There is no block size that"); + printf(" can support this disk\n"); + exit(22); + } + sblock.fs_frag >>= 1; + sblock.fs_fragshift -= 1; + sblock.fs_fsize <<= 1; + sblock.fs_nspf <<= 1; + } + /* + * Ensure that cylinder group with mincpg has enough space for inodes. + */ + inodecramped = 0; + used *= sectorsize; + inospercg = roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); + sblock.fs_ipg = inospercg; + while (inospercg > MAXIPG(&sblock)) { + inodecramped = 1; + if (mincpc == 1 || sblock.fs_frag == 1 || + sblock.fs_bsize == MINBSIZE) + break; + printf("With a block size of %d %s %d\n", sblock.fs_bsize, + "minimum bytes per inode is", + (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); + sblock.fs_bsize >>= 1; + sblock.fs_frag >>= 1; + sblock.fs_fragshift -= 1; + mincpc >>= 1; + sblock.fs_cpg = roundup(mincpgcnt, mincpc); + if (CGSIZE(&sblock) > sblock.fs_bsize) { + sblock.fs_bsize <<= 1; + break; + } + mincpg = sblock.fs_cpg; + inospercg = + roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); + sblock.fs_ipg = inospercg; + } + if (inodecramped) { + if (inospercg > MAXIPG(&sblock)) { + printf("Minimum bytes per inode is %d\n", + (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); + } else if (!mapcramped) { + printf("With %d bytes per inode, ", density); + printf("minimum cylinders per group is %d\n", mincpg); + } + } + if (mapcramped) { + printf("With %d sectors per cylinder, ", sblock.fs_spc); + printf("minimum cylinders per group is %d\n", mincpg); + } + if (inodecramped || mapcramped) { + if (sblock.fs_bsize != bsize) + printf("%s to be changed from %d to %d\n", + "This requires the block size", + bsize, sblock.fs_bsize); + if (sblock.fs_fsize != fsize) + printf("\t%s to be changed from %d to %d\n", + "and the fragment size", + fsize, sblock.fs_fsize); + exit(23); + } + /* + * Calculate the number of cylinders per group + */ + sblock.fs_cpg = cpg; + if (sblock.fs_cpg % mincpc != 0) { + printf("%s groups must have a multiple of %d cylinders\n", + cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); + sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); + if (!cpgflg) + cpg = sblock.fs_cpg; + } + /* + * Must ensure there is enough space for inodes. + */ + sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, + INOPB(&sblock)); + while (sblock.fs_ipg > MAXIPG(&sblock)) { + inodecramped = 1; + sblock.fs_cpg -= mincpc; + sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, + INOPB(&sblock)); + } + /* + * Must ensure there is enough space to hold block map. + */ + while (CGSIZE(&sblock) > sblock.fs_bsize) { + mapcramped = 1; + sblock.fs_cpg -= mincpc; + sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, + INOPB(&sblock)); + } + sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); + if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { + printf("panic (fs_cpg * fs_spc) % NSPF != 0"); + exit(24); + } + if (sblock.fs_cpg < mincpg) { + printf("cylinder groups must have at least %d cylinders\n", + mincpg); + exit(25); + } else if (sblock.fs_cpg != cpg) { + if (!cpgflg) + printf("Warning: "); + else if (!mapcramped && !inodecramped) + exit(26); + if (mapcramped && inodecramped) + printf("Block size and bytes per inode restrict"); + else if (mapcramped) + printf("Block size restricts"); + else + printf("Bytes per inode restrict"); + printf(" cylinders per group to %d.\n", sblock.fs_cpg); + if (cpgflg) + exit(27); + } + sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); + /* + * Now have size for file system and nsect and ntrak. + * Determine number of cylinders and blocks in the file system. + */ + sblock.fs_size = fssize = dbtofsb(&sblock, fssize); + sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; + if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { + sblock.fs_ncyl++; + warn = 1; + } + if (sblock.fs_ncyl < 1) { + printf("file systems must have at least one cylinder\n"); + exit(28); + } + /* + * Determine feasability/values of rotational layout tables. + * + * The size of the rotational layout tables is limited by the + * size of the superblock, SBSIZE. The amount of space available + * for tables is calculated as (SBSIZE - sizeof (struct fs)). + * The size of these tables is inversely proportional to the block + * size of the file system. The size increases if sectors per track + * are not powers of two, because more cylinders must be described + * by the tables before the rotational pattern repeats (fs_cpc). + */ + sblock.fs_interleave = interleave; + sblock.fs_trackskew = trackskew; + sblock.fs_npsect = nphyssectors; + sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; + sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); + if (sblock.fs_ntrak == 1) { + sblock.fs_cpc = 0; + goto next; + } + postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(short); + rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); + totalsbsize = sizeof(struct fs) + rotblsize; + if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { + /* use old static table space */ + sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - + (char *)(&sblock.fs_link); + sblock.fs_rotbloff = &sblock.fs_space[0] - + (u_char *)(&sblock.fs_link); + } else { + /* use dynamic table space */ + sblock.fs_postbloff = &sblock.fs_space[0] - + (u_char *)(&sblock.fs_link); + sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; + totalsbsize += postblsize; + } + if (totalsbsize > SBSIZE || + sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { + printf("%s %s %d %s %d.%s", + "Warning: insufficient space in super block for\n", + "rotational layout tables with nsect", sblock.fs_nsect, + "and ntrak", sblock.fs_ntrak, + "\nFile system performance may be impaired.\n"); + sblock.fs_cpc = 0; + goto next; + } + sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); + /* + * calculate the available blocks for each rotational position + */ + for (cylno = 0; cylno < sblock.fs_cpc; cylno++) + for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) + fs_postbl(&sblock, cylno)[rpos] = -1; + for (i = (rotblsize - 1) * sblock.fs_frag; + i >= 0; i -= sblock.fs_frag) { + cylno = cbtocylno(&sblock, i); + rpos = cbtorpos(&sblock, i); + blk = fragstoblks(&sblock, i); + if (fs_postbl(&sblock, cylno)[rpos] == -1) + fs_rotbl(&sblock)[blk] = 0; + else + fs_rotbl(&sblock)[blk] = + fs_postbl(&sblock, cylno)[rpos] - blk; + fs_postbl(&sblock, cylno)[rpos] = blk; + } +next: + /* + * Compute/validate number of cylinder groups. + */ + sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; + if (sblock.fs_ncyl % sblock.fs_cpg) + sblock.fs_ncg++; + sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); + i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); + if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { + printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", + cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, + sblock.fs_fpg / sblock.fs_frag); + printf("number of cylinders per cylinder group (%d) %s.\n", + sblock.fs_cpg, "must be increased"); + exit(29); + } + j = sblock.fs_ncg - 1; + if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && + cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { + if (j == 0) { + printf("Filesystem must have at least %d sectors\n", + NSPF(&sblock) * + (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); + exit(30); + } + printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n", + (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, + i / sblock.fs_frag); + printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n", + i * NSPF(&sblock)); + sblock.fs_ncg--; + sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; + sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / + NSPF(&sblock); + warn = 0; + } + if (warn && !mfs) { + printf("Warning: %d sector(s) in last cylinder unallocated\n", + sblock.fs_spc - + (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) + * sblock.fs_spc)); + } + /* + * fill in remaining fields of the super block + */ + sblock.fs_csaddr = cgdmin(&sblock, 0); + sblock.fs_cssize = + fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); + i = sblock.fs_bsize / sizeof(struct csum); + sblock.fs_csmask = ~(i - 1); + for (sblock.fs_csshift = 0; i > 1; i >>= 1) + sblock.fs_csshift++; + fscs = (struct csum *)calloc(1, sblock.fs_cssize); + sblock.fs_magic = FS_MAGIC; + sblock.fs_rotdelay = rotdelay; + sblock.fs_minfree = minfree; + sblock.fs_maxcontig = maxcontig; + sblock.fs_headswitch = headswitch; + sblock.fs_trkseek = trackseek; + sblock.fs_maxbpg = maxbpg; + sblock.fs_rps = rpm / 60; + sblock.fs_optim = opt; + sblock.fs_cgrotor = 0; + sblock.fs_cstotal.cs_ndir = 0; + sblock.fs_cstotal.cs_nbfree = 0; + sblock.fs_cstotal.cs_nifree = 0; + sblock.fs_cstotal.cs_nffree = 0; + sblock.fs_fmod = 0; + sblock.fs_ronly = 0; + /* + * Dump out summary information about file system. + */ + if (!mfs) { + printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", + fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, + "cylinders", sblock.fs_ntrak, sblock.fs_nsect); +#define B2MBFACTOR (1 / (1024.0 * 1024.0)) + printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", + (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, + sblock.fs_ncg, sblock.fs_cpg, + (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, + sblock.fs_ipg); +#undef B2MBFACTOR + } + /* + * Now build the cylinders group blocks and + * then print out indices of cylinder groups. + */ + if (!mfs) + printf("super-block backups (for fsck -b #) at:"); + for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { + initcg(cylno, utime); + if (mfs) + continue; + if (cylno % 8 == 0) + printf("\n"); + printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); + } + if (!mfs) + printf("\n"); + if (Nflag && !mfs) + exit(0); + /* + * Now construct the initial file system, + * then write out the super-block. + */ + fsinit(utime); + sblock.fs_time = utime; + wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock); + for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) + wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), + sblock.fs_cssize - i < sblock.fs_bsize ? + sblock.fs_cssize - i : sblock.fs_bsize, + ((char *)fscs) + i); + /* + * Write out the duplicate super blocks + */ + for (cylno = 0; cylno < sblock.fs_ncg; cylno++) + wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), + sbsize, (char *)&sblock); + /* + * Update information about this partion in pack + * label, to that it may be updated on disk. + */ + pp->p_fstype = FS_BSDFFS; + pp->p_fsize = sblock.fs_fsize; + pp->p_frag = sblock.fs_frag; + pp->p_cpg = sblock.fs_cpg; + /* + * Notify parent process of success. + * Dissociate from session and tty. + */ + if (mfs) { + kill(ppid, SIGUSR1); + (void) setsid(); + (void) close(0); + (void) close(1); + (void) close(2); + (void) chdir("/"); + } +} + +/* + * Initialize a cylinder group. + */ +initcg(cylno, utime) + int cylno; + time_t utime; +{ + daddr_t cbase, d, dlower, dupper, dmax, blkno; + long i, j, s; + register struct csum *cs; + + /* + * Determine block bounds for cylinder group. + * Allow space for super block summary information in first + * cylinder group. + */ + cbase = cgbase(&sblock, cylno); + dmax = cbase + sblock.fs_fpg; + if (dmax > sblock.fs_size) + dmax = sblock.fs_size; + dlower = cgsblock(&sblock, cylno) - cbase; + dupper = cgdmin(&sblock, cylno) - cbase; + if (cylno == 0) + dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); + cs = fscs + cylno; + bzero(&acg, sblock.fs_cgsize); + acg.cg_time = utime; + acg.cg_magic = CG_MAGIC; + acg.cg_cgx = cylno; + if (cylno == sblock.fs_ncg - 1) + acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; + else + acg.cg_ncyl = sblock.fs_cpg; + acg.cg_niblk = sblock.fs_ipg; + acg.cg_ndblk = dmax - cbase; + if (sblock.fs_contigsumsize > 0) + acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; + acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_link); + acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(long); + acg.cg_iusedoff = acg.cg_boff + + sblock.fs_cpg * sblock.fs_nrpos * sizeof(short); + acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); + if (sblock.fs_contigsumsize <= 0) { + acg.cg_nextfreeoff = acg.cg_freeoff + + howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); + } else { + acg.cg_clustersumoff = acg.cg_freeoff + howmany + (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - + sizeof(long); + acg.cg_clustersumoff = + roundup(acg.cg_clustersumoff, sizeof(long)); + acg.cg_clusteroff = acg.cg_clustersumoff + + (sblock.fs_contigsumsize + 1) * sizeof(long); + acg.cg_nextfreeoff = acg.cg_clusteroff + howmany + (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); + } + if (acg.cg_nextfreeoff - (long)(&acg.cg_link) > sblock.fs_cgsize) { + printf("Panic: cylinder group too big\n"); + exit(37); + } + acg.cg_cs.cs_nifree += sblock.fs_ipg; + if (cylno == 0) + for (i = 0; i < ROOTINO; i++) { + setbit(cg_inosused(&acg), i); + acg.cg_cs.cs_nifree--; + } + for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) + wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), + sblock.fs_bsize, (char *)zino); + if (cylno > 0) { + /* + * In cylno 0, beginning space is reserved + * for boot and super blocks. + */ + for (d = 0; d < dlower; d += sblock.fs_frag) { + blkno = d / sblock.fs_frag; + setblock(&sblock, cg_blksfree(&acg), blkno); + if (sblock.fs_contigsumsize > 0) + setbit(cg_clustersfree(&acg), blkno); + acg.cg_cs.cs_nbfree++; + cg_blktot(&acg)[cbtocylno(&sblock, d)]++; + cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) + [cbtorpos(&sblock, d)]++; + } + sblock.fs_dsize += dlower; + } + sblock.fs_dsize += acg.cg_ndblk - dupper; + if (i = dupper % sblock.fs_frag) { + acg.cg_frsum[sblock.fs_frag - i]++; + for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { + setbit(cg_blksfree(&acg), dupper); + acg.cg_cs.cs_nffree++; + } + } + for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { + blkno = d / sblock.fs_frag; + setblock(&sblock, cg_blksfree(&acg), blkno); + if (sblock.fs_contigsumsize > 0) + setbit(cg_clustersfree(&acg), blkno); + acg.cg_cs.cs_nbfree++; + cg_blktot(&acg)[cbtocylno(&sblock, d)]++; + cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) + [cbtorpos(&sblock, d)]++; + d += sblock.fs_frag; + } + if (d < dmax - cbase) { + acg.cg_frsum[dmax - cbase - d]++; + for (; d < dmax - cbase; d++) { + setbit(cg_blksfree(&acg), d); + acg.cg_cs.cs_nffree++; + } + } + if (sblock.fs_contigsumsize > 0) { + long *sump = cg_clustersum(&acg); + u_char *mapp = cg_clustersfree(&acg); + int map = *mapp++; + int bit = 1; + int run = 0; + + for (i = 0; i < acg.cg_nclusterblks; i++) { + if ((map & bit) != 0) { + run++; + } else if (run != 0) { + if (run > sblock.fs_contigsumsize) + run = sblock.fs_contigsumsize; + sump[run]++; + run = 0; + } + if ((i & (NBBY - 1)) != (NBBY - 1)) { + bit <<= 1; + } else { + map = *mapp++; + bit = 1; + } + } + if (run != 0) { + if (run > sblock.fs_contigsumsize) + run = sblock.fs_contigsumsize; + sump[run]++; + } + } + sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; + sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; + sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; + sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; + *cs = acg.cg_cs; + wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), + sblock.fs_bsize, (char *)&acg); +} + +/* + * initialize the file system + */ +struct dinode node; + +#ifdef LOSTDIR +#define PREDEFDIR 3 +#else +#define PREDEFDIR 2 +#endif + +struct direct root_dir[] = { + { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, + { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, +#ifdef LOSTDIR + { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, +#endif +}; +struct odirect { + u_long d_ino; + u_short d_reclen; + u_short d_namlen; + u_char d_name[MAXNAMLEN + 1]; +} oroot_dir[] = { + { ROOTINO, sizeof(struct direct), 1, "." }, + { ROOTINO, sizeof(struct direct), 2, ".." }, +#ifdef LOSTDIR + { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, +#endif +}; +#ifdef LOSTDIR +struct direct lost_found_dir[] = { + { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, + { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, + { 0, DIRBLKSIZ, 0, 0, 0 }, +}; +struct odirect olost_found_dir[] = { + { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, + { ROOTINO, sizeof(struct direct), 2, ".." }, + { 0, DIRBLKSIZ, 0, 0 }, +}; +#endif +char buf[MAXBSIZE]; + +fsinit(utime) + time_t utime; +{ + int i; + + /* + * initialize the node + */ + node.di_atime.ts_sec = utime; + node.di_mtime.ts_sec = utime; + node.di_ctime.ts_sec = utime; +#ifdef LOSTDIR + /* + * create the lost+found directory + */ + if (Oflag) { + (void)makedir((struct direct *)olost_found_dir, 2); + for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) + bcopy(&olost_found_dir[2], &buf[i], + DIRSIZ(0, &olost_found_dir[2])); + } else { + (void)makedir(lost_found_dir, 2); + for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) + bcopy(&lost_found_dir[2], &buf[i], + DIRSIZ(0, &lost_found_dir[2])); + } + node.di_mode = IFDIR | UMASK; + node.di_nlink = 2; + node.di_size = sblock.fs_bsize; + node.di_db[0] = alloc(node.di_size, node.di_mode); + node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); + wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); + iput(&node, LOSTFOUNDINO); +#endif + /* + * create the root directory + */ + if (mfs) + node.di_mode = IFDIR | 01777; + else + node.di_mode = IFDIR | UMASK; + node.di_nlink = PREDEFDIR; + if (Oflag) + node.di_size = makedir((struct direct *)oroot_dir, PREDEFDIR); + else + node.di_size = makedir(root_dir, PREDEFDIR); + node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); + node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); + wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); + iput(&node, ROOTINO); +} + +/* + * construct a set of directory entries in "buf". + * return size of directory. + */ +makedir(protodir, entries) + register struct direct *protodir; + int entries; +{ + char *cp; + int i, spcleft; + + spcleft = DIRBLKSIZ; + for (cp = buf, i = 0; i < entries - 1; i++) { + protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); + bcopy(&protodir[i], cp, protodir[i].d_reclen); + cp += protodir[i].d_reclen; + spcleft -= protodir[i].d_reclen; + } + protodir[i].d_reclen = spcleft; + bcopy(&protodir[i], cp, DIRSIZ(0, &protodir[i])); + return (DIRBLKSIZ); +} + +/* + * allocate a block or frag + */ +daddr_t +alloc(size, mode) + int size; + int mode; +{ + int i, frag; + daddr_t d, blkno; + + rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, + (char *)&acg); + if (acg.cg_magic != CG_MAGIC) { + printf("cg 0: bad magic number\n"); + return (0); + } + if (acg.cg_cs.cs_nbfree == 0) { + printf("first cylinder group ran out of space\n"); + return (0); + } + for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) + if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) + goto goth; + printf("internal error: can't find block in cyl 0\n"); + return (0); +goth: + blkno = fragstoblks(&sblock, d); + clrblock(&sblock, cg_blksfree(&acg), blkno); + if (sblock.fs_contigsumsize > 0) + clrbit(cg_clustersfree(&acg), blkno); + acg.cg_cs.cs_nbfree--; + sblock.fs_cstotal.cs_nbfree--; + fscs[0].cs_nbfree--; + if (mode & IFDIR) { + acg.cg_cs.cs_ndir++; + sblock.fs_cstotal.cs_ndir++; + fscs[0].cs_ndir++; + } + cg_blktot(&acg)[cbtocylno(&sblock, d)]--; + cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; + if (size != sblock.fs_bsize) { + frag = howmany(size, sblock.fs_fsize); + fscs[0].cs_nffree += sblock.fs_frag - frag; + sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; + acg.cg_cs.cs_nffree += sblock.fs_frag - frag; + acg.cg_frsum[sblock.fs_frag - frag]++; + for (i = frag; i < sblock.fs_frag; i++) + setbit(cg_blksfree(&acg), d + i); + } + wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, + (char *)&acg); + return (d); +} + +/* + * Allocate an inode on the disk + */ +iput(ip, ino) + register struct dinode *ip; + register ino_t ino; +{ + struct dinode buf[MAXINOPB]; + daddr_t d; + int c; + + c = ino_to_cg(&sblock, ino); + rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, + (char *)&acg); + if (acg.cg_magic != CG_MAGIC) { + printf("cg 0: bad magic number\n"); + exit(31); + } + acg.cg_cs.cs_nifree--; + setbit(cg_inosused(&acg), ino); + wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, + (char *)&acg); + sblock.fs_cstotal.cs_nifree--; + fscs[0].cs_nifree--; + if (ino >= sblock.fs_ipg * sblock.fs_ncg) { + printf("fsinit: inode value out of range (%d).\n", ino); + exit(32); + } + d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); + rdfs(d, sblock.fs_bsize, buf); + buf[ino_to_fsbo(&sblock, ino)] = *ip; + wtfs(d, sblock.fs_bsize, buf); +} + +/* + * Notify parent process that the filesystem has created itself successfully. + */ +void +started() +{ + + exit(0); +} + +/* + * Replace libc function with one suited to our needs. + */ +caddr_t +malloc(size) + register u_long size; +{ + char *base, *i; + static u_long pgsz; + struct rlimit rlp; + + if (pgsz == 0) { + base = sbrk(0); + pgsz = getpagesize() - 1; + i = (char *)((u_long)(base + pgsz) &~ pgsz); + base = sbrk(i - base); + if (getrlimit(RLIMIT_DATA, &rlp) < 0) + perror("getrlimit"); + rlp.rlim_cur = rlp.rlim_max; + if (setrlimit(RLIMIT_DATA, &rlp) < 0) + perror("setrlimit"); + memleft = rlp.rlim_max - (u_long)base; + } + size = (size + pgsz) &~ pgsz; + if (size > memleft) + size = memleft; + memleft -= size; + if (size == 0) + return (0); + return ((caddr_t)sbrk(size)); +} + +/* + * Replace libc function with one suited to our needs. + */ +caddr_t +realloc(ptr, size) + char *ptr; + u_long size; +{ + void *p; + + if ((p = malloc(size)) == NULL) + return (NULL); + bcopy(ptr, p, size); + free(ptr); + return (p); +} + +/* + * Replace libc function with one suited to our needs. + */ +char * +calloc(size, numelm) + u_long size, numelm; +{ + caddr_t base; + + size *= numelm; + base = malloc(size); + bzero(base, size); + return (base); +} + +/* + * Replace libc function with one suited to our needs. + */ +free(ptr) + char *ptr; +{ + + /* do not worry about it for now */ +} + +/* + * read a block from the file system + */ +rdfs(bno, size, bf) + daddr_t bno; + int size; + char *bf; +{ + int n; + + if (mfs) { + bcopy(membase + bno * sectorsize, bf, size); + return; + } + if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) { + printf("seek error: %ld\n", bno); + perror("rdfs"); + exit(33); + } + n = read(fsi, bf, size); + if (n != size) { + printf("read error: %ld\n", bno); + perror("rdfs"); + exit(34); + } +} + +/* + * write a block to the file system + */ +wtfs(bno, size, bf) + daddr_t bno; + int size; + char *bf; +{ + int n; + + if (mfs) { + bcopy(bf, membase + bno * sectorsize, size); + return; + } + if (Nflag) + return; + if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) { + printf("seek error: %ld\n", bno); + perror("wtfs"); + exit(35); + } + n = write(fso, bf, size); + if (n != size) { + printf("write error: %ld\n", bno); + perror("wtfs"); + exit(36); + } +} + +/* + * check if a block is available + */ +isblock(fs, cp, h) + struct fs *fs; + unsigned char *cp; + int h; +{ + unsigned char mask; + + switch (fs->fs_frag) { + case 8: + return (cp[h] == 0xff); + case 4: + mask = 0x0f << ((h & 0x1) << 2); + return ((cp[h >> 1] & mask) == mask); + case 2: + mask = 0x03 << ((h & 0x3) << 1); + return ((cp[h >> 2] & mask) == mask); + case 1: + mask = 0x01 << (h & 0x7); + return ((cp[h >> 3] & mask) == mask); + default: +#ifdef STANDALONE + printf("isblock bad fs_frag %d\n", fs->fs_frag); +#else + fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); +#endif + return (0); + } +} + +/* + * take a block out of the map + */ +clrblock(fs, cp, h) + struct fs *fs; + unsigned char *cp; + int h; +{ + switch ((fs)->fs_frag) { + case 8: + cp[h] = 0; + return; + case 4: + cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); + return; + case 2: + cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); + return; + case 1: + cp[h >> 3] &= ~(0x01 << (h & 0x7)); + return; + default: +#ifdef STANDALONE + printf("clrblock bad fs_frag %d\n", fs->fs_frag); +#else + fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); +#endif + return; + } +} + +/* + * put a block into the map + */ +setblock(fs, cp, h) + struct fs *fs; + unsigned char *cp; + int h; +{ + switch (fs->fs_frag) { + case 8: + cp[h] = 0xff; + return; + case 4: + cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); + return; + case 2: + cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); + return; + case 1: + cp[h >> 3] |= (0x01 << (h & 0x7)); + return; + default: +#ifdef STANDALONE + printf("setblock bad fs_frag %d\n", fs->fs_frag); +#else + fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); +#endif + return; + } +} diff --git a/ufs-utils/newfs.c b/ufs-utils/newfs.c new file mode 100644 index 00000000..f468ef24 --- /dev/null +++ b/ufs-utils/newfs.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 1983, 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)newfs.c 8.8 (Berkeley) 4/18/94";*/ +static char *rcsid = "$Id: newfs.c,v 1.1 1994/08/23 19:30:43 mib Exp $"; +#endif /* not lint */ + +/* + * newfs: friendly front end to mkfs + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if __STDC__ +#include +#else +#include +#endif + +#include "mntopts.h" + +struct mntopt mopts[] = { + MOPT_STDOPTS, + MOPT_ASYNC, + { NULL }, +}; + +#if __STDC__ +void fatal(const char *fmt, ...); +#else +void fatal(); +#endif + +#define COMPAT /* allow non-labeled disks */ + +/* + * The following two constants set the default block and fragment sizes. + * Both constants must be a power of 2 and meet the following constraints: + * MINBSIZE <= DESBLKSIZE <= MAXBSIZE + * sectorsize <= DESFRAGSIZE <= DESBLKSIZE + * DESBLKSIZE / DESFRAGSIZE <= 8 + */ +#define DFL_FRAGSIZE 1024 +#define DFL_BLKSIZE 8192 + +/* + * Cylinder groups may have up to many cylinders. The actual + * number used depends upon how much information can be stored + * on a single cylinder. The default is to use 16 cylinders + * per group. + */ +#define DESCPG 16 /* desired fs_cpg */ + +/* + * ROTDELAY gives the minimum number of milliseconds to initiate + * another disk transfer on the same cylinder. It is used in + * determining the rotationally optimal layout for disk blocks + * within a file; the default of fs_rotdelay is 4ms. + */ +#define ROTDELAY 4 + +/* + * MAXBLKPG determines the maximum number of data blocks which are + * placed in a single cylinder group. The default is one indirect + * block worth of data blocks. + */ +#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) + +/* + * Each file system has a number of inodes statically allocated. + * We allocate one inode slot per NFPI fragments, expecting this + * to be far more than we will ever need. + */ +#define NFPI 4 + +/* + * For each cylinder we keep track of the availability of blocks at different + * rotational positions, so that we can lay out the data to be picked + * up with minimum rotational latency. NRPOS is the default number of + * rotational positions that we distinguish. With NRPOS of 8 the resolution + * of our summary information is 2ms for a typical 3600 rpm drive. + */ +#define NRPOS 8 /* number distinct rotational positions */ + + +int mfs; /* run as the memory based filesystem */ +int Nflag; /* run without writing file system */ +int Oflag; /* format as an 4.3BSD file system */ +int fssize; /* file system size */ +int ntracks; /* # tracks/cylinder */ +int nsectors; /* # sectors/track */ +int nphyssectors; /* # sectors/track including spares */ +int secpercyl; /* sectors per cylinder */ +int trackspares = -1; /* spare sectors per track */ +int cylspares = -1; /* spare sectors per cylinder */ +int sectorsize; /* bytes/sector */ +#ifdef tahoe +int realsectorsize; /* bytes/sector in hardware */ +#endif +int rpm; /* revolutions/minute of drive */ +int interleave; /* hardware sector interleave */ +int trackskew = -1; /* sector 0 skew, per track */ +int headswitch; /* head switch time, usec */ +int trackseek; /* track-to-track seek, usec */ +int fsize = 0; /* fragment size */ +int bsize = 0; /* block size */ +int cpg = DESCPG; /* cylinders/cylinder group */ +int cpgflg; /* cylinders/cylinder group flag was given */ +int minfree = MINFREE; /* free space threshold */ +int opt = DEFAULTOPT; /* optimization preference (space or time) */ +int density; /* number of bytes per inode */ +int maxcontig = 0; /* max contiguous blocks to allocate */ +int rotdelay = ROTDELAY; /* rotational delay between blocks */ +int maxbpg; /* maximum blocks per file in a cyl group */ +int nrpos = NRPOS; /* # of distinguished rotational positions */ +int bbsize = BBSIZE; /* boot block size */ +int sbsize = SBSIZE; /* superblock size */ +int mntflags = MNT_ASYNC; /* flags to be passed to mount */ +u_long memleft; /* virtual memory available */ +caddr_t membase; /* start address of memory based filesystem */ +#ifdef COMPAT +char *disktype; +int unlabeled; +#endif + +char device[MAXPATHLEN]; +char *progname; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + register int ch; + register struct partition *pp; + register struct disklabel *lp; + struct disklabel *getdisklabel(); + struct partition oldpartition; + struct stat st; + struct statfs *mp; + int fsi, fso, len, n; + char *cp, *s1, *s2, *special, *opstring, buf[BUFSIZ]; + + if (progname = rindex(*argv, '/')) + ++progname; + else + progname = *argv; + + if (strstr(progname, "mfs")) { + mfs = 1; + Nflag++; + } + + opstring = mfs ? + "NT:a:b:c:d:e:f:i:m:o:s:" : + "NOS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:"; + while ((ch = getopt(argc, argv, opstring)) != EOF) + switch (ch) { + case 'N': + Nflag = 1; + break; + case 'O': + Oflag = 1; + break; + case 'S': + if ((sectorsize = atoi(optarg)) <= 0) + fatal("%s: bad sector size", optarg); + break; +#ifdef COMPAT + case 'T': + disktype = optarg; + break; +#endif + case 'a': + if ((maxcontig = atoi(optarg)) <= 0) + fatal("%s: bad maximum contiguous blocks\n", + optarg); + break; + case 'b': + if ((bsize = atoi(optarg)) < MINBSIZE) + fatal("%s: bad block size", optarg); + break; + case 'c': + if ((cpg = atoi(optarg)) <= 0) + fatal("%s: bad cylinders/group", optarg); + cpgflg++; + break; + case 'd': + if ((rotdelay = atoi(optarg)) < 0) + fatal("%s: bad rotational delay\n", optarg); + break; + case 'e': + if ((maxbpg = atoi(optarg)) <= 0) + fatal("%s: bad blocks per file in a cylinder group\n", + optarg); + break; + case 'f': + if ((fsize = atoi(optarg)) <= 0) + fatal("%s: bad fragment size", optarg); + break; + case 'i': + if ((density = atoi(optarg)) <= 0) + fatal("%s: bad bytes per inode\n", optarg); + break; + case 'k': + if ((trackskew = atoi(optarg)) < 0) + fatal("%s: bad track skew", optarg); + break; + case 'l': + if ((interleave = atoi(optarg)) <= 0) + fatal("%s: bad interleave", optarg); + break; + case 'm': + if ((minfree = atoi(optarg)) < 0 || minfree > 99) + fatal("%s: bad free space %%\n", optarg); + break; + case 'n': + if ((nrpos = atoi(optarg)) <= 0) + fatal("%s: bad rotational layout count\n", + optarg); + break; + case 'o': + if (mfs) + getmntopts(optarg, mopts, &mntflags); + else { + if (strcmp(optarg, "space") == 0) + opt = FS_OPTSPACE; + else if (strcmp(optarg, "time") == 0) + opt = FS_OPTTIME; + else + fatal("%s: unknown optimization preference: use `space' or `time'."); + } + break; + case 'p': + if ((trackspares = atoi(optarg)) < 0) + fatal("%s: bad spare sectors per track", + optarg); + break; + case 'r': + if ((rpm = atoi(optarg)) <= 0) + fatal("%s: bad revolutions/minute\n", optarg); + break; + case 's': + if ((fssize = atoi(optarg)) <= 0) + fatal("%s: bad file system size", optarg); + break; + case 't': + if ((ntracks = atoi(optarg)) <= 0) + fatal("%s: bad total tracks", optarg); + break; + case 'u': + if ((nsectors = atoi(optarg)) <= 0) + fatal("%s: bad sectors/track", optarg); + break; + case 'x': + if ((cylspares = atoi(optarg)) < 0) + fatal("%s: bad spare sectors per cylinder", + optarg); + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 2 && (mfs || argc != 1)) + usage(); + + special = argv[0]; + cp = rindex(special, '/'); + if (cp == 0) { + /* + * No path prefix; try /dev/r%s then /dev/%s. + */ + (void)sprintf(device, "%sr%s", _PATH_DEV, special); + if (stat(device, &st) == -1) + (void)sprintf(device, "%s%s", _PATH_DEV, special); + special = device; + } + if (Nflag) { + fso = -1; + } else { + fso = open(special, O_WRONLY); + if (fso < 0) + fatal("%s: %s", special, strerror(errno)); + + /* Bail if target special is mounted */ + n = getmntinfo(&mp, MNT_NOWAIT); + if (n == 0) + fatal("%s: getmntinfo: %s", special, strerror(errno)); + + len = sizeof(_PATH_DEV) - 1; + s1 = special; + if (strncmp(_PATH_DEV, s1, len) == 0) + s1 += len; + + while (--n >= 0) { + s2 = mp->f_mntfromname; + if (strncmp(_PATH_DEV, s2, len) == 0) { + s2 += len - 1; + *s2 = 'r'; + } + if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) + fatal("%s is mounted on %s", + special, mp->f_mntonname); + ++mp; + } + } + if (mfs && disktype != NULL) { + lp = (struct disklabel *)getdiskbyname(disktype); + if (lp == NULL) + fatal("%s: unknown disk type", disktype); + pp = &lp->d_partitions[1]; + } else { + fsi = open(special, O_RDONLY); + if (fsi < 0) + fatal("%s: %s", special, strerror(errno)); + if (fstat(fsi, &st) < 0) + fatal("%s: %s", special, strerror(errno)); + if ((st.st_mode & S_IFMT) != S_IFCHR && !mfs) + printf("%s: %s: not a character-special device\n", + progname, special); + cp = index(argv[0], '\0') - 1; + if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) + fatal("%s: can't figure out file system partition", + argv[0]); +#ifdef COMPAT + if (!mfs && disktype == NULL) + disktype = argv[1]; +#endif + lp = getdisklabel(special, fsi); + if (isdigit(*cp)) + pp = &lp->d_partitions[0]; + else + pp = &lp->d_partitions[*cp - 'a']; + if (pp->p_size == 0) + fatal("%s: `%c' partition is unavailable", + argv[0], *cp); + if (pp->p_fstype == FS_BOOT) + fatal("%s: `%c' partition overlaps boot program", + argv[0], *cp); + } + if (fssize == 0) + fssize = pp->p_size; + if (fssize > pp->p_size && !mfs) + fatal("%s: maximum file system size on the `%c' partition is %d", + argv[0], *cp, pp->p_size); + if (rpm == 0) { + rpm = lp->d_rpm; + if (rpm <= 0) + rpm = 3600; + } + if (ntracks == 0) { + ntracks = lp->d_ntracks; + if (ntracks <= 0) + fatal("%s: no default #tracks", argv[0]); + } + if (nsectors == 0) { + nsectors = lp->d_nsectors; + if (nsectors <= 0) + fatal("%s: no default #sectors/track", argv[0]); + } + if (sectorsize == 0) { + sectorsize = lp->d_secsize; + if (sectorsize <= 0) + fatal("%s: no default sector size", argv[0]); + } + if (trackskew == -1) { + trackskew = lp->d_trackskew; + if (trackskew < 0) + trackskew = 0; + } + if (interleave == 0) { + interleave = lp->d_interleave; + if (interleave <= 0) + interleave = 1; + } + if (fsize == 0) { + fsize = pp->p_fsize; + if (fsize <= 0) + fsize = MAX(DFL_FRAGSIZE, lp->d_secsize); + } + if (bsize == 0) { + bsize = pp->p_frag * pp->p_fsize; + if (bsize <= 0) + bsize = MIN(DFL_BLKSIZE, 8 * fsize); + } + /* + * Maxcontig sets the default for the maximum number of blocks + * that may be allocated sequentially. With filesystem clustering + * it is possible to allocate contiguous blocks up to the maximum + * transfer size permitted by the controller or buffering. + */ + if (maxcontig == 0) + maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize - 1); + if (density == 0) + density = NFPI * fsize; + if (minfree < MINFREE && opt != FS_OPTSPACE) { + fprintf(stderr, "Warning: changing optimization to space "); + fprintf(stderr, "because minfree is less than %d%%\n", MINFREE); + opt = FS_OPTSPACE; + } + if (trackspares == -1) { + trackspares = lp->d_sparespertrack; + if (trackspares < 0) + trackspares = 0; + } + nphyssectors = nsectors + trackspares; + if (cylspares == -1) { + cylspares = lp->d_sparespercyl; + if (cylspares < 0) + cylspares = 0; + } + secpercyl = nsectors * ntracks - cylspares; + if (secpercyl != lp->d_secpercyl) + fprintf(stderr, "%s (%d) %s (%lu)\n", + "Warning: calculated sectors per cylinder", secpercyl, + "disagrees with disk label", lp->d_secpercyl); + if (maxbpg == 0) + maxbpg = MAXBLKPG(bsize); + headswitch = lp->d_headswitch; + trackseek = lp->d_trkseek; +#ifdef notdef /* label may be 0 if faked up by kernel */ + bbsize = lp->d_bbsize; + sbsize = lp->d_sbsize; +#endif + oldpartition = *pp; +#ifdef tahoe + realsectorsize = sectorsize; + if (sectorsize != DEV_BSIZE) { /* XXX */ + int secperblk = DEV_BSIZE / sectorsize; + + sectorsize = DEV_BSIZE; + nsectors /= secperblk; + nphyssectors /= secperblk; + secpercyl /= secperblk; + fssize /= secperblk; + pp->p_size /= secperblk; + } +#endif + mkfs(pp, special, fsi, fso); +#ifdef tahoe + if (realsectorsize != DEV_BSIZE) + pp->p_size *= DEV_BSIZE / realsectorsize; +#endif + if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition))) + rewritelabel(special, fso, lp); + if (!Nflag) + close(fso); + close(fsi); +#ifdef MFS + if (mfs) { + struct mfs_args args; + + sprintf(buf, "mfs:%d", getpid()); + args.fspec = buf; + args.export.ex_root = -2; + if (mntflags & MNT_RDONLY) + args.export.ex_flags = MNT_EXRDONLY; + else + args.export.ex_flags = 0; + args.base = membase; + args.size = fssize * sectorsize; + if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0) + fatal("%s: %s", argv[1], strerror(errno)); + } +#endif + exit(0); +} + +#ifdef COMPAT +char lmsg[] = "%s: can't read disk label; disk type must be specified"; +#else +char lmsg[] = "%s: can't read disk label"; +#endif + +struct disklabel * +getdisklabel(s, fd) + char *s; + int fd; +{ + static struct disklabel lab; + + if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { +#ifdef COMPAT + if (disktype) { + struct disklabel *lp, *getdiskbyname(); + + unlabeled++; + lp = getdiskbyname(disktype); + if (lp == NULL) + fatal("%s: unknown disk type", disktype); + return (lp); + } +#endif + warn("ioctl (GDINFO)"); + fatal(lmsg, s); + } + return (&lab); +} + +rewritelabel(s, fd, lp) + char *s; + int fd; + register struct disklabel *lp; +{ +#ifdef COMPAT + if (unlabeled) + return; +#endif + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { + warn("ioctl (WDINFO)"); + fatal("%s: can't rewrite disk label", s); + } +#if vax + if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { + register i; + int cfd; + daddr_t alt; + char specname[64]; + char blk[1024]; + char *cp; + + /* + * Make name for 'c' partition. + */ + strcpy(specname, s); + cp = specname + strlen(specname) - 1; + if (!isdigit(*cp)) + *cp = 'c'; + cfd = open(specname, O_WRONLY); + if (cfd < 0) + fatal("%s: %s", specname, strerror(errno)); + bzero(blk, sizeof(blk)); + *(struct disklabel *)(blk + LABELOFFSET) = *lp; + alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; + for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { + if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, + L_SET) == -1) + fatal("lseek to badsector area: %s", + strerror(errno)); + if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) + warn("alternate label %d write", i/2); + } + close(cfd); + } +#endif +} + +/*VARARGS*/ +void +#if __STDC__ +fatal(const char *fmt, ...) +#else +fatal(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + if (fcntl(STDERR_FILENO, F_GETFL) < 0) { + openlog(progname, LOG_CONS, LOG_DAEMON); + vsyslog(LOG_ERR, fmt, ap); + closelog(); + } else { + vwarnx(fmt, ap); + } + va_end(ap); + exit(1); + /*NOTREACHED*/ +} + +usage() +{ + if (mfs) { + fprintf(stderr, + "usage: %s [ -fsoptions ] special-device mount-point\n", + progname); + } else + fprintf(stderr, + "usage: %s [ -fsoptions ] special-device%s\n", + progname, +#ifdef COMPAT + " [device-type]"); +#else + ""); +#endif + fprintf(stderr, "where fsoptions are:\n"); + fprintf(stderr, + "\t-N do not create file system, just print out parameters\n"); + fprintf(stderr, "\t-O create a 4.3BSD format filesystem\n"); + fprintf(stderr, "\t-S sector size\n"); +#ifdef COMPAT + fprintf(stderr, "\t-T disktype\n"); +#endif + fprintf(stderr, "\t-a maximum contiguous blocks\n"); + fprintf(stderr, "\t-b block size\n"); + fprintf(stderr, "\t-c cylinders/group\n"); + fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); + fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); + fprintf(stderr, "\t-f frag size\n"); + fprintf(stderr, "\t-i number of bytes per inode\n"); + fprintf(stderr, "\t-k sector 0 skew, per track\n"); + fprintf(stderr, "\t-l hardware sector interleave\n"); + fprintf(stderr, "\t-m minimum free space %%\n"); + fprintf(stderr, "\t-n number of distinguished rotational positions\n"); + fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); + fprintf(stderr, "\t-p spare sectors per track\n"); + fprintf(stderr, "\t-s file system size (sectors)\n"); + fprintf(stderr, "\t-r revolutions/minute\n"); + fprintf(stderr, "\t-t tracks/cylinder\n"); + fprintf(stderr, "\t-u sectors/track\n"); + fprintf(stderr, "\t-x spare sectors per cylinder\n"); + exit(1); +} -- cgit v1.2.3 From 1d1418f596f97783a3cb09c74f766831fadd119c Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 19:39:52 +0000 Subject: Formerly Makefile.~2~ --- bsdfsck/Makefile | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index b1e25a2f..b8d9f2a3 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -1,14 +1,35 @@ -# from: @(#)Makefile 8.1 (Berkeley) 6/5/93 -# $Id: Makefile,v 1.1 1994/08/23 19:29:26 mib Exp $ +# +# Copyright (C) 1994 Free Software Foundation +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -PROG= fsck -MAN8= fsck.0 -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 -.PATH: ${.CURDIR}/../../sys/ufs/ffs +dir := fsck +makemode := utility -.if make(install) -SUBDIR+= SMM.doc -.endif +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 +OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ + pass5.o preen.o setup.o utilities.o +target = fsck -.include +include ../Makeconf + +all: fsck.native + +fsck.native: $(addprefix native-,$(OBJS)) + rsh $(mighost) -n cd `pwd` \; gcc $^ -o $@ + +native-%.o: %.c + rsh $(mighost) -n cd `pwd` \; gcc -c $^ -o $@ -- cgit v1.2.3 From e660b21e7c5f3fb483480aea7f33d4e68389a7e4 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 19:44:53 +0000 Subject: Initial revision --- bsdfsck/fsck.h | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 bsdfsck/fsck.h (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h new file mode 100644 index 00000000..ea173b25 --- /dev/null +++ b/bsdfsck/fsck.h @@ -0,0 +1,216 @@ +/* + * 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. + * + * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 + * $Id: fsck.h,v 1.1 1994/08/23 19:44:53 mib Exp $ + */ + +#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 */ + +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif + +#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 */ + +/* + * buffer cache structure. + */ +struct bufarea { + struct bufarea *b_next; /* free list queue */ + struct bufarea *b_prev; /* free list queue */ + daddr_t b_bno; + int b_size; + int b_errs; + int b_flags; + union { + char *b_buf; /* buffer space */ + 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 */ +struct bufarea *getdatablk(); + +#define dirty(bp) (bp)->b_dirty = 1 +#define initbarea(bp) \ + (bp)->b_dirty = 0; \ + (bp)->b_bno = (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}; + +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 */ + 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 +#define ADDR 2 + +/* + * 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; + 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 */ + daddr_t i_blks[1]; /* actually longer */ +} **inphead, **inpsort; +long numdirs, listmax, inplast; + +char *cdevname; /* name of device being checked */ +long dev_bsize; /* computed value of DEV_BSIZE */ +long secsize; /* actual disk sector size */ +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 preen; /* just fix normal inconsistencies */ +char hotroot; /* checking root device */ +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 */ + +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 lastino; /* last inode in use */ +char *statemap; /* ptr to inode state table */ +char *typemap; /* ptr to inode type table */ +short *lncntp; /* ptr to link count table */ + +ino_t lfdir; /* lost & found directory inode number */ +char *lfname; /* lost & found directory name */ +int lfmode; /* lost & found directory creation mode */ + +daddr_t n_blks; /* number of blocks in use */ +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 + +time_t time(); +struct dinode *ginode(); +struct inoinfo *getinoinfo(); +void getblk(); +ino_t allocino(); +int findino(); -- cgit v1.2.3 From 752921f3d206f80f2f3a1436a32a98a7be81b0b5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 19:53:52 +0000 Subject: Formerly fsck.h.~2~ --- bsdfsck/fsck.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index ea173b25..f26f3d8b 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,9 +31,60 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.1 1994/08/23 19:44:53 mib Exp $ + * $Id: fsck.h,v 1.2 1994/08/23 19:53:52 mib Exp $ */ +/* Begin GNU Hurd */ + +/* For GNU Hurd: the ufs DIRSIZ macro is different than the BSD + 4.4 version that fsck expects. So we provide here the BSD version. */ +#undef DIRSIZ +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define DIRSIZ(oldfmt, dp) \ + ((oldfmt) ? \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) +#else +#define DIRSIZ(oldfmt, dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +#endif + +/* GNU ufs has no need of struct dirtemplate; so provide the + BSD version here. */ +/* + * Template for manipulating directories. + * Should use struct direct's, but the name field + * is MAXNAMLEN - 1, and this just won't do. + */ +struct dirtemplate { + u_long dot_ino; + short dot_reclen; + u_char dot_type; + u_char dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_long dotdot_ino; + short dotdot_reclen; + u_char dotdot_type; + u_char dotdot_namlen; + char dotdot_name[4]; /* ditto */ +}; +/* + * This is the old format of directories, sanz type element. + */ +struct odirtemplate { + u_long dot_ino; + short dot_reclen; + u_short dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_long dotdot_ino; + short dotdot_reclen; + u_short dotdot_namlen; + char dotdot_name[4]; /* ditto */ +}; + +/* End GNU Hurd additions */ + + #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 */ -- cgit v1.2.3 From f1424cf76d282077449897e0188a5badd56f1664 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:00:23 +0000 Subject: Formerly main.c.~2~ --- bsdfsck/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/main.c b/bsdfsck/main.c index e8f952a1..609cad6b 100644 --- a/bsdfsck/main.c +++ b/bsdfsck/main.c @@ -39,14 +39,14 @@ static char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/ -static char *rcsid = "$Id: main.c,v 1.1 1994/08/23 19:29:22 mib Exp $"; +static char *rcsid = "$Id: main.c,v 1.2 1994/08/23 20:00:23 mib Exp $"; #endif /* not lint */ #include #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include #include #include -- cgit v1.2.3 From a3264de7fef6cc1a7054fa3c18427ddf069467f5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:02:28 +0000 Subject: entered into RCS --- bsdfsck/pass1b.c | 6 +++--- bsdfsck/pass3.c | 6 +++--- bsdfsck/pass4.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass1b.c b/bsdfsck/pass1b.c index d40e2254..f5aadc06 100644 --- a/bsdfsck/pass1b.c +++ b/bsdfsck/pass1b.c @@ -33,13 +33,13 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1b.c,v 1.1 1994/08/23 19:29:23 mib Exp $"; +static char *rcsid = "$Id: pass1b.c,v 1.2 1994/08/23 20:01:24 mib Exp $"; #endif /* not lint */ #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include #include "fsck.h" diff --git a/bsdfsck/pass3.c b/bsdfsck/pass3.c index 12c40700..78fb6a96 100644 --- a/bsdfsck/pass3.c +++ b/bsdfsck/pass3.c @@ -33,13 +33,13 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass3.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +static char *rcsid = "$Id: pass3.c,v 1.2 1994/08/23 20:02:13 mib Exp $"; #endif /* not lint */ #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include "fsck.h" pass3() diff --git a/bsdfsck/pass4.c b/bsdfsck/pass4.c index b7623f4e..449c96ab 100644 --- a/bsdfsck/pass4.c +++ b/bsdfsck/pass4.c @@ -33,13 +33,13 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass4.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +static char *rcsid = "$Id: pass4.c,v 1.2 1994/08/23 20:02:28 mib Exp $"; #endif /* not lint */ #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include #include #include "fsck.h" -- cgit v1.2.3 From 8d585b0e63babb0788896123ef287c8b77237c75 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:02:44 +0000 Subject: Formerly pass5.c.~2~ --- bsdfsck/pass5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass5.c b/bsdfsck/pass5.c index 66e9efea..a802e35a 100644 --- a/bsdfsck/pass5.c +++ b/bsdfsck/pass5.c @@ -33,13 +33,13 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/ -static char *rcsid = "$Id: pass5.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +static char *rcsid = "$Id: pass5.c,v 1.2 1994/08/23 20:02:44 mib Exp $"; #endif /* not lint */ #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include #include "fsck.h" -- cgit v1.2.3 From d76c940cfcc3522fdadb035888447e2a2eab37ab Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:03:11 +0000 Subject: Formerly setup.c.~2~ --- bsdfsck/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/setup.c b/bsdfsck/setup.c index 475192cb..7dd54d52 100644 --- a/bsdfsck/setup.c +++ b/bsdfsck/setup.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/ -static char *rcsid = "$Id: setup.c,v 1.1 1994/08/23 19:29:25 mib Exp $"; +static char *rcsid = "$Id: setup.c,v 1.2 1994/08/23 20:03:11 mib Exp $"; #endif /* not lint */ #define DKTYPENAMES #include #include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/fs.h" #include #include #include -- cgit v1.2.3 From 2e34b4a32a58f3ec680188bcf4df5a8cb4b3fa87 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:07:33 +0000 Subject: Formerly fsck.h.~3~ --- bsdfsck/fsck.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index f26f3d8b..ef0bee8f 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.2 1994/08/23 19:53:52 mib Exp $ + * $Id: fsck.h,v 1.3 1994/08/23 20:07:33 mib Exp $ */ /* Begin GNU Hurd */ @@ -82,6 +82,14 @@ struct odirtemplate { char dotdot_name[4]; /* ditto */ }; +/* These shouldn't be used by anyone, but fsck seems to need it */ +#define DEV_BSIZE 512 +#define MAXPATHLEN 1024 + +/* Provide mode from struct dinode * */ +#define DI_MODE(dp) (((dp)->di_modeh << 16) & (dp)->di_model) + + /* End GNU Hurd additions */ -- cgit v1.2.3 From 8ae0a451f75953471948abd0fa3e914805cfc82a Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:08:37 +0000 Subject: Formerly dir.c.~2~ --- bsdfsck/dir.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c index e086439e..a97fd40c 100644 --- a/bsdfsck/dir.c +++ b/bsdfsck/dir.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.1 1994/08/23 19:29:21 mib Exp $"; +static char *rcsid = "$Id: dir.c,v 1.2 1994/08/23 20:08:37 mib Exp $"; #endif /* not lint */ #include #include -#include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/dir.h" +#include "../ufs/fs.h" #include #include #include "fsck.h" @@ -275,7 +275,7 @@ fileerror(cwd, ino, errmesg) dp = ginode(ino); if (ftypeok(dp)) pfatal("%s=%s\n", - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); + (DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); else pfatal("NAME=%s\n", pathbuf); } @@ -292,7 +292,7 @@ adjust(idesc, lcnt) clri(idesc, "UNREF", 0); } else { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : - ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE")); + ((DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", dp->di_nlink, dp->di_nlink - lcnt); @@ -374,7 +374,7 @@ linkup(orphan, parentdir) bzero((char *)&idesc, sizeof(struct inodesc)); dp = ginode(orphan); - lostdir = (dp->di_mode & IFMT) == IFDIR; + lostdir = (DI_MODE(dp) & IFMT) == IFDIR; pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); pinode(orphan); if (preen && dp->di_size == 0) @@ -416,7 +416,7 @@ linkup(orphan, parentdir) } } dp = ginode(lfdir); - if ((dp->di_mode & IFMT) != IFDIR) { + if ((DI_MODE(dp) & IFMT) != IFDIR) { pfatal("lost+found IS NOT A DIRECTORY"); if (reply("REALLOCATE") == 0) return (0); -- cgit v1.2.3 From 86b23df2df09b24dbad57ebab8f9e4561ace5ec5 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:12:34 +0000 Subject: Formerly inode.c.~2~ --- bsdfsck/inode.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c index 10a01afa..f159173f 100644 --- a/bsdfsck/inode.c +++ b/bsdfsck/inode.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.1 1994/08/23 19:29:21 mib Exp $"; +static char *rcsid = "$Id: inode.c,v 1.2 1994/08/23 20:12:34 mib Exp $"; #endif /* not lint */ #include #include -#include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/dir.h" +#include "../ufs/fs.h" #ifndef SMALL #include #endif @@ -64,7 +64,7 @@ ckinode(dp, idesc) idesc->id_fix = DONTKNOW; idesc->id_entryno = 0; idesc->id_filesize = dp->di_size; - mode = dp->di_mode & IFMT; + mode = DI_MODE(dp) & IFMT; if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && (dp->di_size < sblock.fs_maxsymlinklen || (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) @@ -382,7 +382,7 @@ clri(idesc, type, flag) dp = ginode(idesc->id_number); if (flag == 1) { pwarn("%s %s", type, - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); + (DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE"); pinode(idesc->id_number); } if (preen || reply("CLEAR") == 1) { @@ -441,7 +441,7 @@ pinode(ino) else #endif printf("%u ", (unsigned)dp->di_uid); - printf("MODE=%o\n", dp->di_mode); + printf("MODE=%o\n", DI_MODE(dp)); if (preen) printf("%s: ", cdevname); printf("SIZE=%qu ", dp->di_size); @@ -514,7 +514,12 @@ allocino(request, type) statemap[ino] = USTATE; return (0); } +#if 0 dp->di_mode = type; +#else + dp->di_modeh = (type & 0xffff0000) >> 16; + dp->di_model = (type & 0x0000ffff); +#endif (void)time(&dp->di_atime.ts_sec); dp->di_mtime = dp->di_ctime = dp->di_atime; dp->di_size = sblock.fs_fsize; -- cgit v1.2.3 From 29416391d928294f00ce6bf92474e4ce213f9589 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:15:16 +0000 Subject: Formerly pass1.c.~2~ --- bsdfsck/pass1.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c index cc15c199..44a35fe8 100644 --- a/bsdfsck/pass1.c +++ b/bsdfsck/pass1.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1.c,v 1.1 1994/08/23 19:29:23 mib Exp $"; +static char *rcsid = "$Id: pass1.c,v 1.2 1994/08/23 20:15:16 mib Exp $"; #endif /* not lint */ #include #include -#include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/dir.h" +#include "../ufs/fs.h" #include #include #include "fsck.h" @@ -99,13 +99,13 @@ checkinode(inumber, idesc) char *symbuf; dp = getnextinode(inumber); - mode = dp->di_mode & IFMT; + mode = DI_MODE(dp) & IFMT; if (mode == 0) { if (bcmp((char *)dp->di_db, (char *)zino.di_db, NDADDR * sizeof(daddr_t)) || bcmp((char *)dp->di_ib, (char *)zino.di_ib, NIADDR * sizeof(daddr_t)) || - dp->di_mode || dp->di_size) { + DI_MODE(dp) || dp->di_size) { pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); if (reply("CLEAR") == 1) { dp = ginode(inumber); @@ -126,7 +126,12 @@ checkinode(inumber, idesc) if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { dp = ginode(inumber); dp->di_size = sblock.fs_fsize; +#if 0 dp->di_mode = IFREG|0600; +#else + dp->di_modeh = 0; + dp->di_model = IFREG|0600; +#endif inodirty(); } ndb = howmany(dp->di_size, sblock.fs_bsize); -- cgit v1.2.3 From dcb05babce12bb748acd05f0b429ad25a0ae16f1 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:17:45 +0000 Subject: Formerly pass2.c.~2~ --- bsdfsck/pass2.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass2.c b/bsdfsck/pass2.c index df3af93c..8d03b734 100644 --- a/bsdfsck/pass2.c +++ b/bsdfsck/pass2.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/ -static char *rcsid = "$Id: pass2.c,v 1.1 1994/08/23 19:29:24 mib Exp $"; +static char *rcsid = "$Id: pass2.c,v 1.2 1994/08/23 20:17:45 mib Exp $"; #endif /* not lint */ #include #include -#include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/dir.h" +#include "../ufs/fs.h" #include #include #include "fsck.h" @@ -92,8 +92,13 @@ pass2() if (reply("FIX") == 0) errexit(""); dp = ginode(ROOTINO); +#if 0 dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; +#else + dp->dp_model &= ~IFMT; + dp->dp_model |= IFDIR; +#endif inodirty(); break; @@ -144,7 +149,12 @@ pass2() } } bzero((char *)&dino, sizeof(struct dinode)); +#if 0 dino.di_mode = IFDIR; +#else + dino.di_modeh = 0; + dino.di_model = IFDIR; +#endif dp->di_size = inp->i_isize; bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0], (size_t)inp->i_numblks); @@ -371,7 +381,7 @@ again: break; dp = ginode(dirp->d_ino); statemap[dirp->d_ino] = - (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; + (DI_MODE(dp) & IFMT) == IFDIR ? DSTATE : FSTATE; lncntp[dirp->d_ino] = dp->di_nlink; goto again; -- cgit v1.2.3 From 4861b7c4e083ac80712404662fee0accfd7dbb70 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Tue, 23 Aug 1994 20:18:15 +0000 Subject: entered into RCS --- bsdfsck/utilities.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/utilities.c b/bsdfsck/utilities.c index 5c31061c..2141e7f8 100644 --- a/bsdfsck/utilities.c +++ b/bsdfsck/utilities.c @@ -33,14 +33,14 @@ #ifndef lint /*static char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: utilities.c,v 1.1 1994/08/23 19:29:26 mib Exp $"; +static char *rcsid = "$Id: utilities.c,v 1.2 1994/08/23 20:18:15 mib Exp $"; #endif /* not lint */ #include #include -#include -#include -#include +#include "../ufs/dinode.h" +#include "../ufs/dir.h" +#include "../ufs/fs.h" #include #include #include @@ -52,7 +52,7 @@ long diskreads, totalreads; /* Disk cache statistics */ ftypeok(dp) struct dinode *dp; { - switch (dp->di_mode & IFMT) { + switch (DI_MODE(dp) & IFMT) { case IFDIR: case IFREG: @@ -65,7 +65,7 @@ ftypeok(dp) default: if (debug) - printf("bad file type 0%o\n", dp->di_mode); + printf("bad file type 0%o\n", DI_MODE(dp)); return (0); } } -- cgit v1.2.3 From 51879167634d0881ae6fba2208e7b7d5f824e913 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 24 Aug 1994 15:11:08 +0000 Subject: Formerly fsck.h.~4~ --- bsdfsck/fsck.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index ef0bee8f..9f247804 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.3 1994/08/23 20:07:33 mib Exp $ + * $Id: fsck.h,v 1.4 1994/08/24 15:11:08 mib Exp $ */ /* Begin GNU Hurd */ @@ -89,6 +89,7 @@ struct odirtemplate { /* Provide mode from struct dinode * */ #define DI_MODE(dp) (((dp)->di_modeh << 16) & (dp)->di_model) +#define NBBY 8 /* End GNU Hurd additions */ -- cgit v1.2.3 From 87019360208204cfc6951c3985423fbbe8a8eeab Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 24 Aug 1994 15:11:56 +0000 Subject: entered into RCS --- bsdfsck/pass2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass2.c b/bsdfsck/pass2.c index 8d03b734..184106c1 100644 --- a/bsdfsck/pass2.c +++ b/bsdfsck/pass2.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/ -static char *rcsid = "$Id: pass2.c,v 1.2 1994/08/23 20:17:45 mib Exp $"; +static char *rcsid = "$Id: pass2.c,v 1.3 1994/08/24 15:11:56 mib Exp $"; #endif /* not lint */ #include @@ -96,8 +96,8 @@ pass2() dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; #else - dp->dp_model &= ~IFMT; - dp->dp_model |= IFDIR; + dp->di_model &= ~IFMT; + dp->di_model |= IFDIR; #endif inodirty(); break; -- cgit v1.2.3 From d8217ba822954c0f6e4088dc9b34ebf578cb2e84 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 25 Aug 1994 15:14:25 +0000 Subject: Formerly Makefile.~4~ --- bsdfsck/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index b8d9f2a3..a4d8e2fb 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -19,9 +19,9 @@ dir := fsck makemode := utility 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 + pass5.c setup.c utilities.c # preen.c OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ - pass5.o preen.o setup.o utilities.o + pass5.o setup.o utilities.o # preen.o target = fsck include ../Makeconf -- cgit v1.2.3 From defc157175896fb7b5e6542b85125f4311718cc8 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 25 Aug 1994 15:17:16 +0000 Subject: Formerly fsck.h.~5~ --- bsdfsck/fsck.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index 9f247804..6b99eb4f 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.4 1994/08/24 15:11:08 mib Exp $ + * $Id: fsck.h,v 1.5 1994/08/25 15:17:16 mib Exp $ */ /* Begin GNU Hurd */ @@ -91,6 +91,14 @@ struct odirtemplate { #define NBBY 8 +#define MAXPHYS (64 * 1024) + +/* The fsck code in setup.c sets the fs_csp table which ufs doesn't want. + So here is the fs_cs macro from ufs for use when that table is real. */ +#undef fs_cs +#define fs_cs(fs, indx) \ + fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] + /* End GNU Hurd additions */ -- cgit v1.2.3 From 0358e74b41cd8682e1f3d1c71b79a7d2df8e19e4 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 25 Aug 1994 15:18:07 +0000 Subject: Formerly main.c.~3~ --- bsdfsck/main.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/main.c b/bsdfsck/main.c index 609cad6b..3535edca 100644 --- a/bsdfsck/main.c +++ b/bsdfsck/main.c @@ -39,15 +39,15 @@ static char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/ -static char *rcsid = "$Id: main.c,v 1.2 1994/08/23 20:00:23 mib Exp $"; +static char *rcsid = "$Id: main.c,v 1.3 1994/08/25 15:18:07 mib Exp $"; #endif /* not lint */ #include #include -#include +/*#include */ #include "../ufs/dinode.h" #include "../ufs/fs.h" -#include +/* #include */ #include #include #include @@ -125,10 +125,14 @@ main(argc, argv) (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); exit(0); } + fprintf (stderr, "You must explicitly name the filesystem to check\n"); + exit (1); +#if 0 ret = checkfstab(preen, maxrun, docheck, checkfilesys); if (returntosingle) exit(2); exit(ret); +#endif } argtoi(flag, req, str, base) @@ -145,6 +149,7 @@ argtoi(flag, req, str, base) return (ret); } +#if 0 /* * Determine whether a filesystem should be checked. */ @@ -159,6 +164,7 @@ docheck(fsp) return (0); return (1); } +#endif /* * Check the specified filesystem. @@ -188,8 +194,10 @@ checkfilesys(filesys, mntpt, auxdata, child) */ if (preen == 0) { printf("** Last Mounted on %s\n", sblock.fs_fsmnt); +#if 0 if (hotroot) printf("** Root file system\n"); +#endif printf("** Phase 1 - Check Blocks and Sizes\n"); } pass1(); @@ -289,6 +297,7 @@ checkfilesys(filesys, mntpt, auxdata, child) return (0); if (!preen) printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); +#if 0 if (hotroot) { struct statfs stfs_buf; /* @@ -315,5 +324,6 @@ checkfilesys(filesys, mntpt, auxdata, child) sync(); return (4); } +#endif return (0); } -- cgit v1.2.3 From 5f380e7bea94ec1407108ef4573f9eddf1b375c0 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 25 Aug 1994 15:22:35 +0000 Subject: entered into RCS --- bsdfsck/setup.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/setup.c b/bsdfsck/setup.c index 7dd54d52..f65ade47 100644 --- a/bsdfsck/setup.c +++ b/bsdfsck/setup.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/ -static char *rcsid = "$Id: setup.c,v 1.2 1994/08/23 20:03:11 mib Exp $"; +static char *rcsid = "$Id: setup.c,v 1.3 1994/08/25 15:22:35 mib Exp $"; #endif /* not lint */ #define DKTYPENAMES @@ -43,7 +43,7 @@ static char *rcsid = "$Id: setup.c,v 1.2 1994/08/23 20:03:11 mib Exp $"; #include "../ufs/fs.h" #include #include -#include +/* #include */ #include #include #include @@ -62,7 +62,7 @@ setup(dev) { long cg, size, asked, i, j; long bmapsize; - struct disklabel *lp; +/* struct disklabel *lp; */ off_t sizepb; struct stat statb; struct fs proto; @@ -100,9 +100,11 @@ setup(dev) asblk.b_un.b_buf = malloc(SBSIZE); if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) errexit("cannot allocate space for superblock\n"); +#if 0 if (lp = getdisklabel((char *)NULL, fsreadfd)) dev_bsize = secsize = lp->d_secsize; else +#endif dev_bsize = secsize = DEV_BSIZE; /* * Read in the superblock, looking for alternates if necessary @@ -391,6 +393,16 @@ badsb(listerr, s) pfatal("BAD SUPER BLOCK: %s\n", s); } +/* XXX */ +calcsb (dev, devfd, fs) + char *dev; + int devfd; + struct fs *fs; +{ + return 0; +} + +#if 0 /* * Calculate a prototype superblock based on information in the disk label. * When done the cgsblock macro can be calculated and the fs_ncg field @@ -465,3 +477,4 @@ getdisklabel(s, fd) } return (&lab); } +#endif -- cgit v1.2.3 From 885d5e9c5de2858aabe8886354657a4570c90716 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 26 Aug 1994 16:04:42 +0000 Subject: Formerly fsck.h.~6~ --- bsdfsck/fsck.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index 6b99eb4f..23542d6d 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.5 1994/08/25 15:17:16 mib Exp $ + * $Id: fsck.h,v 1.6 1994/08/26 16:04:42 mib Exp $ */ /* Begin GNU Hurd */ @@ -99,6 +99,18 @@ struct odirtemplate { #define fs_cs(fs, indx) \ fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] +#define dblksize(fs, dip, lbn) \ + (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) + +/* missing macros */ + +/* Convert bytes to disk blocks */ +#define btodb(bytes) ((bytes) / DEV_BSIZE) + + + /* End GNU Hurd additions */ -- cgit v1.2.3 From 9a37d9b2eb925a3150de43594ea818df3965b0b0 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 26 Aug 1994 16:08:07 +0000 Subject: Formerly Makefile.~5~ --- bsdfsck/Makefile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index a4d8e2fb..b6487f8a 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -26,10 +26,4 @@ target = fsck include ../Makeconf -all: fsck.native - -fsck.native: $(addprefix native-,$(OBJS)) - rsh $(mighost) -n cd `pwd` \; gcc $^ -o $@ - -native-%.o: %.c - rsh $(mighost) -n cd `pwd` \; gcc -c $^ -o $@ +$(OBJS): fsck.h \ No newline at end of file -- cgit v1.2.3 From e03e10773bb1a0a31c3c1af5da2c896b16484d8f Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 26 Aug 1994 16:35:02 +0000 Subject: Formerly inode.c.~3~ --- bsdfsck/inode.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c index f159173f..8e1b646f 100644 --- a/bsdfsck/inode.c +++ b/bsdfsck/inode.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.2 1994/08/23 20:12:34 mib Exp $"; +static char *rcsid = "$Id: inode.c,v 1.3 1994/08/26 16:35:02 mib Exp $"; #endif /* not lint */ #include @@ -100,6 +100,13 @@ ckinode(dp, idesc) sizepb *= NINDIR(&sblock); remsize -= sizepb; } + /* GNU Hurd extension. */ + if (dino.di_trans) + { + idesc->id_blkno = dino.di_trans; + idesc->id_numfrags = sblock.fs_frag; + return (*idesc->id_func)(idesc); + } return (KEEPON); } -- cgit v1.2.3 From 6b2ac8ea0a80bc474988a11d36863204363dc2dd Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 26 Aug 1994 18:03:07 +0000 Subject: entered into RCS --- bsdfsck/pass5.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass5.c b/bsdfsck/pass5.c index a802e35a..11877f9d 100644 --- a/bsdfsck/pass5.c +++ b/bsdfsck/pass5.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/ -static char *rcsid = "$Id: pass5.c,v 1.2 1994/08/23 20:02:44 mib Exp $"; +static char *rcsid = "$Id: pass5.c,v 1.3 1994/08/26 18:03:07 mib Exp $"; #endif /* not lint */ #include @@ -43,6 +43,44 @@ static char *rcsid = "$Id: pass5.c,v 1.2 1994/08/23 20:02:44 mib Exp $"; #include #include "fsck.h" +/* From ../ufs/subr.c: */ + +/* + * Update the frsum fields to reflect addition or deletion + * of some frags. + */ +void +ffs_fragacct(fs, fragmap, fraglist, cnt) + struct fs *fs; + int fragmap; + long fraglist[]; + int cnt; +{ + int inblk; + register int field, subfield; + register int siz, pos; + + inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; + fragmap <<= 1; + for (siz = 1; siz < fs->fs_frag; siz++) { + if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) + continue; + field = around[siz]; + subfield = inside[siz]; + for (pos = siz; pos <= fs->fs_frag; pos++) { + if ((fragmap & field) == subfield) { + fraglist[siz] += cnt; + pos += siz; + field <<= siz; + subfield <<= siz; + } + field <<= 1; + subfield <<= 1; + } + } +} + + pass5() { int c, blk, frags, basesize, sumsize, mapsize, savednrpos; -- cgit v1.2.3 From 7cc7f26c068beba923b9d7074e04772d2f685972 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 26 Aug 1994 18:06:30 +0000 Subject: entered into RCS --- bsdfsck/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/main.c b/bsdfsck/main.c index 3535edca..adf84f74 100644 --- a/bsdfsck/main.c +++ b/bsdfsck/main.c @@ -39,7 +39,7 @@ static char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/ -static char *rcsid = "$Id: main.c,v 1.3 1994/08/25 15:18:07 mib Exp $"; +static char *rcsid = "$Id: main.c,v 1.4 1994/08/26 18:06:30 mib Exp $"; #endif /* not lint */ #include @@ -57,6 +57,9 @@ static char *rcsid = "$Id: main.c,v 1.3 1994/08/25 15:18:07 mib Exp $"; void catch(), catchquit(), voidquit(); int returntosingle; +/* GNU Hurd patch */ +#define blockcheck(a) (a) + main(argc, argv) int argc; char *argv[]; @@ -64,7 +67,8 @@ main(argc, argv) int ch; int ret, maxrun = 0; extern int docheck(), checkfilesys(); - extern char *optarg, *blockcheck(); + extern char *optarg; +/* extern char *blockcheck(); */ extern int optind; sync(); -- cgit v1.2.3 From 178faf94766ba185999f950c9728ecbad7163cbf Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 1 Sep 1994 15:41:03 +0000 Subject: Formerly Makefile.~6~ --- bsdfsck/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index b6487f8a..e40ceb67 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -21,9 +21,12 @@ makemode := utility SRCS = dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ pass5.c setup.c utilities.c # preen.c OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ - pass5.o setup.o utilities.o # preen.o + pass5.o setup.o utilities.o tables.o # preen.o target = fsck include ../Makeconf -$(OBJS): fsck.h \ No newline at end of file +$(OBJS): fsck.h + +tables.o: ../ufs/tables.c + $(CC) $(CFLAGS) -c -o $@ $< -- cgit v1.2.3 From fc133667ee978c7ead629a2736e42122dd41ad6d Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 1 Sep 1994 18:50:58 +0000 Subject: Formerly fsck.h.~7~ --- bsdfsck/fsck.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index 23542d6d..c2768e9b 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.6 1994/08/26 16:04:42 mib Exp $ + * $Id: fsck.h,v 1.7 1994/09/01 18:50:58 mib Exp $ */ /* Begin GNU Hurd */ @@ -87,7 +87,7 @@ struct odirtemplate { #define MAXPATHLEN 1024 /* Provide mode from struct dinode * */ -#define DI_MODE(dp) (((dp)->di_modeh << 16) & (dp)->di_model) +#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) #define NBBY 8 -- cgit v1.2.3 From f2bd17119a00f994b4de116c2e8524017f7da4b0 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 1 Sep 1994 19:15:35 +0000 Subject: Formerly inode.c.~4~ --- bsdfsck/inode.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c index 8e1b646f..6282d1d1 100644 --- a/bsdfsck/inode.c +++ b/bsdfsck/inode.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.3 1994/08/26 16:35:02 mib Exp $"; +static char *rcsid = "$Id: inode.c,v 1.4 1994/09/01 19:15:35 mib Exp $"; #endif /* not lint */ #include @@ -65,9 +65,10 @@ ckinode(dp, idesc) idesc->id_entryno = 0; idesc->id_filesize = dp->di_size; mode = DI_MODE(dp) & IFMT; - if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && - (dp->di_size < sblock.fs_maxsymlinklen || - (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) + if (mode == IFBLK || mode == IFCHR + || (mode == IFLNK && sblock.fs_maxsymlinklen != -1 && + (dp->di_size < sblock.fs_maxsymlinklen + || (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) return (KEEPON); dino = *dp; ndb = howmany(dino.di_size, sblock.fs_bsize); -- cgit v1.2.3 From a6632578d81f1ba501495295bcfe9d65f4986c5d Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 1 Sep 1994 19:19:17 +0000 Subject: Formerly pass1.c.~3~ --- bsdfsck/pass1.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c index 44a35fe8..6f254ca8 100644 --- a/bsdfsck/pass1.c +++ b/bsdfsck/pass1.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1.c,v 1.2 1994/08/23 20:15:16 mib Exp $"; +static char *rcsid = "$Id: pass1.c,v 1.3 1994/09/01 19:19:17 mib Exp $"; #endif /* not lint */ #include @@ -174,8 +174,9 @@ checkinode(inumber, idesc) * Fake ndb value so direct/indirect block checks below * will detect any garbage after symlink string. */ - if (dp->di_size < sblock.fs_maxsymlinklen || - (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)) { + if (sblock.fs_maxsymlinklen != -1 && + (dp->di_size < sblock.fs_maxsymlinklen || + (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0))) { ndb = howmany(dp->di_size, sizeof(daddr_t)); if (ndb > NDADDR) { j = ndb - NDADDR; -- cgit v1.2.3 From 23b0fc0ead7388e0bfcf8cd2e1ad1a6f646187cc Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 16 Sep 1994 14:56:55 +0000 Subject: Formerly fsck.h.~8~ --- bsdfsck/fsck.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index c2768e9b..ea6da35a 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,11 +31,14 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.7 1994/09/01 18:50:58 mib Exp $ + * $Id: fsck.h,v 1.8 1994/09/16 14:56:55 mib Exp $ */ /* Begin GNU Hurd */ +/* GNU ufs doesn't define struct direct, but fsck needs it. */ +#define direct directory_entry + /* For GNU Hurd: the ufs DIRSIZ macro is different than the BSD 4.4 version that fsck expects. So we provide here the BSD version. */ #undef DIRSIZ -- cgit v1.2.3 From aaf97f45a58d426809c0d289a88155a57bf57879 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 1 Oct 1994 01:29:06 +0000 Subject: Formerly Makefile.~7~ --- bsdfsck/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index e40ceb67..bc718b66 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -22,6 +22,7 @@ SRCS = dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ pass5.c setup.c utilities.c # preen.c OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ pass5.o setup.o utilities.o tables.o # preen.o +LCLHDRS = fsck.h target = fsck include ../Makeconf -- cgit v1.2.3 From d8c76eb62f2cdc4c191d869c574db2de3b0541dd Mon Sep 17 00:00:00 2001 From: Hurd Maintainers Date: Wed, 5 Oct 1994 02:51:16 +0000 Subject: Formerly inode.c.~5~ --- bsdfsck/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c index 6282d1d1..293b69c8 100644 --- a/bsdfsck/inode.c +++ b/bsdfsck/inode.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.4 1994/09/01 19:15:35 mib Exp $"; +static char *rcsid = "$Id: inode.c,v 1.5 1994/10/05 02:51:16 root Exp $"; #endif /* not lint */ #include @@ -48,6 +48,9 @@ static char *rcsid = "$Id: inode.c,v 1.4 1994/09/01 19:15:35 mib Exp $"; #include #include "fsck.h" +/* Don't include dirent.h lest we get confused, but we still want this. */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) + static ino_t startinum; ckinode(dp, idesc) @@ -102,7 +105,7 @@ ckinode(dp, idesc) remsize -= sizepb; } /* GNU Hurd extension. */ - if (dino.di_trans) + if (dino.di_trans && idesc->id_type == ADDR) { idesc->id_blkno = dino.di_trans; idesc->id_numfrags = sblock.fs_frag; -- cgit v1.2.3 From 37983942de858432043318761c826d0e69ce3fe7 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 5 Oct 1994 16:53:12 +0000 Subject: entered into RCS --- bsdfsck/pass1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c index 6f254ca8..46b0e109 100644 --- a/bsdfsck/pass1.c +++ b/bsdfsck/pass1.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1.c,v 1.3 1994/09/01 19:19:17 mib Exp $"; +static char *rcsid = "$Id: pass1.c,v 1.4 1994/10/05 16:53:12 mib Exp $"; #endif /* not lint */ #include @@ -101,11 +101,12 @@ checkinode(inumber, idesc) dp = getnextinode(inumber); mode = DI_MODE(dp) & IFMT; if (mode == 0) { + /* Check for DI_TRANS here is a GNU Hurd addition. */ if (bcmp((char *)dp->di_db, (char *)zino.di_db, NDADDR * sizeof(daddr_t)) || bcmp((char *)dp->di_ib, (char *)zino.di_ib, NIADDR * sizeof(daddr_t)) || - DI_MODE(dp) || dp->di_size) { + DI_MODE(dp) || dp->di_size || dp->di_trans) { pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); if (reply("CLEAR") == 1) { dp = ginode(inumber); -- cgit v1.2.3 From a1630bac443f1804ccc3ad0b6e95f4fa7ad46ddf Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 5 Oct 1994 17:05:30 +0000 Subject: entered into RCS --- bsdfsck/inode.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c index 293b69c8..7b48aef6 100644 --- a/bsdfsck/inode.c +++ b/bsdfsck/inode.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.5 1994/10/05 02:51:16 root Exp $"; +static char *rcsid = "$Id: inode.c,v 1.6 1994/10/05 17:05:30 mib Exp $"; #endif /* not lint */ #include @@ -48,9 +48,6 @@ static char *rcsid = "$Id: inode.c,v 1.5 1994/10/05 02:51:16 root Exp $"; #include #include "fsck.h" -/* Don't include dirent.h lest we get confused, but we still want this. */ -#define IFTODT(mode) (((mode) & 0170000) >> 12) - static ino_t startinum; ckinode(dp, idesc) -- cgit v1.2.3 From e34d53fc06cf7e40751a7a81e711860b34e65ef0 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 5 Oct 1994 17:08:23 +0000 Subject: Formerly fsck.h.~9~ --- bsdfsck/fsck.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index ea6da35a..4b95785b 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.8 1994/09/16 14:56:55 mib Exp $ + * $Id: fsck.h,v 1.9 1994/10/05 17:08:23 mib Exp $ */ /* Begin GNU Hurd */ @@ -107,6 +107,10 @@ struct odirtemplate { ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) +/* Don't include dirent.h lest we get confused, but we still want this. */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DT_DIR IFTODT (S_IFDIR) + /* missing macros */ /* Convert bytes to disk blocks */ -- cgit v1.2.3 From 959caac9acdd848cf120ede7b998353c430a6f8b Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Wed, 5 Oct 1994 17:09:06 +0000 Subject: entered into RCS --- bsdfsck/fsck.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h index 4b95785b..c418f66c 100644 --- a/bsdfsck/fsck.h +++ b/bsdfsck/fsck.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.9 1994/10/05 17:08:23 mib Exp $ + * $Id: fsck.h,v 1.10 1994/10/05 17:09:06 mib Exp $ */ /* Begin GNU Hurd */ @@ -109,7 +109,7 @@ struct odirtemplate { /* Don't include dirent.h lest we get confused, but we still want this. */ #define IFTODT(mode) (((mode) & 0170000) >> 12) -#define DT_DIR IFTODT (S_IFDIR) +#define DT_DIR IFTODT (IFDIR) /* missing macros */ -- cgit v1.2.3 From 298e8bc3279155514666d9d80742d6fea511f434 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 6 Oct 1994 17:18:52 +0000 Subject: Formerly dir.c.~3~ --- bsdfsck/dir.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c index a97fd40c..6df56df2 100644 --- a/bsdfsck/dir.c +++ b/bsdfsck/dir.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.2 1994/08/23 20:08:37 mib Exp $"; +static char *rcsid = "$Id: dir.c,v 1.3 1994/10/06 17:18:52 mib Exp $"; #endif /* not lint */ #include @@ -215,9 +215,16 @@ dircheck(idesc, dp) register char *cp; u_char namlen, type; int spaceleft; + spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); + if (dp->d_ino >= maxino || + dp->d_reclen == 0 || + dp->d_reclen > spaceleft || + (dp->d_reclen & 0x3) != 0) + return (0); + if (dp->d_ino == 0) + return (1); size = DIRSIZ(!newinofmt, dp); - spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); # if (BYTE_ORDER == LITTLE_ENDIAN) if (!newinofmt) { type = dp->d_namlen; @@ -230,23 +237,17 @@ dircheck(idesc, dp) namlen = dp->d_namlen; type = dp->d_type; # endif - if (dp->d_ino < maxino && - dp->d_reclen != 0 && - dp->d_reclen <= spaceleft && - (dp->d_reclen & 0x3) == 0 && - dp->d_reclen >= size && - idesc->id_filesize >= size && - namlen <= MAXNAMLEN && - type <= 15) { - if (dp->d_ino == 0) - return (1); - for (cp = dp->d_name, size = 0; size < namlen; size++) - if (*cp == 0 || (*cp++ == '/')) - return (0); - if (*cp == 0) - return (1); - } - return (0); + if (dp->d_reclen < size || + idesc->id_filesize < size || + namlen > MAXNAMLEN || + type > 15) + return (0); + for (cp = dp->d_name, size = 0; size < namlen; size++) + if (*cp == '\0' || (*cp++ == '/')) + return (0); + if (*cp != '\0') + return (0); + return (1); } direrror(ino, errmesg) -- cgit v1.2.3 From df73e9f502c78be8ff3fd0fb5fb47b5573b1e808 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 7 Oct 1994 23:37:52 +0000 Subject: Formerly dir.c.~4~ --- bsdfsck/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c index 6df56df2..28697827 100644 --- a/bsdfsck/dir.c +++ b/bsdfsck/dir.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.3 1994/10/06 17:18:52 mib Exp $"; +static char *rcsid = "$Id: dir.c,v 1.4 1994/10/07 23:37:52 mib Exp $"; #endif /* not lint */ #include @@ -586,7 +586,7 @@ allocdir(parent, request, mode) { ino_t ino; char *cp; - struct dinode *dp; + register struct bufarea *bp; struct dirtemplate *dirp; -- cgit v1.2.3 From ab70d0204f45f42f76ec3505517055108b61af58 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 3 Nov 1994 22:19:05 +0000 Subject: entered into RCS --- bsdfsck/Makefile | 4 ++-- ufs-fsck/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index bc718b66..28adbbd1 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -dir := fsck +dir := bsdfsck makemode := utility SRCS = dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ @@ -23,7 +23,7 @@ SRCS = dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ pass5.o setup.o utilities.o tables.o # preen.o LCLHDRS = fsck.h -target = fsck +target = bsdfsck include ../Makeconf diff --git a/ufs-fsck/Makefile b/ufs-fsck/Makefile index 75b2207a..ef8919a9 100644 --- a/ufs-fsck/Makefile +++ b/ufs-fsck/Makefile @@ -18,14 +18,14 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -dir := newfsck +dir := fsck makemode := utility SRCS = dir.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ pass5.c setup.c utilities.c inode.c OBJS = $(subst .c,.o,$(SRCS)) tables.o LCLHDRS = fsck.h -target = newfsck +target = fsck include ../Makeconf -- cgit v1.2.3 From 7f849d2f7fb1b61d18dcfe7e3167b54b27a511af Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 4 Nov 1994 21:54:56 +0000 Subject: entered into RCS --- bsdfsck/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c index 28697827..e63473ae 100644 --- a/bsdfsck/dir.c +++ b/bsdfsck/dir.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.4 1994/10/07 23:37:52 mib Exp $"; +static char *rcsid = "$Id: dir.c,v 1.5 1994/11/04 21:54:56 mib Exp $"; #endif /* not lint */ #include @@ -586,7 +586,7 @@ allocdir(parent, request, mode) { ino_t ino; char *cp; - + struct dinode *dp; register struct bufarea *bp; struct dirtemplate *dirp; -- cgit v1.2.3 From 0cbb481f3c31a306d1df4944a4668780258b8bde Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 6 Jul 1995 19:43:11 +0000 Subject: Removed dependencies that are now automatically generated. --- bsdfsck/Makefile | 4 +--- ufs-fsck/Makefile | 4 +--- ufs/Makefile | 12 ------------ 3 files changed, 2 insertions(+), 18 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index 28adbbd1..6bc18889 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1994 Free Software Foundation +# Copyright (C) 1994, 1995 Free Software Foundation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -27,7 +27,5 @@ target = bsdfsck include ../Makeconf -$(OBJS): fsck.h - tables.o: ../ufs/tables.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/ufs-fsck/Makefile b/ufs-fsck/Makefile index ef8919a9..d581cda3 100644 --- a/ufs-fsck/Makefile +++ b/ufs-fsck/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1994 Free Software Foundation +# Copyright (C) 1994, 1995 Free Software Foundation # Written by Michael I. Bushnell. # # This file is part of the GNU Hurd. @@ -29,7 +29,5 @@ target = fsck include ../Makeconf -$(OBJS): fsck.h - tables.o: ../ufs/tables.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/ufs/Makefile b/ufs/Makefile index 04bb15fd..33582409 100644 --- a/ufs/Makefile +++ b/ufs/Makefile @@ -36,15 +36,3 @@ vpath %.c ../lib include ../Makeconf -$(OBJS): ufs.h -$(OBJS): $(REMHDRS) -alloc.o: fs.h dinode.h -consts.o: dinode.h -dir.o: dir.h -hyper.o: fs.h -inode.o: dinode.h fs.h -main.o: fs.h -pager.o: fs.h dinode.h -sizes.o: fs.h dinode.h -subr.o: fs.h -tables.o: fs.h -- cgit v1.2.3 From abd78d79f13f61044244822d80d15fa5a1fd6dbb Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 7 Jul 1995 02:00:43 +0000 Subject: (tables.o): Delete target. (vpath tables.c): Tell where to find tables.c. --- bsdfsck/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bsdfsck') diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile index 6bc18889..b5dcfbf2 100644 --- a/bsdfsck/Makefile +++ b/bsdfsck/Makefile @@ -25,7 +25,7 @@ OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ LCLHDRS = fsck.h target = bsdfsck +vpath tables.c ../ufs + include ../Makeconf -tables.o: ../ufs/tables.c - $(CC) $(CFLAGS) -c -o $@ $< -- cgit v1.2.3 From 3a154d3cbff6b7110a67cf8a7dd12356a2a2a289 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 17 Jul 1996 22:55:08 +0000 Subject: Initial revision --- bsdfsck/ChangeLog | 98 ++++ devio/ChangeLog | 253 ++++++++ libmom/ChangeLog | 31 + mkbootfs/ChangeLog | 22 + ufs-fsck/ChangeLog | 245 ++++++++ ufs-utils/ChangeLog | 104 ++++ ufs/ChangeLog | 1586 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 2339 insertions(+) create mode 100644 bsdfsck/ChangeLog create mode 100644 devio/ChangeLog create mode 100644 libmom/ChangeLog create mode 100644 mkbootfs/ChangeLog create mode 100644 ufs-fsck/ChangeLog create mode 100644 ufs-utils/ChangeLog create mode 100644 ufs/ChangeLog (limited to 'bsdfsck') diff --git a/bsdfsck/ChangeLog b/bsdfsck/ChangeLog new file mode 100644 index 00000000..0a948518 --- /dev/null +++ b/bsdfsck/ChangeLog @@ -0,0 +1,98 @@ +Thu Jul 6 15:30:43 1995 Michael I Bushnell + + * Makefile (tables.o): Delete target. + (vpath tables.c): Tell where to find tables.c. + + * Makefile: Removed dependencies that are now automatically + generated. + +Thu Nov 3 17:18:35 1994 Michael I Bushnell + + * Makefile (dir): Changed to bsdfsck. + (target): Changed to bsdfsck. + +Thu Oct 6 13:19:25 1994 Michael I Bushnell + + * dir.c (dircheck): Fix from Charles Hannum: dircheck() shouldn't + be looking at d_type or d_namlen in blank entries *at all*. Not + only is it wrong, but it causes a serious problem on little-endian + machines, since after -c2 conversion, d_type will often be > 15. + +Wed Oct 5 12:53:45 1994 Michael I Bushnell + + * pass1.c (checkinode) [mode == 0]: Check that di_trans + is also clear here. + + * fsck.h (IFTODT): Provide macro here. + * inode.c: Not here. + +Tue Oct 4 22:42:54 1994 Michael I Bushnell + + * inode.c (ckinode) [dino.di_trans set]: Only call IDESC->id_func + if IDESC->id_type is ADDR (meaning call function for each block). + If it's DATA, then that means call dirscan on each data block, + something entirely different. + + * inode.c (IFTODT): Provide macro. + +Fri Sep 30 21:28:57 1994 Roland McGrath + + * Makefile (LCLHDRS): Define. + +Fri Sep 16 10:57:04 1994 Michael I Bushnell + + * fsck.h (direct): Define macro. + +Thu Sep 1 14:51:23 1994 Michael I Bushnell + + * inode.c (ckinode): Don't pay attention to fs_maxsymlinklen + if it's -1. + * pass1.c (checkinode): Likewise. + + * fsck.h (DI_MODE): Use | not & for bitwise disjunction. + +Fri Aug 26 12:35:21 1994 Michael I Bushnell + + * main.c (main): Don't call checkblock. + + * pass5.c (ffs_fragacct): Copy in function from ../ufs/subr.c. + + * inode.c (ckinode): Call IDESC->id_func for passive translator + if it's set. + +Thu Aug 25 11:07:05 1994 Michael I Bushnell + + * setup.c: Don't include . + (setup): Comment out variable LP and label fetching code. + (calcsb, getdisklabel): Comment out functions. Replace + calcsb with one returning constant zero. + + * main.c: Don't include or . + (main): Don't run checkfstab; just print an error in that case. + (docheck): Comment out this function. + (checkfilesys): Comment out special code for HOTROOT. + +Wed Aug 24 11:11:23 1994 Michael I Bushnell + + * fsck.h (NBBY): Define macro. + +Tue Aug 23 15:54:49 1994 Michael I Bushnell + + * dir.c (fileerror): Use DI_MODE instead of di_mode member. + (adjust): Likewise. + (linkup): Likewise. + * inode.c (ckinode): Likewise. + (clri): Likewise. + (pinode): Likewise. + * pass1.c (checkinode): Likewise. + * pass2.c (pass2check): Likewise. + * utilities.c (ftypeok): Likewise. + + * inode.c (allocino): Set di_model and di_modeh instead of di_mode. + * pass1.c (checkinode): Likewise. + * pass2.c (pass2): Likewise. + + * fsck.h (DIRSIZ): Replace ufs version with old BSD version. + (struct dirtemplate, struct odirtemplate): Proved old BSD types. + (DEV_BSIZE, MAXPATHLEN): Provide definitions. + (DI_MODE): New macro. diff --git a/devio/ChangeLog b/devio/ChangeLog new file mode 100644 index 00000000..98362b44 --- /dev/null +++ b/devio/ChangeLog @@ -0,0 +1,253 @@ +Wed Jul 17 10:00:04 1996 Miles Bader + + * MAKEDEV (st): New function. + Use new st function (get rid of chmods). + Accept disk device names without partitions, & with slice + partition. + +Sat Jun 15 14:13:24 1996 Michael I. Bushnell, p/BSG + + * MAKEDEV ([hrs]d*): Allow user to specify slice as well. Patch + from Gord Matzigkeit, gord@enci.ucalgary.ca. + +Thu May 9 12:15:47 1996 Miles Bader + + * io.c (trivfs_S_io_select): Remove TAG arg. + (trivfs_S_file_get_storage_info): Fix param type. + +Tue May 7 16:41:48 1996 Miles Bader + + * io.c (trivfs_S_file_get_storage_info): Swap PORTS_TYPE & NUM_PORTS. + +Mon May 6 20:14:43 1996 Miles Bader + + * io.c (trivfs_S_file_get_storage_info): Enable new version. + +Fri May 3 15:09:00 1996 Miles Bader + + * io.c [0] (trivfs_S_file_get_storage_info): Rewrite for new interface. + +Tue Apr 30 10:03:50 1996 Michael I. Bushnell, p/BSG + + * Makefile (include ../Makeconf): BEFORE dependencies. + ($(prefix)/dev/MAKEDEV): Find MAKEDEV in $(srcdir). + +Fri Feb 16 19:28:32 1996 Miles Bader + + * MAKEDEV: Add rule for `time', and add `time' to std. + +Tue Jan 30 12:34:28 1996 Roland McGrath + + * MAKEDEV: Grok `tty'. + +Thu Jan 25 18:10:24 1996 Miles Bader + + * devio.c (trivfs_goaway): Handle errors from ports_inhibit_class_rpcs. + Allow rpcs to resume if we're going to return EBUSY. + +Tue Jan 16 16:19:51 1996 Miles Bader + + * devio.c (trivfs_modify_stat): The peropen hook holds a struct + open, not a struct dev. + +Fri Dec 29 23:41:39 1995 Miles Bader + + * MAKEDEV (std): Make `fd' one of the standard devices. + +Fri Dec 15 13:30:33 1995 Miles Bader + + * MAKEDEV (ST): Variable holding the proper settrans command, + which use. + (_CWD): Use this variable to pass down the current directory to + sub MAKEDEVS. + (console): Use the new term syntax. + (tty[0-9]?|tty[0-9a-f]): New rule for normal ttys. + ([pt]ty[pqPQ]?): New rule for ptys (both master and slave). + ([pt]ty[pqPQ]): New rule for making sets of ptys. + +Mon Dec 4 15:17:14 1995 Miles Bader + + * io.c (trivfs_S_file_set_size, trivfs_S_file_sync, + trivfs_S_file_syncfs, trivfs_S_file_get_storage_info): Add totally + gratuitous, annoying, and trouble-making reply-port args. + + * io.c (trivfs_S_file_get_storage_info): Use inline return if possible. + +Wed Nov 8 16:44:05 1995 Miles Bader + + * io.c (trivfs_S_file_set_size): Renamed from trivfs_S_file_truncate. + +Sun Nov 5 10:00:56 1995 Miles Bader + + * devio.c (main): Add FLAGS arg to trivfs_startup call. + +Sat Nov 4 20:03:05 1995 Miles Bader + + * io.c (trivfs_S_file_get_storage_info): Add FLAGS argument. + +Fri Oct 6 17:25:37 1995 Miles Bader + + * io.c (trivfs_S_file_get_storage_info): Change type of ADDRESSES + to off_t **, and add BLOCK_SIZE parameter. + +Sun Oct 1 16:20:45 1995 Miles Bader + + * devio.c (main, trivfs_S_fsys_syncfs): Get rid of debugging noise. + * rdwr.c (open_write, open_read): Ditto. + * dev.c (dev_open, dev_sync, dev_write, dev_read): Ditto. + * io.c (trivfs_S_file_syncfs, trivfs_S_file_sync): Ditto. + * devpager.c (pager_write_page, pager_read_page): Ditto. + * window.c (position): Ditto. + +Tue Sep 26 15:33:14 1995 Miles Bader + + * io.c (trivfs_S_file_get_storage_info): New function. + * dev.c (dev_open): Record NAME in the returned dev structure. + * dev.h (struct dev): Add the NAME field. + +Thu Aug 24 10:28:00 1995 Miles Bader + + * Makefile (devio): Put all dependencies here. + (HURDLIBS): Removed. + +Tue Aug 22 10:45:31 1995 Miles Bader + + * Makefile (HURDLIBS): Add libshouldbeinlibc. + (OBJS): Get rid of error.o. + Get rid of rules dealing with error.o. + ($(prefix)/dev/MAKEDEV): Use $(INSTALL_PROGRAM) instead of + $(INSTALL_DATA) + `chmod +x'. + + * devio.c (trivfs_modify_stat): Get the device from CRED now that + we have it. + +Mon Aug 21 16:34:29 1995 Miles Bader + + * devio.c (trivfs_goaway, trivfs_modify_stat): Update arguments. + +Tue Aug 15 19:47:57 1995 Roland McGrath + + * MAKEDEV ([hrs]d*): Fixed partition parsing: use glob pattern, + not regexp. + +Sun Aug 13 10:57:03 1995 Miles Bader + + * devio.c (trivfs_peropen_create_hook): This now returns an error_t. + (open_hook): And thus this does as well. + +Sat Jul 22 18:32:03 1995 Miles Bader + + * rdwr.c (open_read, open_write): Clean up STATE before returning + with an error. + * devpager.c (dev_get_memory_object): A new pager now comes with 1 + ref, so we allocate a ref ourselves when we're using an old one, + and once we've created the send right, remove a reference. + +Mon Jul 10 15:15:45 1995 Miles Bader + + * rdwr.c (open_seek): New function. + (raw_read, raw_write): Return EINVAL if *OFFS isn't a block boundary. + * open.h: Add declaration for open_seek. + * io.c (trivfs_S_io_seek): Call open_seek instead of doing ourselves. + +Sat Jul 8 18:35:17 1995 Miles Bader + + * MAKEDEV (fd): Put the fd server on `fd', not `stdin'. + * MAKEDEV (console): Give /hurd/term a ttyname argument. + +Thu Jul 6 15:33:33 1995 Miles Bader + + * Makefile: Remove include dependencies. + +Wed Jun 28 19:22:47 1995 Miles Bader + + * Makefile (HURDLIBS): Add libihash. + + * iostate.c (io_state_sync): Remember that we've synced the buffer. + * devpager.c (dev_stop_paging): New function. + (pager_dropweak): New function. + * dev.h (struct dev): Add the pager_port_bucket field. + Declare dev_stop_paging (). + * devio.c (trivfs_goaway): Make trivfs_goaway do the right thing. + (clean_exit, close_device): Deleted functions. + (thread_cancel): New function. + + * devpager.c (pager_port_type): Deleted var. + (pager_port_bucket, pager_port_class): New vars. + (dev_get_memory_object): Moved here from dev.c. Also, call + init_dev_pager if necessary. + (service_paging_requests): New function. + (init_dev_pager): New function. + * dev.c (dev_get_memory_object): Moved function to devpager.c. + + * devio.c (fsys_port_class, root_port_class, port_bucket): New vars. + (trivfs_protid_portclasses, trivfs_cntl_portclasses, + trivfs_protid_nportclasses, trivfs_cntl_nportclasses): New vars. + (main): Initialize *portclasses vars, and convert to new trivfs lib. + (trivfs_protid_porttypes, trivfs_cntl_porttypes, + trivfs_protid_nporttypes, trivfs_cntl_nporttypes): Deleted vars. + (trivfs_goaway): Convert args for new trivfs lib. + (ports_cleanroutines): Delete var. + (ports_demuxer, ports_notice_idle, ports_no_live_ports, + ports_no_hard_ports): Delete functions. + * ptypes.h: Deleted file. + +Wed Jun 28 15:51:51 1995 Michael I Bushnell + + * Makefile: Repair mangled include-file dependencies. + +Fri Apr 21 14:17:19 1995 Roland McGrath + + * MAKEDEV: Split out `std' into individual device-makers it calls. + Rewrote /dev/fd stuff (still commented out). Use case built-in + instead of expr program. + +Tue Apr 11 15:46:35 1995 Michael I Bushnell + + * Makefile (DIST_FILES): New var, for MAKEDEV. + (install): Depend on $(prefix)/dev/MAKEDEV. + ($(prefix)/dev/MAKEDEV): New target. + * MAKEDEV: New file. + +Mon Apr 10 10:22:26 1995 Miles Bader + + * rdwr.c (open_write, open_read): Bounds check I/O. + + * io.c (trivfs_S_file_truncate): Always return 0, so O_TRUNC works. + + * devio.c (main, check_open_hook, close_device, trivfs_goaway): + Add a new lock, device_lock, and use it to control access to the + DEVICE variable. + (open_hook, trivfs_modify_stat, trivfs_S_fys_syncfs): Copy DEVICE + before using it, so it doesn't change underneath us. + + * devio.c (clean_exit): Add a new argument that says whether to + aquire a lock before doing our work. + (ports_notice_idle, ports_no_live_ports): Use it. + + * devio.c (close_device): New function, closes DEVICE cleanly. + (clean_exit, ports_no_hard_ports): Use close_device. + + * devio.c (main): Use trivfs_startup instead of doing it manually. + + * devio.c (trivfs_goaway): Try and do it better, paying attention + to flags, etc.; this still isn't right though, we may want to wait + for the ports library to be fixed first. + + * devio.c (DEBUG): New macro, executes its arg with debug_lock locked. + (most everything): use DEBUG instead of doing things manually. + + * open.c (open_create): Supply our dev's size when creating a window. + +Sun Apr 9 14:49:33 1995 Miles Bader + + * window.h: Add a new window field, max_pos. Rename the location + field `pos'. + * window.c (position): Use a shorter than normal window if + necessary to avoid going past the end of the device. + (window_create): Initialize the new MAX_POS field. + (window_create, position, window_write, window_read): Rename the + location field `pos'. + + * devpager.c (pager_read_page, pager_write_page): Read or write + partial pages at the end of the device. + diff --git a/libmom/ChangeLog b/libmom/ChangeLog new file mode 100644 index 00000000..f04006c5 --- /dev/null +++ b/libmom/ChangeLog @@ -0,0 +1,31 @@ +Sat May 25 17:25:09 1996 Michael I. Bushnell, p/BSG + + * refs-identical.c (mom_ports_identical): Omit uses of deleted + members of struct mom_port_ref.c. + + * ref-destroy.c (mom_ref_destroy): Omit uses of deleted members of + struct mom_port_ref.c. + + * mach-port-set.c (mom_mach_port_set): Omit uses of deleted + members of struct mom_port_ref.c. + + * fetch-mach-port.c (mom_fetch_mach_port): Omit uses of deleted + members of struct mom_port_ref.c. + + * copy-ref.c (mom_copy_ref): Likewise. + + * mom-kerndep.h (struct mom_port_ref): Delete members `lock' and + `refcnt'. + * Makefile (SRCS): Delete add-ref.c and drop-ref.c. + * mom.h (mom_add_ref, mom_drop_ref): Delete functions. + * add-ref.c, drop-ref.c: Delete files. + +Fri May 24 16:14:54 1996 Michael I. Bushnell, p/BSG + + * mom.h: Include . + * error-trans.c: New file. + * mom-kerndep.h (mom_error_translate_mach): New function. + * Makefile (LCLHDRS, installhdrs): Add mom-errors.h. + (SRCS): Add error-trans.c. + * mom-errors.h: New file. + diff --git a/mkbootfs/ChangeLog b/mkbootfs/ChangeLog new file mode 100644 index 00000000..787943a2 --- /dev/null +++ b/mkbootfs/ChangeLog @@ -0,0 +1,22 @@ +Fri Jul 22 10:38:17 1994 Michael I Bushnell + + * Makefile: Rewritten in accord with new scheme. + +Wed Jul 20 16:24:08 1994 Michael I Bushnell + + * Makefile (mkbootfs): Put -n after hostname for compat with + old broken rsh. + Use gcc literally instead of MIGHOSTCC. + +Tue Jul 5 14:22:00 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * Makefile (SRCS): New variable. + +Fri May 6 13:25:47 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * Makefile (mkbootfs): Use MIGHOSTCC instead of CC. + +Thu May 5 19:06:21 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * Makefile (mkbootfs): Call rsh with -n flag. + diff --git a/ufs-fsck/ChangeLog b/ufs-fsck/ChangeLog new file mode 100644 index 00000000..1ea09c4a --- /dev/null +++ b/ufs-fsck/ChangeLog @@ -0,0 +1,245 @@ +Sat Jul 6 19:59:27 1996 Miles Bader + + * main.c (argp_program_version): New variable. + : New include. + +Mon Jul 1 12:55:48 1996 Michael I. Bushnell, p/BSG + + * pass2.c (pass2): Don't skip empty directories in `.' and `..' + correctness check; we don't clear them the way BSD does, so we + want `.' and `..' to get created for us. Also handle `.' before + `..' so that they get created in the usual order for empty + directories. + + * dir.c (makeentry): After successful directory expansion, write + out modified directory inode. + + * pass4.c (pass4): If a reconnect fails while we are preening, + give up. + +Mon Jun 24 10:19:39 1996 Michael I. Bushnell, p/BSG + + * utilities.c (errexit, punt): Exit with status 8 for catastrophic + failures. + +Thu May 23 14:12:21 1996 Michael I. Bushnell, p/BSG + + * pass2.c (pass2): Don't clear all node types in directories, just + clear those that are wrong. + +Tue May 14 16:49:46 1996 Miles Bader + + * pass2.c (pass2): Fix up test in preen case. + +Tue May 14 15:29:36 1996 Michael I. Bushnell, p/BSG + + * pass2.c (pass2): Handle directory entry type fields better for + Hurd. + +Sat May 11 01:07:49 1996 Miles Bader + + * main.c (parse_opt): Use ARGP_ERR_UNKNOWN instead of EINVAL. + +Thu May 9 20:12:51 1996 Michael I. Bushnell, p/BSG + + * pass1b.c (pass1b): Bother to initialize NUMBER. + +Fri May 3 00:48:39 1996 Miles Bader + + * main.c (nice_size, show_stats): New functions. + (main): Use show_stats. + +Wed May 1 13:59:06 1996 Miles Bader + + * main.c (main): Shorten summary message so that it fits on one line. + * utilities.c (no_preen): New function. + (problem, warning, pinode): Use it. + (warning): Don't flush all pending problems, just our own. + * dir.c (linkup): Consistently put quotes around filenames. + + * main.c (preen, num_files): New variables. + (main): Implement clean-bit checking in preen mode, and print + summary statistics. + (main, options): Add --force & --silent options. + * pass1.c (pass1): Increment NUM_FILES. + When clearing inode due to bad blocks, continue. + * inode.c (allocino, freeino): Frob NUM_FILES. + * fsck.h (force): New declaration. + * pass5.c (pass5): Vary clean msg depending on whether FSMODIFIED. + * setup.c (setup): Use error to print error msgs. + , : New includes. + + * utilities.c (problem, warning, pextend, pfail): New functions. + (pinode, pfix, reply): Use new problem recording stuff. + (push_problem, resolve_problem, flush_problems): New functions. + (struct problem): New type. + (problems, free_problems): New variables. + (retch, punt): New functions. + * fsck.h (problem, warning, pextend, pfail): New declarations. + (pinode): Update declaration. + * dir.c (validdir, makeentry, linkup): Use new printing functions. + * pass1.c (pass1): Likewise. + * pass1b.c (pass1b): Likewise. + * pass2.c (pass2): Likewise. + * pass3.c (pass3): Likewise. + * pass4.c (pass4): Likewise. + * pass5.c (pass5): Likewise. + * setup.c (setup): Likewise. + +Tue Apr 30 19:06:42 1996 Miles Bader + + * pass5.c (pass5): Be sure to call pwarn before pfix. + * main.c (main): Don't print large obnoxious banner if PREEN. + +Fri Apr 26 16:20:37 1996 Michael I. Bushnell, p/BSG + + * inode.c (allocino): Parenthesize test correctly. + + * fsck.h (swab_disk): Define as constant zero. + + * pass5.c (pass5): If not marked clean, but now it is, then offer + to mark it clean. + * utilities.c (reply): Set fix_denied anytime we return 0. + * fsck.h (fix_denied): New variable. + +Wed Apr 24 13:32:39 1996 Michael I. Bushnell, p/BSG + + * pass1.c (pass1): Don't print block numbers as we go anymore. + +Tue Apr 23 10:11:49 1996 Michael I. Bushnell, p/BSG + + * pass5.c (pass5): Correctly track contig summaries even though + they aren't used by the filesystem; we still need to preserve the + format. + +Mon Apr 15 12:51:41 1996 Michael I. Bushnell, p/BSG + + * Makefile (vpath tables.c): Find ufs directory in $(top_srcdir). + +Tue Apr 2 09:00:53 1996 Michael I. Bushnell, p/BSG + + * pass1.c (pass1): Print mode correctly in unknown file type case. + Recognize inode type IFSOCK too. + +Mon Mar 18 19:48:39 1996 Miles Bader + + * main.c (main): Pass new arg to argp_parse. Use argp_usage correctly. + +Thu Oct 19 17:45:12 1995 Miles Bader + + * main.c (main): Exit with a non-zero status if we fixed anything. + Use argp to parse options. + (options): Converted to argp format. + (args_doc): New variable. + (USAGE, usage, SHORT_OPTIONS): Removed. + Include instead of . + * Makefile ($(target)): Depend on libshouldbeinlibc.a. + +Fri Sep 22 16:55:03 1995 Miles Bader + + * utilities.c (pfix): New function. + (pfatal, pwarn, errexit): Print DEVICE_NAME too if in preen mode. + * fsck.h: Declare DEVICE_NAME. + * setup.c (setup): Set DEVICE_NAME. + * pass1.c, pass2.c, pass3.c, pass4.c, pass5.c (pass1, pass2, + pass3, pass4, pass5): Call pfix instead of printf. + * pass1.c (pass1): Only print progress report if not in preen mode. + * main.c (main): Only print section headers if not in preen mode. + +Wed Sep 20 09:11:59 1995 Miles Bader + + * utilities.c (pinode): Take a message & args to print as well. + * fsck.h: Change declaration of pinode. + * pass2.c (pass2): Use changed pinode. + * pass3.c (pass3): Use changed pinode. + * pass4.c (pass4): Use changed pinode. + +Tue Sep 19 15:37:02 1995 Miles Bader + + * pass1.c (pass1): Change the extent of DBWARN & IBWARN so that + they actually work. + * pass2.c (pass2): Adjust our record of link counts when we + add/change dir entries; also print error messages when we can't. + * pass4.c (pass4): If an unlinked file can't be reconnected, offer + to clear it. Once a reconnect attempt fails, don't try again. + * dir.c (linkup): Print the value of LFNAME rather than `lost+found'. + (searchdir, changeino): Fix backward compare. + (linkup): Don't fail when makeentry succeeds. + (searchdir): Make searchdir return zero if there's an error + during the search. + (linkup): Print appropiate error messages if searchdir fails. + (validdir): Get rid of extra newlines in error messages -- + everyone who calls this routine prints extra information if it + fails, which should immediately follow. + * main.c (main): Use getopt to parse command line options. + (usage): New function. + (options): New variable. + (lfname, lfmode): Variables moved here from setup.c. + (lfname): Made into a char* so that we can change it. + (lfmode): Get rid of IFDIR; it's added when necessary. + * fsck.h: Change LFNAME to char*. + * setup.c (lfname, lfmode): Variables moved to main.c. + +Sat Sep 9 12:12:59 1995 Miles Bader + + * Makefile (target): Changed to `fsck.ufs'. + (installationdir): New variable, install into $(sbindir). + +Thu Jul 6 15:33:46 1995 Michael I Bushnell + + * fsck.h (lookup_directory): New decl. + + * pass1.c (pass1): Remove assignment from if test. + * utilities.c (pinode): Likewise. + + * Makefile (tables.o): Delete rule. + (vpath tables.c): Tell where to find tables.c. + + * Makefile: Removed dependencies that are now automatically + generated. + +Thu Nov 3 17:19:03 1994 Michael I Bushnell + + * Makefile (dir): Changed to fsck. + (target): Changed to fsck. + +Wed Nov 2 14:39:13 1994 Michael I Bushnell + + * pass2.c (pass2): Use DIRECT_NAMLEN instead of d_namlen + throughout. + * dir.c (searchdir): Likewise. + (changeino): Likewise. + (makeentry): Likewise. + +Mon Oct 17 16:07:56 1994 Michael I Bushnell + + * inode.c (inode_iterate): FN takes new third arg. + Keep track of new var `offset' and pass it to FN. + * pass2.c (pass2/checkdirblock): New third arg. + Only scan DIRBLKSIZ chunks to the total size of the file. + * dir.c (searchdir/checkdirblock): Likewise. + (changeino/checkdirblock): Likewise. + (makeentry/checkdirblock): Likewise. + * pass1.c (pass1/checkblock): New third arg (ignored). + * pass1b.c (pass1b/checkblock): Likewise. + + * inode.c (inode_iterate): Compute MAXB correctly. + + * utilities.c (getinode): Multiple ino_to_fsbo by + sizeof (struct dinode). + (write_inode): Likewise. + (getinode): Inode buffer needs to be a full block, not a + fragment. + +Fri Oct 14 21:07:09 1994 Michael I Bushnell + + * utilities.c (lastifrag): New variable. + (getinode): Use lastifrag instead of buf; Only I/O new block + if lastifrag isn't what we want. + (write_inode): Likewise. + +Fri Oct 14 17:44:59 1994 Michael I Bushnell + + * setup.c (setup): Test ISCHR, not ISDIR. + Fix NCYL against NCG * CPG test. + Bother to set MAXFSBLOCK, MAXINO, and DIRECT_SYMLINK_EXTENSION. diff --git a/ufs-utils/ChangeLog b/ufs-utils/ChangeLog new file mode 100644 index 00000000..d6d58f5d --- /dev/null +++ b/ufs-utils/ChangeLog @@ -0,0 +1,104 @@ +Fri Jun 21 02:12:16 1996 Miles Bader + + * dlabel.c (fd_get_device): Supply new args to store_create. + +Sat May 11 01:20:18 1996 Miles Bader + + * mkfs.c (parse_opt): Use ARGP_ERR_UNKNOWN instead of EINVAL. + +Fri May 10 15:50:38 1996 Miles Bader + + * dlabel.c (fd_get_device): Update to use libstore. + : New include. + * Makefile (mkfs.ufs): Depend on ../libstore/libstore.a. + +Tue Apr 30 10:06:21 1996 Michael I. Bushnell, p/BSG + + * Makefile (include ../Makeconf): BEFORE dependencies. + (all): Delete target. + ($(targets)): Each target depends on its associated .o. + +Wed Apr 3 16:31:13 1996 Miles Bader + + * mkfs.c (main): In `Can't get disklabel' error message, specify + which flag the user can use to supply the needed information. + (mkfs): Fiddle with info message. + +Sun Mar 31 14:34:28 1996 Miles Bader + + * stati.c (mode_rep): Prefix octal number with `0'. + +Fri Mar 29 11:56:52 1996 Miles Bader + + * stati.c (main): Print mode & {in,}direct blocks too. + (mode_rep): New function. + (timespec_rep): P shouldn't be static. + + * mkfs.c (main): Argp interface changes. + +Wed Mar 13 18:30:55 1996 Miles Bader + + * mkfs.c (options, args_doc, doc): New variables for option parsing. + (struct amark): New type. + (amarks_add, amarks_contains): New functions. + (default_disklabel): New variable. + (main): Most arguments are now options (and optional). Allow many + more parameters to be specified. Consult the disk label for some + defaults. + (most functions): Add explicit return type declarations. Fix + printf format specifications. Get rid of #ifdefs for MFS. + (started, malloc, realloc, calloc, free): Functions removed. + (mfs, membase): Variables removed. + , , , , , + : New includes + * dlabel.c: New file. + * Makefile (SRCS): Add dlabel.c. + (mkfs.ufs): New target. + +Tue Feb 27 14:52:00 1996 Miles Bader + + * clri.c: Move here from ../utils. + + [Entire directory renamed to `ufs-utils' from `newfs'] + +Sat Sep 9 12:17:11 1995 Miles Bader + + * Makefile (target): Changed to `mkfs.ufs'. + (installationdir): New variable, install into $(sbindir). + +Thu Nov 24 18:39:30 1994 Roland McGrath + + * mkfs.c: Protect all mfs code with #ifdef MFS. + +Wed Oct 12 12:59:01 1994 Michael I Bushnell + + * mkfs.c (main): MAXCONTIG should be zero because we don't + do clustering. + +Fri Sep 9 09:45:23 1994 Michael I Bushnell + + * mkfs.c: Include and . + (main): New function. Punt newfs.c for now. + * Makefile (SRCS, OBJS): Comment out uses of newfs.c. + (target): Build mkfs, not newfs. + + * newfs.c (mopts): Comment out. + (mntflags): Comment out. + (main): Omit check for `mfs'. Omit var `partition'. + (main) [case 'o']: Comment out mfs specific code. + (main): Comment out check for already-mounted partition. + (main): Comment out MFS specific open of FSI. + + * mkfs.c (fsinit): Use DI_MODE to read mode from NODE, and + set di_model and di_modeh instead of di_mode. + (mkfs): Don't set fields in *PP. + + * newfs.c: Include ufs header files with "../ufs/foo.h" instead of + . Don't include , , + or "mntopts.h". + +Thu Sep 8 15:52:05 1994 Michael I Bushnell + + * mkfs.c: Include ufs header files with "../ufs/foo.h" instead of + . Don't include . + diff --git a/ufs/ChangeLog b/ufs/ChangeLog new file mode 100644 index 00000000..368a2f59 --- /dev/null +++ b/ufs/ChangeLog @@ -0,0 +1,1586 @@ +Sat Jul 6 16:14:10 1996 Miles Bader + + * main.c (ufs_version): Variable removed. + +Sat Jul 6 12:45:36 1996 Michael I. Bushnell, p/BSG + + * inode.c (read_disknode): Don't set allocsize based on st->size + for kludged symlinks. + + * sizes.c (diskfs_truncate): Call record_poke after truncating a + kludged symlink. + +Wed Jul 3 13:27:04 1996 Michael I. Bushnell, p/BSG + + * main.c: Include . + (startup_parents, runtime_parents): Declare const. + +Tue Jun 25 14:02:02 1996 Miles Bader + + * main.c (diskfs_get_options): Include `--compat=' in options. + +Mon Jun 24 16:59:12 1996 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_lookup_hard): Use diskfs_check_readonly instead of + diskfs_readonly. + (diskfs_dirempty): Likewise. + + * dir.c (diskfs_lookup_hard): Use diskfs_check_readonly instead of + diskfs_readonly. + (diskfs_dirempty): Likewise. + * inode.c (diskfs_cached_lookup): Likewise. + (read_symlink_hook): Likewise. + * sizes.c (diskfs_truncate): Call diskfs_check_readonly. + (diskfs_grow): Likewise. + * hyper.c (diskfs_set_hypermetadata): If CLEAN is not set, make + sure we clear the clean bit on disk. Always call sync_disk (with + appropriate WAIT). + (diskfs_readonly_changed): Don't do set_hypermetadata here. + (copy_sblock): Don't track clean state here. + + * pager.c (diskfs_shutdown_pager): Don't shutdown DISKPAGER ever, + just sync it instead. + +Sat Jun 22 17:45:34 1996 Miles Bader + + * main.c (diskfs_get_options): New function. + (options): Make const. + +Fri Jun 21 01:32:09 1996 Miles Bader + + * main.c (parse_opt): Handle runtime invalid selection of 4.2 mode. + Save select mode until we're done to correctly deal with external + errors at runtime. + (startup_parents, startup_argp, runtime_parents, runtime_argp): + New variables. + (main): Argp vars made global. + (argp_parents): diskfs_device_startup_argp --> + &diskfs_std_device_startup_argp. + +Sat Jun 15 13:57:27 1996 Miles Bader + + * main.c (options): New variable. + (parse_opt): New function. + (main): Parse ufs-specific options too. + : New include. + +Fri May 10 09:29:03 1996 Michael I. Bushnell, p/BSG + + * inode.c (diskfs_set_statfs): Fix one reference to old name of ST + member. + +Thu May 9 11:54:13 1996 Michael I. Bushnell, p/BSG + + * Makefile (ufs.static ufs): s/ioserver/iohelp/g + * ufs.h: ioserver.h -> iohelp.h. + + * inode.c (diskfs_set_statfs): Use and fill in new statfs + structure. + +Mon May 6 14:23:54 1996 Michael I. Bushnell, p/BSG + + * main.c (ufs_version): Upgrade to 0.0. + +Fri May 3 09:15:33 1996 Michael I. Bushnell, p/BSG + + * sizes.c (block_extended): Rewrite code that moves pages + to be more efficient, and not deadlock too, using unlocked + pagein permission feature (read "hack"). Return value + now indicates whether we expect a sync. + (diskfs_grow): If a call to block_extended returns nonzero, + then sync the file before returning. + * pager.c (diskfs_get_filemap): Initialize + UPI->allow_unlocked_pagein and UPI->unlocked_pagein_length. + (unlocked_pagein_lock): New variable. + (find_address): New parameter `isread'; all callers changed. + If ISREAD and we are in the unlocked pagein region, don't + attempt to acquire NP->dn->allocptrlock. + * ufs.h (struct user_pager_info): New members + `allow_unlocked_pagein' and `unlocked_pagein_length'. + (unlocked_pagein_lock): New variable. + +Thu May 2 10:56:10 1996 Michael I. Bushnell, p/BSG + + * sizes.c (offer_data): Offer pages at ADDR each time through the + loop, not the same page over and over. + (block_extended): When moving data, sync in-core pager both before + reading from disk and after providing data to kernel. + (diskfs_grow): Always call block_extended or offer_data before + adjusting block pointer. + +Tue Apr 30 13:38:42 1996 Michael I. Bushnell, p/BSG + + * sizes.c (diskfs_grow): In last offer_data, don't offer a block + number as an address. + +Fri Apr 26 15:35:53 1996 Michael I. Bushnell, p/BSG + + * Makefile (makemode): Now `servers'. + (targets): Renamed from `target'; now include ufs.static. + (ufs.static-LDFLAGS): Renamed from `LDFLAGS'. + (ufs.static): Depend on same things as `ufs'. + (include ../Makeconf): Must come before dependency information. + +Wed Apr 24 14:05:48 1996 Michael I. Bushnell, p/BSG + + * dir.h (DIRECT_NAMLEN) [! LITTLE_ENDIAN]: Deal correctly with the + case where it was written on a little endian machine without the + extension. + (DIRECT_NAMLEN) [LITTLE_ENDIAN]: Deal with case correctly where it + was written without the extension on a big endian machine. + * dir.c (dirscanblock): Use read/write_disk_entry when reading or + writing fields from directory entries. + (diskfs_direnter_hard): Likewise. + (diskfs_dirremove_hard): Likewise. + (diskfs_dirrewrite_hard): Likewise. + (diskfs_get_directs): Likewise. + (diskfs_dirempty): Likewise. + (count_dirents): Likewise. + +Tue Apr 23 11:28:42 1996 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_dirempty): node_update -> diskfs_node_update. + + * hyper.c (swab_sblock, swab_csums): New functions. + (get_hypermetadata): If this is a swapped filesystem, set swab_disk. + Also swap csum and sblock after reading them. + (diskfs_set_hypermetadata): If swab_disk, swap the csums back before + writing them. + (copy_sblock): If swab_disk, swap the sblock before writing it. + * ufs.h (swab_disk): New variable. + (swab_short, swab_long, swab_long_long): New functions. + (read_disk_entry, write_disk_entry): New macros. + * alloc.c (ffs_realloccg): Use read/write_disk_entry when + reading/writing on-disk inode fields. + * bmap.c (fetch_indir_spec): Likewise. + * inode.c (read_disknode): Likewise. + (write_node): Likewise. + (diskfs_set_translator): Likewise. + (diskfs_get_translator): Likewise. + (diskfs_S_file_get_storage_info): Likewise. + * sizes.c (diskfs_truncate): Likewise. + (diskfs_grow): Likewise. + * pager.c (pager_unlock_page): Likewise. + * bmap.c (fetch_indir_spec): Use read/write_disk_entry when + reading/writing on-disk indirect blocks. + * sizes.c (diskfs_truncate): Likewise. + (indir_release): Likewise. + (diskfs_grow): Likewise. + * pager.c (pager_unlock_page): Likewise. + * alloc.c: Include + (ffs_blkpref): Use read_disk_entry when reading from BAP array. + (swab_cg, read_cg, release_cg): New functions. + (ffs_fragextend, ffs_alloccg, ffs_nodealloccg, ffs_blkfree, + diskfs_free_node): Use new cg access functions. + +Thu Apr 18 14:50:30 1996 Michael I. Bushnell, p/BSG + + * sizes.c (diskfs_grow): New variable `pagerpt'. + (offer_zeroes, block_extended): New functions. + (diskfs_grow): In initializing newly allocated data disk blocks with + zeroes, use less aggressive offer_zeroes instead of immediate + synchronous writes. After ffs_realloccg succeeds, use + block_extended to handle the magic. Get rid of old poke calls. + * alloc.c (ffs_realloccg): If we are allocating a new block, don't + actually free the old one here. + * sizes.c (diskfs_grow): New variable `pagerpt'. + (offer_zeroes, block_extended): New functions. + (diskfs_grow): In initializing newly allocated data disk blocks + with zeroes, use less aggressive offer_zeroes instead of immediate + synchronous writes. After ffs_realloccg succeeds, use + block_extended to handle the magic. Get rid of old poke calls. + +Tue Apr 16 15:20:07 1996 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_lookup_hard): Set atime appropriately, and sync + the new atime if we are running synchronously (!). + (diskfs_dirempty): Likewise. + (diskfs_direnter_hard): Set mtime appropriately. + (diskfs_dirremove_hard): Likewise. + (diskfs_dirrewrite_hard): Likewise. + + * inode.c (diskfs_write_disknode): Only do sync if WAIT is set. + +Thu Apr 4 16:39:22 1996 Miles Bader + + * inode.c (diskfs_cached_lookup): Intialize NP->cache_id *after* + NP exists. + +Wed Apr 3 16:03:51 1996 Michael I. Bushnell, p/BSG + + * inode.c (diskfs_cached_lookup): Renamed from `iget'. All + callers changed. Initialize NP->cache_id. + +Fri Mar 29 16:52:31 1996 Michael I. Bushnell, p/BSG + + * sizes.c (diskfs_truncate): Cast DI->di_shortlink to correct type + before adding a character count to it. + +Mon Mar 25 13:08:10 1996 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_null_dirstat): New function. + +Fri Mar 22 23:43:53 1996 Miles Bader + + * inode.c (read_symlink_hook): Only set NP's atime if !readonly. + +Wed Mar 20 14:36:31 1996 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_lookup_hard): Don't do initial or final permission + checking here. + * dir.c (diskfs_dirrewrite_hard): Renamed from diskfs_dirrewrite. + No longer call modification tracking routines. + (diskfs_dirremove_hard): Renamed from diskfs_dirremove. No longer call + modification tracking routines. + (diskfs_direnter_hard): Renamed from diskfs_direnter. No longer call + modification tracking routines. + (diskfs_lookup_hard): Renamed from diskfs_lookup. + +Mon Mar 18 19:50:41 1996 Miles Bader + + * main.c (main): Pass new arg to argp_parse. + +Mon Mar 18 12:33:06 1996 Michael I. Bushnell, p/BSG + + * pager.c (diskfs_max_user_pager_prot) [add_pager_max_prot]: + (a == b) ? 1 : 0 ====> (a == b). + +Fri Feb 23 15:27:05 1996 Roland McGrath + + * hyper.c (get_hypermetadata): Use diskfs_device_arg in unclean msgs. + +Wed Feb 21 05:57:12 1996 Roland McGrath + + * hyper.c: Implement proper handling of the filesystem `clean bit'. + (ufs_clean): New variable. + (get_hypermetadata): Set it from the fs_clean flag. If not clean, + complain and force read-only. Complain when ignoring COMPAT_BSD42. + (diskfs_set_hypermetadata): Set the clean flag in the superblock + when CLEAN and fs was clean to start with. + (copy_sblock): Remove bogus clean flag frobnication. + +Fri Feb 16 17:05:36 1996 Miles Bader + + * main.c (main): Check error return from diskfs_init_diskfs. + +Sat Jan 6 11:50:14 1996 Roland McGrath + + * ufs.h (diskpager, diskpagerport, disk_image): Variables removed. + Include instead. + (sync_disk_blocks): Use `disk_pager' in place of `diskpager->p'. + * pager.c (diskfs_shutdown_pager, diskfs_sync_everything): Use + `disk_pager' in place of `diskpager->p'. + (create_disk_pager): Rewritten using disk_pager_setup. + * pokeloc.c (sync_disk): Use `disk_pager' in place of `diskpager->p'. + * sizes.c (indir_release): Likewise. + * main.c (diskfs_reload_global_state): Likewise. + +Thu Jan 4 19:10:11 1996 Roland McGrath + + * main.c (main): Don't map disk image here; create_disk_pager now + does it. + + * hyper.c (get_hypermetadata, copy_sblock): Don't put + diskfs_catch_exception () inside assert, bonehead! Use + assert_perror on a variable of its result. + +Mon Jan 1 16:38:14 1996 Michael I. Bushnell, p/BSG + + * pager.c (pager_unlock_page): When allocating block in direct + array, clear it synchronously just like we do when it goes in the + indirect array. + +Thu Nov 9 14:01:30 1995 Michael I. Bushnell, p/BSG + + * dir.c (struct dirstat): New member `nbytes'. + (dirscanblock): If DS->type is COMPRESS, still look + for TAKE/SHRINK possibilities. Also, if it's COMPRESS, + still look to see if the current block can be compressed + with fewer byte copies. + +Sun Nov 5 02:08:38 1995 Miles Bader + + * main.c (main): Add flags arg to diskfs_startup_diskfs call. + +Sat Nov 4 20:01:58 1995 Miles Bader + + * inode.c (diskfs_S_file_get_storage_info): Add FLAGS argument. + +Thu Oct 19 12:50:11 1995 Miles Bader + + * pager.c (diskfs_max_user_pager_prot): Return what we discovered, + instead of 1. + + * dir.c (diskfs_lookup, diskfs_dirempty): Give diskfs_get_filemap + a protection arg. + * sizes.c (diskfs_truncate, diskfs_grow): Ditto. + + * hyper.c (diskfs_readonly_changed): Give the 2nd arg to + vm_protect an appropiate type. + + * pager.c (diskfs_max_user_pager_prot): Stop iterating early if poss. + +Wed Oct 18 16:28:42 1995 Miles Bader + + * ufs.h (struct user_pager_info): Add max_prot field. + * pager.c (diskfs_get_filemap): Add PROT parameter, & use it. + (diskfs_pager_users): Split out block_caching & enable_caching. + (block_caching, enable_caching): New function. + (diskfs_max_user_pager_prot): New function. + + * main.c (main): Always include VM_PROT_WRITE in max prot. + * hyper.c (diskfs_readonly_changed): Change the protection of + DISK_IMAGE to reflect the new state. Clear SBLOCK_DIRTY if readonly. + + * inode.c (read_disknode): Bother to set the allocsize field. + + * ufs.h (struct rwlock): Structure deleted. + (rwlock_init, rwlock_reader_unlock, rwlock_reader_lock, + rwlock_writer_lock, rwlock_writer_unlock): Functions deleted. + + +Tue Oct 17 14:49:43 1995 Miles Bader + + * inode.c (diskfs_node_reload): New function. + (iget): Move allocsize setting into read_disknode. + * pager.c (flush_node_pager): New function. + * ufs.h (zeroblock, sblock, csum): Declare extern. + (flush_node_pager, flush_pokes): New declarations. + * pokeloc.c (flush_pokes): New function. + * hyper.c (diskfs_readonly_changed): New function. + (get_hypermetadata): Move compat_mode futzing & disk size + validation here from main. + (zeroblock, sblock, csum): Define (were common). + (get_hypermetadata): Only allocate SBLOCK if not already done. + Deallocate any old ZEROBLOCK and CSUM storage. + (diskfs_readonly_changed): New function. + * main.c (main): Move stuff into get_hypermetadata. + Writable init code moved to diskfs_readonly_changed. + (diskfs_reload_global_state): New function. + +Fri Oct 13 15:03:37 1995 Miles Bader + + * main.c (main): Use new handy diskfs routines and get rid of + tons of junk. Main should be almost all ufs-specific now. + (USAGE, usage, SHORT_OPTS, long_opts, parse_opt, trans_parse_arg): RIP. + (printf_lock): Initialize. + +Thu Oct 12 18:48:04 1995 Miles Bader + + * pager.c (pager_unlock_page, pager_write_page, pager_read_page): + Use diskfs_device_{read,write}_sync instead of dev_{read,write}_sync. + * hyper.c (diskfs_set_hypermetadata): Ditto. + * sizes.c (diskfs_grow): Ditto. + * pager.c (pager_report_extent): Calculate the pager size. + * ufs.h (dev_read_sync, dev_write_sync, dev_write, diskpagersize): + Decls removed. + + * Makefile (SRCS): Remove devio.c. + * ufs.h (ufs_device, ufs_device_name): Variables removed. + * inode.c (diskfs_S_file_get_storage_info): Use DISKFS_DEVICE + instead of UFS_DEVICE, and DISKFS_DEVICE_NAME instead of + UFS_DEVICE_NAME. + +Sat Oct 7 20:47:56 1995 Miles Bader + + * main.c (diskfs_init_completed): Function deleted (now in libdiskfs). + (thread_cancel): Function deleted. + +Fri Oct 6 17:30:23 1995 Miles Bader + + * inode.c (diskfs_S_file_get_storage_info): Change type of + ADDRESSES to off_t **, and add the BLOCK_SIZE parameter. + +Wed Oct 4 17:21:33 1995 Miles Bader + + * inode.c (diskfs_set_statfs): fsys_stb_bsize -> fsys_stb_iosize. + fsys_stb_fsize -> fsys_stb_bsize. + + * main.c (parse_opt): Rearrange slightly. + +Tue Sep 26 11:54:35 1995 Michael I. Bushnell, p/BSG + + * inode.c: Include . + (diskfs_S_file_get_storage_info): New function. + * main.c (main): Delete var `devname'. Use `ufs_device_name' + throughout instead. + * ufs.h (ufs_device_name): New var. + +Fri Sep 22 13:22:42 1995 Roland McGrath + + * hyper.c (get_hypermetadata): Use %Zd format for result of sizeof. + +Tue Sep 19 13:41:46 1995 Miles Bader + + * Makefile (LDFLAGS): New variable. + +Wed Sep 13 12:30:23 1995 Michael I. Bushnell, p/BSG + + * dir.c (diskfs_lookup): Don't attempt to lock NP if NPP is not + set. Don't even set NP if NPP is not set; use INUM as "lookup + succeeded flag" instead. Lookups for REMOVE and RENAME now *must* + set NPP. + +Wed Sep 6 11:01:50 1995 Miles Bader + + * pager.c (diskfs_pager_users): Ignore the disk pager when seeing + if there are any active pagers. + +Mon Aug 28 17:07:36 1995 Roland McGrath + + * Makefile (ufs): Depend on ../libshouldbeinlibc/libshouldbeinlibc.a. + +Fri Aug 25 17:14:09 1995 Michael I. Bushnell, p/BSG + + * sizes.c (diskfs_truncate): When freeing direct blocks mentioned + in a single indirect block, or single indirect blocks mentioned in + a double, only call the free routine (ffs_blkfree or + indir_release, respectively) if the block is actually allocated. + +Wed Aug 23 12:24:07 1995 Miles Bader + + * Makefile (ufs): Add explicit dependencies. + (HURDLIBS, LDFLAGS, REMHDRS): Removed. + Rules associated with ../lib removed. + +Fri Jul 21 17:48:12 1995 Michael I Bushnell + + * pager.c (diskfs_get_filemap): Drop initial reference created by + pager_create. + + * pager.c (diskfs_get_filemap): Avoid race with simultaneous + termination by looping until we win. + (pager_clear_user_data): Only clear UPI->np->dn->fileinfo if it + still points to us. + +Mon Jul 17 14:35:25 1995 Michael I Bushnell + + * pager.c (thread_function): Don't have any global timeout here; + we don't use it anyhow. + +Thu Jul 6 15:42:52 1995 Michael I Bushnell + + * Makefile: Removed dependencies that are now automatically + generated. + +Mon Jun 26 20:17:42 1995 Michael I Bushnell + + * pager.c: Include . + (diskfs_pager_users): New function. + +Thu Jun 22 11:41:04 1995 Michael I Bushnell + + * pager.c (thread_function): Move thread_function to be non-local, + of course, because it needs to live even after create_disk_pager + returns. + + * main.c (thread_cancel): New function (HACK). + + * Makefile (HURDLIBS): Add libihash. + + * main.c (main): Have main thread exit when done instead of + calling a diskfs function. + +Wed Jun 21 12:20:01 1995 Michael I Bushnell + + * ufs.h (user_pager_info): Removed members next and prevp. + * pager.c (pager_clear_user_data): Don't maintain pager linked + list. + (diskfs_get_filemap): Don't maintain pager linked list. + (pager_dropweak): New function. + (pager_traverse): Delete function. + (diskfs_shutdown_pager): Use ports_bucket_iterate instead of + pager_traverse. + (diskfs_sync_everything): Likewise. + + * pager.c (pager_bucket): New variable. + (create_disk_pager): Provide pager_bucket in call to pager_create. + (diskfs_get_filemap): Likewise. + (diskfs_file_update): Use ports reference calls directly instead + of pager wrappers. + (drop_pager_softrefs): Likewise. + (allow_pager_softrefs): Likewise. + (pager_traverse): Likewise. + (create_disk_pager): Initialize pager_bucket here and fork off + service thread for pager ports. + + * sizes.c (diskfs_truncate): Likewise. + + * dir.c (diskfs_lookup): Provide initialization for BUFLEN. + (diskfs_direnter): Move assignment out of if test. + +Tue Jun 20 11:48:06 1995 Michael I Bushnell + + * sizes.c (diskfs_grow): Provide initialization of POKE_OFF. + * alloc.c (ffs_realloccg): Remove assignment from if tests. + * sizes.c (diskfs_truncate): Likewise. + * bmap.c (fetch_indir_spec): Likewise. + +Mon Jun 19 21:17:21 1995 Michael I Bushnell + + * inode.c (diskfs_node_iterate): New function. + (write_all_disknodes): Use it. + +Wed Jun 14 16:18:55 1995 Michael I Bushnell + + * inode.c (diskfs_get_translator): Conform to new memory usage + semantic. + +Sat May 20 00:17:30 1995 Miles Bader + + * main.c (trans_parse_args): Use options_parse & + diskfs_standard_startup_options to parse our translator options. + (usage): New function. + (parse_opt): New function. + + * Makefile (CPPFLAGS): Add -I../lib, to get include lib include files, + and $(CPPFLAGS-$(notdir $<)) to get file-specific cpp options. + Add a vpath for %.c to ../lib, so we can use source files from there. + +Mon May 15 13:14:48 1995 Michael I Bushnell + + * pager.c (pager_clear_user_data): Doc fix. + +Sat May 13 05:04:11 1995 Roland McGrath + + * Makefile (OBJS): Remove exec_server_image.o. + (exec_server_image.o): Rule removed. + +Mon May 8 08:43:43 1995 Miles Bader + + * dir.c (diskfs_lookup): When looping back to try_again: because + we're looking up "..", be sure and trash the mapping we made of + the directory's pager -- otherwise the reference to the pager + never gets dropped and we can never free the node. + + * dir.c (diskfs_lookup): ds->type was being compared to LOOKING, which + value it can never have. Compare ds->stat against LOOKING instead. + + * pager.c (pager_clear_user_data): Don't die when called on the + disk pager. + + * inode.c (write_all_disknodes): Fix typo `alloc' --> `alloca'. + +Tue May 2 11:59:09 1995 Michael I Bushnell + + * pager.c (pager_clear_user_data): Acquire pagerlistlock around + modifications to UPI->next/prevp list structure. + +Fri Apr 28 19:02:05 1995 Michael I Bushnell + + * inode.c (write_all_disknodes): We have to really lock the nodes + around the calls to diskfs_set_node_times and write_node; this in + turn forces us to have real refereces. + +Thu Apr 13 16:36:57 1995 Miles Bader + + * main.c (main): Don't abort if a std file descriptor is already open. + +Tue Apr 4 20:08:25 1995 Michael I Bushnell + + * inode.c (diskfs_set_translator): When freeing passive + translator, account for blocks freed in NP->dn_stat.st_blocks. + +Fri Mar 31 13:43:27 1995 Michael I Bushnell + + * sizes.c (diskfs_truncate): Don't acquire writer lock on + NP->dn->allocptrlock until after forcing delayed copies through; + otherwise the pageins will deadlock attempting to get a reader + lock to service them. This is safe, because we only need + NP->allocsize here, and that can't change as long as we hold + NP->lock. + +Mon Mar 20 13:58:44 1995 Michael I Bushnell + + * consts.c (diskfs_synchronous): New variable. + +Fri Mar 17 14:31:04 1995 Michael I Bushnell + + * alloc.c (ffs_clusteracct): Make static. + (alloc_sync): New function. + (ffs_alloc): Call alloc_sync. + (ffs_realloccg): Likewise. + (diskfs_alloc_node): Likewise. + (ffs_blkfree): Likewise. + (diskfs_free_node): Likewise. + +Sat Jan 28 14:59:26 1995 Roland McGrath + + * Makefile (OBJS): Remove reference to libc's devstream.o. + +Fri Nov 11 11:45:38 1994 Michael I Bushnell + + * hyper.c (diskfs_set_hypermetadata): Always use dev_write_sync to + avoid device_write bug that says you can't modify the buffer until + device_write returns. Also remember to deallocate BUF. + +Thu Nov 10 13:27:09 1994 Michael I Bushnell + + * main.c (main): Issue decent prompt. + + * hyper.c (diskfs_set_hypermetadata): Copy CSUM into a + page-aligned page-sized buffer for disk write to avoid inane + kernel bug. + +Wed Nov 9 05:43:14 1994 Michael I Bushnell + + * main.c (main): Behave more reasonably if we can't open DEVNAME. + +Tue Nov 8 00:03:20 1994 Roland McGrath + + * pager.c (pager_write_page): Use %p for printing PAGER. + + * ufs.h: Declare copy_sblock. + +Wed Nov 2 16:06:10 1994 Michael I Bushnell + + * hyper.c (copy_sblock): Don't copy csum here. + (diskfs_set_hypermetadata): Write csum directly to disk here. + +Thu Oct 27 20:58:08 1994 Michael I Bushnell + + * dir.c (diskfs_lookup): diskfs_get_filemap returns a send right, + so don't create an additional one here. + (diskfs_dirempty): Likewise. + * sizes.c (diskfs_truncate): Likewise. + (diskfs_grow): Likewise. + +Tue Oct 25 12:49:41 1994 Michael I Bushnell + + * hyper.c (copy_sblock): Call record_poke for csum and superblock + after modifying them. + + * pager.c (diskfs_shutdown_pager): Call copy_sblock. + (diskfs_sync_everything): Likewise. + + * alloc.c (ffs_fragextend): Call record_poke for CG after + modifying it. Also set CSUM_DIRTY and SBLOCK_DIRTY. + (ffs_alloccg): Likewise. + (ffs_alloccgblk): Likewise. + (ffs_nodealloccg): Likewise. + (ffs_blkfree): Likewise. + (diskfs_free_node): Likewise. + +Fri Oct 7 01:32:56 1994 Roland McGrath + + * main.c (diskfs_init_completed): Don't call _hurd_proc_init. + (saved_argv): Variable removed. + (main): Don't set saved_argv. Pass ARGV to diskfs_start_bootstrap. + +Wed Oct 5 22:18:46 1994 Michael I Bushnell + + * inode.c (read_disknode): If we are the bootstrap filesystem, + then getpid changes once proc starts up. So only call getpid + once, thus not allowing st_dev values to mysteriously change. + +Wed Oct 5 12:56:53 1994 Michael I Bushnell + + * alloc.c (diskfs_alloc_node): Abort if free inode has + translator attached. + +Tue Oct 4 18:33:35 1994 Michael I Bushnell + + * pager.c (pager_unlock_page): Call diskfs_catch_exception. + +Tue Oct 4 00:16:04 1994 Michael I Bushnell + + * inode.c (diskfs_lost_hardrefs): Comment out body. + * ufs.h (node2pagelock): New variable. + * pager.c (node2pagelock): Initialize. + (diskfs_get_filemap): Don't let node hold a reference to the pager. + (pager_clear_user_data): Acquire node2pagelock and clear + the node's reference to the pager. + (diskfs_file_update): Hold node2pagelock for reference + of NP->dn->fileinfo. + (drop_pager_softrefs): Likewise. + (allow_pager_softrefs): Likewise. + (diskfs_get_filemap): Likewise. + * sizes.c (diskfs_truncate): Likewise. + + * Makefile (SRCS): Added pokeloc.c. + +Mon Oct 3 15:03:38 1994 Michael I Bushnell + + * sizes.c (diskfs_truncate): Rewritten. + + * bmap.c (fetch_indir_spec): Initialize OFFSET values to -2, + meaning that the entry is not needed. If LBN is negative, + then don't set values for the data block. + + * inode.c (write_node): Call record_poke after writing + dinode. + (create_symlink_hook): Likewise. + (diskfs_set_translator): Likewise. + * pager.c (pager_unlock_page): Likewise. + * sizes.c (diskfs_truncate): Likewise. + * pager.c (pager_unlock_page): Call record_poke after writing + indirect block. + * sizes.c (diskfs_grow): Likewise. + (diskfs_grow): Likewise. + * pager.c (diskfs_sync_everything) [sync_one]: If this is the + disk pager, call sync_disk instead. + * pokeloc.c: New file. + +Fri Sep 30 11:25:36 1994 Michael I Bushnell + + * dir.h: Delete DT_* definitions; they are now in . + * dir.c (diskfs_get_directs): Set USERP->d_type as DT_UNKNOWN. + When the bugs in the type fields are fixed (dealing with + multiple links and mode changes) then this can actually return + the value. + +Thu Sep 29 17:16:58 1994 Roland McGrath + + * main.c (main): Test getpid()>0 to decide we are a normal + translator instead of the boot fs. Fetch bootstrap port after + possibly calling diskfs_parse_bootargs, not before. + +Tue Sep 27 15:24:58 1994 Michael I Bushnell + + * sizes.c (diskfs_grow) [computation of newallocsize]: Last block + number is one less than the total number of blocks. + +Tue Sep 27 11:58:44 1994 Michael I Bushnell + + * bmap.c (fetch_indir_spec): Single indirect block pointer is + in the INDIR_SINGLE slot, not the INDIR_DOUBLE slot. + +Mon Sep 26 20:47:30 1994 Michael I Bushnell + + * Makefile (SRCS): Added bmap.c. + + * main.c (main): Don't call pager_init. + + * inode.c (diskfs_get_translator): Repair to read translator + correctly. + + * sizes.c (diskfs_grow): Compute block numbers in a more clean + (and confidently correct) fashion. + (diskfs_truncate): Set NP->allocsize from a properly rounded + value. + +Mon Sep 26 12:50:38 1994 Michael I Bushnell + + * inode.c (diskfs_lost_hardrefs): "Know" that a pager starts + with a portinfo; we don't actually have access to the pager + struct here. + +Fri Sep 23 14:21:55 1994 Michael I Bushnell + + [ Continuing yesterday's changes. ] + * ufs.h (struct dirty_indir): New type. + (struct disknode): New member `dirty'. + * inode.c (iget): Initialize DN->dirty. + * bmap.c (mark_indir_dirty): New function. + * pager.c (pager_unlock_page): Call mark_indir_dirty before + writing into indirect blocks. + (diskfs_file_update): Sync indirect blocks here. + (pager_traverse): Simplify; do FILE_DATA and diskpager. + (pager_init): Removed function. + (create_disk_pager): New function. + * sizes.c: Completely rewritten. + * main.c (main): Spawn first thread sooner so we can + map and look at the disk image. + * hyper.c (get_hypermetadata): Moved firewall asserts + here from pager_init. + +Thu Sep 22 11:28:46 1994 Michael I Bushnell + + [This long series of changes deletes the DINODE, CG, SINDIR, + and DINDIR pagers and adds a new pager type DISK.] + * ufs.h (struct disknode) Removed DINLOCK, SINLOCK, and + SININFO members. New member ALLOCPTRLOCK renamed from DATALOCK. + Removed SINLOC, DINLOC, SINLOCLEN, and DINLOCLEN. + (struct user_pager_info) [enum pager_type]: Removed types + DINODE, CG, SINDIR and DINDIR; added type DISK. + (dinpager, dinodepager, cgpager): Deleted vars. + (diskpager): New var. + (dinmaplock, sinmaplock, pagernplock): Deleted vars. + (sblock_dirty, csum_dirty, cgs, dinodes): Deleted vars. + (fsaddr): New macro. + (dino, indir_block, cg_locate): New inline functions. + (sync_disk_blocks, sync_dinode): New inline functions. + (struct iblock_spec): New type. + * pager.c (dinport, dinodeport, cgport, sinlist): Deleted vars. + (filepagerlist): Renamed from filelist. + (pagernplock): Deleted variable. + (find_address): Removed switch; support only DISK and FILE_DATA. + (pager_report_extent): Likewise. + (pager_unlock_page): Removed switch. Return without comment for + DISK; allocate indirect blocks as necessary right here for + FILE_DATA. + (sin_map, sin_remap, sin_unmap, din_map, din_unmap): Deleted + functions. + (indir_alloc, sync_dinode): Deleted functions. + (enqueue_pager, dequeue_pager): Deleted functions. + (diskfs_file_update): No longer lock pagernplock; nothing + to do with sininfo. + (drop_pager_softrefs): Likewise. + (allow_pager_softrefs): Likewise. + (diskfs_get_filemap): Put pager on filepagerlist right here + instead of through pager_enqueue. + (pager_clear_user_data): Likewise, mutatis mutandis. + * main.c (main): Call create_disk_pager and then map the + entire disk into disk_image. + * hyper.c (get_hypermetadata): Use bcopy instead of dev_read_sync. + (diskfs_set_hypermetadata): NOP out function. + (copy_sblock): New function, substance of code is from old + diskfs_set_hypermetadata. + * inode.c (iget): Don't initialize deleted disknode fields. + (diskfs_node_norefs): Don't verify that deleted disknode + fields are not set. + (read_disknode): Get dinode from DINO, not DINODES array. + (write_node): Likewise. + (create_symlink_hook): Likewise. + (read_symlink_hook): Likewise. + (diskfs_set_translator): Likewise. + (diskfs_get_translator): Likewise. + (diskfs_node_translated): Likewise. + * alloc.c (ffs_realloccg): Likewise. + (ffs_fragextend): Use cg_locate instead of cgs array. + (ffs_alloccg): Likewise. + (ffs_nodealloccg): Likewise. + (ffs_blkfree): Likewise. + (diskfs_free_node): Likewise. + * inode.c (diskfs_set_translator): Use bcopy and sync_disk_blocks + instead of dev_write_sync. + (diskfs_get_translator): Likewise, mutatis mutandis. + (read_disknode): Initialize NP->istranslated. + (diskfs_set_translator): Set/clear NP->istranslated as appropriate. + (diskfs_node_translated): Removed function. + * bmap.c: New file. + + [This improves the RWLOCK mechanism and makes it more + orthogonal. It should probably be moved into a library.] + * ufs.h (struct rwlock): Added MASTER and WAKEUP members. + (struct disknode): Removed RWLOCK_MASTER and RWLOCK_WAKEUP + fields. + (rwlock_reader_lock): Ommitted arg DN; use new MASTER and WAKEUP + members inside LOCK instead. + (rwlock_writer_lock): Likewise. + (rwlock_reader_unlock): Likewise. + (rwlock_init): Initialize new MASTER and WAKEUP fields. + * inode.c (iget): Don't deal with RWLOCK_MASTER and RWLOCK_WAKEUP. + * pager.c (find_address): Deleted arg DNP. Only pass one + arg to rwlock functions. + (pager_read_page): Deleted var DN; only pass one arg to rwlock + functions. + (pager_write_page): Likewise. + +Wed Sep 21 00:26:25 1994 Michael I Bushnell + + * pager.c (allow_pager_softrefs): Unlock PAGERNPLOCK when + we're done with it. + (sin_map): Hold PAGERNPLOCK all the way until we're done + with the sininfo pointer. + (pagernplock): No longer static. + * ufs.h (pagernplock): Declare here. + + * sizes.c (diskfs_grow): Don't call diskfs_file_update here. + This was done to prevent too much dirty data from accumulating + and then overwhelming the pager later. But that's really the + pager's responsibility. + + * ufs.h (struct disknode): New members `dinloclen' and `sinloclen'. + * inode.c (iget): Initialize DN->dinloclen and DN->sinloclen. + (diskfs_node_norefs): Verify that DN->dinloclen and DN->sinloclen + are both zero. + * pager.c (find_address) [SINDIR]: Verify that reference is + within bounds of NP->dn->dinloc. + (pager_unlock_page) [SINDIR]: Likewise. + (din_map): Set NP->dn->dinloclen. + (din_unmap): Clear NP->dn->dinloclen. + (find_address) [FILE_DATA]: Verify that reference is within + bounds of NP->dn->sinloc. + (pager_unlock_page) [FILE_DATE]: Likewise. + (sin_map): Set NP->dn->sinloclen. + (sin_remap): Reset NP->dn->sinloclen. + (sin_unmap): Clean NP->dn->sinloclen. + + * pager.c (pager_write_page): Flush stdout after printf. + (pager_unlock_page) [FILE_DATA]: Likewise. + + * sizes.c (diskfs_truncate): In all references to sinloc and + dinloc arrays, verify that references are within allocated bounds. + (diskfs_grow): Likewise. + (sindir_drop): Likewise. + + * pager.c: Create new mapping with extent NEWSIZE, not SIZE (which + was the old size of the mapping). + +Tue Sep 20 15:51:35 1994 Michael I Bushnell + + * pager.c (pager_report_extent) [SINDIR]: Remove erroneous extra + division by block size. + (sin_remap): Likewise. + +Mon Sep 19 17:34:11 1994 Michael I Bushnell + + * inode.c (create_symlink_hook): Write assert test correctly. + + * dir.c (diskfs_direnter) [EXTEND]: Reference file size only + *once*; don't rely on the behavior if diskfs_grow vis a vis + file size. + +Fri Sep 16 10:29:42 1994 Michael I Bushnell + + * dir.c (dirscanblock): Compute offset correctly for mangled + entry notice. + + * dir.c (diskfs_direnter) [EXTEND]: Reference file size only + once before calling diskfs_grow in case diskfs_grow actually + increases the size. + + * inode.c (diskfs_set_statfs): Set fsid from getpid. + (read_disknode): Likewise. + + * dir.h (struct directory_entry): Renamed from struct direct. + * dir.c: All uses of struct direct changed to use + struct directory_entry. + (diskfs_get_directs): New var `userp'. Copy from *ENTRYP into + it (set at DATAP) more cleanly. + +Mon Sep 12 11:30:48 1994 Michael I Bushnell + + * hyper.c (diskfs_set_hypermetadata): Don't frob clean and dirty + bits if we are readonly. + +Sat Sep 10 11:41:06 1994 Roland McGrath + + * main.c (main): When started up as a passive translator, + open fds 0, 1, and 2 on /dev/console for debugging messages. + Call diskfs_init_diskfs with no args; after warp_root, call + diskfs_startup_diskfs on BOOTSTRAP. Compare BOOTSTRAP to + MACH_PORT_NULL instead of zero. + +Fri Sep 9 13:02:33 1994 Michael I Bushnell + + * main.c (trans_parse_args): Fix and enable. + +Tue Sep 6 11:29:55 1994 Michael I Bushnell + + * inode.c (iget): Remove old assert test that checked for bad + inode block allocations. + +Thu Sep 1 11:39:12 1994 Michael I Bushnell + + * tables.c: Don't include "ufs.h"; include . Then + this file can be used unmodified by fsck. + +Tue Aug 30 13:36:37 1994 Michael I Bushnell + + * inode.c (diskfs_set_translator): ffs_blkfree doesn't have + a return value. + +Mon Aug 29 12:49:17 1994 Michael I Bushnell + + * inode.c (diskfs_set_translator): If NAMELEN is zero, then + make the node have no translator. + +Fri Aug 26 12:28:20 1994 Michael I Bushnell + + * inode.c (read_disknode): 4.4 fsck sometimes sets the author + field to -1 to mean "ignore old uid location"; take that to mean + "author == uid". + (diskfs_set_translator): If we are allocating a new block for + the translator, then account for it in st_blocks. + +Thu Aug 18 12:41:12 1994 Michael I Bushnell + + * Makefile (HURDLIBS): Use short version. + + * alloc.c (diskfs_alloc_node): Bother to set *NPP before + returning. + +Tue Aug 16 10:48:04 1994 Michael I Bushnell + + * Makefile (LDFLAGS): New variable. + +Fri Aug 5 15:51:09 1994 Michael I Bushnell + + * dir.c (diskfs_direnter) [EXTEND]: Crash if the entry won't + fit in the new block. + (diskfs_lookup): Return ENAMETOOLONG if the name is bigger than + MAXNAMLEN. + + * dir.c (diskfs_get_directs): Set USERD->d_reclen correctly. + +Fri Jul 22 15:12:35 1994 Michael I Bushnell + + * Makefile: Rewritten in accord with new scheme. + +Wed Jul 20 13:28:38 1994 Michael I Bushnell + + * main.c (main): Don't set diskfs_dotdot_file. + +Tue Jul 19 21:51:54 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * ufs.h: Removed defns of u_quad_t, quad_t; now in . + Removed defn of struct timespec; now in . + +Tue Jul 19 12:47:31 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * main.c (main): Deleted var `diskfs_dotdot_file'. + (trans_parse_args): Don't set diskfs_dotdot_file; don't expect + dotdot from fsys_getroot. + + * Makefile (LDFLAGS): Moved to rule for `ufs' and commented out. + (ufs): Don't use variable $(link) anymore. + +Mon Jul 18 14:55:17 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dir.c (diskfs_get_directs): Return data to user in old format. + Add new code for new format, maintaining compatibility correctly, + but comment it out until the library is ready. + + * hyper.c (diskfs_set_hypermetadata): If we presumed to + set new values of fs_maxfilesize, fs_qbmask, and fs_qfmask, + then restore the originals before writing out the superblock. + + * pager.c (diskfs_get_filemap): Test should be S_ISLNK, not + S_ISSOCK. + + * hyper.c (get_hypermetadata): Set new constants in filesystems + which don't have them yet. + (get_hypermetadata): Cast MAXSYMLINKLEN to long to avoid + converting sblock->fs_maxsymlinklen into an unsigned. + + * subr.c (scanc, skipc): New functions. + (ffs_setblock): Use assert instead of panic. + + * inode.c (read_disknode): Set old stat structure until the header + file gets changed. + +Fri Jul 15 12:07:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * sizes.c: Include for bzero. + * fs.h (blksize): Comment out dblksize macro. In blksize + macro, use NP->allocsize instead of IP->i_size. + + * dinode.h (INDIR_SINGLE, INDIR_DOUBLE, INDIR_TRIPLE): New macros. + + * inode.c (read_disknode, write_node): Use new stat and dinode + fields for times. + + * ufs.h: Change `nextgennumber' to be `u_long' instead of int. + Change prototypes of some alloc.c functions. + * alloc.c (ffs_alloc): Declare to return error_t. + (ffs_realloccg): Likewise. + (ffs_hashalloc, ffs_alloccg, ffs_fragextend, ffs_alloccg, + ffs_dirpref, ffs_nodealloccg, ffs_allccgblk, ffs_mapsearch, + ffs_clusteracct): Provide forward declarations. + (ffs_realloccg): Use printf instead of log. + Make BPREF volatile for setjmp safety. + (diskfs_alloc_node): Use diskfs global variable instead of TIME. + (ffs_nodealloccg): Likewise. + (ffs_blkfree): Likewise. + (diskfs_free_node): Likewise. + (ffs_blkfree, ffs_clusteracct): Declare as void. + (ffs_alloccg, ffs_nodealloccg): Declare as u_long. + + * ufs.h: Change prototypes of some subr.c functions. + * subr.c (ffs_isblock): Use assert instead of panic. + (ffs_clrblock): Likewise. + + * hyper.c: Include "dinode.h". + + * dinode.h (LINK_MAX): New macro, from BSD sys/sys/syslimits.h. + * fs.h (MAXBSIZE, MAXFRAG): New macros, from BSD sys/sys/param.h. + + * hyper.c (get_hypermetadata): Provide first arg in call to + fsbtodb. + (diskfs_set_hypermetadata): Likewise. + * inode.c (diskfs_set_translator): Likewise. + (diskfs_get_translator): Likewise. + * pager.c (find_address): Likewise. + (indir_alloc): Likewise. + * inode.c (iget): Provide first arg in call to lblkno. + * sizes.c (diskfs_truncate): Likewise. + * pager.c (find_address): Likewise. + * sizes.c (diskfs_grow): Likewise. + * inode.c (iget): Provide first arg in call to fragroundup. + * sizes.c (diskfs_trucate): Likewise. + * sizes.c (diskfs_grow): Likewise. + * inode.c (iget): Provide first arg in call to blkroundup. + * pager.c (pager_unlock_page): Likewise. + * sizes.c (diskfs_truncate): Likewise. + * sizes.c (diskfs_grow): Likewise. + * pager.c (find_address): Provide first arg in call to cgtod. + * pager.c (find_address): Provide first arg in call to cgimin. + * pager.c (find_address): Provide first arg in call to blktofrags. + * pager.c (find_address): Provide first arg in call to blkoff. + * sizes.c (diskfs_truncate): Likewise. + * sizes.c (diskfs_grow): Likewise. + * sizes.c (diskfs_truncate): Provide first arg in call to blksize. + * sizes.c (diskfs_grow): Likewise. + * sizes.c (diskfs_truncate): Provide first arg in call to numfrags. + + * ufs.h: Added temporary declarations of `u_quad_t', `quad_t', and + `struct timespec'. + + * pager.c (diskfs_get_filemap): Make sure that this is + a kind of node that can be validly read. + + * inode.c (create_symlink_hook): Renamed from symlink_hook. + (read_symlink_hook): New function. + (diskfs_read_symlink_hook): Initialize. + +Thu Jul 14 12:23:45 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * alloc.c: New from 4.4 BSD; BSD version `8.8 2/21/94'. + Remove old includes; include "ufs.h", "fs.h", "dinode.h", + and . Replace panics with asserts and comment out + uprintfs. Use prototypes throughout. Replace calls + to ffs_fserr with printf. + (alloclock): New variable. + (ffs_alloc): Variable struct inode *IP is now struct node *NP; + refer to it appropriately. Initialize FS to sblock. + Lock alloclock around actual allocation steps. Reverse order + of BNP and CRED arguments; declare CRED as a protid and use + accordingly. Permit CRED to be null. + (ffs_realloccg): Variable struct inode *IP is now struct node *NP; + refer to it accordingly. Comment out U*x buffer management code. + Lock alloclock around actual allocation steps. Initialize FS + from sblock. Declare CRED as a protid and use it accordingly. + Change BUF arg to PBN (physical block number); return new block + there. + (ffs_reallocblks): Comment out. + (diskfs_alloc_node): Renamed from ialloc. Initialize FS from + sblock. Use calling sequence from . Acquire + alloclock aroud actual allocation steps. Deleted vars + `pip', `pvp' (use dir instead). Use iget instead of VFS_VGET. + Var struct inode *IP now struct node *NP. Lock gennumberlock + around frobbing of nextgennumber. + (ffs_blkpref): Arg struct inode *ip is now struct node *np; + refer to it accordingly. Initialize FS to sblock. Lock + alloclock during actual work. Use csum instead of fs_cs macro. + (ffs_hashalloc): Arg struct inode *IP is now struct node *NP; + use it accordingly. Initialize FS from sblock. + (ffs_fragextend): Arg struct inode *IP is now struct node *NP; + use it accordingly. Initialize FS from sblock. Initialize + CGP from cgs array; don't use bread. Comment out calls to brelse + and bdwrite. Set CGP->time from diskfs global var. Use csum + instead of fs_cs macro. + (ffs_alloccg): Arg struct inode *IP is now struct node *NP. + Initialize FS from sblock. Initialize CGP from cgs array; + don't use bread. Comment out calls to brelse and bdwrite. + Set CGP->time from diskfs global var. Use csum instead of + fs_cs macro. + (ffs_nodealloccg): Arg struct inode *IP is now struct node *NP. + Initialize FS from sblock. Initialize CGP from cgs array; + don't use bread. Comment out calls to brelse and bdwrite. Use + csum instead of fs_cs macro. + (ffs_blkfree): Arg struct inode *IP is now struct node *NP. + Initialize FS from sblock. Initialize CGP from cgs array; + don't use bread. Comment out calls to brelse and bdwrite. Use + csum instead of fs_cs macro. + (diskfs_free_node): Renamed from ffs_vfree. Use calling + sequence from . Initialize FS from sblock. + Deleted vars pip,pvp (use NP instead). Initialize CGP from + cgs array; don't use bread. Comment out calls to brelse and + bdwrite. Use csum instead of fs_cs macro. + (ffs_fserr): Commented out. + (ffs_dirpref): Use csum instead of fs_cs macro. + + * ufs.h (ffs_alloc): Renamed from alloc; all callers changed. + (ffs_blkfree): New arg NP; renamed from blkfree; all callers changed. + (ffs_blkpref): Renamed from blkpref; all callers changed. + (ffs_realloocg): Rename from realloccg; all callers changed. + + * fs.h: New from 4.4 BSD; BSD version `8.7 4/19/94'. + (fs_cs): Don't use fs_csp; use global csum instead. + + * subr.c: New from 4.4 BSD; BSD version `8.2 9/21/93'. + Remove old includes. Include "ufs.h" and "fs.h". + (ffs_blkatoff, ffs_checkoverlap): Comment out. + + * tables.c: New from 4.4 BSD; BSD version `8.1 6/11/93'. + Don't include ; do include "ufs.h" and "fs.h". + + * dinode.h: New from 4.4 BSD; BSD version `8.3 1/21/94'. + Remove oldids/inum union; replace with author. + Renamed di_mode to be di_model; allocated di_modeh from spare. + Allocate di_trans from spare. + (di_inumber): Remove macro. + * inode.c (read_disknode): Fetch uid and gid from new (long) + fields in dinode unless we are the old inode format, in which + case fetch them from the old fields. + (write_node): Only set new uid and gid fields if we are not + COMPAT_BSD4. Set old fields if the superblock says to. + (symlink_hook): New function. + (diskfs_create_symlink_hook): Initialize. + * sizes.c (diskfs_truncate): Deal with truncation of short + symlink properly. + + * dir.h: New from 4.4 BSD; BSD version `8.2 1/21/94'. + Substitute our version of DIRSIZ which uses the namelen. + Comment out declarations of struct dirtemplate and struct + odirtemplate. + (DIRECT_TYPE, DIRECT_NAMLEN): New macros. + * ufs.h (direct_symlink_extension): New variable. + * hyper.c (get_hypermetadata): Set direct_symlink_extension. + * dir.c (dirscanblock): Use DIRECT_NAMLEN instead of d_namlen. + (diskfs_direnter): Likewise. + (diskfs_dirempty): Likewise. + (diskfs_get_directs): Likewise. + (diskfs_direnter): Set d_type field of new slot if + direct_symlink_extension is set. + (diskfs_dirrewrite): Likewise. + + * ufs.h (compat_mode): New variable. + * main.c (main): Set compat_mode to zero if we are the bootstrap + filesystem. + * inode.c (diskfs_set_translator): Return error if compat_mode + is set. + (write_node): Don't set GNU dinode field extensions unless + compat_mode is COMPAT_GNU. + +Mon Jul 11 18:14:26 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dir.c (diskfs_get_directs): When copying entries into DATAP, + set the d_reclen parameter of the copy to the minimum length + (because that's all we use) rather than the size that it had + in the directory itself. + +Wed Jul 6 14:41:48 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dir.c (dirscanblock): In main loop, initialize PREVOFF + to zero, not BLOCKADDR. Otherwise, the wrong value is + stored into DS->prevoff and then diskfs_dirremove crashes. + +Tue Jul 5 14:07:38 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dinode.h: Include before test of BYTE_ORDER. + + * Makefile (TAGSLIBS): New variable. + +Tue Jun 21 13:45:04 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dir.c (diskfs_direnter): Update dirents of DP, not NP. + +Mon Jun 20 16:43:48 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * dir.c (diskfs_direnter) [case SHRINK]: NEW should be set to + OLDNEEDED past DS->entry, not to the start of the next entry. + + * dir.c (diskfs_direnter) [case EXTEND]: Cast in assignment + to NEW needs proper scope. + + * inode.c (diskfs_node_norefs): Free dirents list of structure + being deallocated. Also add assert checks to make sure other + state is already clean. + +Thu Jun 16 11:38:17 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * dir.c (diskfs_dirempty): Map directory contents ourselves + instead of using diskfs_node_rdwr. + (struct dirstat): New structure to cache mapping between + lookup and commit operation and avoid use of diskfs_node_rdwr. + (diskfs_lookup): Map directory ourselves. Keep mapping in + DS if DS is nonzero and we might use it in direnter, dirremove, + or dirrewrite. Deallocate mapped buffer if we return some + error (other than ENOENT), or if DS is zero, or if there is + no possible commit operation to follow. When setting DS->stat + to EXTEND, do it the new way. + (dirscanblock): Changed BLKOFF to be virtual address of mapped + block and renamed it BLKADDR. New arg IDX. Use mapped block + instead of calling diskfs_node_rdwr. Set DS according to the new + rules. + (diskfs_direnter): Interpret new dirstat format. + (diskfs_dirremove): Likewise. + (diskfs_dirrewrite): Likewise. + (diskfs_drop_dirstat): Deallocate cached mapping here. + + * dir.c (dirscanblock): When we find the node for type CREATE, + invalidate DS by setting type to LOOKUP, not LOOKING. + + * dir.c (diskfs_direnter, diskfs_dirremove, diskfs_dirrewrite): + Call diskfs_notice_dirchange when appropriate. + + * dir.c (diskfs_get_directs): Deal properly with case where + BUFSIZ==0 and where NENTRIES==-1. + +Wed Jun 15 16:40:12 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * main.c (main): Check device sector size and media size + on startup. + +Tue Jun 14 14:41:17 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * ufs.h (struct disknode) [dirents]: New member. + * inode.c (iget): Initialize DN->dirents. + * dir.c (diskfs_direnter, diskfs_dirremove): Keep track + of dirents member. + (dirscanblock): New var `nentries'; use it to count the + number of directory entries in this block and set it if + we end up scanning the entire block. + (count_dirents): New function. + (diskfs_get_directs): New function. + +Mon Jun 13 13:50:00 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * ufs.h (sinmaplock, dinmaplock): New global vars. + * inode.c (inode_init): Initialize sinmaplock and dinmaplock. + * pager.c (find_address, pager_unlock_page): Protect use + if dinloc array with dinmaplock. + (din_map, din_unmap): Doc fix. + (find_address, pager_unlock_page): Protect use of sinloc array + with sinmaplock. + (sin_map, sin_remap, sin_unmap): Doc fix. + (pager_clear_user_data): Acquire sinmaplock and dinmaplock + instead of NP->dn->datalock and NP->dn->sinlock respectively. + + * sizes.c (diskfs_truncate, diskfs_grow): Protect use of sinloc + and sindir mapping functions with sinmaplock. + (sindir_drop): Protect use of dinloc and dindir mapping functions + with dinmaplock. + + * ufs.h (struct rwlock): New type. + (struct disknode) [dinlock, sinlock, datalock]: Use read-write lock. + Change comments so that these don't lock dinloc and sinloc anymore. + [rwlock_master, rwlock_wakeup]: New members. + (rwlock_reader_lock, rwlock_writer_lock, rwlock_reader_unlock, + rwlock_writer_unlock, rwlock_init): New functions. + * inode.c (iget): Initialize DN->rwlock_master and + DN->rwlock_wakeup. Change initialization of DN->dinlock, + DN->sinlock, and DN->datalock to use rwlock_init. + * pager.c (find_address): Lock NP->dn->dinlock, NP->dn->sinlock, + and NP->dn->datalock with rwlock_reader_lock. Change type of + parameter NPLOCK to be a read-write lock. New parm DNP. Callers + changed. + (pager_read_page, pager_write_page): Change type of NPLOCK to be + read-write lock; call rwlock_reader_unlock instead of + mutex_unlock. New variable DN. + (pager_unlock_page): Use rwlock_writer_lock to lock + NP->dn->dinlock, NP->dn->sinlock, and NP->dn->datalock. + * sizes.c (diskfs_truncate, diskfs_grow): Change locks of DATALOCK + field to use rwlock_writer_{un,}lock. + (sindir_drop): Ditto for SINLOCK field. + (dindir_drop): Ditto for DINLOCK field. + +Mon Jun 6 19:23:26 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * sizes.c (diskfs_grow): After realloccg, zero new data (which I'm + not sure is really necessary, but until I figure it out, this is + safest). Also poke old data (the latter only if the block has + moved)--otherwise the kernel won't know to page it out to the new + location. + (poke_pages): When poking, be careful not to actually change the data. + LEN should be end - start, not start - end. + +Fri Jun 3 12:37:27 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * inode.c (iget): When we find the node in the table, acquire the + mutex *after* incrementing NP->references and unlocking + diskfs_node_refcnt_lock; otherwise we can deadlock against + diskfs_nput. + +Thu Jun 2 12:16:09 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * ufs.h (sblock_dirty, csum_dirty, alloclock): New global variables. + * alloc.c (alloclock): Remove static keyword.. + * alloc.c (realloccg): Set sblock_dirty after changing sblock. + (blkpref): Likewise. + (fragextend): Likewise. + (alloccg): Likewise. + (alloccgblk): Likewise. + (ialloccg): Likewise. + (blkfree): Likewise. + (diskfs_free_node): Likewise. + * hyper.c (diskfs_set_hypermetadata): Likewise. + * alloc.c (fragextend): Set csum_dirty after changi csum. + (alloccg): Likewise. + (alloccgblk): Likewise. + (ialloccg): Likewise. + (blkfree): Likewise. + (diskfs_free_node): Likewise. + * hyper.c (diskfs_set_hypermetadata): Acquire alloclock while + writing hypermetadata. Only write csum and sblock if + csum_dirty or sblock_dirty, respectively, is set, and then + clear it after starting the write. + + * main.c (main): Likewise. + + * sizes.c (diskfs_truncate): Don't turn off caching; the new + light reference system takes care of this. + * pager.c (diskfs_get_filemap): No longer necessary to turn + on caching here, because truncate no longer turns it off. + + * inode.c (diskfs_lost_hardrefs, diskfs_new_hardrefs): New functions. + * pager.c (drop_pager_softrefs, allow_pager_softrefs): New functions. + (sin_map): Use diskfs_nref_light, not diskfs_nref. + (diskfs_get_filemap): Use diskfs_nref_light, not diskfs_nref. + (pager_clear_user_data): Use diskfs_nrele_light, not diskfs_nrele. + * ufs.h (drop_pager_softrefs, allow_pager_softrefs): New + declarations. + +Wed Jun 1 13:35:11 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * sizes.c (diskfs_truncate): After calling sin_unmap, turn + off caching on the sininfo pager so that it gets freed promptly + (there's generally no value in keeping it around because there + is no live fileinfo pager). + * pager.c (diskfs_get_filemap): Make sure we turn caching back on + here, however, if we start using the file pager. + + * pager.c (sin_map): When np->dn->sininfo is set, we have + to insert a valid send right after fetching the receive name. + + * pager.c (sin_unmap, din_unmap): New functions. + (pager_clear_user_data): Call sin_unmap and din_unmap + instead of doing it right here. + + * sizes.c (diskfs_truncate): Call sin_unmap instead of + doing it right here. + (sindir_drop): Call din_unmap instead of doing it right + here. Also, call it always, not just when wo do dindir_drop. + + * sizes.c (diskfs_grow): After alloc into sindir area, + unmap it if we don't have an active data pager. + * ufs.h (sin_unmap, din_unmap): New declarations. + + * sizes.c (diskfs_grow): In computing OSIZE in the realloc + case of lbn < NDADDR, deal correctly with the case where + np->allocsize is already an integral number of blocks. + + * sizes.c (diskfs_grow): Compute SIZE correctly. + + * alloc.c (alloc, realloccg, blkfree): When checking validity + of size arguments, also make sure the size isn't zero. + + * alloc.c (diskfs_alloc_node): Lock ALLOCLOCK before checking + sblock->fs_cstotal.cs_nifree. + +Tue May 31 18:47:42 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * ufs.h (DONT_CACHE_MEMORY_OBJECTS): Define it. + + * dir.c (diskfs_direnter: case TAKE): Assert that OLD->d_reclen >= + NEEDED, not that it is strictly >. + +Tue May 31 11:10:28 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * sizes.c (diskfs_grow): Call diskfs_node_update (but don't wait) + after successful completion to prevent old data from hanging around + too long and getting flushed all at once from the kernel. + + * sizes.c (diskfs_grow): Change SIZE to be the size of the last + block allocated. Delete variable NSIZE; use SIZE instead. + +Fri May 27 13:15:26 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * sizes.c (diskfs_truncate): Set NP->dn_stat_dirty after each + modification of NP->dn_stat. + + * sizes.c (diskfs_truncate): Compute new value of NP->allocsize + correctly. + + * inode.c (iget): Set NP->allocsize to be the *actual* allocsize. + +Thu May 26 11:51:45 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * sizes.c (diskfs_truncate): In blkfree loop of blocks past + NDADDR, subtract NDADDR from idx to index correctly into + sinloc array. Start this loop with idx not less than NDADDR. + (diskfs_truncate): If olastblock == NDADDR, then we also + need to truncate blocks (one) mapped by single indirect blocks. + (diskfs_truncate): New variable `first2free'. Use in place + of older losing calculations involving lastblock. + (sindir_drop): Rename parameters to be FIRST and LAST. Change + interpretation of FIRST by one to correspond with changed call + in diskfs_truncate. + + * pager.c (sin_remap): When computing NEWSIZE, round up to + a page boundary, thus mimicing the SINDIR computation in + pager_report_extent properly. + + * pager.c (pager_unlock_page) [case SINDIR; vblkno == 0]: Read + from ....di_ib[INDIR_SINGLE] rather than invalid data before + NP->dn->dinloc. + + * alloc.c (alloc) [nospace]: Unlock alloclock. + (realloccg): Unlock alloclock before jumping to nospace. + (blkpref) [!(lbn < NDADDR)]: Unlock alloclock before returning + success. + + * sizes.c (diskfs_grow): When allocing a block past NDADDR, the + tbl arg to blkpref is the table of direct block pointers + NP->dn->sinloc, not the table of indirect block pointers + ...->di_ib. + + * sizes.c (diskfs_grow): When writing into the SINDIR area, call + sin_map instead of sin_remap if the sindir isn't already mapped. + Also set np->allocsize *before* calling sin_map, but *after* + calling sin_remap, to meet the requirements of those separate + routines. + + * sizes.c (diskfs_grow): If END isn't bigger than NP->allocsize, + then don't try and do anything. In computation of LBN and the + first use of NB, round up to block boundary correctly. Don't + attempt to realloc an old block if the size is 0 (in which case + NB is -1 and unsigned comparison rules might foul things up). + +Mon May 23 13:18:33 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * Makefile (ufs): Give -n in the proper order to rsh. + + * main.c: Include . + + * ufs.h (DONT_CACHE_MEMORY_OBJECTS): New compilation flag. + * pager.c (pager_report_attributes): Deleted function. + (MAY_CACHE): New macro; more useful form for using + DONT_CACHE_MEMORY_OBJECTS. + (sin_map, pager_init, diskfs_get_filemap): Provide new + args in calls to pager_create. + * sizes.c (MAY_CACHE): New macro; more useful form for + using DONT_CACHE_MEMORY_OBJECTS. + (diskfs_truncate): Use MAY_CACHE in calls to pager_change_attributes. + +Fri May 20 18:52:41 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * sizes.c (diskfs_truncate): Force any delayed copies of the + vanishing region to be taken immediately before stopping, and + prevent any new delayed copies from being made until we are done + manipulating things. + (poke_pages): New function. + * pager.c (pager_report_attributes): New function. + +Wed May 18 15:51:40 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * alloc.c (alloc, realloccg, diskfs_alloc_node, alloccgblk, + blkfree, diskfs_free_node, mapsearch): Added helpful strings to + asserts. + (realloccg): Split up assert. + +Tue May 17 13:26:22 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * main.c (main): Delete unused variable PROC. + +Mon May 16 15:32:07 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * alloc.c (realloccg): When fragextend succeeds, bother to set + *PBN. + + * sizes.c (diskfs_grow): In fragment growth case, NSIZE should + not be the amount to hold SIZE (SIZE is the amount the file is + growing by), but rather the old size of the fragment plus the + SIZE. + + * dir.c (diskfs_direnter case COMPRESS): Rewrite loop to deal + properly with the case where from and to overlap. + +Mon May 9 16:51:44 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * main.c (ufs_version): New variable. + (save_argv): New variable. + (main): Set save_argv. + (diskfs_init_completed): New function. + +Thu May 5 19:06:54 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * Makefile (exec_server_image.o): Use -n when calling rsh. + +Thu May 5 07:39:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Makefile ($(OBJS)): Use $(includedir) instead of $(headers) in deps. + -- cgit v1.2.3