diff options
52 files changed, 1 insertions, 18155 deletions
diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile deleted file mode 100644 index 4e237e98..00000000 --- a/bsdfsck/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (C) 1994, 1995, 2012 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. - -dir := bsdfsck -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 tables.o # preen.o -target = bsdfsck - -vpath tables.c ../ufs - -include ../Makeconf - diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c deleted file mode 100644 index e63473ae..00000000 --- a/bsdfsck/dir.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.5 1994/11/04 21:54:56 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -char *lfname = "lost+found"; -int lfmode = 01777; -struct dirtemplate emptydir = { 0, DIRBLKSIZ }; -struct dirtemplate dirhead = { - 0, 12, DT_DIR, 1, ".", - 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." -}; -struct odirtemplate odirhead = { - 0, 12, 1, ".", - 0, DIRBLKSIZ - 12, 2, ".." -}; - -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; - 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); -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt) { - type = dp->d_namlen; - namlen = dp->d_type; - } else { - namlen = dp->d_namlen; - type = dp->d_type; - } -# else - namlen = dp->d_namlen; - type = dp->d_type; -# endif - if (dp->d_reclen < size || - idesc->id_filesize < size || - namlen > MAXNAMLEN || - type > 15) - 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) - 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", - (DI_MODE(dp) & 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 : - ((DI_MODE(dp) & 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 = (DI_MODE(dp) & 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 ((DI_MODE(dp) & 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/fsck.h b/bsdfsck/fsck.h deleted file mode 100644 index 04bb7698..00000000 --- a/bsdfsck/fsck.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.10 1994/10/05 17:09:06 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 -#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 */ -}; - -/* 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) - -#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] - -#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)))) - -/* Don't include dirent.h lest we get confused, but we still want this. */ -#define IFTODT(mode) (((mode) & 0170000) >> 12) -#define DT_DIR IFTODT (IFDIR) - -/* missing macros */ - -/* Convert bytes to disk blocks */ -#define btodb(bytes) ((bytes) / DEV_BSIZE) - - - -/* 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 */ -#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 occurrences 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(); diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c deleted file mode 100644 index 7b48aef6..00000000 --- a/bsdfsck/inode.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.6 1994/10/05 17:05:30 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#ifndef SMALL -#include <pwd.h> -#endif -#include <stdlib.h> -#include <string.h> -#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 = DI_MODE(dp) & IFMT; - 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); - 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; - } - /* GNU Hurd extension. */ - if (dino.di_trans && idesc->id_type == ADDR) - { - idesc->id_blkno = dino.di_trans; - idesc->id_numfrags = sblock.fs_frag; - return (*idesc->id_func)(idesc); - } - 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, - (DI_MODE(dp) & 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", DI_MODE(dp)); - 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); - } -#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; - 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 deleted file mode 100644 index adf84f74..00000000 --- a/bsdfsck/main.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static 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.4 1994/08/26 18:06:30 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -/*#include <sys/mount.h> */ -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -/* #include <fstab.h> */ -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include "fsck.h" - -void catch(), catchquit(), voidquit(); -int returntosingle; - -/* GNU Hurd patch */ -#define blockcheck(a) (a) - -main(argc, argv) - int argc; - char *argv[]; -{ - int ch; - int ret, maxrun = 0; - extern int docheck(), checkfilesys(); - extern char *optarg; -/* extern char *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); - } - 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) - 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); -} - -#if 0 -/* - * 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); -} -#endif - -/* - * 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 0 - if (hotroot) - printf("** Root file system\n"); -#endif - 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 0 - 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); - } -#endif - return (0); -} diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c deleted file mode 100644 index 46b0e109..00000000 --- a/bsdfsck/pass1.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1.c,v 1.4 1994/10/05 16:53:12 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#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 = 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 || dp->di_trans) { - 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; -#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); - 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 (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; - 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 deleted file mode 100644 index f5aadc06..00000000 --- a/bsdfsck/pass1b.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1b.c,v 1.2 1994/08/23 20:01:24 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <string.h> -#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 deleted file mode 100644 index 184106c1..00000000 --- a/bsdfsck/pass2.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/ -static char *rcsid = "$Id: pass2.c,v 1.3 1994/08/24 15:11:56 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#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); -#if 0 - dp->di_mode &= ~IFMT; - dp->di_mode |= IFDIR; -#else - dp->di_model &= ~IFMT; - dp->di_model |= IFDIR; -#endif - 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)); -#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); - 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] = - (DI_MODE(dp) & 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 deleted file mode 100644 index 78fb6a96..00000000 --- a/bsdfsck/pass3.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass3.c,v 1.2 1994/08/23 20:02:13 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#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 deleted file mode 100644 index 449c96ab..00000000 --- a/bsdfsck/pass4.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass4.c,v 1.2 1994/08/23 20:02:28 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#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 deleted file mode 100644 index 11877f9d..00000000 --- a/bsdfsck/pass5.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/ -static char *rcsid = "$Id: pass5.c,v 1.3 1994/08/26 18:03:07 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <string.h> -#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; - 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/preen.c b/bsdfsck/preen.c deleted file mode 100644 index 5650f900..00000000 --- a/bsdfsck/preen.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*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 <sys/param.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <fstab.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> - -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; /* auxiliary 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); -} diff --git a/bsdfsck/setup.c b/bsdfsck/setup.c deleted file mode 100644 index f65ade47..00000000 --- a/bsdfsck/setup.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/ -static char *rcsid = "$Id: setup.c,v 1.3 1994/08/25 15:22:35 mib Exp $"; -#endif /* not lint */ - -#define DKTYPENAMES -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <sys/stat.h> -#include <sys/ioctl.h> -/* #include <sys/disklabel.h> */ -#include <sys/file.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#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 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 - */ - 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); -} - -/* 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 - * 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); -} -#endif diff --git a/bsdfsck/utilities.c b/bsdfsck/utilities.c deleted file mode 100644 index 1c281b1b..00000000 --- a/bsdfsck/utilities.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: utilities.c,v 1.2 1994/08/23 20:18:15 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "fsck.h" - -long diskreads, totalreads; /* Disk cache statistics */ - -ftypeok(dp) - struct dinode *dp; -{ - switch (DI_MODE(dp) & 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", DI_MODE(dp)); - 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 occurred. - * 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/libddekit/pgtab.c b/libddekit/pgtab.c index 81138108..64ac6af6 100644 --- a/libddekit/pgtab.c +++ b/libddekit/pgtab.c @@ -12,6 +12,7 @@ */ #include <unistd.h> +#include <stdlib.h> #include <error.h> #include <errno.h> #include <mach.h> diff --git a/ufs-fsck/Makefile b/ufs-fsck/Makefile deleted file mode 100644 index 03ce9cc7..00000000 --- a/ufs-fsck/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 1994, 1995, 1996, 2012 Free Software Foundation -# Written by Michael I. Bushnell. -# -# This file is part of the GNU Hurd. -# -# The GNU Hurd 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. -# -# The GNU Hurd 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. - -dir := ufs-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 -target = fsck.ufs -installationdir = $(sbindir) -HURDLIBS=shouldbeinlibc - -include ../Makeconf - -vpath tables.c $(top_srcdir)/ufs - diff --git a/ufs-fsck/dir.c b/ufs-fsck/dir.c deleted file mode 100644 index 85757b16..00000000 --- a/ufs-fsck/dir.c +++ /dev/null @@ -1,567 +0,0 @@ -/* Directory management subroutines - Copyright (C) 1994,96,99,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -/* This routine is used in pass 1 to initialize DIRARRAY and DIRSORTED. - Copy information from DP (for number NUMBER) into a newly allocated - dirinfo structure and add it to the arrays. */ -void -record_directory (struct dinode *dp, ino_t number) -{ - u_int blks; - struct dirinfo *dnp; - - blks = howmany (dp->di_size, sblock->fs_bsize); - if (blks > NDADDR) - blks = NDADDR + NIADDR; - blks *= sizeof (daddr_t); - dnp = malloc (sizeof (struct dirinfo) + blks); - - dnp->i_number = number; - dnp->i_parent = dnp->i_dotdot = 0; - dnp->i_isize = dp->di_size; - dnp->i_numblks = blks; - bcopy (dp->di_db, dnp->i_blks, blks); - - if (dirarrayused == dirarraysize) - { - if (dirarraysize == 0) - { - dirarraysize = 100; - dirarray = malloc (dirarraysize * sizeof (struct dirinfo *)); - dirsorted = malloc (dirarraysize * sizeof (struct dirinfo *)); - } - else - { - dirarraysize *= 2; - dirarray = realloc (dirarray, - dirarraysize * sizeof (struct dirinfo *)); - dirsorted = realloc (dirsorted, - dirarraysize * sizeof (struct dirinfo *)); - } - } - dirarray[dirarrayused] = dnp; - dirsorted[dirarrayused] = dnp; - dirarrayused++; -} - -/* Return the cached dirinfo structure for directory INO. */ -struct dirinfo * -lookup_directory (ino_t ino) -{ - int i; - - for (i = 0; i < dirarrayused; i++) - if (dirarray[i]->i_number == ino) - return dirarray[i]; - - errexit ("Cannot find cached directory I=%Ld\n", ino); -} - -/* Check to see if DIR is really a readable directory; if it - isn't, then bail with an appropriate message and return 0; - else return 1. MSG identifies the action contemplated */ -static int -validdir (ino_t dir, char *action) -{ - switch (inodestate[dir]) - { - case DIRECTORY: - case DIRECTORY|DIR_REF: - return 1; - - case UNALLOC: - warning (1, "CANNOT %s I=%Ld; NOT ALLOCATED", action, dir); - return 0; - - case BADDIR: - warning (1, "CANNOT %s I=%Ld; BAD BLOCKS", action, dir); - return 0; - - case REG: - warning (1, "CANNOT %s I=%Ld; NOT DIRECTORY", action, dir); - return 0; - - default: - errexit ("ILLEGAL STATE"); - } -} - -/* Search directory DIR for name NAME. If NAME is found, then - set *INO to the inode of the entry; otherwise clear INO. Returns 1 if all - was normal, or 0 if there was some error doing the search. */ -int -searchdir (ino_t dir, char *name, ino_t *ino) -{ - struct dinode dino; - int len; - - /* Scan through one directory block and see if it - contains NAME. */ - void - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return; - - if (dp->d_ino == 0 || dp->d_ino > maxino) - continue; - - if (DIRECT_NAMLEN (dp) == len && strcmp (dp->d_name, name) == 0) - { - *ino = dp->d_ino; - return; - } - } - } - - /* Read part of a directory and look to see if it contains - NAME. Return 1 if we should keep looking at more - blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - check1block (bufp); - if (*ino) - return 0; - } - return 1; - } - - *ino = 0; - - if (!validdir (dir, "READ")) - return 0; - - getinode (dir, &dino); - - len = strlen (name); - datablocks_iterate (&dino, checkdirblock); - - return 1; -} - -/* Change the existing entry in DIR for name NAME to be - inode INO. Return 1 if the entry was found and - replaced, else return 0. */ -int -changeino (ino_t dir, char *name, ino_t ino) -{ - struct dinode dino; - int len; - int madechange; - - /* Scan through a directory block looking for NAME; - if we find it then change the inode pointer to point - at INO and return 1; if we don't find it then return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return 0; - - if (dp->d_ino == 0 || dp->d_ino > maxino) - continue; - - if (DIRECT_NAMLEN (dp) == len && strcmp (dp->d_name, name) == 0) - { - dp->d_ino = ino; - madechange = 1; - return 1; - } - } - return 0; - } - - /* Read part of a directory and look to see if it - contains NAME. Return 1 if we should keep looking - at more blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - { - writeblock (fsbtodb (sblock, bno), buf, - nfrags * sblock->fs_fsize); - return 0; - } - } - return 1; - } - - if (!validdir (dir, "REWRITE")) - return 0; - - getinode (dir, &dino); - len = strlen (name); - madechange = 0; - datablocks_iterate (&dino, checkdirblock); - return madechange; -} - -/* Attempt to expand the size of a directory. Return - 1 if we succeeded. */ -static int -expanddir (struct dinode *dp) -{ - daddr_t lastbn, newblk; - char *cp, buf[sblock->fs_bsize]; - - lastbn = lblkno (sblock, dp->di_size); - if (blkoff (sblock, dp->di_size) && lastbn >= NDADDR - 1) - return 0; - else if (!blkoff (sblock, dp->di_size) && lastbn >= NDADDR) - return 0; - else if (blkoff (sblock, dp->di_size) && !dp->di_db[lastbn]) - return 0; - else if (!blkoff (sblock, dp->di_size) && dp->di_db[lastbn]) - return 0; - - newblk = allocblk (sblock->fs_frag); - if (!newblk) - return 0; - - if (blkoff (sblock, dp->di_size)) - dp->di_db[lastbn + 1] = dp->di_db[lastbn]; - dp->di_db[lastbn] = newblk; - dp->di_size += sblock->fs_bsize; - dp->di_blocks += sblock->fs_bsize / DEV_BSIZE; - - for (cp = buf; cp < buf + sblock->fs_bsize; cp += DIRBLKSIZ) - { - struct directory_entry *dir = (struct directory_entry *) cp; - dir->d_ino = 0; - dir->d_reclen = DIRBLKSIZ; - } - - writeblock (fsbtodb (sblock, newblk), buf, sblock->fs_bsize); - return 1; -} - -/* Add a new link into directory DIR with name NAME and target - INO. Return 1 if we succeeded and 0 if we failed. It is - an error to call this routine if NAME is already present - in DIR. */ -int -makeentry (ino_t dir, ino_t ino, char *name) -{ - int len; - struct dinode dino; - int needed; - int madeentry; - - /* Read a directory block and see if it contains room for the - new entry. If so, add it and return 1; otherwise return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return 0; - if (dp->d_ino - && dp->d_reclen - DIRSIZ (DIRECT_NAMLEN (dp)) >= needed) - { - struct directory_entry *newdp; - newdp = (struct directory_entry *) - ((void *)dp + DIRSIZ (DIRECT_NAMLEN (dp))); - - newdp->d_reclen = dp->d_reclen - DIRSIZ (DIRECT_NAMLEN (dp)); - DIRECT_NAMLEN (newdp) = len; - newdp->d_ino = ino; - if (direct_symlink_extension) - newdp->d_type = typemap[ino]; - bcopy (name, newdp->d_name, len + 1); - - dp->d_reclen -= newdp->d_reclen; - madeentry = 1; - return 1; - } - else if (!dp->d_ino && dp->d_reclen >= needed) - { - DIRECT_NAMLEN (dp) = len; - dp->d_ino = ino; - if (direct_symlink_extension) - dp->d_type = typemap[ino]; - bcopy (name, dp->d_name, len + 1); - madeentry = 1; - return 1; - } - } - return 0; - } - - /* Read part of a directory and look to see if it - contains NAME. Return 1 if we should keep looking - at more blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - { - writeblock (fsbtodb (sblock, bno), buf, - nfrags * sblock->fs_fsize); - return 0; - } - } - return 1; - } - - if (!validdir (dir, "MODIFY")) - return 0; - - getinode (dir, &dino); - len = strlen (name); - needed = DIRSIZ (len); - madeentry = 0; - datablocks_iterate (&dino, checkdirblock); - if (!madeentry) - { - /* Attempt to expand the directory. */ - problem (0, "NO SPACE LEFT IN DIR INO=%Ld", dir); - if (preen || reply ("EXPAND")) - { - if (expanddir (&dino)) - { - write_inode (ino, &dino); - datablocks_iterate (&dino, checkdirblock); - pfix ("EXPANDED"); - } - else - { - pfail (0); - warning (1, "CANNOT EXPAND DIRECTORY"); - } - } - } - return madeentry; -} - -/* Create a directory node whose parent is to be PARENT, whose inode - is REQUEST, and whose mode is to be MODE. If REQUEST is zero, then - allocate any inode. Initialze the contents of the - directory. Return the inode of the new directory. */ -ino_t -allocdir (ino_t parent, ino_t request, mode_t mode) -{ - ino_t ino; - - mode |= IFDIR; - - ino = allocino (request, mode); - if (!ino) - return 0; - if (!makeentry (ino, ino, ".")) - goto bad; - if (!makeentry (ino, parent, "..")) - goto bad; - - linkfound[ino]++; - linkfound[parent]++; - return ino; - - bad: - freeino (ino); - return 0; -} - -/* Link node INO into lost+found. If PARENT is positive then INO is - a directory, and PARENT is the number of `..' as found in INO. - If PARENT is zero then INO is a directory without any .. entry. - If the node could be linked, return 1; else return 0. */ -int -linkup (ino_t ino, ino_t parent) -{ - int search_failed; - struct dinode lfdino; - char *tempname; - ino_t foo; - - if (lfdir == 0) - { - if (!searchdir (ROOTINO, lfname, &lfdir)) - { - warning (1, "FAILURE SEARCHING FOR `%s'", lfname); - return 0; - } - if (lfdir == 0) - { - problem (0, "NO `%s' DIRECTORY", lfname); - if (preen || reply ("CREATE")) - { - lfdir = allocdir (ROOTINO, 0, lfmode); - if (lfdir != 0) - { - if (! makeentry (ROOTINO, lfdir, lfname)) - { - freeino (lfdir); - linkfound[ROOTINO]--; - lfdir = 0; - } - } - } - if (lfdir) - pfix ("CREATED"); - else - { - pfail (0); - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - } - } - - getinode (lfdir, &lfdino); - if ((lfdino.di_model & IFMT) != IFDIR) - { - ino_t oldlfdir; - - problem (1, "`%s' IS NOT A DIRECTORY", lfname); - if (! reply ("REALLOCATE")) - return 0; - - oldlfdir = lfdir; - - lfdir = allocdir (ROOTINO, 0, lfmode); - if (!lfdir) - { - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - if (!changeino (ROOTINO, lfname, lfdir)) - { - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - - /* One less link to the old one */ - linkfound[oldlfdir]--; - - getinode (lfdir, &lfdino); - } - - if (inodestate[lfdir] != DIRECTORY && inodestate[lfdir] != (DIRECTORY|DIR_REF)) - { - warning (1, "SORRY. `%s' DIRECTORY NOT ALLOCATED", lfname); - return 0; - } - - asprintf (&tempname, "#%Ld", ino); - search_failed = !searchdir (lfdir, tempname, &foo); - while (foo) - { - char *newname; - asprintf (&newname, "%sa", tempname); - free (tempname); - tempname = newname; - search_failed = !searchdir (lfdir, tempname, &foo); - } - if (search_failed) - { - warning (1, "FAILURE SEARCHING FOR `%s' IN `%s'", tempname, lfname); - free (tempname); - return 0; - } - if (!makeentry (lfdir, ino, tempname)) - { - free (tempname); - warning (1, "SORRY, NO SPACE IN `%s' DIRECTORY", lfname); - return 0; - } - free (tempname); - linkfound[ino]++; - - if (parent != -1) - { - /* Reset `..' in ino */ - if (parent) - { - if (!changeino (ino, "..", lfdir)) - { - warning (1, "CANNOT ADJUST `..' LINK I=%Ld", ino); - return 0; - } - /* Forget about link to old parent */ - linkfound[parent]--; - } - else if (!makeentry (ino, lfdir, "..")) - { - warning (1, "CANNOT CREAT `..' LINK I=%Ld", ino); - return 0; - } - - /* Account for link to lost+found; update inode directly - here to avoid confusing warning later. */ - linkfound[lfdir]++; - linkcount[lfdir]++; - lfdino.di_nlink++; - write_inode (lfdir, &lfdino); - - if (parent) - warning (0, "DIR I=%Ld CONNECTED; PARENT WAS I=%Ld", ino, parent); - else - warning (0, "DIR I=%Ld CONNECTED", ino); - } - return 1; -} diff --git a/ufs-fsck/fsck.h b/ufs-fsck/fsck.h deleted file mode 100644 index 4a5dabf5..00000000 --- a/ufs-fsck/fsck.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 1994,95,96,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include <sys/types.h> -#include <sys/time.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <dirent.h> - -#define swab_disk 0 - -#include "../ufs/fs.h" -#include "../ufs/dinode.h" -#include "../ufs/dir.h" - -/* Type of an inode */ -#define UNALLOC 0 -#define REG 1 -#define DIRECTORY 2 -#define BADDIR 3 - -/* Added to directories in pass 2 */ -#define DIR_REF 4 /* dir has been found in connectivity search */ - -/* State of each inode (set by pass 1) */ -char *inodestate; - -/* Number of links claimed by each inode (set by pass 1) */ -nlink_t *linkcount; - -/* Number of links found to each inode (set by pass 2) */ -nlink_t *linkfound; - -/* DT_foo type of each inode (set by pass 1) */ -char *typemap; - -/* Map of blocks allocated */ -char *blockmap; - -/* A string identifying what we're trying to check. */ -extern char *device_name; - - -/* Command line flags */ -int nowrite; /* all questions fail */ -int noquery; /* all questions succeed */ - - -enum contret -{ - RET_STOP, - RET_GOOD, - RET_BAD, -}; - - -/* One of these structures is set up for each directory by - pass 1 and used by passes 2 and 3. */ -struct dirinfo -{ - struct inoinfo *i_nexthash; /* next entry in hash chain */ - ino_t i_number; /* inode entry of this dir */ - ino_t i_parent; /* inode entry of parent */ - ino_t i_dotdot; /* inode number of `..' */ - ino_t i_dot; /* inode number of `.' */ - u_int i_isize; /* size of inode */ - u_int i_numblks; /* size of block array in bytes */ - daddr_t i_blks[0]; /* array of inode block addresses */ -}; - -/* Array of all the dirinfo structures in inode number order */ -struct dirinfo **dirarray; - -/* Array of all thi dirinfo structures sorted by their first - block address */ -struct dirinfo **dirsorted; - -int dirarrayused; /* number of directories */ -int dirarraysize; /* alloced size of dirarray/dirsorted */ - -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 */ - - -extern struct fs *sblock; - -extern daddr_t maxfsblock; -extern int maxino; -extern int direct_symlink_extension; - -extern int newinofmt; - -/* Terse automatic mode for noninteractive use; punts on severe problems. */ -extern int preen; - -extern int readfd, writefd; - -extern int fix_denied; - -extern int fsmodified; - -extern ino_t lfdir; - -/* Total number of files found on the partition. */ -extern long num_files; - -extern mode_t lfmode; -extern char *lfname; - -#define NBBY 8 -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY)) -#define DEV_BSIZE 512 - -#define setbmap(blkno) setbit (blockmap, blkno) -#define testbmap(blkno) isset (blockmap, blkno) -#define clrbmap(blkno) clrbit (blockmap, blkno) - -#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) - - - -int setup (char *); -void pass1 (), pass1b (), pass2 (), pass3 (), pass4 (), pass5 (); - -void readblock (daddr_t, void *, size_t); -void writeblock (daddr_t, void *, size_t); - -void getinode (ino_t, struct dinode *); -void write_inode (ino_t, struct dinode *); -void clear_inode (ino_t, struct dinode *); - -daddr_t allocblk (int); -int check_range (daddr_t, int); - -ino_t allocino (ino_t, mode_t); -void freeino (ino_t); -ino_t allocdir (ino_t, ino_t, mode_t); - -int makeentry (ino_t, ino_t, char *); -int changeino (ino_t, char *, ino_t); - -int linkup (ino_t, ino_t); - -void datablocks_iterate (struct dinode *, int (*)(daddr_t, int, off_t)); -void allblock_iterate (struct dinode *, int (*)(daddr_t, int, off_t)); - -void record_directory (struct dinode *, ino_t); -struct dirinfo *lookup_directory (ino_t); - -void errexit (char *, ...) __attribute__ ((format (printf, 1, 2), noreturn)); -void warning (int, char *, ...) __attribute__ ((format (printf, 2, 3))); -void problem (int, char *, ...) __attribute__ ((format (printf, 2, 3))); -void pinode (int, ino_t, char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -void pextend (char *, ...) __attribute__ ((format (printf, 1, 2))); -void pfix (char *fix), pfail (char *reason); -int reply (char *); diff --git a/ufs-fsck/inode.c b/ufs-fsck/inode.c deleted file mode 100644 index df4b880e..00000000 --- a/ufs-fsck/inode.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Inode allocation, deallocation, etc. - Copyright (C) 1994, 1996 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -static void -inode_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t), - int doaddrblocks) -{ - mode_t mode = dp->di_model & IFMT; - int nb, maxb; - off_t totaloffset = 0; - - /* Call FN for iblock IBLOCK of level LEVEL and recurse down - the indirect block pointers. */ - int - scaniblock (daddr_t iblock, int level) - { - int cont; - daddr_t ptrs[NINDIR(sblock)]; - int i; - - if (doaddrblocks) - { - cont = (*fn)(iblock, sblock->fs_frag, totaloffset); - if (cont == RET_STOP) - return RET_STOP; - else if (cont == RET_BAD) - return RET_GOOD; - } - - readblock (fsbtodb (sblock, iblock), ptrs, sblock->fs_bsize); - for (i = 0; i < NINDIR (sblock); i++) - { - if (!ptrs[i]) - continue; - - if (level == 0) - { - cont = (*fn)(ptrs[i], sblock->fs_frag, totaloffset); - totaloffset += sblock->fs_bsize; - } - else - cont = scaniblock (ptrs[i], level - 1); - if (cont == RET_STOP) - return RET_STOP; - } - return RET_GOOD; - } - - 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; - - maxb = lblkno (sblock, dp->di_size - 1); - totaloffset = 0; - for (nb = 0; nb < NDADDR; nb++) - { - int offset; - int nfrags; - - if (nb == maxb && (offset = blkoff (sblock, dp->di_size))) - nfrags = numfrags (sblock, fragroundup (sblock, offset)); - else - nfrags = sblock->fs_frag; - - if (dp->di_db[nb] - && (*fn)(dp->di_db[nb], nfrags, totaloffset) != RET_GOOD) - return; - totaloffset += nfrags * sizeof (sblock->fs_fsize); - } - - for (nb = 0; nb < NIADDR; nb++) - if (dp->di_ib[nb] && scaniblock (dp->di_ib[nb], nb) != RET_GOOD) - return; - - if (doaddrblocks && dp->di_trans) - (*fn)(dp->di_trans, sblock->fs_frag, totaloffset); -} - -void -datablocks_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t)) -{ - inode_iterate (dp, fn, 0); -} - -void -allblock_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t)) -{ - inode_iterate (dp, fn, 1); -} - -/* Allocate an inode. If INUM is nonzero, then allocate that - node specifically, otherwise allocate any available inode. - MODE is the mode of the new file. Return the allocated - inode number (or 0 if the allocation failed). */ -ino_t -allocino (ino_t request, mode_t mode) -{ - ino_t ino; - struct dinode dino; - struct timeval tv; - - if (request) - { - if (inodestate[request] != UNALLOC) - return 0; - ino = request; - } - else - { - for (ino = ROOTINO; ino < maxino; ino++) - if (inodestate[ino] == UNALLOC) - break; - if (ino == maxino) - return 0; - } - - if ((mode & IFMT) == IFDIR) - inodestate[ino] = DIRECTORY | DIR_REF; - else - inodestate[ino] = REG; - - getinode (ino, &dino); - dino.di_modeh = (mode & 0xffff0000) >> 16; - dino.di_model = (mode & 0x0000ffff); - gettimeofday (&tv, 0); - dino.di_atime.tv_sec = tv.tv_sec; - dino.di_atime.tv_nsec = tv.tv_usec * 1000; - dino.di_mtime = dino.di_ctime = dino.di_atime; - dino.di_size = 0; - dino.di_blocks = 0; - num_files++; - write_inode (ino, &dino); - typemap[ino] = IFTODT (mode); - return ino; -} - -/* Deallocate inode INUM. */ -void -freeino (ino_t inum) -{ - struct dinode dino; - - int - clearblock (daddr_t bno, int nfrags, off_t offset) - { - int i; - - for (i = 0; i < nfrags; i++) - { - if (check_range (bno + i, 1)) - return RET_BAD; - if (testbmap (bno + i)) - { - struct dups *dlp; - for (dlp = duplist; dlp; dlp = dlp->next) - { - if (dlp->dup != bno + i) - continue; - dlp->dup = duplist->dup; - dlp = duplist; - duplist = duplist->next; - free (dlp); - break; - } - if (dlp == 0) - clrbmap (bno + i); - } - } - return RET_GOOD; - } - - getinode (inum, &dino); - allblock_iterate (&dino, clearblock); - - clear_inode (inum, &dino); - inodestate[inum] = UNALLOC; - - num_files--; -} diff --git a/ufs-fsck/main.c b/ufs-fsck/main.c deleted file mode 100644 index 34c32a67..00000000 --- a/ufs-fsck/main.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Main program for GNU fsck - Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include <errno.h> -#include <argp.h> -#include <hurd.h> -#include <version.h> - -#include "fsck.h" - -const char *argp_program_version = STANDARD_HURD_VERSION (fsck.ufs); - -char *lfname = "lost+found"; -mode_t lfmode = 0755; - -/* Terse automatic mode for noninteractive use; punts on severe problems. */ -int preen = 0; - -/* Total number of files found on the partition. */ -long num_files = 0; - -static struct argp_option options[] = -{ - {"preen", 'p', 0, 0, "Terse automatic mode", 1}, - {"yes", 'y', 0, 0, "Automatically answer yes to all questions"}, - {"no", 'n', 0, 0, "Automatically answer no to all questions"}, - {"lost+found", 'l', "NAME", 0, "The name of the lost+found directory in /"}, - {"lf-mode", 'm', "MODE", 0, "The mode of the lost+found directory in /"}, - {0, 0, 0, 0, "In --preen mode, the following also apply:", 2}, - {"force", 'f', 0, 0, "Check even if clean"}, - {"silent", 's', 0, 0, "Only print diagostic messages"}, - {0, 0} -}; -char *args_doc = "DEVICE"; - -/* Returns a malloced buffer containing a nice printable size for FRAGS. */ -static char * -nice_size (long frags) -{ - char *rep; - char *units = "KMGT", *u = units; - float num = ((float)frags * sblock->fs_fsize) / 1024; - - while (num > 1024) - { - num /= 1024; - u++; - } - - asprintf (&rep, num >= 1000 ? "%.0f%c" : "%.3g%c", num, *u); - - return rep; -} - -/* Print summary statistics. */ -static void -show_stats () -{ - long num_ffree = sblock->fs_cstotal.cs_nffree; - long num_bfree = sblock->fs_cstotal.cs_nbfree; - long tot_ffree = num_ffree + sblock->fs_frag * num_bfree; - char *urep = nice_size (sblock->fs_dsize - tot_ffree); - char *frep = nice_size (tot_ffree); - warning (0, "%ld files, %s used, %s free (%ld.%ld%% fragmentation)", - num_files, urep, frep, - (num_ffree * 100) / sblock->fs_dsize, - (((num_ffree * 1000 + sblock->fs_dsize / 2) / sblock->fs_dsize) - % 10)); - free (urep); - free (frep); -} - -int -main (int argc, char **argv) -{ - int silent = 0, force = 0; - char *device = 0; - error_t parse_opt (int key, char *arg, struct argp_state *state) - { - switch (key) - { - case 'p': preen = 1; break; - case 'y': noquery = 1; break; - case 'n': nowrite = 1; break; - case 'l': lfname = arg; break; - case 'm': lfmode = strtol (arg, 0, 8); break; - case 'f': force = 1; break; - case 's': silent = 1; break; - case ARGP_KEY_ARG: - if (!device) - { - device = arg; - break; - } - /* Fall through */ - case ARGP_KEY_NO_ARGS: - argp_usage (state); - default: - return ARGP_ERR_UNKNOWN; - } - return 0; - } - struct argp argp = {options, parse_opt, args_doc}; - - preen = nowrite = noquery = 0; - argp_parse (&argp, argc, argv, 0, 0, 0); - - if (!setup (device)) - exit (1); - - if (preen && sblock->fs_clean && !force) - { - if (! silent) - warning (0, "FILESYSTEM CLEAN"); - } - else - { - if (!preen) - printf ("** Phase 1 -- Check Blocks and Sizes\n"); - pass1 (); - - if (duplist) - { - if (!preen) - printf ("** Phase 1b -- Rescan for More Duplicates\n"); - pass1b (); - } - - if (!preen) - printf ("** Phase 2 -- Check Pathnames\n"); - pass2 (); - - if (!preen) - printf ("** Phase 3 -- Check Connectivity\n"); - pass3 (); - - if (!preen) - printf ("** Phase 4 -- Check Reference Counts\n"); - pass4 (); - - if (!preen) - printf ("** Phase 5 -- Check Cyl Groups\n"); - pass5 (); - - if (! silent) - show_stats (sblock); - } - - if (fsmodified && !preen) - printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - - exit (fsmodified ? 2 : 0); -} diff --git a/ufs-fsck/pass1.c b/ufs-fsck/pass1.c deleted file mode 100644 index bd41cc62..00000000 --- a/ufs-fsck/pass1.c +++ /dev/null @@ -1,437 +0,0 @@ -/* Pass one of GNU fsck -- count blocks and verify inodes - Copyright (C) 1994,95,96,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - - - -#include "fsck.h" - -static struct dinode zino; - -/* Find all the blocks in use by files and filesystem reserved blocks. - Set them in the global block map. For each file, if a block is found - allocated twice, then record the block and inode in DUPLIST. - Initialize INODESTATE, LINKCOUNT, and TYPEMAP. */ -void -pass1 () -{ - ino_t number; - ino_t i; - int cg; - struct dinode dino; - struct dinode *dp = &dino; - mode_t mode, type; - int ndb; - int holdallblocks; - int lbn; - int nblocks; - int blkerror; - int nblkrngerrors; - int nblkduperrors; - - /* This function is called for each block of DP. Check to see - if the block number is valid. If so, set the entry in the - block map. If the block map entry is already set, then keep - track of this block and see if the user wants to clear the - node. Increment NBLOCKS by the number of data blocks held. - Set BLKERROR if this block is invalid. - Return RET_GOOD, RET_BAD, RET_STOP if the block is good, - bad, or if we should entirely stop checking blocks in this - inode. */ - int - checkblock (daddr_t bno, int nfrags, off_t offset) - { -#define MAXBAD 10 - int outofrange; - struct dups *dlp, *new; - int wasbad = 0; - - /* Check to see if this block is in range */ - outofrange = check_range (bno, nfrags); - if (outofrange) - { - blkerror = 1; - wasbad = 1; - if (nblkrngerrors == 0) - warning (0, "I=%Ld HAS BAD BLOCKS", number); - if (nblkrngerrors++ > MAXBAD) - { - problem (0, "EXCESSIVE BAD BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - } - - for (; nfrags > 0; bno++, nfrags--) - { - if (outofrange && check_range (bno, 1)) - warning (0, "BAD BLOCK %lu", bno); - else - { - if (!testbmap (bno)) - setbmap (bno); - else - { - blkerror = 1; - if (nblkduperrors == 0) - warning (0, "I=%Ld HAS DUPLICATE BLOCKS", number); - warning (0, "DUPLICATE BLOCK %ld", bno); - wasbad = 1; - if (nblkduperrors++ > MAXBAD) - { - problem (0, "EXCESSIVE DUP BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - new = malloc (sizeof (struct dups)); - new->dup = bno; - 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 == bno) - break; - if (dlp == muldup && dlp->dup != bno) - muldup = new; - } - } - nblocks += sblock->fs_fsize / DEV_BSIZE; - } - return wasbad ? RET_BAD : RET_GOOD; - } - - - /* Account for blocks used by meta data */ - for (cg = 0; cg < sblock->fs_ncg; cg++) - { - daddr_t firstdata, firstcgblock, bno; - - /* Each cylinder group past the first reserves data - from its cylinder group copy to (but not including) - the first datablock. - - The first, however, reserves from the very front of the - cylinder group (thus including the boot block), and it also - reserves the data blocks holding the csum information. */ - firstdata = cgdmin (sblock, cg); - if (cg == 0) - { - firstcgblock = cgbase (sblock, cg); - firstdata += howmany (sblock->fs_cssize, sblock->fs_fsize); - } - else - firstcgblock = cgsblock (sblock, cg); - - /* Mark the blocks set */ - for (bno = firstcgblock; bno < firstdata; bno++) - setbmap (bno); - } - - /* Loop through each inode, doing initial checks */ - for (number = 0, cg = 0; cg < sblock->fs_ncg; cg++) - for (i = 0; i < sblock->fs_ipg; i++, number++) - { - /* These record whether we've already complained about extra - direct/indirect blocks. */ - int dbwarn = 0, ibwarn = 0; - -/* if (!preen && !(number % 10000)) - printf ("I=%Ld\n", number); */ - - if (number < ROOTINO) - continue; - - getinode (number, dp); - mode = DI_MODE (dp); - type = mode & IFMT; - - /* If the node is not allocated, then make sure it's - properly clear */ - if (type == 0) - { - if (bcmp (dp->di_db, zino.di_db, NDADDR * sizeof (daddr_t)) - || bcmp (dp->di_ib, zino.di_ib, NIADDR * sizeof (daddr_t)) - || dp->di_trans - || DI_MODE (dp) - || dp->di_size) - { - problem (0, "PARTIALLY ALLOCATED INODE I=%Ld", number); - if (preen || reply ("CLEAR")) - { - clear_inode (number, dp); - pfix ("CLEARED"); - } - } - inodestate[number] = UNALLOC; - } - else - { - /* Node is allocated. */ - - /* Check to see if we think the node should be cleared */ - - /* Verify size for basic validity */ - holdallblocks = 0; - - if (dp->di_size + sblock->fs_bsize - 1 < dp->di_size) - { - problem (1, "OVERFLOW IN FILE SIZE I=%Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Decode type and set NDB - also set inodestate correctly. */ - inodestate[number] = REG; - switch (type) - { - case IFBLK: - case IFCHR: - ndb = 1; - break; - - case IFIFO: - case IFSOCK: - ndb = 0; - break; - - case IFLNK: - if (sblock->fs_maxsymlinklen != -1) - { - /* Check to see if this is a fastlink. The - old fast link format has fs_maxsymlinklen - of zero and di_blocks zero; the new format has - fs_maxsymlinklen set and we ignore di_blocks. - So check for either. */ - if ((sblock->fs_maxsymlinklen - && dp->di_size < sblock->fs_maxsymlinklen) - || (!sblock->fs_maxsymlinklen && !dp->di_blocks)) - { - /* Fake NDB value so that we will check - all the block pointers past the symlink */ - ndb = howmany (dp->di_size, sizeof (daddr_t)); - if (ndb > NDADDR) - { - int j = ndb - NDADDR; - for (ndb = 1; j > 1; i--) - ndb *= NINDIR (sblock); - ndb += NDADDR; - } - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - case IFDIR: - inodestate[number] = DIRECTORY; - /* Fall through */ - case IFREG: - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - default: - problem (1, "UNKNOWN FILE TYPE I=%Ld (MODE=%ol)", number, mode); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - holdallblocks = 1; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld " - "AS ALLOCATED", number); - ndb = 0; - } - - if (ndb < 0) - { - problem (1, "BAD FILE SIZE I= %Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Make sure that direct and indirect block pointers - past the file size are zero. If the size is bogus, then - don't bother (they should all be zero, but the user has - requested that they be treated as allocated). */ - if (!holdallblocks) - { - if (dp->di_size - && (type == IFBLK || type == IFCHR - || type == IFSOCK || type == IFIFO)) - { - problem (1, "SPECIAL NODE I=%Ld (MODE=%ol) HAS SIZE %lld", - number, mode, dp->di_size); - if (reply ("TRUNCATE")) - { - dp->di_size = 0; - write_inode (number, dp); - } - } - - /* If we haven't set NDB speciall above, then it is set from - the file size correctly by the size check. */ - - /* Check all the direct and indirect blocks that are past the - amount necessary to be zero. */ - for (lbn = ndb; lbn < NDADDR; lbn++) - { - if (dp->di_db[lbn]) - { - if (!dbwarn) - { - dbwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA DIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_db[lbn] = 0; - dbwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (dbwarn == 2) - dp->di_db[lbn] = 0; - } - if (dbwarn == 2) - write_inode (number, dp); - } - - for (lbn = 0, ndb -= NDADDR; ndb > 0; lbn++) - ndb /= NINDIR (sblock); - for (; lbn < NIADDR; lbn++) - { - if (dp->di_ib[lbn]) - { - if (ibwarn) - { - ibwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA INDIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_ib[lbn] = 0; - ibwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (ibwarn == 2) - dp->di_ib[lbn] = 0; - } - if (ibwarn == 2) - write_inode (number, dp); - } - } - - /* If this node is really allocated (as opposed to something - that we should clear but the user won't) then set LINKCOUNT - and TYPEMAP entries. */ - if (inodestate[number] != UNALLOC) - { - linkcount[number] = dp->di_nlink; - typemap[number] = IFTODT (mode); - } - - /* Iterate over the blocks of the file, - calling CHECKBLOCK for each file. */ - nblocks = 0; - blkerror = 0; - nblkduperrors = 0; - nblkrngerrors = 0; - allblock_iterate (dp, checkblock); - - if (blkerror) - { - if (preen) - warning (1, "DUPLICATE or BAD BLOCKS"); - else - { - problem (0, "I=%Ld has ", number); - if (nblkduperrors) - { - pextend ("%d DUPLICATE BLOCKS", nblkduperrors); - if (nblkrngerrors) - pextend (" and "); - } - if (nblkrngerrors) - pextend ("%d BAD BLOCKS", nblkrngerrors); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - else if (inodestate[number] == DIRECTORY) - inodestate[number] = BADDIR; - } - } - else if (dp->di_blocks != nblocks) - { - problem (0, "INCORRECT BLOCK COUNT I=%Ld (%ld should be %d)", - number, dp->di_blocks, nblocks); - if (preen || reply ("CORRECT")) - { - dp->di_blocks = nblocks; - write_inode (number, dp); - pfix ("CORRECTED"); - } - } - - num_files++; - - if (type == IFDIR) - record_directory (dp, number); - } - } -} diff --git a/ufs-fsck/pass1b.c b/ufs-fsck/pass1b.c deleted file mode 100644 index 4da86974..00000000 --- a/ufs-fsck/pass1b.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Pass 1b of fsck -- scan inodes for references to duplicate blocks - Copyright (C) 1994,96,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -void -pass1b () -{ - struct dinode dino; - struct dinode *dp = &dino; - int cg, i; - ino_t number = 0; - int dupblk; - struct dups *duphead = duplist; - - /* Check each block of file DP; if the block is in the dup block - list then add it to the dup block list under this file. - Return RET_GOOD or RET_BAD if the block is - good or bad, respectively. */ - int - checkblock (daddr_t bno, int nfrags, off_t offset) - { - struct dups *dlp; - int hadbad = 0; - - for (; nfrags > 0; bno++, nfrags--) - { - if (check_range (bno, 1)) - return RET_BAD; - for (dlp = duphead; dlp; dlp = dlp->next) - { - if (dlp->dup == bno) - { - dupblk++; - warning (0, "DUPLICATE BLOCK %ld\n", bno); - dlp->dup = duphead->dup; - duphead->dup = bno; - duphead = duphead->next; - hadbad = 1; - } - if (dlp == muldup) - break; - } - } - return hadbad ? RET_BAD : RET_GOOD; - } - - /* Call CHECKBLOCK for each block of each node, to see if it holds - a block already found to be a duplicate. */ - for (cg = 0; cg < sblock->fs_ncg; cg++) - for (i = 0; i < sblock->fs_ipg; i++, number++) - { - if (number < ROOTINO) - continue; - if (inodestate[number] != UNALLOC) - { - getinode (number, dp); - dupblk = 0; - allblock_iterate (dp, checkblock); - if (dupblk) - { - problem (1, "I=%Ld HAS %d DUPLICATE BLOCKS", number, dupblk); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - } - else if (inodestate[number] == DIRECTORY) - inodestate[number] = BADDIR; - } - } - } -} diff --git a/ufs-fsck/pass2.c b/ufs-fsck/pass2.c deleted file mode 100644 index d95929ef..00000000 --- a/ufs-fsck/pass2.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Pass 2 of GNU fsck -- examine all directories for validity - Copyright (C) 1994,96,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" -#include <assert.h> - -/* Verify root inode's allocation and check all directories for - viability. Set DIRSORTED array fully and check to make sure - each directory has a correct . and .. in it. */ -void -pass2 () -{ - int nd; - struct dirinfo *dnp; - struct dinode dino; - - /* Return negative, zero, or positive according to the - ordering of the first data block of **DNP1 and **DNP2. */ - int - sortfunc (const void *ptr1, const void *ptr2) - { - struct dirinfo * const *dnp1 = ptr1; - struct dirinfo * const *dnp2 = ptr2; - return ((*dnp1)->i_blks[0] - (*dnp2)->i_blks[0]); - } - - /* Called for each DIRBLKSIZ chunk of the directory. - BUF is the data of the directory block. Return - 1 if this block has been modified and should be written - to disk; otherwise return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - int mod = 0; - u_char namlen; - char type; - int i; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - /* Check RECLEN for basic validity */ - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - { - /* Perhaps the entire dir block is zero. UFS does that - when extending directories. So allow preening - to safely patch up all-null dir blocks. */ - if (dp == buf) - { - char *bp; - for (bp = (char *)buf; bp < (char *)buf + DIRBLKSIZ; bp++) - if (*bp) - goto reclen_problem; - - problem (0, "NULL BLOCK IN DIRECTORY"); - if (preen || reply ("PATCH")) - { - /* Mark this entry free, and return. */ - dp->d_ino = 0; - dp->d_reclen = DIRBLKSIZ; - pfix ("PATCHED"); - return 1; - } - else - return mod; - } - - reclen_problem: - problem (1, "BAD RECLEN IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Skip over everything else in this dirblock; - mark this entry free. */ - dp->d_ino = 0; - dp->d_reclen = DIRBLKSIZ - ((void *)dp - buf); - return 1; - } - else - /* But give up regardless */ - return mod; - } - - /* Check INO */ - if (dp->d_ino > maxino) - { - problem (1, "BAD INODE NUMBER IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - - if (!dp->d_ino) - continue; - - /* Check INO */ - if (inodestate[dp->d_ino] == UNALLOC) - { - pinode (0, dnp->i_number, "REF TO UNALLOCATED NODE IN"); - if (preen || reply ("REMOVE")) - { - dp->d_ino = 0; - mod = 1; - pfix ("REMOVED"); - continue; - } - } - - /* Check NAMLEN */ - namlen = DIRECT_NAMLEN (dp); - if (namlen > MAXNAMLEN) - { - problem (1, "BAD NAMLEN IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - else - { - /* Check for illegal characters */ - for (i = 0; i < DIRECT_NAMLEN (dp); i++) - if (dp->d_name[i] == '\0' || dp->d_name[i] == '/') - { - problem (1, "ILLEGAL CHARACTER IN FILE NAME"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - break; - } - } - if (dp->d_name[DIRECT_NAMLEN (dp)]) - { - problem (1, "DIRECTORY NAME NOT TERMINATED"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - } - - if (!dp->d_ino) - continue; - - /* Check TYPE */ - type = DIRECT_TYPE (dp); - if (type != DT_UNKNOWN && type != typemap[dp->d_ino]) - { - problem (0, "INCORRECT NODE TYPE IN DIRECTORY"); - if (preen || reply ("CLEAR")) - { - pfix ("CLEARED"); - dp->d_type = 0; - mod = 1; - } - } - - /* Here we should check for duplicate directory entries; - that's too much trouble right now. */ - - /* Account for the inode in the linkfound map */ - if (inodestate[dp->d_ino] != UNALLOC) - linkfound[dp->d_ino]++; - - if (inodestate[dp->d_ino] == DIRECTORY - || inodestate[dp->d_ino] == BADDIR) - { - if (DIRECT_NAMLEN (dp) == 1 && dp->d_name[0] == '.') - dnp->i_dot = dp->d_ino; - else if (DIRECT_NAMLEN (dp) == 2 - && dp->d_name[0] == '.' && dp->d_name[1] == '.') - dnp->i_dotdot = dp->d_ino; - else - { - struct dirinfo *targetdir; - targetdir = lookup_directory (dp->d_ino); - if (targetdir->i_parent) - { - problem (0, "EXTRANEOUS LINK `%s' TO DIR I=%ld", - dp->d_name, dp->d_ino); - pextend (" FOUND IN DIR I=%Ld", dnp->i_number); - if (preen || reply ("REMOVE")) - { - dp->d_ino = 0; - mod = 1; - pfix ("REMOVED"); - } - } - else - targetdir->i_parent = dnp->i_number; - } - } - } - return mod; - } - - /* Called for each filesystem block of the directory. Load BNO - into core and then call CHECK1BLOCK for each DIRBLKSIZ chunk. - OFFSET is the offset this block occupies ithe file. - Always return 1. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - int rewrite; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - rewrite = 0; - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dnp->i_isize; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - rewrite = 1; - } - if (rewrite) - writeblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - return 1; - } - - switch (inodestate [ROOTINO]) - { - default: - errexit ("BAD STATE %d FOR ROOT INODE", (int) (inodestate[ROOTINO])); - - case DIRECTORY: - break; - - case UNALLOC: - problem (1, "ROOT INODE UNALLOCATED"); - if (!reply ("ALLOCATE")) - errexit ("ABORTING"); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - break; - - case REG: - problem (1, "ROOT INODE NOT DIRECTORY"); - if (reply ("REALLOCATE")) - freeino (ROOTINO); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - break; - - case BADDIR: - problem (1, "DUPLICATE or BAD BLOCKS IN ROOT INODE"); - if (reply ("REALLOCATE")) - { - freeino (ROOTINO); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - } - if (reply ("CONTINUE") == 0) - errexit ("ABORTING"); - break; - } - - /* Sort inpsort */ - qsort (dirsorted, dirarrayused, sizeof (struct dirinfo *), sortfunc); - - /* Check basic integrity of each directory */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - if (dnp->i_isize == 0) - continue; - if (dnp->i_isize % DIRBLKSIZ) - { - problem (0, "DIRECTORY INO=%Ld: LENGTH %d NOT MULTIPLE OF %d", - dnp->i_number, dnp->i_isize, DIRBLKSIZ); - if (preen || reply ("ADJUST")) - { - getinode (dnp->i_number, &dino); - dino.di_size = roundup (dnp->i_isize, DIRBLKSIZ); - write_inode (dnp->i_number, &dino); - pfix ("ADJUSTED"); - } - } - bzero (&dino, sizeof (struct dinode)); - dino.di_size = dnp->i_isize; - assert (dnp->i_numblks <= (NDADDR + NIADDR) * sizeof (daddr_t)); - bcopy (dnp->i_blks, dino.di_db, dnp->i_numblks); - - datablocks_iterate (&dino, checkdirblock); - } - - - /* At this point for each directory: - If this directory is an entry in another directory, then i_parent is - set to that node's number. - If this directory has a `..' entry, then i_dotdot is set to that link. - Check to see that `..' is set correctly. */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - /* Root is considered to be its own parent even though it isn't - listed. */ - if (dnp->i_number == ROOTINO && !dnp->i_parent) - dnp->i_parent = ROOTINO; - - /* Check `.' to make sure it exists and is correct */ - if (dnp->i_dot == 0) - { - dnp->i_dot = dnp->i_number; - pinode (0, dnp->i_number, "MISSING `.' IN"); - if ((preen || reply ("FIX")) - && makeentry (dnp->i_number, dnp->i_number, ".")) - { - linkfound[dnp->i_number]++; - pfix ("FIXED"); - } - else - pfail (0); - } - else if (dnp->i_dot != dnp->i_number) - { - pinode (0, dnp->i_number, "BAD INODE NUMBER FOR `.' IN"); - if (preen || reply ("FIX")) - { - ino_t old_dot = dnp->i_dot; - dnp->i_dot = dnp->i_number; - if (changeino (dnp->i_number, ".", dnp->i_number)) - { - linkfound[dnp->i_number]++; - if (inodestate[old_dot] != UNALLOC) - linkfound[old_dot]--; - pfix ("FIXED"); - } - else - pfail (0); - } - } - - /* Check `..' to make sure it exists and is correct */ - if (dnp->i_parent && dnp->i_dotdot == 0) - { - dnp->i_dotdot = dnp->i_parent; - pinode (0, dnp->i_number, "MISSING `..' IN"); - if ((preen || reply ("FIX")) - && makeentry (dnp->i_number, dnp->i_parent, "..")) - { - linkfound[dnp->i_parent]++; - pfix ("FIXED"); - } - else - pfail (0); - } - else if (dnp->i_parent && dnp->i_dotdot != dnp->i_parent) - { - pinode (0, dnp->i_number, "BAD INODE NUMBER FOR `..' IN"); - if (preen || reply ("FIX")) - { - ino_t parent = dnp->i_parent, old_dotdot = dnp->i_dotdot; - dnp->i_dotdot = parent; - if (changeino (dnp->i_number, "..", parent)) - /* Adjust what the parent's link count should be; the actual - count will be corrected in an later pass. */ - { - linkfound[parent]++; - if (inodestate[old_dotdot] != UNALLOC) - linkfound[old_dotdot]--; - pfix ("FIXED"); - } - else - pfail (0); - } - } - } -} diff --git a/ufs-fsck/pass3.c b/ufs-fsck/pass3.c deleted file mode 100644 index fd5ad1b0..00000000 --- a/ufs-fsck/pass3.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Pass 3 of GNU fsck -- Look for disconnected directories - Copyright (C) 1994, 1996 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -void -pass3 () -{ - struct dirinfo *dnp; - int nd; - int change; - - /* Mark all the directories that can be found from the root. */ - - inodestate[ROOTINO] |= DIR_REF; - - do - { - change = 0; - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - if (dnp->i_parent - && inodestate[dnp->i_parent] == (DIRECTORY | DIR_REF) - && inodestate[dnp->i_number] == DIRECTORY) - { - inodestate[dnp->i_number] |= DIR_REF; - change = 1; - } - } - } - while (change); - - /* Check for orphaned directories */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - if (dnp->i_parent == 0) - { - if (inodestate[dnp->i_number] & DIR_REF) - errexit ("ORPHANED DIR MARKED WITH CONNECT"); - pinode (0, dnp->i_number, "UNREF"); - if ((preen || reply ("RECONNECT")) - && linkup (dnp->i_number, dnp->i_dotdot)) - { - dnp->i_parent = dnp->i_dotdot = lfdir; - pfix ("RECONNECTED"); - } - else - pfail (0); - } - } -} diff --git a/ufs-fsck/pass4.c b/ufs-fsck/pass4.c deleted file mode 100644 index f8fe9814..00000000 --- a/ufs-fsck/pass4.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Pass 4 of GNU fsck -- Check reference counts - Copyright (C) 1994, 1996 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -void -pass4() -{ - ino_t number; - /* True if any reconnect attempt failed, in which case we don't try again. */ - int reconn_failed = 0; - - for (number = ROOTINO; number < maxino; number++) - { - if (linkfound[number] && inodestate[number] != UNALLOC) - { - if (linkcount[number] != linkfound[number]) - { - pinode (0, number, - "LINK COUNT %d SHOULD BE %d IN", - linkcount[number], linkfound[number]); - if (preen || reply ("ADJUST")) - { - struct dinode dino; - getinode (number, &dino); - dino.di_nlink = linkfound[number]; - write_inode (number, &dino); - pfix ("ADJUSTED"); - } - } - } - else if (linkfound[number] && inodestate[number] == UNALLOC) - { - /* This can't happen because we never count links to unallocated - nodes. */ - errexit ("LINK RECORDED FOR UNALLOCATED NODE"); - } - else if (!linkfound[number] && inodestate[number] != UNALLOC) - { - /* No links to allocated node. If the size is zero, then - we want to clear it; if the size is positive, then we - want to reattach in. */ - struct dinode dino; - - pinode (0, number, "UNREF"); - - getinode (number, &dino); - if (dino.di_size && !reconn_failed) - { - /* This can't happen for dirctories because pass 3 should - already have reset them up. */ - if ((DI_MODE (&dino) & IFMT) == IFDIR) - errexit ("NO LINKS TO NONZERO DIRECTORY"); - - if (preen || reply ("RECONNECT")) - reconn_failed = !linkup (number, -1); - if (! reconn_failed) - pfix ("RECONNECTED"); - if (preen && reconn_failed) - pfail ("RECONNECT FAILED"); - } - if (dino.di_size == 0 || reconn_failed) - { - if (reconn_failed && !preen) - /* If preening, the previous call to problem is still active - (more likely the failure was too severe, and exited). */ - problem (0, "RECONNECT FAILED"); - if (preen || reply ("CLEAR")) - { - inodestate[number] = UNALLOC; - clear_inode (number, &dino); - pfix ("CLEARED"); - } - } - } - } -} diff --git a/ufs-fsck/pass5.c b/ufs-fsck/pass5.c deleted file mode 100644 index cb426a7d..00000000 --- a/ufs-fsck/pass5.c +++ /dev/null @@ -1,450 +0,0 @@ -/* Pass 5 of GNU fsck -- check allocation maps and summaries - Copyright (C) 1994,96,2001 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" - -/* From ../ufs/subr.c: */ - -/* - * Update the frsum fields to reflect addition or deletion - * of some frags. - */ -static 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; - } - } -} - -void -pass5 () -{ - struct cg *newcg, *cg; - struct ocg *newocg; - int savednrpos = 0; - struct csum cstotal; - int i, j; - int c; - daddr_t d; - struct csum *sbcsums; - - int basesize; /* size of cg not counting flexibly sized */ - int sumsize; /* size of block totals and pos tbl */ - int mapsize; /* size of inode map + block map */ - - int writesb; - int writecg; - int writecsum; - - writesb = 0; - writecsum = 0; - - cg = alloca (sblock->fs_cgsize); - - newcg = alloca (sblock->fs_cgsize); - newocg = (struct ocg *)newcg; - - sbcsums = alloca (fragroundup (sblock, sblock->fs_cssize)); - - readblock (fsbtodb (sblock, sblock->fs_csaddr), sbcsums, - fragroundup (sblock, sblock->fs_cssize)); - - /* Construct a CG structure; initialize everything that's the same - in each cylinder group. */ - bzero (newcg, sblock->fs_cgsize); - newcg->cg_niblk = sblock->fs_ipg; - switch (sblock->fs_postblformat) - { - case FS_42POSTBLFMT: - /* Initialize size information */ - basesize = (char *)(&newocg->cg_btot[0]) - (char *)(&newocg->cg_link); - sumsize = &newocg->cg_iused[0] - (char *)(&newocg->cg_btot[0]); - mapsize = (&newocg->cg_free[howmany(sblock->fs_fpg, NBBY)] - - (u_char *)&newocg->cg_iused[0]); - savednrpos = sblock->fs_nrpos; - sblock->fs_nrpos = 8; - break; - - case FS_DYNAMICPOSTBLFMT: - /* Set fields unique to new cg structure */ - newcg->cg_btotoff = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link); - newcg->cg_boff = newcg->cg_btotoff + sblock->fs_cpg * sizeof (long); - newcg->cg_iusedoff = newcg->cg_boff + (sblock->fs_cpg - * sblock->fs_nrpos - * sizeof (short)); - newcg->cg_freeoff = newcg->cg_iusedoff + howmany (sblock->fs_ipg, NBBY); - - if (sblock->fs_contigsumsize <= 0) - { - newcg->cg_nextfreeoff = - (newcg->cg_freeoff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPF (sblock), - NBBY)); - } - else - { - newcg->cg_clustersumoff = - (newcg->cg_freeoff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPF (sblock), NBBY) - - sizeof (long)); - newcg->cg_clustersumoff = - roundup (newcg->cg_clustersumoff, sizeof (long)); - newcg->cg_clusteroff = - (newcg->cg_clustersumoff - + (sblock->fs_contigsumsize + 1) * sizeof (long)); - newcg->cg_nextfreeoff = - (newcg->cg_clusteroff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPB (sblock), - NBBY)); - } - - newcg->cg_magic = CG_MAGIC; - - /* Set map sizes */ - 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 POSTBL FORMAT"); - } - - bzero (&cstotal, sizeof (struct csum)); - - /* Mark fragments past the end of the filesystem as used. */ - j = blknum (sblock, sblock->fs_size + sblock->fs_frag - 1); - for (i = sblock->fs_size; i < j; i++) - setbmap (i); - - /* Now walk through the cylinder groups, checking each one. */ - for (c = 0; c < sblock->fs_ncg; c++) - { - int dbase, dmax; - - /* Read the cylinder group structure */ - readblock (fsbtodb (sblock, cgtod (sblock, c)), cg, sblock->fs_cgsize); - writecg = 0; - - if (!cg_chkmagic (cg)) - warning (1, "CG %d: BAD MAGIC NUMBER", c); - - /* Compute first and last data block addresses in this group */ - dbase = cgbase (sblock, c); - dmax = dbase + sblock->fs_fpg; - if (dmax > sblock->fs_size) - dmax = sblock->fs_size; - - /* Initialize newcg fully; values from cg for those - we can't check. */ - newcg->cg_time = cg->cg_time; - newcg->cg_cgx = c; - if (c == sblock->fs_ncg - 1) - newcg->cg_ncyl = sblock->fs_ncyl % sblock->fs_cpg; - else - newcg->cg_ncyl = sblock->fs_cpg; - newcg->cg_ndblk = dmax - dbase; - if (sblock->fs_contigsumsize > 0) - newcg->cg_nclusterblks = newcg->cg_ndblk / sblock->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 = sblock->fs_ipg; - - /* Check these for basic viability; if they are wrong - then clear them. */ - newcg->cg_rotor = cg->cg_rotor; - newcg->cg_frotor = cg->cg_frotor; - newcg->cg_irotor = cg->cg_irotor; - if (newcg->cg_rotor > newcg->cg_ndblk) - { - problem (0, "ILLEGAL ROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_rotor = 0; - cg->cg_rotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - if (newcg->cg_frotor > newcg->cg_ndblk) - { - problem (0, "ILLEGAL FROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_frotor = 0; - cg->cg_frotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - if (newcg->cg_irotor > newcg->cg_niblk) - { - problem (0, "ILLEGAL IROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_irotor = 0; - cg->cg_irotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - - /* Zero the block maps and summary areas */ - bzero (&newcg->cg_frsum[0], sizeof newcg->cg_frsum); - bzero (&cg_blktot (newcg)[0], sumsize + mapsize); - if (sblock->fs_postblformat == FS_42POSTBLFMT) - newocg->cg_magic = CG_MAGIC; - - /* Walk through each inode, accounting for it in - the inode map and in newcg->cg_cs. */ - /* In this loop, J is the inode number, and I is the - inode number relative to this CG. */ - j = sblock->fs_ipg * c; - for (i = 0; i < sblock->fs_ipg; j++, i++) - switch (inodestate[j]) - { - case DIRECTORY: - case DIRECTORY | DIR_REF: - case BADDIR: - newcg->cg_cs.cs_ndir++; - /* Fall through... */ - case REG: - newcg->cg_cs.cs_nifree--; - setbit (cg_inosused (newcg), i); - /* Fall through... */ - case UNALLOC: - break; - - default: - errexit ("UNKNOWN STATE I=%d", j); - } - /* Account for inodes 0 and 1 */ - if (c == 0) - for (i = 0; i < ROOTINO; i++) - { - setbit (cg_inosused (newcg), i); - newcg->cg_cs.cs_nifree--; - } - - /* Walk through each data block, accounting for it in - the block map and in newcg->cg_cs. */ - /* In this look, D is the block number and I is the - block number relative to this CG. */ - for (i = 0, d = dbase; - d < dmax; - d += sblock->fs_frag, i += sblock->fs_frag) - { - int frags = 0; - - /* Set each free frag of this block in the block map; - count how many frags were free. */ - for (j = 0; j < sblock->fs_frag; j++) - { - if (testbmap (d + j)) - continue; - setbit (cg_blksfree (newcg), i + j); - frags++; - } - - /* If all the frags were free, then count this as - a free block too. */ - if (frags == sblock->fs_frag) - { - newcg->cg_cs.cs_nbfree++; - j = cbtocylno (sblock, i); - cg_blktot(newcg)[j]++; - cg_blks(sblock, newcg, j)[cbtorpos(sblock, i)]++; - if (sblock->fs_contigsumsize > 0) - setbit (cg_clustersfree (newcg), i / sblock->fs_frag); - } - else if (frags) - { - /* Partial; account for the frags. */ - int blk; - newcg->cg_cs.cs_nffree += frags; - blk = blkmap (sblock, cg_blksfree (newcg), i); - ffs_fragacct (sblock, blk, newcg->cg_frsum, 1); - } - } - - if (sblock->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) - { - 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]++; - } - } - - /* Add this cylinder group's totals into the superblock's - totals. */ - 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; - - /* Check counts in superblock */ - if (bcmp (&newcg->cg_cs, &sbcsums[c], sizeof (struct csum))) - { - problem (0, "FREE BLK COUNTS FOR CG %d WRONG IN SUPERBLOCK", c); - if (preen || reply ("FIX")) - { - bcopy (&newcg->cg_cs, &sbcsums[c], sizeof (struct csum)); - writecsum = 1; - pfix ("FIXED"); - } - } - - /* Check inode and block maps */ - if (bcmp (cg_inosused (newcg), cg_inosused (cg), mapsize)) - { - problem (0, "BLKS OR INOS MISSING IN CG %d BIT MAPS", c); - if (preen || reply ("FIX")) - { - bcopy (cg_inosused (newcg), cg_inosused (cg), mapsize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (bcmp (&cg_blktot(newcg)[0], &cg_blktot(cg)[0], sumsize)) - { - problem (0, "SUMMARY INFORMATION FOR CG %d BAD", c); - if (preen || reply ("FIX")) - { - bcopy (&cg_blktot(newcg)[0], &cg_blktot(cg)[0], sumsize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (bcmp (newcg, cg, basesize)) - { - problem (0, "CYLINDER GROUP %d BAD", c); - if (preen || reply ("FIX")) - { - bcopy (newcg, cg, basesize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (writecg) - writeblock (fsbtodb (sblock, cgtod (sblock, c)), - cg, sblock->fs_cgsize); - } - - /* Restore nrpos */ - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sblock->fs_nrpos = savednrpos; - - if (bcmp (&cstotal, &sblock->fs_cstotal, sizeof (struct csum))) - { - problem (0, "TOTAL FREE BLK COUNTS WRONG IN SUPERBLOCK"); - if (preen || reply ("FIX")) - { - bcopy (&cstotal, &sblock->fs_cstotal, sizeof (struct csum)); - sblock->fs_ronly = 0; - sblock->fs_fmod = 0; - writesb = 1; - pfix ("FIXED"); - } - } - - if (sblock->fs_clean == 0 && !fix_denied) - { - problem (0, fsmodified ? "FILESYSTEM MODIFIED" : "FILESYSTEM UNCLEAN"); - if (preen || reply ("MARK CLEAN")) - { - sblock->fs_clean = 1; - writesb = 1; - pfix ("MARKED CLEAN"); - } - } - - if (writesb) - writeblock (SBLOCK, sblock, SBSIZE); - - if (writecsum) - { - const int cssize = fragroundup (sblock, sblock->fs_cssize); - struct csum *test; - - writeblock (fsbtodb (sblock, sblock->fs_csaddr), sbcsums, - fragroundup (sblock, sblock->fs_cssize)); - - test = alloca (cssize); - readblock (fsbtodb (sblock, sblock->fs_csaddr), test, cssize); - if (bcmp (test, sbcsums, cssize)) - warning (0, "CSUM WRITE INCONSISTENT"); - } -} diff --git a/ufs-fsck/setup.c b/ufs-fsck/setup.c deleted file mode 100644 index 9433bd68..00000000 --- a/ufs-fsck/setup.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - Copyright (C) 1994,96,99,2002 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <error.h> - -static char sblockbuf[SBSIZE]; -struct fs *sblock = (struct fs *)sblockbuf; - -/* A string identifying what we're trying to check. */ -char *device_name = 0; - -daddr_t maxfsblock; -int maxino; -int direct_symlink_extension; - -int newinofmt; - -int readfd, writefd; - -int fix_denied = 0; - -int fsmodified = 0; - -ino_t lfdir; - -/* Get ready to run on device with pathname DEV. */ -int -setup (char *dev) -{ - struct stat st; - int changedsb; - size_t bmapsize; - - device_name = dev; - - if (stat (dev, &st) == -1) - { - error (0, errno, "%s", dev); - return 0; - } - if (!S_ISCHR (st.st_mode) && !S_ISBLK (st.st_mode)) - { - problem (1, "%s is not a character or block device", dev); - if (! reply ("CONTINUE")) - return 0; - } - if (preen == 0) - printf ("** %s", dev); - if (!nowrite) - readfd = open (dev, O_RDWR); - if (nowrite || readfd == -1) - { - readfd = open (dev, O_RDONLY); - if (readfd == -1) - { - error (0, errno, "%s", dev); - return 0; - } - writefd = -1; - nowrite = 1; - if (preen) - warning (1, "NO WRITE ACCESS"); - printf (" (NO WRITE)"); - } - else - writefd = readfd; - - if (preen == 0) - printf ("\n"); - - lfdir = 0; - - /* We don't do the alternate superblock stuff here (yet). */ - readblock (SBLOCK, sblock, SBSIZE); - changedsb = 0; - - if (sblock->fs_magic != FS_MAGIC) - { - warning (1, "BAD MAGIC NUMBER"); - return 0; - } - if (sblock->fs_ncg < 1) - { - warning (1, "NCG OUT OF RANGE"); - return 0; - } - if (sblock->fs_cpg < 1) - { - warning (1, "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) - { - warning (1, "NCYL INCONSISTENT WITH NCG AND CPG"); - return 0; - } - if (sblock->fs_sbsize > SBSIZE) - { - warning (1, "SBLOCK SIZE PREPONTEROUSLY LARGE"); - return 0; - } - if (sblock->fs_optim != FS_OPTTIME && sblock->fs_optim != FS_OPTSPACE) - { - problem (1, "UNDEFINED OPTIMIZATION IN SUPERBLOCK"); - if (reply ("SET TO DEFAULT")) - { - sblock->fs_optim = FS_OPTTIME; - changedsb = 1; - } - } - if (sblock->fs_minfree < 0 || sblock->fs_minfree > 99) - { - problem (0, "IMPOSSIBLE MINFREE=%ld IN SUPERBLOCK", sblock->fs_minfree); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_minfree = 10; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_interleave < 1 - || sblock->fs_interleave > sblock->fs_nsect) - { - problem (0, "IMPOSSIBLE INTERLEAVE=%ld IN SUPERBLOCK", - sblock->fs_interleave); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_interleave = 1; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_npsect < sblock->fs_nsect - || sblock->fs_npsect > sblock->fs_nsect * 2) - { - problem (0, "IMPOSSIBLE NPSECT=%ld IN SUPERBLOCK", sblock->fs_npsect); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_npsect = sblock->fs_nsect; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_inodefmt >= FS_44INODEFMT) - newinofmt = 1; - else - { - sblock->fs_qbmask = ~sblock->fs_bmask; - sblock->fs_qfmask = ~sblock->fs_fmask; - newinofmt = 0; - } - - if (changedsb) - writeblock (SBLOCK, sblock, SBSIZE); - - /* Constants */ - maxfsblock = sblock->fs_size; - maxino = sblock->fs_ncg * sblock->fs_ipg; - direct_symlink_extension = sblock->fs_maxsymlinklen > 0; - - /* Allocate and initialize maps */ - bmapsize = roundup (howmany (maxfsblock, NBBY), sizeof (short)); - blockmap = calloc (bmapsize, sizeof (char)); - inodestate = calloc (maxino + 1, sizeof (char)); - typemap = calloc (maxino + 1, sizeof (char)); - linkcount = calloc (maxino + 1, sizeof (nlink_t)); - linkfound = calloc (maxino + 1, sizeof (nlink_t)); - return 1; -} diff --git a/ufs-fsck/utilities.c b/ufs-fsck/utilities.c deleted file mode 100644 index 14705f84..00000000 --- a/ufs-fsck/utilities.c +++ /dev/null @@ -1,455 +0,0 @@ -/* Miscellaneous functions for fsck - Copyright (C) 1994,95,96,99,2001,02 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "fsck.h" -#include <fcntl.h> -#include <sys/file.h> -#include <unistd.h> -#include <stdarg.h> -#include <pwd.h> -#include <error.h> -#include <time.h> - -static void retch (char *reason); - -/* Read disk block ADDR into BUF of SIZE bytes. */ -void -readblock (daddr_t addr, void *buf, size_t size) -{ - if (lseek (readfd, addr * DEV_BSIZE, L_SET) == -1) - errexit ("CANNOT SEEK TO BLOCK %ld", addr); - if (read (readfd, buf, size) != size) - errexit ("CANNOT READ BLOCK %ld", addr); -} - -/* Write disk block BLKNO from BUF of SIZE bytes. */ -void -writeblock (daddr_t addr, void *buf, size_t size) -{ - if (lseek (writefd, addr * DEV_BSIZE, L_SET) == -1) - errexit ("CANNOT SEEK TO BLOCK %ld", addr); - if (write (writefd, buf, size) != size) - errexit ("CANNOT WRITE BLOCK %ld", addr); - fsmodified = 1; -} - -/* Last filesystem fragment that we read an inode from */ -static char *lastifrag; -static daddr_t lastifragaddr; - -/* Read inode number INO into DINODE. */ -void -getinode (ino_t ino, struct dinode *di) -{ - daddr_t iblk; - - if (!lastifrag) - lastifrag = malloc (sblock->fs_bsize); - - iblk = ino_to_fsba (sblock, ino); - if (iblk != lastifragaddr) - readblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); - lastifragaddr = iblk; - bcopy (lastifrag + ino_to_fsbo (sblock, ino) * sizeof (struct dinode), - di, sizeof (struct dinode)); -} - -/* Write inode number INO from DINODE. */ -void -write_inode (ino_t ino, struct dinode *di) -{ - daddr_t iblk; - - iblk = ino_to_fsba (sblock, ino); - if (iblk != lastifragaddr) - readblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); - lastifragaddr = iblk; - bcopy (di, lastifrag + ino_to_fsbo (sblock, ino) * sizeof (struct dinode), - sizeof (struct dinode)); - writeblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); -} - -/* Clear inode number INO and zero DI. */ -void -clear_inode (ino_t ino, struct dinode *di) -{ - bzero (di, sizeof (struct dinode)); - write_inode (ino, di); -} - -/* Allocate and return a block and account for it in all the block - maps locally. Don't trust or change the disk block maps. - The block should be NFRAGS fragments long. */ -daddr_t -allocblk (int nfrags) -{ - daddr_t i; - int j, k; - - if (nfrags <= 0 || nfrags > sblock->fs_frag) - return 0; - - /* Examine each block of the filesystem. */ - for (i = 0; i < maxfsblock - sblock->fs_frag; i += sblock->fs_frag) - { - /* For each piece of the block big enough to hold this frag... */ - for (j = 0; j <= sblock->fs_frag - nfrags; j++) - { - /* For each frag of this piece... */ - for (k = 0; k < nfrags; k++) - if (testbmap (i + j + k)) - break; - - /* If one of the frags was allocated... */ - if (k < nfrags) - { - /* Skip at least that far (short cut) */ - j += k; - continue; - } - - /* It's free (at address i + j) */ - - /* Mark the frags allocated in our map */ - for (k = 0; k < nfrags; k++) - setbmap (i + j + k); - - return (i + j); - } - } - return 0; -} - -/* Check if a block starting at BLK and extending for CNT - fragments is out of range; if it is, then return 1; otherwise return 0. */ -int -check_range (daddr_t blk, int cnt) -{ - int c; - - if ((unsigned)(blk + cnt) > maxfsblock) - return 1; - - c = dtog (sblock, blk); - if (blk < cgdmin (sblock, c)) - { - if (blk + cnt > cgsblock (sblock, c)) - return 1; - } - else - { - if (blk + cnt > cgbase (sblock, c + 1)) - return 1; - } - - return 0; -} - -struct problem { - char *desc; - struct problem *prev; -}; - -/* A queue of problems found by fsck that are waiting resolution. The front - of the list is the most recent problem found (and presumably since - previous problems haven't been resolved yet, they depend on this one being - solved for their resolution). */ -static struct problem *problems = 0; - -static struct problem *free_problems = 0; - -static void -push_problem (char *fmt, va_list args) -{ - struct problem *prob = free_problems; - - if (! prob) - prob = malloc (sizeof (struct problem)); - else - problems = prob->prev; - if (! prob) - retch ("malloc failed"); - - if (vasprintf (&prob->desc, fmt, args) < 0) - retch ("vasprintf failed"); - - prob->prev = problems; - problems = prob; -} - -/* Print the most recent problem, and perhaps how it was resolved. */ -static void -resolve_problem (char *fix) -{ - struct problem *prob = problems; - - if (! prob) - retch ("no more problems"); - - problems = prob->prev; - prob->prev = free_problems; - - if (preen && device_name) - printf ("%s: %s", device_name, prob->desc); - else - printf ("%s", prob->desc); - if (fix) - printf (" (%s)\n", fix); - else - putchar ('\n'); - free (prob->desc); -} - -/* Retire all problems as if they failed. We print them in chronological - order rather than lifo order, as this is a bit clearer, and we can do it - when we know they're all going to fail. */ -static void -flush_problems () -{ - struct problem *fail (struct problem *prob) - { - struct problem *last = prob->prev ? fail (prob->prev) : prob; - if (preen && device_name) - printf ("%s: %s\n", device_name, prob->desc); - else - puts (prob->desc); - free (prob->desc); - return last; - } - if (problems) - { - fail (problems)->prev = free_problems; - free_problems = problems; - } -} - -/* Like printf, but exit after printing. */ -void -errexit (char *fmt, ...) -{ - va_list args; - - flush_problems (); - - if (preen && device_name) - printf ("%s: ", device_name); - - va_start (args, fmt); - vprintf (fmt, args); - va_end (args); - putchar ('\n'); - - exit (8); -} - -static void -retch (char *reason) -{ - flush_problems (); - error (99, 0, "(internal error) %s!", reason); -} - -/* Prints all unresolved problems and exits, printing MSG as well. */ -static void -punt (char *msg) -{ - problem (0, "%s", msg); - flush_problems (); - exit (8); -} - -/* If SEVERE is true, and we're in preen mode, then things are too hair to - fix automatically, so tell the user to do it himself and punt. */ -static void -no_preen (int severe) -{ - if (severe && preen) - punt ("PLEASE RUN fsck MANUALLY"); -} - -/* Store away the given message about a problem found. A call to problem must - be matched later with a call to pfix, pfail, or reply; to print more - in the same message, intervening calls to pextend can be used. If SEVERE is - true, and we're in preen mode, then the program is terminated. */ -void -problem (int severe, char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - - no_preen (severe); -} - -/* Following a call to problem (with perhaps intervening calls to - pmore), appends the given message to that message. */ -void -pextend (char *fmt, ...) -{ - va_list args; - char *more, *concat; - struct problem *prob = problems; - - if (! prob) - retch ("No pending problem to add to"); - - va_start (args, fmt); - if (vasprintf (&more, fmt, args) < 0) - retch ("vasprintf failed"); - va_end (args); - - concat = realloc (prob->desc, strlen (prob->desc) + 1 + strlen (more) + 1); - if (! concat) - retch ("realloc failed"); - - strcpy (concat + strlen (concat), more); - prob->desc = concat; - free (more); -} - -/* Like problem, but as if immediately followed by pfail. */ -void -warning (int severe, char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - - no_preen (severe); - - resolve_problem (0); -} - -/* Like problem, but appends a helpful description of the given inode number to - the message. */ -void -pinode (int severe, ino_t ino, char *fmt, ...) -{ - if (fmt) - { - va_list args; - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - } - - if (ino < ROOTINO || ino > maxino) - pextend (" (BOGUS INODE) I=%Ld", ino); - else - { - char *p; - struct dinode dino; - struct passwd *pw; - - getinode (ino, &dino); - - pextend (" %s I=%Ld", (DI_MODE (&dino) & IFMT) == IFDIR ? "DIR" : "FILE", - ino); - - pw = getpwuid (dino.di_uid); - if (pw) - pextend (" O=%s", pw->pw_name); - else - pextend (" O=%lu", dino.di_uid); - - pextend (" M=0%o", DI_MODE (&dino)); - pextend (" SZ=%llu", dino.di_size); - p = ctime (&dino.di_mtime.tv_sec); - pextend (" MT=%12.12s %4.4s", &p[4], &p[20]); - } - - no_preen (severe); -} - -/* Print a successful resolution to a pending problem. Must follow a call to - problem or pextend. */ -void -pfix (char *fix) -{ - if (preen) - resolve_problem (fix ?: "FIXED"); -} - -/* Print an unsuccessful resolution to a pending problem. Must follow a call - to problem or pextend. */ -void -pfail (char *failure) -{ - if (preen) - resolve_problem (failure); -} - -/* Ask the user a question; return 1 if the user says yes, and 0 - if the user says no. This call must follow a call to problem or pextend, - which it completes. */ -int -reply (char *question) -{ - int persevere; - char c; - - if (preen) - retch ("Got to reply() in preen mode"); - - /* Emit the problem to which the question pertains. */ - resolve_problem (0); - - persevere = !strcmp (question, "CONTINUE"); - - if (!persevere && (nowrite || writefd < 0)) - { - fix_denied = 1; - printf ("%s? no\n\n", question); - return 0; - } - else if (noquery || (persevere && nowrite)) - { - printf ("%s? yes\n\n", question); - return 1; - } - else - { - do - { - printf ("%s? [yn] ", question); - fflush (stdout); - c = getchar (); - while (c != '\n' && getchar () != '\n') - if (feof (stdin)) - { - fix_denied = 1; - return 0; - } - } - while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); - putchar ('\n'); - if (c == 'y' || c == 'Y') - return 1; - else - { - fix_denied = 1; - return 0; - } - } -} diff --git a/ufs-utils/Makefile b/ufs-utils/Makefile deleted file mode 100644 index df22440e..00000000 --- a/ufs-utils/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (C) 1994, 1996, 2008 Free Software Foundation -# Written by Michael I. Bushnell. -# -# This file is part of the GNU Hurd. -# -# The GNU Hurd 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. -# -# The GNU Hurd 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. - -dir := ufs-utils -makemode := utilities - -targets = mkfs.ufs clri.ufs stati.ufs -target-suffix = .ufs -SRCS = mkfs.c clri.c stati.c dlabel.c -installationdir = $(sbindir) - -OBJS = $(SRCS:.c=.o) -HURDLIBS = store shouldbeinlibc - -include ../Makeconf - -mkfs.ufs: mkfs.o dlabel.o ../libstore/libstore.a ../libshouldbeinlibc/libshouldbeinlibc.a - -$(targets): %.ufs: %.o - - diff --git a/ufs-utils/clri.c b/ufs-utils/clri.c deleted file mode 100644 index 1ad348a1..00000000 --- a/ufs-utils/clri.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rich $alz of BBN Inc. - * - * 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) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; - -static char copyright[] __attribute__ ((unused)); -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)clri.c 8.2 (Berkeley) 9/23/93"; -static char sccsid[] __attribute__ ((unused)); -#endif /* not lint */ - -/* Modified by Michael I. Bushnell for GNU Hurd. */ - -#include <sys/param.h> -#include <sys/time.h> - -#include "../ufs/dinode.h" -#include "../ufs/fs.h" - - - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> - -#define MAXPHYS (64 * 1024) -#define DEV_BSIZE 512 - - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register struct fs *sbp; - register struct dinode *ip; - register int fd; - struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)]; - long generation, bsize; - off_t offset; - int inonum; - char *fs, sblock[SBSIZE]; - - if (argc < 3) { - (void)fprintf(stderr, "usage: clri filesystem inode ...\n"); - exit(1); - } - - fs = *++argv; - - /* get the superblock. */ - if ((fd = open(fs, O_RDWR, 0)) < 0) - { - perror (fs); - exit (1); - } - if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) { - (void)fprintf(stderr, - "clri: %s: can't read the superblock.\n", fs); - exit(1); - } - - sbp = (struct fs *)sblock; - if (sbp->fs_magic != FS_MAGIC) { - (void)fprintf(stderr, - "clri: %s: superblock magic number 0x%lux, not 0x%x.\n", - fs, sbp->fs_magic, FS_MAGIC); - exit(1); - } - bsize = sbp->fs_bsize; - - /* remaining arguments are inode numbers. */ - while (*++argv) { - /* get the inode number. */ - if ((inonum = atoi(*argv)) <= 0) { - (void)fprintf(stderr, - "clri: %s is not a valid inode number.\n", *argv); - exit(1); - } - (void)printf("clearing %d\n", inonum); - - /* read in the appropriate block. */ - offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */ - offset = fsbtodb(sbp, offset); /* fs blk disk blk */ - offset *= DEV_BSIZE; /* disk blk to bytes */ - - /* seek and read the block */ - if (lseek(fd, offset, SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - - /* get the inode within the block. */ - ip = &ibuf[ino_to_fsbo(sbp, inonum)]; - - /* clear the inode, and bump the generation count. */ - generation = ip->di_gen + 1; - memset(ip, 0, sizeof(*ip)); - ip->di_gen = generation; - - /* backup and write the block */ - if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0) - { - perror (fs); - exit (1); - } - if (write(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - (void)fsync(fd); - } - (void)close(fd); - exit(0); -} diff --git a/ufs-utils/dlabel.c b/ufs-utils/dlabel.c deleted file mode 100644 index 355cb3f6..00000000 --- a/ufs-utils/dlabel.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Get the disklabel from a device node - - Copyright (C) 1996,99,2001 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.org> - - 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. */ - -#include <errno.h> -#include <hurd.h> -#include <mach.h> -#include <string.h> -#include <device/device.h> -#include <device/disk_status.h> -#include <hurd/store.h> - -/* XXX Ick. */ -#define IOCPARM_MASK 0x1fff/* parameter length, at most 13 bits */ -#define IOC_OUT 0x40000000/* copy out parameters */ -#define _IOC(inout,group,num,len) \ - (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) -#define _IOR(g,n,t) _IOC(IOC_OUT,(g), (n), sizeof(t)) - -static error_t -fd_get_device (int fd, device_t *device) -{ - error_t err; - struct store *store; - file_t node = getdport (fd); - - if (node == MACH_PORT_NULL) - return errno; - - err = store_create (node, 0, 0, &store); /* consumes NODE on success */ - if (! err) - { - if (store->class->id != STORAGE_DEVICE - /* In addition to requiring a device, we also want the *whole* - device -- one contiguous run starting at 0. */ - || store->num_runs != 1 - || store->runs[0].start != 0) - err = ENODEV; - else if (store->port == MACH_PORT_NULL) - /* Usually getting a null port back means we didn't have sufficient - privileges. */ - err = EPERM; - else - { - *device = store->port; - store->port = MACH_PORT_NULL; /* Steal the port from STORE! */ - } - store_free (store); - } - else - mach_port_deallocate (mach_task_self (), node); - - return err; -} - -error_t -fd_get_disklabel (int fd, struct disklabel *label) -{ - device_t device; - error_t err = fd_get_device (fd, &device); - - if (! err) - { - mach_msg_type_number_t label_len = sizeof *label / sizeof (integer_t); - - err = device_get_status (device, DIOCGDINFO, - (dev_status_t)label, &label_len); - if (!err && label_len != sizeof *label / sizeof (integer_t)) - err = ERANGE; - - mach_port_deallocate (mach_task_self (), device); - } - - return err; -} diff --git a/ufs-utils/mkfs.c b/ufs-utils/mkfs.c deleted file mode 100644 index aef3ea92..00000000 --- a/ufs-utils/mkfs.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * 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.22 2006/03/14 23:27:50 tschwinge Exp $"; -#endif /* not lint */ - -#include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <argp.h> -#include <assert.h> -#include <error.h> -#include <string.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -/* #include <sys/disklabel.h> */ -#include <sys/stat.h> -#include <fcntl.h> -#include <dirent.h> -#include <version.h> - -#include <device/device_types.h> -#include <device/disk_status.h> - -#include <hurd.h> - -/* Begin misc additions for GNU Hurd */ - -/* For GNU Hurd: the ufs DIRSIZ macro is different than the BSD - 4.4 version that mkfs expects. So we provide here the BSD version. */ -#undef DIRSIZ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRSIZ(oldfmt, dp) \ - ((oldfmt) ? \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) -#else -#define DIRSIZ(oldfmt, dp) \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) -#endif - -#define MAXPHYS (64 * 1024) - -/* Provide mode from struct dinode * */ -#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) - -#define DEV_BSIZE 512 - -#define btodb(bytes) ((bytes) / DEV_BSIZE) - -/* End additions for GNU Hurd */ - -#ifndef STANDALONE -#include <a.out.h> -#include <stdio.h> -#include <time.h> -#endif - -/* - * make file system for cylinder-group style file systems - */ - -extern error_t fd_get_disklabel (int fd, struct disklabel *lab); -static void mkfs (), initcg (), fsinit (), setblock (); -static void iput (), rdfs (), clrblock (), wtfs (); -static int makedir (), isblock (); - -/* - * 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. - */ -#define extern -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 */ -#undef extern - -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(); - -const char *argp_program_version = STANDARD_HURD_VERSION (mkfs.ufs); - -#define _STRINGIFY(arg) #arg -#define STRINGIFY(arg) _STRINGIFY (arg) - -static const struct argp_option options[] = { - {0,0,0,0,0, 1}, - {"just-print", 'N', 0, 0, - "Just print the file system parameters that would be used"}, - {"old-format", 'O', 0, 0, "Create a 4.3BSD format filesystem"}, - {"max-contig", 'a', "BLOCKS", 0, - "The maximum number of contiguous blocks that will be laid out before" - " forcing a rotational delay; the default is no limit"}, - {"block-size", 'b', "BYTES", 0, "The block size of the file system"}, - {"group-cylinders", 'c', "N", 0, - "The number of cylinders per cylinder group; the default 16"}, - {"rot-delay", 'd', "MSEC", 0, - "The expected time to service a transfer completion interrupt and" - " initiate a new transfer on the same disk; the default is 0"}, - {"max-bpg", 'e', "BLOCKS", 0, - "Maximum number of blocks any single file can allocate out of a cylinder" - " group before it is forced to begin allocating blocks from another" - " cylinder group; the default is about one quarter of the total blocks" - " in a cylinder group"}, - {"frag-size", 'f', "BYTES", 0, "The fragment size"}, - {"inode-density", 'i', "BYTES", 0, - "The density of inodes in the file system, in bytes of data space per" - " inode; the default is one inode per 4 filesystem frags"}, - {"minfree", 'm', "PERCENT", 0, - "The percentage of space reserved from normal users; the default is " - STRINGIFY (MINFREE) "%"}, - {"rot-positions", 'n', "N", 0, - "The number of distinct rotational positions; the default is 8"}, - {"optimization", 'o', "METH", 0, "``space'' or ``time''"}, - {"size", 's', "SECTORS", 0, "The size of the file system"}, - - {0,0,0,0, - "The following options override the standard sizes for the disk" - " geometry; their default values are taken from the disk label:", 2}, - - {"sector-size", 'S', "BYTES", 0, "The size of a sector (usually 512)"}, - {"skew", 'k', "SECTORS", 0, "Sector 0 skew, per track"}, - {"interleave", 'l', "LOG-PHYS-RATIO", 0, "Hardware sector interleave"}, - {"rpm", 'r', "RPM", 0, "The speed of the disk in revolutions per minute"}, - {"tracks", 't', "N", 0, "The number of tracks/cylinder"}, - {"sectors", 'u', "N", 0, - "The number of sectors per track (does not include sectors reserved for" - " bad block replacement"}, - {"spare-sectors", 'p', "N", 0, - "Spare sectors (for bad sector replacement) at the end of each track"}, - {"cyl-spare-sectors", 'x', "N", 0, - "Spare sectors (for bad sector replacement) at the end of the last track" - " in each cylinder"}, - {0, 0} -}; -static char *args_doc = "DEVICE"; -static char *doc = "Write a ufs filesystem image onto DEVICE."; - -struct amark { void *addr; struct amark *next; }; - -static void -amarks_add (struct amark **amarks, void *addr) - { - struct amark *up = malloc (sizeof (struct amark)); - assert (up != 0); - up->addr = addr; - up->next = *amarks; - *amarks = up; - } -static int -amarks_contains (struct amark *amarks, void *addr) - { - while (amarks) - if (amarks->addr == addr) - return 1; - else - amarks = amarks->next; - return 0; - } - -static const struct disklabel default_disklabel = { - d_rpm: 3600, - d_interleave: 1, - d_secsize: DEV_BSIZE, - d_sparespertrack: 0, - d_sparespercyl: 0, - d_trackskew: 0, - d_cylskew: 0, - d_headswitch: 0, - d_trkseek: 0, -}; - -char *device = 0; - -#define deverr(code, err, fmt, args...) \ - error (code, err, "%s: " fmt, device , ##args) - -int -main (int argc, char **argv) -{ - int fdo, fdi; - struct amark *uparams = 0; - error_t label_err = 0; - struct disklabel label_buf, *label = 0; - int nspares = 0, ncspares = 0; - - /* Parse our options... */ - error_t parse_opt (int key, char *arg, struct argp_state *state) - { - switch (key) - { - case 'N': Nflag = 1; break; - case 'O': Oflag = 1; break; - -/* Mark &VAR as being a uparam, and set VAR. */ -#define UP_INT(var) { amarks_add (&uparams, &var); var = atoi (arg); } - - case 'a': UP_INT (maxcontig); break; - case 'b': UP_INT (bsize); break; - case 'c': UP_INT (cpg); cpgflg = 1; break; - case 'd': UP_INT (rotdelay); break; - case 'e': UP_INT (maxbpg); break; - case 'f': UP_INT (fsize); break; - case 'i': UP_INT (density); break; - case 'm': UP_INT (minfree); break; - case 'n': UP_INT (nrpos); break; - case 's': UP_INT (fssize); break; - case 'S': UP_INT (sectorsize); break; - case 'k': UP_INT (trackskew); break; - case 'l': UP_INT (interleave); break; - case 'r': UP_INT (rpm); break; - case 't': UP_INT (ntracks); break; - case 'u': UP_INT (nsectors); break; - case 'p': UP_INT (nspares); break; - case 'x': UP_INT (ncspares); break; - - case 'o': - amarks_add (&uparams, &opt); - if (strcmp (arg, "time") == 0) - opt = FS_OPTTIME; - else if (strcmp (arg, "space") == 0) - opt = FS_OPTSPACE; - else - argp_error (state, "%s: Invalid value for --optimization", arg); - break; - - case ARGP_KEY_ARG: - if (state->arg_num > 0) - return ARGP_ERR_UNKNOWN; - device = arg; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; - } - const struct argp argp = { options, parse_opt, args_doc, doc }; - - /* Tries to get the disklabel for DEVICE; if it can't, then if PARAM_NAME - is 0, returns 0, otherwise an error is printed (using PARAM_NAME) and - the program exits. */ - struct disklabel *dl (char *param_name) - { - if (! label) - { - if (! label_err) - { - label_err = fd_get_disklabel (fdi, &label_buf); - if (! label_err) - label = &label_buf; - } - if (label_err && param_name) - error (9, label_err, - "%s: Can't get disklabel; please specify --%s", - device, param_name); - } - return label; - } - /* Tries to get the integer field at offset OFFS from the disklabel for - DEVICE; if it can't, then if PARAM_NAME is 0, returns the corresponding - value from DEFAULT_DISKLABEL, otherwise an error is printed and the - program exits. */ - int dl_int (char *param_name, size_t offs) - { - struct disklabel *l = dl (param_name); - return *(int *)((char *)(l ?: &default_disklabel) + offs); - } - /* A version of dl_int that takes the field name instead of an offset. */ -#define DL_INT(param_name, field) \ - dl_int (param_name, offsetof (struct disklabel, field)) - - /* Like dl_int, but adjust for any difference in sector size between the - disklabel and SECTORSIZE. */ - int dl_secs (char *param_name, size_t offs) - { - int val = dl_int (param_name, offs); - int dl_ss = DL_INT (0, d_secsize); - if (sectorsize < dl_ss) - deverr (10, 0, - "%d: Sector size is less than device sector size (%d)", - sectorsize, dl_ss); - else if (sectorsize > dl_ss) - if (sectorsize % dl_ss != 0) - deverr (11, 0, - "%d: Sector size not a multiple of device sector size (%d)", - sectorsize, dl_ss); - else - val /= sectorsize / dl_ss; - return val; - } - /* A version of dl_secs that takes the field name instead of an offset. */ -#define DL_SECS(param_name, field) \ - dl_secs (param_name, offsetof (struct disklabel, field)) - - /* Parse our arguments. */ - argp_parse (&argp, argc, argv, 0, 0, 0); - - fdi = open (device, O_RDONLY); - if (fdi == -1) - error (2, errno, "%s", device); - fdo = open (device, O_WRONLY); - if (fdo == -1) - error (3, errno, "%s", device); - - /* If VAR hasn't been set by the user, set it to DEF_VAL. */ -#define DEFAULT(var, def_val) \ - (amarks_contains (uparams, &var) ? 0 : (((var) = (def_val)), 0)) - - DEFAULT (sectorsize, DEV_BSIZE); - DEFAULT (fssize, - ({ struct stat st; - if (fstat (fdi, &st) == -1) - deverr (4, errno, "Cannot get size"); - st.st_size / sectorsize; })); - DEFAULT (ntracks, DL_INT ("tracks", d_ntracks)); - DEFAULT (nsectors, DL_SECS ("sectors", d_nsectors)); - DEFAULT (nspares, DL_SECS (0, d_sparespertrack)); - DEFAULT (ncspares, DL_SECS (0, d_sparespercyl)); - - if (nspares >= nsectors) - deverr (5, 0, "%d: Too many spare sectors per track", nspares); - if (ncspares >= nsectors) - deverr (5, 0, "%d: Too many spare sectors per cylinder", ncspares); - nphyssectors = nsectors + nspares; - - secpercyl = nsectors * ntracks; - - DEFAULT (rpm, DL_INT (0, d_rpm)); - DEFAULT (interleave, DL_INT (0, d_interleave)); - DEFAULT (trackskew, DL_SECS (0, d_trackskew)); - DEFAULT (headswitch, DL_INT (0, d_headswitch)); - DEFAULT (trackseek, DL_INT (0, d_trkseek)); - - DEFAULT (fsize, 1024); - DEFAULT (bsize, 8192); - - DEFAULT (cpg, 16); - DEFAULT (minfree, MINFREE); - DEFAULT (opt, DEFAULTOPT); - DEFAULT (density, 4 * fsize); -/* maxcontig = MAX (1, MIN (MAXPHYS, MAXBSIZE) / bsize - 1); */ - DEFAULT (maxcontig, 0); - DEFAULT (rotdelay, 4); -#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) - DEFAULT (maxbpg, MAXBLKPG (bsize)); - DEFAULT (nrpos, 8); - - bbsize = BBSIZE; - sbsize = SBSIZE; - - mkfs (0, device, fdi, fdo); - - return 0; -} - -void -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; - time_t utime; - quad_t sizepb; - -#ifndef STANDALONE - time(&utime); -#endif - 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) - deverr (13, 0, "preposterous size %d", fssize); - 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) - deverr (14, 0, "preposterous ntrak %ld", sblock.fs_ntrak); - if (sblock.fs_nsect <= 0) - deverr (15, 0, "preposterous nsect %ld", sblock.fs_nsect); - /* - * collect and verify the block and fragment sizes - */ - sblock.fs_bsize = bsize; - sblock.fs_fsize = fsize; - if (!POWEROF2(sblock.fs_bsize)) - deverr (16, 0, - "block size must be a power of 2, not %ld", - sblock.fs_bsize); - if (!POWEROF2(sblock.fs_fsize)) - deverr (17, 0, - "fragment size must be a power of 2, not %ld", - sblock.fs_fsize); - if (sblock.fs_fsize < sectorsize) - deverr (18, 0, - "fragment size %ld is too small, minimum is %d", - sblock.fs_fsize, sectorsize); - if (sblock.fs_bsize < MINBSIZE) - deverr (19, 0, - "block size %ld is too small, minimum is %d", - sblock.fs_bsize, MINBSIZE); - if (sblock.fs_bsize < sblock.fs_fsize) - deverr (20, 0, - "block size (%ld) cannot be smaller than fragment size (%ld)", - sblock.fs_bsize, sblock.fs_fsize); - 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) - deverr (21, 0, - "fragment size %ld is too small, minimum with block size %ld is %ld", - sblock.fs_fsize, sblock.fs_bsize, - sblock.fs_bsize / MAXFRAG); - 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) - deverr (22, 0, - "There is no block size that can support this disk"); - 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; - deverr (0, 0, - "With a block size of %ld %s %ld", 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)) - deverr (0, 0, "Minimum bytes per inode is %ld", - (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); - else if (!mapcramped) - deverr (0, 0, - "With %d bytes per inode," - " minimum cylinders per group is %ld", - density, mincpg); - } - if (mapcramped) - deverr (0, 0, - "With %ld sectors per cylinder," - " minimum cylinders per group is %ld", - sblock.fs_spc, mincpg); - if (inodecramped || mapcramped) - if (sblock.fs_bsize != bsize) - { - deverr (0, 0, - "This requires the block size to be changed from %d to %ld", - bsize, sblock.fs_bsize); - deverr (23, 0, - "and the fragment size to be changed from %d to %ld", - fsize, sblock.fs_fsize); - } - else - exit(23); - /* - * Calculate the number of cylinders per group - */ - sblock.fs_cpg = cpg; - if (sblock.fs_cpg % mincpc != 0) { - deverr (0, 0, - "%s groups must have a multiple of %ld cylinders", - 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) - deverr (24, 0, "panic (fs_cpg * fs_spc) %% NSPF != 0"); - if (sblock.fs_cpg < mincpg) - deverr (25, 0, - "cylinder groups must have at least %ld cylinders", mincpg); - else if (sblock.fs_cpg != cpg) - { - if (cpgflg && !mapcramped && !inodecramped) - exit(26); - deverr (0, 0, - "%s%s cylinders per group to %ld", - (cpgflg ? "" : "Warning: "), - ((mapcramped && inodecramped) - ? "Block size and bytes per inode restrict" - : mapcramped ? "Block size restricts" - : "Bytes per inode restrict"), - 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) - deverr (28, 0, "file systems must have at least one cylinder"); - /* - * 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)) - { - deverr (0, 0, - "Warning: insufficient space in super block for " - "rotational layout tables with nsect %ld and ntrak %ld", - sblock.fs_nsect, sblock.fs_ntrak); - deverr (0, 0, "File system performance may be impaired"); - 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) - { - deverr (0, 0, - "Inode blocks/cyl group (%ld) >= data blocks (%ld)", - cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, - sblock.fs_fpg / sblock.fs_frag); - deverr (29, 0, - "number of cylinders per cylinder group (%ld)" - " must be increased", sblock.fs_cpg); - } - 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) - deverr (30, 0, - "Filesystem must have at least %ld sectors", - NSPF(&sblock) - * (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); - deverr (0, 0, - "Warning: inode blocks/cyl group (%ld) >=" - " data blocks (%ld) in last cylinder group.", - ((cgdmin(&sblock, j) - cgbase(&sblock, j)) - / sblock.fs_frag), - i / sblock.fs_frag); - deverr (0, 0, - "This implies %ld sector(s) cannot be allocated", - 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) - deverr (0, 0, - "Warning: %ld sector(s) in last cylinder unallocated", - 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; - sblock.fs_clean = 1; - - /* - * Dump out summary information about file system. - */ - printf("%s:\n\t%ld sectors in %ld %s of %ld tracks, %ld 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 %ld cyl groups (%ld c/g, %.2fMB/g, %ld 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. - */ - printf("\tsuperblock backups at:"); - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { - initcg(cylno, utime); - if (cylno % 8 == 0) - printf("\n\t"); - printf(" %ld,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); - } - printf("\n"); - if (Nflag) - 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); -#if 0 /* Not in Hurd (yet) */ - /* - * 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; -#endif -} - -/* - * Initialize a cylinder group. - */ -void -initcg(cylno, utime) - int cylno; - time_t utime; -{ - long i; - daddr_t cbase, d, dlower, dupper, dmax, blkno; - 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) - deverr (37, 0, "Panic: cylinder group too big"); - 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; - i = dupper % sblock.fs_frag; - if (i) { - 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 directory_entry root_dir[] = { - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 1, "." }, - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 2, ".." }, -#ifdef LOSTDIR - { LOSTFOUNDINO, sizeof(struct directory_entry), DT_DIR, 10, "lost+found" }, -#endif -}; -struct odirectory_entry { - u_long d_ino; - u_short d_reclen; - u_short d_namlen; - u_char d_name[MAXNAMLEN + 1]; -} oroot_dir[] = { - { ROOTINO, sizeof(struct directory_entry), 1, "." }, - { ROOTINO, sizeof(struct directory_entry), 2, ".." }, -#ifdef LOSTDIR - { LOSTFOUNDINO, sizeof(struct directory_entry), 10, "lost+found" }, -#endif -}; -#ifdef LOSTDIR -struct directory_entry lost_found_dir[] = { - { LOSTFOUNDINO, sizeof(struct directory_entry), DT_DIR, 1, "." }, - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 2, ".." }, - { 0, DIRBLKSIZ, 0, 0, 0 }, -}; -struct odirectory_entry olost_found_dir[] = { - { LOSTFOUNDINO, sizeof(struct directory_entry), 1, "." }, - { ROOTINO, sizeof(struct directory_entry), 2, ".." }, - { 0, DIRBLKSIZ, 0, 0 }, -}; -#endif -char buf[MAXBSIZE]; - -void -fsinit(utime) - time_t utime; -{ - /* - * initialize the node - */ - node.di_atime.tv_sec = utime; - node.di_mtime.tv_sec = utime; - node.di_ctime.tv_sec = utime; -#ifdef LOSTDIR - /* - * create the lost+found directory - */ - if (Oflag) { - (void)makedir((struct directory_entry *)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_model = ifdir | UMASK; - node.di_modeh = 0; - node.di_nlink = 2; - node.di_size = sblock.fs_bsize; - node.di_db[0] = alloc(node.di_size, DI_MODE (&node)); - 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 - */ - node.di_model = IFDIR | UMASK; - node.di_modeh = 0; - node.di_nlink = PREDEFDIR; - - /* Set the uid/gid to non-root if run by a non-root user. This - is what mke2fs does in e2fsprogs-1.18 (actually it uses the - real IDs iff geteuid()!=0, but that is just wrong). */ - node.di_uid = geteuid(); - if (node.di_uid != 0) - node.di_gid = getegid(); - - if (Oflag) - node.di_size = makedir((struct directory_entry *)oroot_dir, PREDEFDIR); - else - node.di_size = makedir(root_dir, PREDEFDIR); - node.di_db[0] = alloc(sblock.fs_fsize, DI_MODE (&node)); - 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. - */ -int -makedir(protodir, entries) - register struct directory_entry *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) { - deverr (0, 0, "cg 0: bad magic number"); - return (0); - } - if (acg.cg_cs.cs_nbfree == 0) { - deverr (0, 0, "first cylinder group ran out of space"); - 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; - deverr (0, 0, "internal error: can't find block in cyl 0"); - 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 - */ -void -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) - deverr (31, 0, "cg 0: bad magic number"); - 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) - deverr (32, 0, "fsinit: inode value out of range (%Ld)", ino); - 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); -} - -/* - * read a block from the file system - */ -void -rdfs(bno, size, bf) - daddr_t bno; - int size; - char *bf; -{ - int n; - if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) - deverr (33, errno, "rdfs: %ld: seek error", bno); - n = read(fsi, bf, size); - if (n != size) - deverr (34, errno, "rdfs: %ld: read error", bno); -} - -/* - * write a block to the file system - */ -void -wtfs(bno, size, bf) - daddr_t bno; - int size; - char *bf; -{ - int n; - if (Nflag) - return; - if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) - deverr (35, errno, "wtfs: %ld: seek error", bno); - n = write(fso, bf, size); - if (n != size) - deverr (36, errno, "wtfs: %ld: write error", bno); -} - -/* - * check if a block is available - */ -int -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: - deverr (0, 0, "isblock bad fs_frag %ld", fs->fs_frag); - return (0); - } -} - -/* - * take a block out of the map - */ -void -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: - deverr (0, 0, "clrblock bad fs_frag %ld", fs->fs_frag); - return; - } -} - -/* - * put a block into the map - */ -void -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: - deverr (0, 0, "setblock bad fs_frag %ld", fs->fs_frag); - return; - } -} diff --git a/ufs-utils/newfs.c b/ufs-utils/newfs.c deleted file mode 100644 index efc7dbea..00000000 --- a/ufs-utils/newfs.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * 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.2 1994/09/09 14:11:41 mib Exp $"; -#endif /* not lint */ - -/* - * newfs: friendly front end to mkfs - */ -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -/* #include <sys/disklabel.h> */ -#include <sys/file.h> -/* #include <sys/mount.h> */ - -#include "../ufs/dir.h" -#include "../ufs/fs.h" - -#include <ctype.h> -#include <errno.h> -#include <paths.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -/* #include "mntopts.h" */ - -/* GNU Hurd additions */ -#define MAXPATHLEN 2048 - -/* End GNU Hurd additions */ - - -#if 0 -struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_ASYNC, - { NULL }, -}; -#endif - -#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 0 - if (strstr(progname, "mfs")) { - mfs = 1; - Nflag++; - } -#endif - - 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 0 - if (mfs) - getmntopts(optarg, mopts, &mntflags); - else -#endif - { - 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)); - -#if 0 - /* 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; - } -#endif - } -#if 0 - 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); - } -#endif - /* GNU Hurd specific here */ - 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)); - fssize = st.st_size; - /* End GNU Hurd specific */ - - 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); -} diff --git a/ufs-utils/stati.c b/ufs-utils/stati.c deleted file mode 100644 index ba545bf2..00000000 --- a/ufs-utils/stati.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rich $alz of BBN Inc. - * - * 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) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; - -static char copyright[] __attribute__ ((unused)); -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)clri.c 8.2 (Berkeley) 9/23/93"; -static char sccsid[] __attribute__ ((unused)); -#endif /* not lint */ - -/* Modified by Michael I. Bushnell for GNU Hurd. */ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/stat.h> - -#include "../ufs/dinode.h" -#include "../ufs/fs.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <time.h> -#include <unistd.h> -#include <pwd.h> -#include <grp.h> - -#define MAXPHYS (64 * 1024) -#define DEV_BSIZE 512 - -/* Returns a nice representation of a file mode in a static buffer. */ -static char * -mode_rep (unsigned short mode) -{ - static char buf[30]; - char *p = buf; - - void add_perms (int shift, unsigned sid_mask) - { - unsigned short smode = mode << shift; - *p++ = (smode & S_IREAD) ? 'r' : '-'; - *p++ = (smode & S_IWRITE) ? 'w' : '-'; - *p++ = (smode & S_IEXEC) ? ((mode & sid_mask) ? 's' : 'x') : '-'; - } - - switch (mode & S_IFMT) - { - case S_IFREG: *p++ = '-'; break; - case S_IFDIR: *p++ = 'd'; break; - case S_IFCHR: *p++ = 'c'; break; - case S_IFBLK: *p++ = 'b'; break; - case S_IFLNK: *p++ = 'l'; break; - case S_IFSOCK:*p++ = 'p'; break; - case S_IFIFO: *p++ = 'f'; break; - default: *p++ = '?'; - } - - add_perms (0, S_ISUID); - add_perms (3, S_ISGID); - add_perms (6, 0); - - snprintf (p, buf + sizeof buf - p, " [0%0o]", mode); - - return buf; -} - -/* Returns a nice representation of a struct timespec in a static buffer. */ -static char * -timespec_rep (struct timespec *ts) -{ - static char buf[200]; - char *p = buf; - if (ts->tv_sec || ts->tv_nsec) - { - time_t time = ts->tv_sec; - strcpy (buf, ctime (&time)); - p += strlen (buf); - if (p[-1] == '\n') - p--; - *p++ = ' '; - } - snprintf (p, buf + sizeof buf - p, "[%ld, %ld]", ts->tv_sec, ts->tv_nsec); - return buf; -} - -/* Returns a nice representation of a uid in a static buffer. */ -static char * -uid_rep (uid_t uid) -{ - static char buf[200]; - struct passwd *pw = getpwuid (uid); - if (pw) - snprintf (buf, sizeof buf, "%d(%s)", uid, pw->pw_name); - else - snprintf (buf, sizeof buf, "%d", uid); - return buf; -} - -/* Returns a nice representation of a gid in a static buffer. */ -static char * -gid_rep (gid_t gid) -{ - static char buf[200]; - struct group *gr = getgrgid (gid); - if (gr) - snprintf (buf, sizeof buf, "%d(%s)", gid, gr->gr_name); - else - snprintf (buf, sizeof buf, "%d", gid); - return buf; -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register struct fs *sbp; - register struct dinode *ip; - register int fd; - struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)]; - long bsize; - off_t offset; - int inonum; - char *fs, sblock[SBSIZE]; - - if (argc < 3) { - (void)fprintf(stderr, "usage: stati filesystem inode ...\n"); - exit(1); - } - - fs = *++argv; - - /* get the superblock. */ - if ((fd = open(fs, O_RDWR, 0)) < 0) - { - perror (fs); - exit (1); - } - if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) { - (void)fprintf(stderr, - "stati: %s: can't read the superblock.\n", fs); - exit(1); - } - - sbp = (struct fs *)sblock; - if (sbp->fs_magic != FS_MAGIC) { - (void)fprintf(stderr, - "stati: %s: superblock magic number 0x%lux, not 0x%x.\n", - fs, sbp->fs_magic, FS_MAGIC); - exit(1); - } - bsize = sbp->fs_bsize; - - /* remaining arguments are inode numbers. */ - while (*++argv) { - int i; - - /* get the inode number. */ - if ((inonum = atoi(*argv)) <= 0) { - (void)fprintf(stderr, - "stati: %s is not a valid inode number.\n", *argv); - exit(1); - } - - /* read in the appropriate block. */ - offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */ - offset = fsbtodb(sbp, offset); /* fs blk disk blk */ - offset *= DEV_BSIZE; /* disk blk to bytes */ - - /* seek and read the block */ - if (lseek(fd, offset, SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - - /* get the inode within the block. */ - ip = &ibuf[ino_to_fsbo(sbp, inonum)]; - - if (argc > 3) - printf ("inode: %d\n", inonum); - - printf ("mode: %s\n", mode_rep (ip->di_model)); - printf ("nlink: %d\n", ip->di_nlink); - printf ("size: %qd\n", ip->di_size); - printf ("atime: %s\n", timespec_rep (&ip->di_atime)); - printf ("mtime: %s\n", timespec_rep (&ip->di_mtime)); - printf ("ctime: %s\n", timespec_rep (&ip->di_ctime)); - printf ("flags: %#lx\n", ip->di_flags); - printf ("blocks: %ld\n", ip->di_blocks); - printf ("gener: %ld\n", ip->di_gen); - printf ("uid: %s\n", uid_rep (ip->di_uid)); - printf ("gid: %s\n", gid_rep (ip->di_gid)); - printf ("dblks: "); - for (i = 0; i < NDADDR; i++) - printf ("%s%ld", (i == 0 ? "" : ", "), ip->di_db[i]); - putchar ('\n'); - printf ("iblks: "); - for (i = 0; i < NIADDR; i++) - printf ("%s%ld", (i == 0 ? "" : ", "), ip->di_ib[i]); - putchar ('\n'); - printf ("trans: %ld\n", ip->di_trans); - - if (argv[1]) - putchar ('\n'); - } - (void)close(fd); - exit(0); -} diff --git a/ufs/Makefile b/ufs/Makefile deleted file mode 100644 index b66a6259..00000000 --- a/ufs/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Makefile for ufs -# -# Copyright (C) 1994,95,96,99,2000,02,12 Free Software Foundation, Inc. -# -# 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. - -dir := ufs -makemode := server - -target = ufs -SRCS = alloc.c consts.c dir.c hyper.c inode.c main.c pager.c \ - sizes.c subr.c tables.c bmap.c pokeloc.c xinl.c - -OBJS = $(SRCS:.c=.o) -HURDLIBS = diskfs iohelp fshelp store pager ports ihash shouldbeinlibc -OTHERLIBS = -lpthread - -include ../Makeconf - -ufs.static: $(boot-store-types:%=../libstore/libstore_%.a) diff --git a/ufs/alloc.c b/ufs/alloc.c deleted file mode 100644 index 9056a8b7..00000000 --- a/ufs/alloc.c +++ /dev/null @@ -1,1703 +0,0 @@ -/* Disk allocation routines - Copyright (C) 1993,94,95,96,98,2002 Free Software Foundation, Inc. - -This file is part of the GNU Hurd. - -The GNU Hurd 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. - -The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Modified from UCB by Michael I. Bushnell. */ -/* - * Copyright (c) 1982, 1986, 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. - * - * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 - */ - -#include "ufs.h" -#include <stdio.h> -#include <string.h> - - -/* These don't work *at all* here; don't even try setting them. */ -#undef DIAGNOSTIC -#undef QUOTA - -extern u_long nextgennumber; - -pthread_spinlock_t alloclock = PTHREAD_SPINLOCK_INITIALIZER; - -/* Forward declarations */ -static u_long ffs_hashalloc (struct node *, int, long, int, - u_long (*)(struct node *, int, daddr_t, int)); -static u_long ffs_alloccg (struct node *, int, daddr_t, int); -static daddr_t ffs_fragextend (struct node *, int, long, int, int); -static ino_t ffs_dirpref (struct fs *); -static u_long ffs_nodealloccg (struct node *, int, daddr_t, int); -static daddr_t ffs_alloccgblk (struct fs *, struct cg *, daddr_t); -static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int); -static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); - -/* Sync all allocation information and nod eNP if diskfs_synchronous. */ -inline void -alloc_sync (struct node *np) -{ - if (diskfs_synchronous) - { - if (np) - diskfs_node_update (np, 1); - copy_sblock (); - diskfs_set_hypermetadata (1, 0); - sync_disk (1); - } -} - -/* Byteswap everything in CGP. */ -void -swab_cg (struct cg *cg) -{ - int i, j; - - if (swab_long (cg->cg_magic) == CG_MAGIC - || cg->cg_magic == CG_MAGIC) - { - cg->cg_magic = swab_long (cg->cg_magic); - cg->cg_time = swab_long (cg->cg_time); - cg->cg_cgx = swab_long (cg->cg_cgx); - cg->cg_ncyl = swab_short (cg->cg_ncyl); - cg->cg_niblk = swab_short (cg->cg_niblk); - cg->cg_cs.cs_ndir = swab_long (cg->cg_cs.cs_ndir); - cg->cg_cs.cs_nbfree = swab_long (cg->cg_cs.cs_nbfree); - cg->cg_cs.cs_nifree = swab_long (cg->cg_cs.cs_nifree); - cg->cg_cs.cs_nffree = swab_long (cg->cg_cs.cs_nffree); - cg->cg_rotor = swab_long (cg->cg_rotor); - cg->cg_irotor = swab_long (cg->cg_irotor); - for (i = 0; i < MAXFRAG; i++) - cg->cg_frsum[i] = swab_long (cg->cg_frsum[i]); - cg->cg_btotoff = swab_long (cg->cg_btotoff); - cg->cg_boff = swab_long (cg->cg_boff); - cg->cg_iusedoff = swab_long (cg->cg_iusedoff); - cg->cg_freeoff = swab_long (cg->cg_freeoff); - cg->cg_nextfreeoff = swab_long (cg->cg_nextfreeoff); - cg->cg_clustersumoff = swab_long (cg->cg_clustersumoff); - cg->cg_clusteroff = swab_long (cg->cg_clusteroff); - cg->cg_nclusterblks = swab_long (cg->cg_nclusterblks); - - /* blktot map */ - for (i = 0; i < cg->cg_ncyl; i++) - cg_blktot(cg)[i] = swab_long (cg_blktot(cg)[i]); - - /* blks map */ - for (i = 0; i < cg->cg_ncyl; i++) - for (j = 0; j < sblock->fs_nrpos; j++) - cg_blks(sblock, cg, i)[j] = swab_short (cg_blks (sblock, cg, i)[j]); - - for (i = 0; i < sblock->fs_contigsumsize; i++) - cg_clustersum(cg)[i] = swab_long (cg_clustersum(cg)[i]); - - /* inosused, blksfree, and cg_clustersfree are char arrays */ - } - else - { - /* Old format cylinder group... */ - struct ocg *ocg = (struct ocg *) cg; - - if (swab_long (ocg->cg_magic) != CG_MAGIC - && ocg->cg_magic != CG_MAGIC) - return; - - ocg->cg_time = swab_long (ocg->cg_time); - ocg->cg_cgx = swab_long (ocg->cg_cgx); - ocg->cg_ncyl = swab_short (ocg->cg_ncyl); - ocg->cg_niblk = swab_short (ocg->cg_niblk); - ocg->cg_ndblk = swab_long (ocg->cg_ndblk); - ocg->cg_cs.cs_ndir = swab_long (ocg->cg_cs.cs_ndir); - ocg->cg_cs.cs_nbfree = swab_long (ocg->cg_cs.cs_nbfree); - ocg->cg_cs.cs_nifree = swab_long (ocg->cg_cs.cs_nifree); - ocg->cg_cs.cs_nffree = swab_long (ocg->cg_cs.cs_nffree); - ocg->cg_rotor = swab_long (ocg->cg_rotor); - ocg->cg_frotor = swab_long (ocg->cg_frotor); - ocg->cg_irotor = swab_long (ocg->cg_irotor); - for (i = 0; i < 8; i++) - ocg->cg_frsum[i] = swab_long (ocg->cg_frsum[i]); - for (i = 0; i < 32; i++) - ocg->cg_btot[i] = swab_long (ocg->cg_btot[i]); - for (i = 0; i < 32; i++) - for (j = 0; j < 8; j++) - ocg->cg_b[i][j] = swab_short (ocg->cg_b[i][j]); - ocg->cg_magic = swab_long (ocg->cg_magic); - } -} - - -/* Read cylinder group indexed CG. Set *CGPP to point at it. - Return 1 if caller should call release_cgp when we're done with it; - otherwise zero. */ -int -read_cg (int cg, struct cg **cgpp) -{ - struct cg *diskcg = cg_locate (cg); - - if (swab_disk) - { - *cgpp = malloc (sblock->fs_cgsize); - bcopy (diskcg, *cgpp, sblock->fs_cgsize); - swab_cg (*cgpp); - return 1; - } - else - { - *cgpp = diskcg; - return 0; - } -} - -/* Caller of read_cg is done with cg; write it back to disk (swapping it - along the way) and free the memory allocated in read_cg. */ -void -release_cg (struct cg *cgp) -{ - int cgx = cgp->cg_cgx; - swab_cg (cgp); - bcopy (cgp, cg_locate (cgx), sblock->fs_cgsize); - free (cgp); -} - - -/* - * Allocate a block in the file system. - * - * The size of the requested block is given, which must be some - * multiple of fs_fsize and <= fs_bsize. - * A preference may be optionally specified. If a preference is given - * the following hierarchy is used to allocate a block: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate a block in the same cylinder group. - * 4) quadradically rehash into other cylinder groups, until an - * available block is located. - * If no block preference is given the following hierarchy is used - * to allocate a block: - * 1) allocate a block in the cylinder group that contains the - * inode for the file. - * 2) quadradically rehash into other cylinder groups, until an - * available block is located. - */ -error_t -ffs_alloc(register struct node *np, - daddr_t lbn, - daddr_t bpref, - int size, - daddr_t *bnp, - struct protid *cred) -{ - register struct fs *fs; - daddr_t bno; - int cg; - - *bnp = 0; - fs = sblock; -#ifdef DIAGNOSTIC - if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { - printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", - ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); - panic("ffs_alloc: bad size"); - } - assert (cred); -#endif /* DIAGNOSTIC */ - pthread_spin_lock (&alloclock); - if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) - goto nospace; - if (cred && !idvec_contains (cred->user->uids, 0) - && freespace(fs, fs->fs_minfree) <= 0) - goto nospace; -#ifdef QUOTA - if (error = chkdq(ip, (long)btodb(size), cred, 0)) - return (error); -#endif - if (bpref >= fs->fs_size) - bpref = 0; - if (bpref == 0) - cg = ino_to_cg(fs, np->dn->number); - else - cg = dtog(fs, bpref); - bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, size, - (u_long (*)())ffs_alloccg); - if (bno > 0) { - pthread_spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(size); - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - *bnp = bno; - alloc_sync (np); - return (0); - } -#ifdef QUOTA - /* - * Restore user's disk quota because allocation failed. - */ - (void) chkdq(ip, (long)-btodb(size), cred, FORCE); -#endif -nospace: - pthread_spin_unlock (&alloclock); - printf ("file system full"); -/* ffs_fserr(fs, cred->cr_uid, "file system full"); */ -/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */ - return (ENOSPC); -} - -/* - * Reallocate a fragment to a bigger size - * - * The number and size of the old block is given, and a preference - * and new size is also specified. The allocator attempts to extend - * the original block. Failing that, the regular block allocator is - * invoked to get an appropriate block. - */ -error_t -ffs_realloccg(register struct node *np, - daddr_t lbprev, - volatile daddr_t bpref, - int osize, - int nsize, - daddr_t *pbn, - struct protid *cred) -{ - register struct fs *fs; - int cg, error; - volatile int request; - daddr_t bprev, bno; - - *pbn = 0; - fs = sblock; -#ifdef DIAGNOSTIC - if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || - (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { - printf( - "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", - ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); - panic("ffs_realloccg: bad size"); - } - if (cred == NOCRED) - panic("ffs_realloccg: missing credential\n"); -#endif /* DIAGNOSTIC */ - - pthread_spin_lock (&alloclock); - - if (!idvec_contains (cred->user->uids, 0) - && freespace(fs, fs->fs_minfree) <= 0) - goto nospace; - error = diskfs_catch_exception (); - if (error) - return error; - bprev = read_disk_entry ((dino (np->dn->number))->di_db[lbprev]); - diskfs_end_catch_exception (); - assert ("old block not allocated" && bprev); - -#if 0 /* Not needed in GNU Hurd ufs */ - /* - * Allocate the extra space in the buffer. - */ - if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) { - brelse(bp); - return (error); - } -#ifdef QUOTA - if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) { - brelse(bp); - return (error); - } -#endif -#endif /* 0 */ - - /* - * Check for extension in the existing location. - */ - cg = dtog(fs, bprev); - bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize); - if (bno) { - assert (bno == bprev); - pthread_spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(nsize - osize); - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - *pbn = bno; -#if 0 /* Not done this way in GNU Hurd ufs. */ - allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); - *bpp = bp; -#endif - alloc_sync (np); - return (0); - } - /* - * Allocate a new disk location. - */ - if (bpref >= fs->fs_size) - bpref = 0; - switch ((int)fs->fs_optim) { - case FS_OPTSPACE: - /* - * Allocate an exact sized fragment. Although this makes - * best use of space, we will waste time relocating it if - * the file continues to grow. If the fragmentation is - * less than half of the minimum free reserve, we choose - * to begin optimizing for time. - */ - request = nsize; - if (fs->fs_minfree < 5 || - fs->fs_cstotal.cs_nffree > - fs->fs_dsize * fs->fs_minfree / (2 * 100)) - break; - printf ("%s: optimization changed from SPACE to TIME\n", - fs->fs_fsmnt); - fs->fs_optim = FS_OPTTIME; - break; - case FS_OPTTIME: - /* - * At this point we have discovered a file that is trying to - * grow a small fragment to a larger fragment. To save time, - * we allocate a full sized block, then free the unused portion. - * If the file continues to grow, the `ffs_fragextend' call - * above will be able to grow it in place without further - * copying. If aberrant programs cause disk fragmentation to - * grow within 2% of the free reserve, we choose to begin - * optimizing for space. - */ - request = fs->fs_bsize; - if (fs->fs_cstotal.cs_nffree < - fs->fs_dsize * (fs->fs_minfree - 2) / 100) - break; - printf ("%s: optimization changed from TIME to SPACE\n", - fs->fs_fsmnt); - fs->fs_optim = FS_OPTSPACE; - break; - default: - assert (0); - /* NOTREACHED */ - } - bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, request, - (u_long (*)())ffs_alloccg); - if (bno > 0) { -#if 0 /* Not necessary in GNU Hurd ufs */ - bp->b_blkno = fsbtodb(fs, bno); - (void) vnode_pager_uncache(ITOV(ip)); -#endif -/* Commented out here for Hurd; we don't want to free this until we've - saved the old contents. Callers are responsible for freeing the - block when they are done with it. */ -/* ffs_blkfree(np, bprev, (long)osize); */ - if (nsize < request) - ffs_blkfree(np, bno + numfrags(fs, nsize), - (long)(request - nsize)); - pthread_spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(nsize - osize); - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - *pbn = bno; -#if 0 /* Not done this way in GNU Hurd ufs */ - allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); - *bpp = bp; -#endif /* 0 */ - alloc_sync (np); - return (0); - } -#ifdef QUOTA - /* - * Restore user's disk quota because allocation failed. - */ - (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE); -#endif -#if 0 /* Not necesarry in GNU Hurd ufs */ - brelse(bp); -#endif -nospace: - /* - * no space available - */ - pthread_spin_unlock (&alloclock); - printf ("file system full"); -/* ffs_fserr(fs, cred->cr_uid, "file system full"); */ -/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */ - return (ENOSPC); -} - -#if 0 /* Not used (yet?) in GNU Hurd ufs */ -/* - * Reallocate a sequence of blocks into a contiguous sequence of blocks. - * - * The vnode and an array of buffer pointers for a range of sequential - * logical blocks to be made contiguous is given. The allocator attempts - * to find a range of sequential blocks starting as close as possible to - * an fs_rotdelay offset from the end of the allocation for the logical - * block immediately preceding the current range. If successful, the - * physical block numbers in the buffer pointers and in the inode are - * changed to reflect the new allocation. If unsuccessful, the allocation - * is left unchanged. The success in doing the reallocation is returned. - * Note that the error return is not reflected back to the user. Rather - * the previous block allocation will be used. - */ -#include <sys/sysctl.h> -int doasyncfree = 1; -struct ctldebug debug14 = { "doasyncfree", &doasyncfree }; -int -ffs_reallocblks(ap) - struct vop_reallocblks_args /* { - struct vnode *a_vp; - struct cluster_save *a_buflist; - } */ *ap; -{ - struct fs *fs; - struct inode *ip; - struct vnode *vp; - struct buf *sbp, *ebp; - daddr_t *bap, *sbap, *ebap; - struct cluster_save *buflist; - daddr_t start_lbn, end_lbn, soff, eoff, newblk, blkno; - struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int i, len, start_lvl, end_lvl, pref, ssize; - - vp = ap->a_vp; - ip = VTOI(vp); - fs = ip->i_fs; - if (fs->fs_contigsumsize <= 0) - return (ENOSPC); - buflist = ap->a_buflist; - len = buflist->bs_nchildren; - start_lbn = buflist->bs_children[0]->b_lblkno; - end_lbn = start_lbn + len - 1; -#ifdef DIAGNOSTIC - for (i = 1; i < len; i++) - if (buflist->bs_children[i]->b_lblkno != start_lbn + i) - panic("ffs_reallocblks: non-cluster"); -#endif - /* - * If the latest allocation is in a new cylinder group, assume that - * the filesystem has decided to move and do not force it back to - * the previous cylinder group. - */ - if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) != - dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno))) - return (ENOSPC); - if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) || - ufs_getlbns(vp, end_lbn, end_ap, &end_lvl)) - return (ENOSPC); - /* - * Get the starting offset and block map for the first block. - */ - if (start_lvl == 0) { - sbap = &ip->i_db[0]; - soff = start_lbn; - } else { - idp = &start_ap[start_lvl - 1]; - if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) { - brelse(sbp); - return (ENOSPC); - } - sbap = (daddr_t *)sbp->b_data; - soff = idp->in_off; - } - /* - * Find the preferred location for the cluster. - */ - pref = ffs_blkpref(ip, start_lbn, soff, sbap); - /* - * If the block range spans two block maps, get the second map. - */ - if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { - ssize = len; - } else { -#ifdef DIAGNOSTIC - if (start_ap[start_lvl-1].in_lbn == idp->in_lbn) - panic("ffs_reallocblk: start == end"); -#endif - ssize = len - (idp->in_off + 1); - if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp)) - goto fail; - ebap = (daddr_t *)ebp->b_data; - } - /* - * Search the block map looking for an allocation of the desired size. - */ - if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref, - len, (u_long (*)())ffs_clusteralloc)) == 0) - goto fail; - /* - * We have found a new contiguous block. - * - * First we have to replace the old block pointers with the new - * block pointers in the inode and indirect blocks associated - * with the file. - */ - blkno = newblk; - for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) { - if (i == ssize) - bap = ebap; -#ifdef DIAGNOSTIC - if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) - panic("ffs_reallocblks: alloc mismatch"); -#endif - *bap++ = blkno; - } - /* - * Next we must write out the modified inode and indirect blocks. - * For strict correctness, the writes should be synchronous since - * the old block values may have been written to disk. In practise - * they are almost never written, but if we are concerned about - * strict correctness, the `doasyncfree' flag should be set to zero. - * - * The test on `doasyncfree' should be changed to test a flag - * that shows whether the associated buffers and inodes have - * been written. The flag should be set when the cluster is - * started and cleared whenever the buffer or inode is flushed. - * We can then check below to see if it is set, and do the - * synchronous write only when it has been cleared. - */ - if (sbap != &ip->i_db[0]) { - if (doasyncfree) - bdwrite(sbp); - else - bwrite(sbp); - } else { - ip->i_flag |= IN_CHANGE | IN_UPDATE; - if (!doasyncfree) - VOP_UPDATE(vp, &time, &time, MNT_WAIT); - } - if (ssize < len) - if (doasyncfree) - bdwrite(ebp); - else - bwrite(ebp); - /* - * Last, free the old blocks and assign the new blocks to the buffers. - */ - for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) { - ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), - fs->fs_bsize); - buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); - } - return (0); - -fail: - if (ssize < len) - brelse(ebp); - if (sbap != &ip->i_db[0]) - brelse(sbp); - return (ENOSPC); -} -#endif /* 0 */ - -/* - * Allocate an inode in the file system. - * - * If allocating a directory, use ffs_dirpref to select the inode. - * If allocating in a directory, the following hierarchy is followed: - * 1) allocate the preferred inode. - * 2) allocate an inode in the same cylinder group. - * 3) quadradically rehash into other cylinder groups, until an - * available inode is located. - * If no inode preference is given the following hierarchy is used - * to allocate an inode: - * 1) allocate an inode in cylinder group 0. - * 2) quadradically rehash into other cylinder groups, until an - * available inode is located. - */ -/* This is now the diskfs_alloc_node callback from the diskfs library - (described in <hurd/diskfs.h>). It used to be ffs_valloc in BSD. */ -error_t -diskfs_alloc_node (struct node *dir, - mode_t mode, - struct node **npp) -{ - register struct fs *fs; - struct node *np; - ino_t ino, ipref; - int cg, error; - int sex; - - fs = sblock; - - - pthread_spin_lock (&alloclock); - - if (fs->fs_cstotal.cs_nifree == 0) - { - pthread_spin_unlock (&alloclock); - goto noinodes; - } - - if (S_ISDIR (mode)) - ipref = ffs_dirpref(fs); - else - ipref = dir->dn->number; - - if (ipref >= fs->fs_ncg * fs->fs_ipg) - ipref = 0; - cg = ino_to_cg(fs, ipref); - ino = (ino_t)ffs_hashalloc(dir, cg, (long)ipref, - mode, ffs_nodealloccg); - pthread_spin_unlock (&alloclock); - if (ino == 0) - goto noinodes; - error = diskfs_cached_lookup (ino, &np); - assert ("duplicate allocation" && !np->dn_stat.st_mode); - assert (! (np->dn_stat.st_mode & S_IPTRANS)); - if (np->dn_stat.st_blocks) { - printf("free inode %Ld had %Ld blocks\n", - ino, np->dn_stat.st_blocks); - np->dn_stat.st_blocks = 0; - np->dn_set_ctime = 1; - } - np->dn_stat.st_flags = 0; - /* - * Set up a new generation number for this inode. - */ - pthread_spin_lock (&gennumberlock); - sex = diskfs_mtime->seconds; - if (++nextgennumber < (u_long)sex) - nextgennumber = sex; - np->dn_stat.st_gen = nextgennumber; - pthread_spin_unlock (&gennumberlock); - - *npp = np; - alloc_sync (np); - return (0); -noinodes: - printf ("out of inodes"); -/* ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); */ -/* uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);*/ - return (ENOSPC); -} - -/* - * Find a cylinder to place a directory. - * - * The policy implemented by this algorithm is to select from - * among those cylinder groups with above the average number of - * free inodes, the one with the smallest number of directories. - */ -static ino_t -ffs_dirpref(register struct fs *fs) -{ - int cg, minndir, mincg, avgifree; - - avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; - minndir = fs->fs_ipg; - mincg = 0; - for (cg = 0; cg < fs->fs_ncg; cg++) - if (csum[cg].cs_ndir < minndir && - csum[cg].cs_nifree >= avgifree) { - mincg = cg; - minndir = csum[cg].cs_ndir; - } - return ((ino_t)(fs->fs_ipg * mincg)); -} - -/* - * Select the desired position for the next block in a file. The file is - * logically divided into sections. The first section is composed of the - * direct blocks. Each additional section contains fs_maxbpg blocks. - * - * If no blocks have been allocated in the first section, the policy is to - * request a block in the same cylinder group as the inode that describes - * the file. If no blocks have been allocated in any other section, the - * policy is to place the section in a cylinder group with a greater than - * average number of free blocks. An appropriate cylinder group is found - * by using a rotor that sweeps the cylinder groups. When a new group of - * blocks is needed, the sweep begins in the cylinder group following the - * cylinder group from which the previous allocation was made. The sweep - * continues until a cylinder group with greater than the average number - * of free blocks is found. If the allocation is for the first block in an - * indirect block, the information on the previous allocation is unavailable; - * here a best guess is made based upon the logical block number being - * allocated. - * - * If a section is already partially allocated, the policy is to - * contiguously allocate fs_maxcontig blocks. The end of one of these - * contiguous blocks and the beginning of the next is physically separated - * so that the disk head will be in transit between them for at least - * fs_rotdelay milliseconds. This is to allow time for the processor to - * schedule another I/O transfer. - */ -daddr_t -ffs_blkpref(struct node *np, - daddr_t lbn, - int indx, - daddr_t *bap) -{ - register struct fs *fs; - register int cg; - int avgbfree, startcg; - daddr_t nextblk; - - fs = sblock; - pthread_spin_lock (&alloclock); - if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { - if (lbn < NDADDR) { - cg = ino_to_cg(fs, np->dn->number); - pthread_spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - /* - * Find a cylinder with greater than average number of - * unused data blocks. - */ - if (indx == 0 || bap[indx - 1] == 0) - startcg = - (ino_to_cg(fs, np->dn->number) - + lbn / fs->fs_maxbpg); - else - startcg = dtog(fs, - read_disk_entry (bap[indx - 1])) + 1; - startcg %= fs->fs_ncg; - avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; - for (cg = startcg; cg < fs->fs_ncg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) { - fs->fs_cgrotor = cg; - pthread_spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - for (cg = 0; cg <= startcg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) { - fs->fs_cgrotor = cg; - pthread_spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - pthread_spin_unlock (&alloclock); - return 0; - } - pthread_spin_unlock (&alloclock); - /* - * One or more previous blocks have been laid out. If less - * than fs_maxcontig previous blocks are contiguous, the - * next block is requested contiguously, otherwise it is - * requested rotationally delayed by fs_rotdelay milliseconds. - */ - nextblk = read_disk_entry (bap[indx - 1]) + fs->fs_frag; - if (indx < fs->fs_maxcontig - || (read_disk_entry (bap[indx - fs->fs_maxcontig]) + - blkstofrags(fs, fs->fs_maxcontig) != nextblk)) - { - return (nextblk); - } - if (fs->fs_rotdelay != 0) - /* - * Here we convert ms of delay to frags as: - * (frags) = (ms) * (rev/sec) * (sect/rev) / - * ((sect/frag) * (ms/sec)) - * then round up to the next block. - */ - nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / - (NSPF(fs) * 1000), fs->fs_frag); - return (nextblk); -} - -/* - * Implement the cylinder overflow algorithm. - * - * The policy implemented by this algorithm is: - * 1) allocate the block in its requested cylinder group. - * 2) quadradically rehash on the cylinder group number. - * 3) brute force search for a free block. - */ -/*VARARGS5*/ -static u_long -ffs_hashalloc(struct node *np, - int cg, - long pref, - int size, /* size for data blocks, mode for inodes */ - u_long (*allocator)()) -{ - register struct fs *fs; - long result; - int i, icg = cg; - - fs = sblock; - /* - * 1: preferred cylinder group - */ - result = (*allocator)(np, cg, pref, size); - if (result) - return (result); - /* - * 2: quadratic rehash - */ - for (i = 1; i < fs->fs_ncg; i *= 2) { - cg += i; - if (cg >= fs->fs_ncg) - cg -= fs->fs_ncg; - result = (*allocator)(np, cg, 0, size); - if (result) - return (result); - } - /* - * 3: brute force search - * Note that we start at i == 2, since 0 was checked initially, - * and 1 is always checked in the quadratic rehash. - */ - cg = (icg + 2) % fs->fs_ncg; - for (i = 2; i < fs->fs_ncg; i++) { - result = (*allocator)(np, cg, 0, size); - if (result) - return (result); - cg++; - if (cg == fs->fs_ncg) - cg = 0; - } - return 0; -} - -/* - * Determine whether a fragment can be extended. - * - * Check to see if the necessary fragments are available, and - * if they are, allocate them. - */ -static daddr_t -ffs_fragextend(struct node *np, - int cg, - long bprev, - int osize, - int nsize) -{ - register struct fs *fs; - struct cg *cgp; - long bno; - int frags, bbase; - int i; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nffree < numfrags(fs, nsize - osize)) - return 0; - frags = numfrags(fs, nsize); - bbase = fragnum(fs, bprev); - if (bbase > fragnum(fs, (bprev + frags - 1))) { - /* cannot extend across a block boundary */ - return 0; - } -#if 0 /* Wrong for GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(fs, bprev); - for (i = numfrags(fs, osize); i < frags; i++) - if (isclr(cg_blksfree(cgp), bno + i)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - /* - * the current fragment can be extended - * deduct the count on fragment being extended into - * increase the count on the remaining fragment (if any) - * allocate the extended piece - */ - for (i = frags; i < fs->fs_frag - bbase; i++) - if (isclr(cg_blksfree(cgp), bno + i)) - break; - cgp->cg_frsum[i - numfrags(fs, osize)]--; - if (i != frags) - cgp->cg_frsum[i - frags]++; - for (i = numfrags(fs, osize); i < frags; i++) { - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree--; - fs->fs_cstotal.cs_nffree--; - csum[cg].cs_nffree--; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; -/* bdwrite(bp); */ - return (bprev); -} - -/* - * Determine whether a block can be allocated. - * - * Check to see if a block of the appropriate size is available, - * and if it is, allocate it. - */ -static u_long -ffs_alloccg(struct node *np, - int cg, - daddr_t bpref, - int size) -{ - register struct fs *fs; - struct cg *cgp; - register int i; - int bno, frags, allocsiz; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize) - return 0; -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp) || - (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (size == fs->fs_bsize) { - bno = ffs_alloccgblk(fs, cgp, bpref); -/* bdwrite(bp); */ - if (releasecg) - release_cg (cgp); - return (bno); - } - /* - * check to see if any fragments are already available - * allocsiz is the size which will be allocated, hacking - * it down to a smaller size if necessary - */ - frags = numfrags(fs, size); - for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) - if (cgp->cg_frsum[allocsiz] != 0) - break; - if (allocsiz == fs->fs_frag) { - /* - * no fragments were available, so a block will be - * allocated, and hacked up - */ - if (cgp->cg_cs.cs_nbfree == 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - bno = ffs_alloccgblk(fs, cgp, bpref); - bpref = dtogd(fs, bno); - for (i = frags; i < fs->fs_frag; i++) - setbit(cg_blksfree(cgp), bpref + i); - i = fs->fs_frag - frags; - cgp->cg_cs.cs_nffree += i; - fs->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - fs->fs_fmod = 1; - cgp->cg_frsum[i]++; - - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (bno); - } - bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); - if (bno < 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - for (i = 0; i < frags; i++) - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree -= frags; - fs->fs_cstotal.cs_nffree -= frags; - csum[cg].cs_nffree -= frags; - fs->fs_fmod = 1; - cgp->cg_frsum[allocsiz]--; - if (frags != allocsiz) - cgp->cg_frsum[allocsiz - frags]++; - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (cg * fs->fs_fpg + bno); -} - -/* - * Allocate a block in a cylinder group. - * - * This algorithm implements the following policy: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate the next available block on the block rotor for the - * specified cylinder group. - * Note that this routine only allocates fs_bsize blocks; these - * blocks may be fragmented by the routine that allocates them. - */ -static daddr_t -ffs_alloccgblk(register struct fs *fs, - register struct cg *cgp, - daddr_t bpref) -{ - daddr_t bno, blkno; - int cylno, pos, delta; - short *cylbp; - register int i; - - if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) { - bpref = cgp->cg_rotor; - goto norot; - } - bpref = blknum(fs, bpref); - bpref = dtogd(fs, bpref); - /* - * if the requested block is available, use it - */ - if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) { - bno = bpref; - goto gotit; - } - /* - * check for a block available on the same cylinder - */ - cylno = cbtocylno(fs, bpref); - if (cg_blktot(cgp)[cylno] == 0) - goto norot; - if (fs->fs_cpc == 0) { - /* - * Block layout information is not available. - * Leaving bpref unchanged means we take the - * next available free block following the one - * we just allocated. Hopefully this will at - * least hit a track cache on drives of unknown - * geometry (e.g. SCSI). - */ - goto norot; - } - /* - * check the summary information to see if a block is - * available in the requested cylinder starting at the - * requested rotational position and proceeding around. - */ - cylbp = cg_blks(fs, cgp, cylno); - pos = cbtorpos(fs, bpref); - for (i = pos; i < fs->fs_nrpos; i++) - if (cylbp[i] > 0) - break; - if (i == fs->fs_nrpos) - for (i = 0; i < pos; i++) - if (cylbp[i] > 0) - break; - if (cylbp[i] > 0) { - /* - * found a rotational position, now find the actual - * block. A panic if none is actually there. - */ - pos = cylno % fs->fs_cpc; - bno = (cylno - pos) * fs->fs_spc / NSPB(fs); - assert (fs_postbl(fs, pos)[i] != -1); - for (i = fs_postbl(fs, pos)[i];; ) { - if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) { - bno = blkstofrags(fs, (bno + i)); - goto gotit; - } - delta = fs_rotbl(fs)[i]; - if (delta <= 0 || - delta + i > fragstoblks(fs, fs->fs_fpg)) - break; - i += delta; - } - printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); - assert (0); - } -norot: - /* - * no blocks in the requested cylinder, so take next - * available one in this cylinder group. - */ - bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); - if (bno < 0) - return 0; - cgp->cg_rotor = bno; -gotit: - blkno = fragstoblks(fs, bno); - ffs_clrblock(fs, cg_blksfree(cgp), (long)blkno); - ffs_clusteracct(fs, cgp, blkno, -1); - cgp->cg_cs.cs_nbfree--; - fs->fs_cstotal.cs_nbfree--; - csum[cgp->cg_cgx].cs_nbfree--; - cylno = cbtocylno(fs, bno); - cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; - cg_blktot(cgp)[cylno]--; - fs->fs_fmod = 1; - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - return (cgp->cg_cgx * fs->fs_fpg + bno); -} - -#if 0 /* Not needed in GNU Hurd ufs (yet?) */ -/* - * Determine whether a cluster can be allocated. - * - * We do not currently check for optimal rotational layout if there - * are multiple choices in the same cylinder group. Instead we just - * take the first one that we find following bpref. - */ -static daddr_t -ffs_clusteralloc(ip, cg, bpref, len) - struct inode *ip; - int cg; - daddr_t bpref; - int len; -{ - register struct fs *fs; - register struct cg *cgp; - struct buf *bp; - int i, run, bno, bit, map; - u_char *mapp; - - fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nbfree < len) - return (NULL); - if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, - NOCRED, &bp)) - goto fail; - cgp = (struct cg *)bp->b_data; - if (!cg_chkmagic(cgp)) - goto fail; - /* - * Check to see if a cluster of the needed size (or bigger) is - * available in this cylinder group. - */ - for (i = len; i <= fs->fs_contigsumsize; i++) - if (cg_clustersum(cgp)[i] > 0) - break; - if (i > fs->fs_contigsumsize) - goto fail; - /* - * Search the cluster map to find a big enough cluster. - * We take the first one that we find, even if it is larger - * than we need as we prefer to get one close to the previous - * block allocation. We do not search before the current - * preference point as we do not want to allocate a block - * that is allocated before the previous one (as we will - * then have to wait for another pass of the elevator - * algorithm before it will be read). We prefer to fail and - * be recalled to try an allocation in the next cylinder group. - */ - if (dtog(fs, bpref) != cg) - bpref = 0; - else - bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref))); - mapp = &cg_clustersfree(cgp)[bpref / NBBY]; - map = *mapp++; - bit = 1 << (bpref % NBBY); - for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) { - if ((map & bit) == 0) { - run = 0; - } else { - run++; - if (run == len) - break; - } - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - if (i == cgp->cg_nclusterblks) - goto fail; - /* - * Allocate the cluster that we have found. - */ - bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1); - len = blkstofrags(fs, len); - for (i = 0; i < len; i += fs->fs_frag) - if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i) - panic("ffs_clusteralloc: lost block"); - brelse(bp); - return (bno); - -fail: - brelse(bp); - return (0); -} -#endif - -/* - * Determine whether an inode can be allocated. - * - * Check to see if an inode is available, and if it is, - * allocate it using the following policy: - * 1) allocate the requested inode. - * 2) allocate the next available inode after the requested - * inode in the specified cylinder group. - */ -static u_long -ffs_nodealloccg(struct node *np, - int cg, - daddr_t ipref, - int mode) -{ - register struct fs *fs; - struct cg *cgp; - int start, len, loc, map, i; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nifree == 0) - return 0; -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (ipref) { - ipref %= fs->fs_ipg; - if (isclr(cg_inosused(cgp), ipref)) - goto gotit; - } - start = cgp->cg_irotor / NBBY; - len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY); - loc = skpc(0xff, len, &cg_inosused(cgp)[start]); - if (loc == 0) { - len = start + 1; - start = 0; - loc = skpc(0xff, len, &cg_inosused(cgp)[0]); - assert (loc != 0); - } - i = start + len - loc; - map = cg_inosused(cgp)[i]; - ipref = i * NBBY; - for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { - if ((map & i) == 0) { - cgp->cg_irotor = ipref; - goto gotit; - } - } - assert (0); - /* NOTREACHED */ -gotit: - setbit(cg_inosused(cgp), ipref); - cgp->cg_cs.cs_nifree--; - fs->fs_cstotal.cs_nifree--; - csum[cg].cs_nifree--; - fs->fs_fmod = 1; - if ((mode & IFMT) == IFDIR) { - cgp->cg_cs.cs_ndir++; - fs->fs_cstotal.cs_ndir++; - csum[cg].cs_ndir++; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (cg * fs->fs_ipg + ipref); -} - -/* - * Free a block or fragment. - * - * The specified block or fragment is placed back in the - * free map. If a fragment is deallocated, a possible - * block reassembly is checked. - */ -void -ffs_blkfree(register struct node *np, - daddr_t bno, - long size) -{ - register struct fs *fs; - struct cg *cgp; - daddr_t blkno; - int i, cg, blk, frags, bbase; - int releasecg; - - fs = sblock; - assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); - cg = dtog(fs, bno); - if ((u_int)bno >= fs->fs_size) { - printf("bad block %ld, ino %Ld\n", bno, np->dn->number); -/* ffs_fserr(fs, ip->i_uid, "bad block"); */ - return; - } -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return; - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(fs, bno); - if (size == fs->fs_bsize) { - blkno = fragstoblks(fs, bno); - assert (!ffs_isblock(fs, cg_blksfree (cgp), blkno)); - ffs_setblock(fs, cg_blksfree(cgp), blkno); - ffs_clusteracct(fs, cgp, blkno, 1); - cgp->cg_cs.cs_nbfree++; - fs->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(fs, bno); - cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++; - cg_blktot(cgp)[i]++; - } else { - bbase = bno - fragnum(fs, bno); - /* - * decrement the counts associated with the old frags - */ - blk = blkmap(fs, cg_blksfree(cgp), bbase); - ffs_fragacct(fs, blk, cgp->cg_frsum, -1); - /* - * deallocate the fragment - */ - frags = numfrags(fs, size); - for (i = 0; i < frags; i++) { - assert (!isset (cg_blksfree(cgp), bno + i)); - setbit(cg_blksfree(cgp), bno + i); - } - cgp->cg_cs.cs_nffree += i; - fs->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - /* - * add back in counts associated with the new frags - */ - blk = blkmap(fs, cg_blksfree(cgp), bbase); - ffs_fragacct(fs, blk, cgp->cg_frsum, 1); - /* - * if a complete block has been reassembled, account for it - */ - blkno = fragstoblks(fs, bbase); - if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { - cgp->cg_cs.cs_nffree -= fs->fs_frag; - fs->fs_cstotal.cs_nffree -= fs->fs_frag; - csum[cg].cs_nffree -= fs->fs_frag; - ffs_clusteracct(fs, cgp, blkno, 1); - cgp->cg_cs.cs_nbfree++; - fs->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(fs, bbase); - cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++; - cg_blktot(cgp)[i]++; - } - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; - alloc_sync (np); -/* bdwrite(bp); */ -} - -/* - * Free an inode. - * - * The specified inode is placed back in the free map. - */ -/* Implement diskfs call back diskfs_free_node (described in - <hurd/diskfs.h>. This was called ffs_vfree in BSD. */ -void -diskfs_free_node (struct node *np, mode_t mode) -{ - register struct fs *fs; - struct cg *cgp; - ino_t ino = np->dn->number; - int cg; - int releasecg; - - fs = sblock; - assert (ino < fs->fs_ipg * fs->fs_ncg); - cg = ino_to_cg(fs, ino); -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (0); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - ino %= fs->fs_ipg; - if (isclr(cg_inosused(cgp), ino)) { -/* printf("dev = 0x%x, ino = %Ld, fs = %s\n", - pip->i_dev, ino, fs->fs_fsmnt); */ - assert (diskfs_readonly); - } - clrbit(cg_inosused(cgp), ino); - if (ino < cgp->cg_irotor) - cgp->cg_irotor = ino; - cgp->cg_cs.cs_nifree++; - fs->fs_cstotal.cs_nifree++; - csum[cg].cs_nifree++; - if ((mode & IFMT) == IFDIR) { - cgp->cg_cs.cs_ndir--; - fs->fs_cstotal.cs_ndir--; - csum[cg].cs_ndir--; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; - alloc_sync (np); -/* bdwrite(bp); */ -} - -/* - * Find a block of the specified size in the specified cylinder group. - * - * It is a panic if a request is made to find a block if none are - * available. - */ -static daddr_t -ffs_mapsearch(register struct fs *fs, - register struct cg *cgp, - daddr_t bpref, - int allocsiz) -{ - daddr_t bno; - int start, len, loc, i; - int blk, field, subfield, pos; - - /* - * find the fragment by searching through the free block - * map for an appropriate bit pattern - */ - if (bpref) - start = dtogd(fs, bpref) / NBBY; - else - start = cgp->cg_frotor / NBBY; - len = howmany(fs->fs_fpg, NBBY) - start; - loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start], - (u_char *)fragtbl[fs->fs_frag], - (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); - if (loc == 0) { - len = start + 1; - start = 0; - loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0], - (u_char *)fragtbl[fs->fs_frag], - (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); - assert (loc); - - } - bno = (start + len - loc) * NBBY; - cgp->cg_frotor = bno; - /* - * found the byte in the map - * sift through the bits to find the selected frag - */ - for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { - blk = blkmap(fs, cg_blksfree(cgp), bno); - blk <<= 1; - field = around[allocsiz]; - subfield = inside[allocsiz]; - for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { - if ((blk & field) == subfield) - return (bno + pos); - field <<= 1; - subfield <<= 1; - } - } - assert (0); - return (-1); -} - -/* - * Update the cluster map because of an allocation or free. - * - * Cnt == 1 means free; cnt == -1 means allocating. - */ -static void -ffs_clusteracct(struct fs *fs, - struct cg *cgp, - daddr_t blkno, - int cnt) -{ - long *sump; - u_char *freemapp, *mapp; - int i, start, end, forw, back, map, bit; - - if (fs->fs_contigsumsize <= 0) - return; - freemapp = cg_clustersfree(cgp); - sump = cg_clustersum(cgp); - /* - * Allocate or clear the actual block. - */ - if (cnt > 0) - setbit(freemapp, blkno); - else - clrbit(freemapp, blkno); - /* - * Find the size of the cluster going forward. - */ - start = blkno + 1; - end = start + fs->fs_contigsumsize; - if (end >= cgp->cg_nclusterblks) - end = cgp->cg_nclusterblks; - mapp = &freemapp[start / NBBY]; - map = *mapp++; - bit = 1 << (start % NBBY); - for (i = start; i < end; i++) { - if ((map & bit) == 0) - break; - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - forw = i - start; - /* - * Find the size of the cluster going backward. - */ - start = blkno - 1; - end = start - fs->fs_contigsumsize; - if (end < 0) - end = -1; - mapp = &freemapp[start / NBBY]; - map = *mapp--; - bit = 1 << (start % NBBY); - for (i = start; i > end; i--) { - if ((map & bit) == 0) - break; - if ((i & (NBBY - 1)) != 0) { - bit >>= 1; - } else { - map = *mapp--; - bit = 1 << (NBBY - 1); - } - } - back = start - i; - /* - * Account for old cluster and the possibly new forward and - * back clusters. - */ - i = back + forw + 1; - if (i > fs->fs_contigsumsize) - i = fs->fs_contigsumsize; - sump[i] += cnt; - if (back > 0) - sump[back] -= cnt; - if (forw > 0) - sump[forw] -= cnt; -} - -#if 0 -/* - * Fserr prints the name of a file system with an error diagnostic. - * - * The form of the error message is: - * fs: error message - */ -static void -ffs_fserr(fs, uid, cp) - struct fs *fs; - u_int uid; - char *cp; -{ - - log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); -} -#endif diff --git a/ufs/bmap.c b/ufs/bmap.c deleted file mode 100644 index 1a138f39..00000000 --- a/ufs/bmap.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Interpretation of indirect block structure - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "ufs.h" - -/* For logical block number LBN of file NP, look it the block address, - giving the "path" of indirect blocks to the file, starting - with the least indirect. Fill *INDIRS with information for - the block. */ -error_t -fetch_indir_spec (struct node *np, volatile daddr_t lbn, - struct iblock_spec *indirs) -{ - struct dinode *di = dino (np->dn->number); - error_t err; - daddr_t *siblock; - - err = diskfs_catch_exception (); - if (err) - return err; - - indirs[0].offset = -2; - indirs[1].offset = -2; - indirs[2].offset = -2; - indirs[3].offset = -2; - - if (lbn < NDADDR) - { - if (lbn >= 0) - { - indirs[0].bno = read_disk_entry (di->di_db[lbn]); - indirs[0].offset = -1; - } - - diskfs_end_catch_exception (); - return 0; - } - - lbn -= NDADDR; - - indirs[0].offset = lbn % NINDIR (sblock); - - if (lbn / NINDIR (sblock)) - { - /* We will use the double indirect block */ - int ibn; - daddr_t *diblock; - - ibn = lbn / NINDIR (sblock) - 1; - - indirs[1].offset = ibn % NINDIR (sblock); - - /* We don't support triple indirect blocks, but this - is where we'd do it. */ - assert (!(ibn / NINDIR (sblock))); - - indirs[2].offset = -1; - indirs[2].bno = read_disk_entry (di->di_ib[INDIR_DOUBLE]); - - if (indirs[2].bno) - { - diblock = indir_block (indirs[2].bno); - indirs[1].bno = read_disk_entry (diblock[indirs[1].offset]); - } - else - indirs[1].bno = 0; - } - else - { - indirs[1].offset = -1; - indirs[1].bno = read_disk_entry (di->di_ib[INDIR_SINGLE]); - } - - if (indirs[1].bno) - { - siblock = indir_block (indirs[1].bno); - indirs[0].bno = read_disk_entry (siblock[indirs[0].offset]); - } - else - indirs[0].bno = 0; - - diskfs_end_catch_exception (); - return 0; -} - - -/* Mark indirect block BNO as dirty on node NP's list. NP must - be locked. */ -void -mark_indir_dirty (struct node *np, daddr_t bno) -{ - struct dirty_indir *d; - - for (d = np->dn->dirty; d; d = d->next) - if (d->bno == bno) - return; - - d = malloc (sizeof (struct dirty_indir)); - d->bno = bno; - d->next = np->dn->dirty; - np->dn->dirty = d; -} - diff --git a/ufs/consts.c b/ufs/consts.c deleted file mode 100644 index 69221233..00000000 --- a/ufs/consts.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Various constants wanted by the diskfs library - Copyright (C) 1994, 1995, 1996, 1999 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. */ - -#include "ufs.h" -#include "dir.h" -#include <version.h> - -int diskfs_link_max = LINK_MAX; -int diskfs_name_max = MAXNAMLEN; -int diskfs_maxsymlinks = 8; -int diskfs_shortcut_symlink = 1; -int diskfs_shortcut_chrdev = 1; -int diskfs_shortcut_blkdev = 1; -int diskfs_shortcut_fifo = 1; -int diskfs_shortcut_ifsock = 1; -char *diskfs_server_name = "ufs"; -char *diskfs_server_version = HURD_VERSION; -char *diskfs_extra_version = "GNU Hurd"; -int diskfs_synchronous = 0; diff --git a/ufs/dinode.h b/ufs/dinode.h deleted file mode 100644 index 00be0d94..00000000 --- a/ufs/dinode.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - 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. */ - -/* - * Copyright (c) 1982, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * 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. - * - * @(#)dinode.h 8.3 (Berkeley) 1/21/94 - */ - -/* - * The root inode is the root of the file system. Inode 0 can't be used for - * normal purposes and historically bad blocks were linked to inode 1, thus - * the root inode is 2. (Inode 1 is no longer used for this purpose, however - * numerous dump tapes make this assumption, so we are stuck with it). - */ -#define ROOTINO ((ino_t)2) - -/* - * A dinode contains all the meta-data associated with a UFS file. - * This structure defines the on-disk format of a dinode. - */ - -#define NDADDR 12 /* Direct addresses in inode. */ -#define NIADDR 3 /* Indirect addresses in inode. */ - -/* Maximum value of di_nlink field. */ -#define LINK_MAX 32767 - -/* Indexes into di_ib */ -#define INDIR_SINGLE 0 -#define INDIR_DOUBLE 1 -#define INDIR_TRIPLE 2 /* NOT SUPPORTED */ - -struct dinode { - u_short di_model; /* 0: IFMT and permissions. */ - short di_nlink; /* 2: File link count. */ - union - { - u_long diu_author; /* 4: File author */ - u_short diu_oldids[2]; /* Old format uid and gid */ - } di_u; - u_quad_t di_size; /* 8: File byte count. */ - struct timespec di_atime; /* 16: Last access time. */ - struct timespec di_mtime; /* 24: Last modified time. */ - struct timespec di_ctime; /* 32: Last inode change time. */ - daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ - daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ - u_long di_flags; /* 100: Status flags (chflags). */ - long di_blocks; /* 104: Blocks actually held. */ - long di_gen; /* 108: Generation number. */ - u_long di_uid; /* 112: File owner. */ - u_long di_gid; /* 116: File group. */ - u_short di_modeh; /* 120: Mode high bits */ - u_short di_spare; /* 122: unused */ - long di_trans; /* 124: filesystem translator */ -}; - -#define di_author di_u.diu_author /* GNU extension */ -#define di_ouid di_u.diu_oldids[0] -#define di_ogid di_u.diu_oldids[1] - -/* - * The di_db fields may be overlaid with other information for - * file types that do not have associated disk storage. Block - * and character devices overlay the first data block with their - * dev_t value. Short symbolic links place their path in the - * di_db area. - */ -#define di_rdev di_db[0] -#define di_shortlink di_db -#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(daddr_t)) - -/* File modes. */ -#define IEXEC 0000100 /* Executable. */ -#define IWRITE 0000200 /* Writeable. */ -#define IREAD 0000400 /* Readable. */ -#define ISVTX 0001000 /* Sticky bit. */ -#define ISGID 0002000 /* Set-gid. */ -#define ISUID 0004000 /* Set-uid. */ - -/* File types. */ -#define IFMT 0170000 /* Mask of file type. */ -#define IFIFO 0010000 /* Named pipe (fifo). */ -#define IFCHR 0020000 /* Character device. */ -#define IFDIR 0040000 /* Directory file. */ -#define IFBLK 0060000 /* Block device. */ -#define IFREG 0100000 /* Regular file. */ -#define IFLNK 0120000 /* Symbolic link. */ -#define IFSOCK 0140000 /* UNIX domain socket. */ diff --git a/ufs/dir.c b/ufs/dir.c deleted file mode 100644 index c3bd424e..00000000 --- a/ufs/dir.c +++ /dev/null @@ -1,988 +0,0 @@ -/* Directory management routines - - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2007 - Free Software Foundation, Inc. - - 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. */ - -#include "ufs.h" -#include "dir.h" - -#include <string.h> -#include <stdio.h> -#include <dirent.h> - -#undef d_ino - -enum slot_status -{ - /* This means we haven't yet found room for a new entry. */ - LOOKING, - - /* This means that the specified entry is free and should be used. */ - TAKE, - - /* This means that the specified entry has enough room at the end - to hold the new entry. */ - SHRINK, - - /* This means that there is enough space in the block, but not in - any one single entry, so they all have to be shifted to make - room. */ - COMPRESS, - - /* This means that the directory will have to be grown to hold the - entry. */ - EXTEND, - - /* For removal and rename, this means that this is the location - of the entry found. */ - HERE_TIS, -}; - -struct dirstat -{ - /* Type of followp operation expected */ - enum lookup_type type; - - /* One of the statuses above */ - enum slot_status stat; - - /* Mapped address and length of directory */ - vm_address_t mapbuf; - vm_size_t mapextent; - - /* Index of this directory block. */ - int idx; - - /* For stat COMPRESS, this is the address (inside mapbuf) - of the first direct in the directory block to be compressed. */ - /* For stat HERE_TIS, SHRINK, and TAKE, this is the entry referenced. */ - struct directory_entry *entry; - - /* For stat HERE_TIS, type REMOVE, this is the address of the immediately - previous direct in this directory block, or zero if this is the first. */ - struct directory_entry *preventry; - - /* For stat COMPRESS, this is the number of bytes needed to be copied - in order to undertake the compression. */ - size_t nbytes; -}; - -const size_t diskfs_dirstat_size = sizeof (struct dirstat); - -/* Initialize DS such that diskfs_drop_dirstat will ignore it. */ -void -diskfs_null_dirstat (struct dirstat *ds) -{ - ds->type = LOOKUP; -} - -static error_t -dirscanblock (vm_address_t blockoff, struct node *dp, int idx, - const char *name, int namelen, enum lookup_type type, - struct dirstat *ds, ino_t *inum); - -/* Implement the diskfs_lookup from the diskfs library. See - <hurd/diskfs.h> for the interface specification. */ -error_t -diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, - struct node **npp, struct dirstat *ds, struct protid *cred) -{ - error_t err; - ino_t inum; - int namelen; - int spec_dotdot; - struct node *np = 0; - int retry_dotdot = 0; - memory_object_t memobj; - vm_prot_t prot = - (type == LOOKUP) ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_WRITE); - vm_address_t buf = 0; - vm_size_t buflen = 0; - int blockaddr; - int idx, lastidx; - int looped; - - if ((type == REMOVE) || (type == RENAME)) - assert (npp); - - if (npp) - *npp = 0; - - spec_dotdot = type & SPEC_DOTDOT; - type &= ~SPEC_DOTDOT; - - namelen = strlen (name); - - if (namelen > MAXNAMLEN) - { - if (ds) - diskfs_null_dirstat (ds); - return ENAMETOOLONG; - } - - try_again: - if (ds) - { - ds->type = LOOKUP; - ds->mapbuf = 0; - ds->mapextent = 0; - } - if (buf) - { - munmap ((caddr_t) buf, buflen); - buf = 0; - } - if (ds && (type == CREATE || type == RENAME)) - ds->stat = LOOKING; - - /* Map in the directory contents. */ - memobj = diskfs_get_filemap (dp, prot); - - if (memobj == MACH_PORT_NULL) - return errno; - - buf = 0; - /* We allow extra space in case we have to do an EXTEND. */ - buflen = round_page (dp->dn_stat.st_size + DIRBLKSIZ); - err = vm_map (mach_task_self (), - &buf, buflen, 0, 1, memobj, 0, 0, prot, prot, 0); - mach_port_deallocate (mach_task_self (), memobj); - - inum = 0; - - diskfs_set_node_atime (dp); - - /* Start the lookup at DP->dn->dir_idx. */ - idx = dp->dn->dir_idx; - if (idx * DIRBLKSIZ > dp->dn_stat.st_size) - idx = 0; /* just in case */ - blockaddr = buf + idx * DIRBLKSIZ; - looped = (idx == 0); - lastidx = idx; - if (lastidx == 0) - lastidx = dp->dn_stat.st_size / DIRBLKSIZ; - - while (!looped || idx < lastidx) - { - err = dirscanblock (blockaddr, dp, idx, name, namelen, type, ds, &inum); - if (!err) - { - dp->dn->dir_idx = idx; - break; - } - if (err != ENOENT) - { - munmap ((caddr_t) buf, buflen); - return err; - } - - blockaddr += DIRBLKSIZ; - idx++; - if (blockaddr - buf >= dp->dn_stat.st_size && !looped) - { - /* We've gotten to the end; start back at the beginning */ - looped = 1; - blockaddr = buf; - idx = 0; - } - } - - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - - /* If err is set here, it's ENOENT, and we don't want to - think about that as an error yet. */ - err = 0; - - if (inum && npp) - { - if (namelen != 2 || name[0] != '.' || name[1] != '.') - { - if (inum == dp->dn->number) - { - np = dp; - diskfs_nref (np); - } - else - { - err = diskfs_cached_lookup (inum, &np); - if (err) - goto out; - } - } - - /* We are looking up .. */ - /* Check to see if this is the root of the filesystem. */ - else if (dp->dn->number == 2) - { - err = EAGAIN; - goto out; - } - - /* We can't just do diskfs_cached_lookup, because we would then deadlock. - So we do this. Ick. */ - else if (retry_dotdot) - { - /* Check to see that we got the same answer as last time. */ - if (inum != retry_dotdot) - { - /* Drop what we *thought* was .. (but isn't any more) and - try *again*. */ - diskfs_nput (np); - pthread_mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); - pthread_mutex_lock (&dp->lock); - if (err) - goto out; - retry_dotdot = inum; - goto try_again; - } - /* Otherwise, we got it fine and np is already set properly. */ - } - else if (!spec_dotdot) - { - /* Lock them in the proper order, and then - repeat the directory scan to see if this is still - right. */ - pthread_mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); - pthread_mutex_lock (&dp->lock); - if (err) - goto out; - retry_dotdot = inum; - goto try_again; - } - - /* Here below are the spec dotdot cases. */ - else if (type == RENAME || type == REMOVE) - np = ifind (inum); - - else if (type == LOOKUP) - { - diskfs_nput (dp); - err = diskfs_cached_lookup (inum, &np); - if (err) - goto out; - } - else - assert (0); - } - - if ((type == CREATE || type == RENAME) && !inum && ds && ds->stat == LOOKING) - { - /* We didn't find any room, so mark ds to extend the dir */ - ds->type = CREATE; - ds->stat = EXTEND; - ds->idx = dp->dn_stat.st_size / DIRBLKSIZ; - } - - /* Return to the user; if we can't, release the reference - (and lock) we acquired above. */ - out: - /* Deallocate or save the mapping. */ - if ((err && err != ENOENT) - || !ds - || ds->type == LOOKUP) - { - munmap ((caddr_t) buf, buflen); - if (ds) - ds->type = LOOKUP; /* set to be ignored by drop_dirstat */ - } - else - { - ds->mapbuf = buf; - ds->mapextent = buflen; - } - - if (np) - { - assert (npp); - if (err) - { - if (!spec_dotdot) - { - /* Normal case */ - if (np == dp) - diskfs_nrele (np); - else - diskfs_nput (np); - } - else if (type == RENAME || type == REMOVE) - /* We just did ifind to get np; that allocates - no new references, so we don't have anything to do */ - ; - else if (type == LOOKUP) - /* We did diskfs_cached_lookup */ - diskfs_nput (np); - } - else - *npp = np; - } - - return err ? : inum ? 0 : ENOENT; -} - -/* Scan block at address BLKADDR (of node DP; block index IDX), for - name NAME of length NAMELEN. Args TYPE, DS are as for - diskfs_lookup. If found, set *INUM to the inode number, else - return ENOENT. */ -static error_t -dirscanblock (vm_address_t blockaddr, struct node *dp, int idx, - const char *name, int namelen, enum lookup_type type, - struct dirstat *ds, ino_t *inum) -{ - int nfree = 0; - int needed = 0; - vm_address_t currentoff, prevoff; - struct directory_entry *entry = 0; - int nentries = 0; - size_t nbytes = 0; - int looking = 0; - int countcopies = 0; - int consider_compress = 0; - - if (ds && (ds->stat == LOOKING - || ds->stat == COMPRESS)) - { - looking = 1; - countcopies = 1; - needed = DIRSIZ (namelen); - } - - for (currentoff = blockaddr, prevoff = 0; - currentoff < blockaddr + DIRBLKSIZ; - prevoff = currentoff, currentoff += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *)currentoff; - - if (!entry->d_reclen - || read_disk_entry (entry->d_reclen) % 4 - || DIRECT_NAMLEN (entry) > MAXNAMLEN - || (currentoff + read_disk_entry (entry->d_reclen) - > blockaddr + DIRBLKSIZ) - || entry->d_name[DIRECT_NAMLEN (entry)] - || DIRSIZ (DIRECT_NAMLEN (entry)) > read_disk_entry (entry->d_reclen) - || memchr (entry->d_name, '\0', DIRECT_NAMLEN (entry))) - { - fprintf (stderr, "Bad directory entry: inode: %Ld offset: %zd\n", - dp->dn->number, currentoff - blockaddr + idx * DIRBLKSIZ); - return ENOENT; - } - - if (looking || countcopies) - { - int thisfree; - - /* Count how much free space this entry has in it. */ - if (entry->d_ino == 0) - thisfree = read_disk_entry (entry->d_reclen); - else - thisfree = (read_disk_entry (entry->d_reclen) - - DIRSIZ (DIRECT_NAMLEN (entry))); - - /* If this isn't at the front of the block, then it will - have to be copied if we do a compression; count the - number of bytes there too. */ - if (countcopies && currentoff != blockaddr) - nbytes += DIRSIZ (DIRECT_NAMLEN (entry)); - - if (ds->stat == COMPRESS && nbytes > ds->nbytes) - /* The previously found compress is better than - this one, so don't bother counting any more. */ - countcopies = 0; - - if (thisfree >= needed) - { - ds->type = CREATE; - ds->stat = read_disk_entry (entry->d_ino) == 0 ? TAKE : SHRINK; - ds->entry = entry; - ds->idx = idx; - looking = countcopies = 0; - } - else - { - nfree += thisfree; - if (nfree >= needed) - consider_compress = 1; - } - } - - if (entry->d_ino) - nentries++; - - if (DIRECT_NAMLEN (entry) == namelen - && entry->d_name[0] == name[0] - && entry->d_ino - && !bcmp (entry->d_name, name, namelen)) - break; - } - - if (consider_compress - && (ds->type == LOOKING - || (ds->type == COMPRESS && ds->nbytes > nbytes))) - { - ds->type = CREATE; - ds->stat = COMPRESS; - ds->entry = (struct directory_entry *) blockaddr; - ds->idx = idx; - ds->nbytes = nbytes; - } - - if (currentoff >= blockaddr + DIRBLKSIZ) - { - int i; - /* The name is not in this block. */ - - /* Because we scanned the entire block, we should write - down how many entries there were. */ - if (!dp->dn->dirents) - { - dp->dn->dirents = malloc ((dp->dn_stat.st_size / DIRBLKSIZ) - * sizeof (int)); - for (i = 0; i < dp->dn_stat.st_size/DIRBLKSIZ; i++) - dp->dn->dirents[i] = -1; - } - /* Make sure the count is correct if there is one now. */ - assert (dp->dn->dirents[idx] == -1 - || dp->dn->dirents[idx] == nentries); - dp->dn->dirents[idx] = nentries; - - return ENOENT; - } - - /* We have found the required name. */ - - if (ds && type == CREATE) - ds->type = LOOKUP; /* it's invalid now */ - else if (ds && (type == REMOVE || type == RENAME)) - { - ds->type = type; - ds->stat = HERE_TIS; - ds->entry = entry; - ds->idx = idx; - ds->preventry = (struct directory_entry *) prevoff; - } - - *inum = read_disk_entry (entry->d_ino); - return 0; -} - -/* Following a lookup call for CREATE, this adds a node to a directory. - DP is the directory to be modified; NAME is the name to be entered; - NP is the node being linked in; DS is the cached information returned - by lookup; CRED describes the user making the call. This call may - only be made if the directory has been held locked continuously since - the preceding lookup call, and only if that call returned ENOENT. */ -error_t -diskfs_direnter_hard(struct node *dp, - const char *name, - struct node *np, - struct dirstat *ds, - struct protid *cred) -{ - struct directory_entry *new; - int namelen = strlen (name); - int needed = DIRSIZ (namelen); - int oldneeded; - vm_address_t fromoff, tooff; - int totfreed; - error_t err; - size_t oldsize = 0; - - assert (ds->type == CREATE); - - dp->dn_set_mtime = 1; - - switch (ds->stat) - { - case TAKE: - /* We are supposed to consume this slot. */ - assert (ds->entry->d_ino == 0 - && read_disk_entry (ds->entry->d_reclen) >= needed); - - write_disk_entry (ds->entry->d_ino, np->dn->number); - DIRECT_NAMLEN (ds->entry) = namelen; - if (direct_symlink_extension) - ds->entry->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, ds->entry->d_name, namelen + 1); - - break; - - case SHRINK: - /* We are supposed to take the extra space at the end - of this slot. */ - oldneeded = DIRSIZ (DIRECT_NAMLEN (ds->entry)); - assert (read_disk_entry (ds->entry->d_reclen) - oldneeded >= needed); - - new = (struct directory_entry *) ((vm_address_t) ds->entry + oldneeded); - - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, - read_disk_entry (ds->entry->d_reclen) - oldneeded); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - - write_disk_entry (ds->entry->d_reclen, oldneeded); - - break; - - case COMPRESS: - /* We are supposed to move all the entries to the - front of the block, giving each the minimum - necessary room. This should free up enough space - for the new entry. */ - fromoff = tooff = (vm_address_t) ds->entry; - - while (fromoff < (vm_address_t) ds->entry + DIRBLKSIZ) - { - struct directory_entry *from = (struct directory_entry *)fromoff; - struct directory_entry *to = (struct directory_entry *) tooff; - int fromreclen = read_disk_entry (from->d_reclen); - - if (from->d_ino != 0) - { - assert (fromoff >= tooff); - - bcopy (from, to, fromreclen); - write_disk_entry (to->d_reclen, DIRSIZ (DIRECT_NAMLEN (to))); - - tooff += read_disk_entry (to->d_reclen); - } - fromoff += fromreclen; - } - - totfreed = (vm_address_t) ds->entry + DIRBLKSIZ - tooff; - assert (totfreed >= needed); - - new = (struct directory_entry *) tooff; - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, totfreed); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - break; - - case EXTEND: - /* Extend the file. */ - assert (needed <= DIRBLKSIZ); - - oldsize = dp->dn_stat.st_size; - if ((off_t)(oldsize + DIRBLKSIZ) != dp->dn_stat.st_size + DIRBLKSIZ) - { - /* We can't possibly map the whole directory in. */ - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - return EOVERFLOW; - } - while (oldsize + DIRBLKSIZ > dp->allocsize) - { - err = diskfs_grow (dp, oldsize + DIRBLKSIZ, cred); - if (err) - { - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - return err; - } - } - - new = (struct directory_entry *) (ds->mapbuf + oldsize); - - dp->dn_stat.st_size = oldsize + DIRBLKSIZ; - dp->dn_set_ctime = 1; - - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, DIRBLKSIZ); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - break; - - default: - assert (0); - } - - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - if (ds->stat != EXTEND) - { - /* If we are keeping count of this block, then keep the count up - to date. */ - if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1) - dp->dn->dirents[ds->idx]++; - } - else - { - int i; - /* It's cheap, so start a count here even if we aren't counting - anything at all. */ - if (dp->dn->dirents) - { - dp->dn->dirents = realloc (dp->dn->dirents, - (dp->dn_stat.st_size / DIRBLKSIZ - * sizeof (int))); - for (i = oldsize / DIRBLKSIZ; - i < dp->dn_stat.st_size / DIRBLKSIZ; - i++) - dp->dn->dirents[i] = -1; - - dp->dn->dirents[ds->idx] = 1; - } - else - { - dp->dn->dirents = malloc (dp->dn_stat.st_size / DIRBLKSIZ - * sizeof (int)); - for (i = 0; i < dp->dn_stat.st_size / DIRBLKSIZ; i++) - dp->dn->dirents[i] = -1; - dp->dn->dirents[ds->idx] = 1; - } - } - - diskfs_file_update (dp, 1); - - return 0; -} - -/* Following a lookup call for REMOVE, this removes the link from the - directory. DP is the directory being changed and DS is the cached - information returned from lookup. This call is only valid if the - directory has been locked continuously since the call to lookup, and - only if that call succeeded. */ -error_t -diskfs_dirremove_hard(struct node *dp, - struct dirstat *ds) -{ - assert (ds->type == REMOVE); - assert (ds->stat == HERE_TIS); - - dp->dn_set_mtime = 1; - - if (ds->preventry == 0) - ds->entry->d_ino = 0; - else - { - assert ((vm_address_t) ds->entry - (vm_address_t) ds->preventry - == read_disk_entry (ds->preventry->d_reclen)); - write_disk_entry (ds->preventry->d_reclen, - (read_disk_entry (ds->preventry->d_reclen) - + read_disk_entry (ds->entry->d_reclen))); - } - - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - /* If we are keeping count of this block, then keep the count up - to date. */ - if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1) - dp->dn->dirents[ds->idx]--; - - diskfs_file_update (dp, 1); - - return 0; -} - - -/* Following a lookup call for RENAME, this changes the inode number - on a directory entry. DP is the directory being changed; NP is - the new node being linked in; DP is the cached information returned - by lookup. This call is only valid if the directory has been locked - continuously since the call to lookup, and only if that call - succeeded. */ -error_t -diskfs_dirrewrite_hard(struct node *dp, - struct node *np, - struct dirstat *ds) -{ - assert (ds->type == RENAME); - assert (ds->stat == HERE_TIS); - - dp->dn_set_mtime = 1; - write_disk_entry (ds->entry->d_ino, np->dn->number); - if (direct_symlink_extension) - ds->entry->d_type = IFTODT (np->dn_stat.st_mode); - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - diskfs_file_update (dp, 1); - - return 0; -} - -/* Tell if DP is an empty directory (has only "." and ".." entries). */ -/* This routine must be called from inside a catch_exception (). */ -int -diskfs_dirempty(struct node *dp, - struct protid *cred) -{ - struct directory_entry *entry; - vm_address_t buf, curoff; - memory_object_t memobj; - error_t err; - - memobj = diskfs_get_filemap (dp, VM_PROT_READ); - - if (memobj == MACH_PORT_NULL) - /* XXX should reflect error properly */ - return 0; - - buf = 0; - - err = vm_map (mach_task_self (), &buf, dp->dn_stat.st_size, 0, - 1, memobj, 0, 0, VM_PROT_READ, VM_PROT_READ, 0); - mach_port_deallocate (mach_task_self (), memobj); - assert (!err); - - diskfs_set_node_atime (dp); - - for (curoff = buf; - curoff < buf + dp->dn_stat.st_size; - curoff += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *) curoff; - - if (entry->d_ino != 0 - && (DIRECT_NAMLEN (entry) > 2 - || entry->d_name[0] != '.' - || (entry->d_name[1] != '.' - && entry->d_name[1] != '\0'))) - { - munmap ((caddr_t) buf, dp->dn_stat.st_size); - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - return 0; - } - } - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - munmap ((caddr_t) buf, dp->dn_stat.st_size); - return 1; -} - -/* Make DS an invalid dirstat. */ -error_t -diskfs_drop_dirstat (struct node *dp, struct dirstat *ds) -{ - if (ds->type != LOOKUP) - { - assert (ds->mapbuf); - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - ds->type = LOOKUP; - } - return 0; -} - - -/* Count the entries in directory block NB for directory DP and - write the answer down in its dirents array. As a side affect - fill BUF with the block. */ -static error_t -count_dirents (struct node *dp, int nb, char *buf) -{ - size_t amt; - char *offinblk; - struct directory_entry *entry; - int count = 0; - error_t err; - - assert (dp->dn->dirents); - assert ((nb + 1) * DIRBLKSIZ <= dp->dn_stat.st_size); - - err = diskfs_node_rdwr (dp, buf, nb * DIRBLKSIZ, DIRBLKSIZ, 0, 0, &amt); - if (err) - return err; - assert (amt == DIRBLKSIZ); - - for (offinblk = buf; - offinblk < buf + DIRBLKSIZ; - offinblk += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *) offinblk; - if (entry->d_ino) - count++; - } - - assert (dp->dn->dirents[nb] == -1 || dp->dn->dirents[nb] == count); - dp->dn->dirents[nb] = count; - return 0; -} - -/* Implement the disikfs_get_directs callback as described in - <hurd/diskfs.h>. */ -error_t -diskfs_get_directs (struct node *dp, - int entry, - int nentries, - char **data, - size_t *datacnt, - vm_size_t bufsiz, - int *amt) -{ - int blkno; - int nblks; - int curentry; - char buf[DIRBLKSIZ]; - char *bufp; - int bufvalid; - error_t err; - int i; - char *datap; - struct directory_entry *entryp; - int allocsize; - size_t checklen; - struct dirent *userp; - - nblks = dp->dn_stat.st_size/DIRBLKSIZ; - - if (!dp->dn->dirents) - { - dp->dn->dirents = malloc (nblks * sizeof (int)); - for (i = 0; i < nblks; i++) - dp->dn->dirents[i] = -1; - } - - /* Scan through the entries to find ENTRY. If we encounter - a -1 in the process then stop to fill it. When we run - off the end, ENTRY is too big. */ - curentry = 0; - bufvalid = 0; - for (blkno = 0; blkno < nblks; blkno++) - { - if (dp->dn->dirents[blkno] == -1) - { - err = count_dirents (dp, blkno, buf); - if (err) - return err; - bufvalid = 1; - } - - if (curentry + dp->dn->dirents[blkno] > entry) - /* ENTRY starts in this block. */ - break; - - curentry += dp->dn->dirents[blkno]; - - bufvalid = 0; - } - - if (blkno == nblks) - { - /* We reached the end of the directory without seeing ENTRY. - This is treated as an EOF condition, meaning we return - success with empty results. */ - *datacnt = 0; - *amt = 0; - return 0; - } - - /* Allocate enough space to hold the maximum we might return */ - if (!bufsiz || bufsiz > dp->dn_stat.st_size) - allocsize = round_page (dp->dn_stat.st_size); - else - allocsize = round_page (bufsiz); - - if (allocsize > *datacnt) - *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - - /* Set bufp appropriately */ - bufp = buf; - if (curentry != entry) - { - /* Look through the block to find out where to start, - setting bufp appropriately. */ - if (!bufvalid) - { - err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ, - 0, 0, &checklen); - if (err) - return err; - assert (checklen == DIRBLKSIZ); - bufvalid = 1; - } - for (i = 0, bufp = buf; - i < entry - curentry && bufp - buf < DIRBLKSIZ; - (bufp - += read_disk_entry (((struct directory_entry *)bufp)->d_reclen)), - i++) - ; - /* Make sure we didn't run off the end. */ - assert (bufp - buf < DIRBLKSIZ); - } - - i = 0; - datap = *data; - - /* Copy the entries, one at a time. */ - while (((nentries == -1) || (i < nentries)) - && (!bufsiz || (datap - *data < bufsiz) ) - && blkno < nblks) - { - if (!bufvalid) - { - err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ, - 0, 0, &checklen); - if (err) - return err; - assert (checklen == DIRBLKSIZ); - bufvalid = 1; - bufp = buf; - } - - entryp = (struct directory_entry *)bufp; - - if (entryp->d_ino) - { - userp = (struct dirent *) datap; - - userp->d_fileno = read_disk_entry (entryp->d_ino); - userp->d_reclen = DIRSIZ (DIRECT_NAMLEN (entryp)); - userp->d_namlen = DIRECT_NAMLEN (entryp); - bcopy (entryp->d_name, userp->d_name, DIRECT_NAMLEN (entryp) + 1); - userp->d_type = DT_UNKNOWN; /* until fixed */ - i++; - datap += DIRSIZ (DIRECT_NAMLEN (entryp)); - } - - bufp += read_disk_entry (entryp->d_reclen); - if (bufp - buf == DIRBLKSIZ) - { - blkno++; - bufvalid = 0; - } - } - - /* We've copied all we can. If we allocated our own array - but didn't fill all of it, then free whatever memory we didn't use. */ - if (allocsize > *datacnt) - { - if (round_page (datap - *data) < allocsize) - munmap (*data + round_page (datap - *data), - allocsize - round_page (datap - *data)); - } - - /* Set variables for return */ - *datacnt = datap - *data; - *amt = i; - return 0; -} diff --git a/ufs/dir.h b/ufs/dir.h deleted file mode 100644 index 5730ef44..00000000 --- a/ufs/dir.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Modified from BSD by Michael I. Bushnell for GNU Hurd ufs server. */ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * 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. - * - * @(#)dir.h 8.2 (Berkeley) 1/21/94 - */ - -#ifndef _DIR_H_ -#define _DIR_H_ - -#include <endian.h> - -/* - * A directory consists of some number of blocks of DIRBLKSIZ - * bytes, where DIRBLKSIZ is chosen such that it can be transferred - * to disk in a single atomic operation (e.g. 512 bytes on most machines). - * - * Each DIRBLKSIZ byte block contains some number of directory entry - * structures, which are of variable length. Each directory entry has - * a struct direct at the front of it, containing its inode number, - * the length of the entry, and the length of the name contained in - * the entry. These are followed by the name padded to a 4 byte boundary - * with null bytes. All names are guaranteed null terminated. - * The maximum length of a name in a directory is MAXNAMLEN. - * - * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent - * a directory entry. Free space in a directory is represented by - * entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes - * in a directory block are claimed by the directory entries. This - * usually results in the last entry in a directory having a large - * dp->d_reclen. When entries are deleted from a directory, the - * space is returned to the previous entry in the same directory - * block by increasing its dp->d_reclen. If the first entry of - * a directory block is free, then its dp->d_ino is set to 0. - * Entries other than the first in a directory do not normally have - * dp->d_ino set to 0. - */ -#define DIRBLKSIZ DEV_BSIZE -#undef MAXNAMLEN -#define MAXNAMLEN 255 - -/* Don't call this struct DIRECT because the library defines that - (sometimes) in a possible different way. */ - -struct directory_entry { - u_long d_ino; /* inode number of entry */ - u_short d_reclen; /* length of this record */ - u_char d_type; /* file type, see below */ - u_char d_namlen; /* length of string in d_name */ - char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */ -}; - -/* Return the type from a struct directory_entry, paying attention to whether - this filesystem supports the type extension */ -#define DIRECT_TYPE(dp) (direct_symlink_extension ? (dp)->d_type : DT_UNKNOWN) - -/* Return the namlen from a struct direct, paying attention to whether - this filesystem supports the type extension */ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRECT_NAMLEN(dp) (*(direct_symlink_extension || swab_disk \ - ? &(dp)->d_namlen \ - : &(dp)->d_type)) -#else -#define DIRECT_NAMLEN(dp) (*(!direct_symlink_extension && swab_disk \ - ? &(dp)->d_type \ - : &(dp)->d_namlen)) -#endif - -/* - * The DIRSIZ macro gives the minimum record length which will hold - * the directory entry. This requires the amount of space in struct direct - * without the d_name field, plus enough space for the name with a terminating - * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. - */ -/* In BSD this macro takes a struct direct. Modified by MIB here to - take the namelen (as computed by strlen). */ -#define DIRSIZ(namelen) \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((namelen)+1 + 3) &~ 3)) - -#if 0 /* This is the BSD definition */ -#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 -#endif /* 0 */ - -#define OLDDIRFMT 1 -#define NEWDIRFMT 0 - -#if 0 /* Not used in GNU */ -/* - * 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 */ -}; -#endif /* 0 */ - -#endif /* !_DIR_H_ */ diff --git a/ufs/fs.h b/ufs/fs.h deleted file mode 100644 index a2a3cc9b..00000000 --- a/ufs/fs.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 1982, 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. - * - * @(#)fs.h 8.7 (Berkeley) 4/19/94 - */ - -/* - * Each disk drive contains some number of file systems. - * A file system consists of a number of cylinder groups. - * Each cylinder group has inodes and data. - * - * A file system is described by its super-block, which in turn - * describes the cylinder groups. The super-block is critical - * data and is replicated in each cylinder group to protect against - * catastrophic loss. This is done at `newfs' time and the critical - * super-block data does not change, so the copies need not be - * referenced further unless disaster strikes. - * - * For file system fs, the offsets of the various blocks of interest - * are given in the super block as: - * [fs->fs_sblkno] Super-block - * [fs->fs_cblkno] Cylinder group block - * [fs->fs_iblkno] Inode blocks - * [fs->fs_dblkno] Data blocks - * The beginning of cylinder group cg in fs, is given by - * the ``cgbase(fs, cg)'' macro. - * - * The first boot and super blocks are given in absolute disk addresses. - * The byte-offset forms are preferred, as they don't imply a sector size. - */ -#define BBSIZE 8192 -#define SBSIZE 8192 -#define BBOFF ((off_t)(0)) -#define SBOFF ((off_t)(BBOFF + BBSIZE)) -#define BBLOCK ((daddr_t)(0)) -#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) - -/* - * Addresses stored in inodes are capable of addressing fragments - * of `blocks'. File system blocks of at most size MAXBSIZE can - * be optionally broken into 2, 4, or 8 pieces, each of which is - * addressible; these pieces may be DEV_BSIZE, or some multiple of - * a DEV_BSIZE unit. - * - * Large files consist of exclusively large data blocks. To avoid - * undue wasted disk space, the last data block of a small file may be - * allocated as only as many fragments of a large block as are - * necessary. The file system format retains only a single pointer - * to such a fragment, which is a piece of a single large block that - * has been divided. The size of such a fragment is determinable from - * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. - * - * The file system records space availability at the fragment level; - * to determine block availability, aligned fragments are examined. - */ - -/* - * The file system is made out of blocks of at most MAXBSIZE units, with - * smaller units (fragments) only in the last direct block. MAXBSIZE - * primarily determines the size of buffers in the buffer pool. It may be - * made larger without any effect on existing file systems; however making - * it smaller make make some file systems unmountable. - */ -#define MAXBSIZE MAXPHYS -#define MAXFRAG 8 - -/* - * MINBSIZE is the smallest allowable block size. - * In order to insure that it is possible to create files of size - * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. - * MINBSIZE must be big enough to hold a cylinder group block, - * thus changes to (struct cg) must keep its size within MINBSIZE. - * Note that super blocks are always of size SBSIZE, - * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. - */ -#define MINBSIZE 4096 - -/* - * The path name on which the file system is mounted is maintained - * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in - * the super block for this name. - * The limit on the amount of summary information per file system - * is defined by MAXCSBUFS. It is currently parameterized for a - * maximum of two million cylinders. - */ -#define MAXMNTLEN 512 -#define MAXCSBUFS 32 - -/* - * A summary of contiguous blocks of various sizes is maintained - * in each cylinder group. Normally this is set by the initial - * value of fs_maxcontig. To conserve space, a maximum summary size - * is set by FS_MAXCONTIG. - */ -#define FS_MAXCONTIG 16 - -/* - * MINFREE gives the minimum acceptable percentage of file system - * blocks which may be free. If the freelist drops below this level - * only the superuser may continue to allocate blocks. This may - * be set to 0 if no reserve of free blocks is deemed necessary, - * however throughput drops by fifty percent if the file system - * is run at between 95% and 100% full; thus the minimum default - * value of fs_minfree is 5%. However, to get good clustering - * performance, 10% is a better choice. hence we use 10% as our - * default value. With 10% free space, fragmentation is not a - * problem, so we choose to optimize for time. - */ -#define MINFREE 5 -#define DEFAULTOPT FS_OPTTIME - -/* - * Per cylinder group information; summarized in blocks allocated - * from first cylinder group data blocks. These blocks have to be - * read in from fs_csaddr (size fs_cssize) in addition to the - * super block. - * - * N.B. sizeof(struct csum) must be a power of two in order for - * the ``fs_cs'' macro to work (see below). - */ -struct csum { - long cs_ndir; /* number of directories */ - long cs_nbfree; /* number of free blocks */ - long cs_nifree; /* number of free inodes */ - long cs_nffree; /* number of free frags */ -}; - -/* - * Super block for a file system. - */ -struct fs { - struct fs *fs_link; /* linked list of file systems */ - struct fs *fs_rlink; /* used for incore super blocks */ - daddr_t fs_sblkno; /* addr of super-block in filesys */ - daddr_t fs_cblkno; /* offset of cyl-block in filesys */ - daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ - daddr_t fs_dblkno; /* offset of first data after cg */ - long fs_cgoffset; /* cylinder group offset in cylinder */ - long fs_cgmask; /* used to calc mod fs_ntrak */ - time_t fs_time; /* last time written */ - long fs_size; /* number of blocks in fs */ - long fs_dsize; /* number of data blocks in fs */ - long fs_ncg; /* number of cylinder groups */ - long fs_bsize; /* size of basic blocks in fs */ - long fs_fsize; /* size of frag blocks in fs */ - long fs_frag; /* number of frags in a block in fs */ -/* these are configuration parameters */ - long fs_minfree; /* minimum percentage of free blocks */ - long fs_rotdelay; /* num of ms for optimal next block */ - long fs_rps; /* disk revolutions per second */ -/* these fields can be computed from the others */ - long fs_bmask; /* ``blkoff'' calc of blk offsets */ - long fs_fmask; /* ``fragoff'' calc of frag offsets */ - long fs_bshift; /* ``lblkno'' calc of logical blkno */ - long fs_fshift; /* ``numfrags'' calc number of frags */ -/* these are configuration parameters */ - long fs_maxcontig; /* max number of contiguous blks */ - long fs_maxbpg; /* max number of blks per cyl group */ -/* these fields can be computed from the others */ - long fs_fragshift; /* block to frag shift */ - long fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - long fs_sbsize; /* actual size of super block */ - long fs_csmask; /* csum block offset */ - long fs_csshift; /* csum block number */ - long fs_nindir; /* value of NINDIR */ - long fs_inopb; /* value of INOPB */ - long fs_nspf; /* value of NSPF */ -/* yet another configuration parameter */ - long fs_optim; /* optimization preference, see below */ -/* these fields are derived from the hardware */ - long fs_npsect; /* # sectors/track including spares */ - long fs_interleave; /* hardware sector interleave */ - long fs_trackskew; /* sector 0 skew, per track */ - long fs_headswitch; /* head switch time, usec */ - long fs_trkseek; /* track-to-track seek, usec */ -/* sizes determined by number of cylinder groups and their sizes */ - daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ - long fs_cssize; /* size of cyl grp summary area */ - long fs_cgsize; /* cylinder group size */ -/* these fields are derived from the hardware */ - long fs_ntrak; /* tracks per cylinder */ - long fs_nsect; /* sectors per track */ - long fs_spc; /* sectors per cylinder */ -/* this comes from the disk driver partitioning */ - long fs_ncyl; /* cylinders in file system */ -/* these fields can be computed from the others */ - long fs_cpg; /* cylinders per group */ - long fs_ipg; /* inodes per group */ - long fs_fpg; /* blocks per group * fs_frag */ -/* this data must be re-computed after crashes */ - struct csum fs_cstotal; /* cylinder summary information */ -/* these fields are cleared at mount time */ - char fs_fmod; /* super block modified flag */ - char fs_clean; /* file system is clean flag */ - char fs_ronly; /* mounted read-only flag */ - char fs_flags; /* currently unused flag */ - char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ -/* these fields retain the current block allocation info */ - long fs_cgrotor; /* last cg searched */ - struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */ - long fs_cpc; /* cyl per cycle in postbl */ - short fs_opostbl[16][8]; /* old rotation block list head */ - long fs_sparecon[50]; /* reserved for future constants */ - long fs_contigsumsize; /* size of cluster summary array */ - long fs_maxsymlinklen; /* max length of an internal symlink */ - long fs_inodefmt; /* format of on-disk inodes */ - u_quad_t fs_maxfilesize; /* maximum representable file size */ - quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */ - quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */ - long fs_state; /* validate fs_clean field */ - long fs_postblformat; /* format of positional layout tables */ - long fs_nrpos; /* number of rotational positions */ - long fs_postbloff; /* (short) rotation block list head */ - long fs_rotbloff; /* (u_char) blocks for each rotation */ - long fs_magic; /* magic number */ - u_char fs_space[1]; /* list of blocks for each rotation */ -/* actually longer */ -}; -/* - * Filesystem idetification - */ -#define FS_MAGIC 0x011954 /* the fast filesystem magic number */ -#define FS_OKAY 0x7c269d38 /* superblock checksum */ -#define FS_42INODEFMT -1 /* 4.2BSD inode format */ -#define FS_44INODEFMT 2 /* 4.4BSD inode format */ -/* - * Preference for optimization. - */ -#define FS_OPTTIME 0 /* minimize allocation time */ -#define FS_OPTSPACE 1 /* minimize disk fragmentation */ - -/* - * Rotational layout table format types - */ -#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ -#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ -/* - * Macros for access to superblock array structures - */ -#define fs_postbl(fs, cylno) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_opostbl[cylno]) \ - : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) -#define fs_rotbl(fs) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_space) \ - : ((u_char *)((char *)(fs) + (fs)->fs_rotbloff))) - -/* - * The size of a cylinder group is calculated by CGSIZE. The maximum size - * is limited by the fact that cylinder groups are at most one block. - * Its size is derived from the size of the maps maintained in the - * cylinder group and the (struct cg) size. - */ -#define CGSIZE(fs) \ - /* base cg */ (sizeof(struct cg) + sizeof(long) + \ - /* blktot size */ (fs)->fs_cpg * sizeof(long) + \ - /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \ - /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ - /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\ - /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ - /* cluster sum */ (fs)->fs_contigsumsize * sizeof(long) + \ - /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY))) - -#if 0 /* Wrong for GNU Hurd ufs; we don't use fs_csp at all. */ -/* - * Convert cylinder group to base address of its global summary info. - * - * N.B. This macro assumes that sizeof(struct csum) is a power of two. - */ -#define fs_cs(fs, indx) \ - fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] -#else -/* Global variable csum is declared in ufs.h; use it instead - of fs_cs stuff. */ -#define fs_cs(fs, indx) this will generate a syntax error. -#endif - -/* - * Cylinder group block for a file system. - */ -#define CG_MAGIC 0x090255 -struct cg { - struct cg *cg_link; /* linked list of cyl groups */ - long cg_magic; /* magic number */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[MAXFRAG]; /* counts of available frags */ - long cg_btotoff; /* (long) block totals per cylinder */ - long cg_boff; /* (short) free block positions */ - long cg_iusedoff; /* (char) used inode map */ - long cg_freeoff; /* (u_char) free block map */ - long cg_nextfreeoff; /* (u_char) next available space */ - long cg_clustersumoff; /* (long) counts of avail clusters */ - long cg_clusteroff; /* (char) free cluster map */ - long cg_nclusterblks; /* number of clusters this cg */ - long cg_sparecon[13]; /* reserved for future use */ - u_char cg_space[1]; /* space for cylinder group maps */ -/* actually longer */ -}; -/* - * Macros for access to cylinder group array structures - */ -#define cg_blktot(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_btot) \ - : ((long *)((char *)(cgp) + (cgp)->cg_btotoff))) -#define cg_blks(fs, cgp, cylno) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_b[cylno]) \ - : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) -#define cg_inosused(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_iused) \ - : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) -#define cg_blksfree(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_free) \ - : ((u_char *)((char *)(cgp) + (cgp)->cg_freeoff))) -#define cg_chkmagic(cgp) \ - ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) -#define cg_clustersfree(cgp) \ - ((u_char *)((char *)(cgp) + (cgp)->cg_clusteroff)) -#define cg_clustersum(cgp) \ - ((long *)((char *)(cgp) + (cgp)->cg_clustersumoff)) - -/* - * The following structure is defined - * for compatibility with old file systems. - */ -struct ocg { - struct ocg *cg_link; /* linked list of cyl groups */ - struct ocg *cg_rlink; /* used for incore cyl groups */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[8]; /* counts of available frags */ - long cg_btot[32]; /* block totals per cylinder */ - short cg_b[32][8]; /* positions of free blocks */ - char cg_iused[256]; /* used inode map */ - long cg_magic; /* magic number */ - u_char cg_free[1]; /* free block map */ -/* actually longer */ -}; - -/* - * Turn file system block numbers into disk block addresses. - * This maps file system blocks to device size blocks. - */ -#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) -#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) - -/* - * Cylinder group macros to locate things in cylinder groups. - * They calc file system addresses of cylinder group data structures. - */ -#define cgbase(fs, c) ((daddr_t)((fs)->fs_fpg * (c))) -#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ -#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ -#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ -#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ -#define cgstart(fs, c) \ - (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) - -/* - * Macros for handling inode numbers: - * inode number to file system block offset. - * inode number to cylinder group number. - * inode number to file system block address. - */ -#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) -#define ino_to_fsba(fs, x) \ - ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ - (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) -#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) - -/* - * Give cylinder group number for a file system block. - * Give cylinder group block number for a file system block. - */ -#define dtog(fs, d) ((d) / (fs)->fs_fpg) -#define dtogd(fs, d) ((d) % (fs)->fs_fpg) - -/* - * Extract the bits for a block from a map. - * Compute the cylinder and rotational position of a cyl block addr. - */ -#define blkmap(fs, map, loc) \ - (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) -#define cbtocylno(fs, bno) \ - ((bno) * NSPF(fs) / (fs)->fs_spc) -#define cbtorpos(fs, bno) \ - (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \ - (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \ - (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect) - -/* - * The following macros optimize certain frequently calculated - * quantities by using shifts and masks in place of divisions - * modulos and multiplications. - */ -#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ - ((loc) & (fs)->fs_qbmask) -#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ - ((loc) & (fs)->fs_qfmask) -#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ - ((blk) << (fs)->fs_bshift) -#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ - ((loc) >> (fs)->fs_bshift) -#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ - ((loc) >> (fs)->fs_fshift) -#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ - (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) -#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ - (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) -#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ - ((frags) >> (fs)->fs_fragshift) -#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ - ((blks) << (fs)->fs_fragshift) -#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ - ((fsb) & ((fs)->fs_frag - 1)) -#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ - ((fsb) &~ ((fs)->fs_frag - 1)) - -/* - * Determine the number of available frags given a - * percentage to hold in reserve - */ -#define freespace(fs, percentreserved) \ - (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ - (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100)) - -/* - * Determining the size of a file block in the file system. - */ -/* Changed from BSD to use allocsize instead of i_size. */ -#define blksize(fs, np, lbn) \ - (((lbn) >= NDADDR || (np)->allocsize >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (np)->allocsize)))) - -#if 0 /* Don't use this */ -#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)))) -#endif - -/* - * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. - */ -#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) -#define NSPF(fs) ((fs)->fs_nspf) - -/* - * INOPB is the number of inodes in a secondary storage block. - */ -#define INOPB(fs) ((fs)->fs_inopb) -#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) - -/* - * NINDIR is the number of indirects in a file system block. - */ -#define NINDIR(fs) ((fs)->fs_nindir) - -extern int inside[], around[]; -extern u_char *fragtbl[]; diff --git a/ufs/hyper.c b/ufs/hyper.c deleted file mode 100644 index 95013895..00000000 --- a/ufs/hyper.c +++ /dev/null @@ -1,414 +0,0 @@ -/* Fetching and storing the hypermetadata (superblock and cg summary info). - Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. - - 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. */ - -#include "ufs.h" -#include <string.h> -#include <stdio.h> -#include <error.h> -#include <hurd/store.h> - -static int ufs_clean; /* fs clean before we started writing? */ - -static int oldformat; - -void *zeroblock; - -struct fs *sblock; -struct csum *csum; - -void -swab_sblock (struct fs *sblock) -{ - int i, j; - - sblock->fs_sblkno = swab_long (sblock->fs_sblkno); - sblock->fs_cblkno = swab_long (sblock->fs_cblkno); - sblock->fs_iblkno = swab_long (sblock->fs_iblkno); - sblock->fs_dblkno = swab_long (sblock->fs_dblkno); - sblock->fs_cgoffset = swab_long (sblock->fs_cgoffset); - sblock->fs_cgmask = swab_long (sblock->fs_cgmask); - sblock->fs_time = swab_long (sblock->fs_time); - sblock->fs_size = swab_long (sblock->fs_size); - sblock->fs_dsize = swab_long (sblock->fs_dsize); - sblock->fs_ncg = swab_long (sblock->fs_ncg); - sblock->fs_bsize = swab_long (sblock->fs_bsize); - sblock->fs_fsize = swab_long (sblock->fs_fsize); - sblock->fs_frag = swab_long (sblock->fs_frag); - sblock->fs_minfree = swab_long (sblock->fs_minfree); - sblock->fs_rotdelay = swab_long (sblock->fs_rotdelay); - sblock->fs_rps = swab_long (sblock->fs_rps); - sblock->fs_bmask = swab_long (sblock->fs_bmask); - sblock->fs_fmask = swab_long (sblock->fs_fmask); - sblock->fs_bshift = swab_long (sblock->fs_bshift); - sblock->fs_fshift = swab_long (sblock->fs_fshift); - sblock->fs_maxcontig = swab_long (sblock->fs_maxcontig); - sblock->fs_maxbpg = swab_long (sblock->fs_maxbpg); - sblock->fs_fragshift = swab_long (sblock->fs_fragshift); - sblock->fs_fsbtodb = swab_long (sblock->fs_fsbtodb); - sblock->fs_sbsize = swab_long (sblock->fs_sbsize); - sblock->fs_csmask = swab_long (sblock->fs_csmask); - sblock->fs_csshift = swab_long (sblock->fs_csshift); - sblock->fs_nindir = swab_long (sblock->fs_nindir); - sblock->fs_inopb = swab_long (sblock->fs_inopb); - sblock->fs_nspf = swab_long (sblock->fs_nspf); - sblock->fs_optim = swab_long (sblock->fs_optim); - sblock->fs_npsect = swab_long (sblock->fs_npsect); - sblock->fs_interleave = swab_long (sblock->fs_interleave); - sblock->fs_trackskew = swab_long (sblock->fs_trackskew); - sblock->fs_headswitch = swab_long (sblock->fs_headswitch); - sblock->fs_trkseek = swab_long (sblock->fs_trkseek); - sblock->fs_csaddr = swab_long (sblock->fs_csaddr); - sblock->fs_cssize = swab_long (sblock->fs_cssize); - sblock->fs_cgsize = swab_long (sblock->fs_cgsize); - sblock->fs_ntrak = swab_long (sblock->fs_ntrak); - sblock->fs_nsect = swab_long (sblock->fs_nsect); - sblock->fs_spc = swab_long (sblock->fs_spc); - sblock->fs_ncyl = swab_long (sblock->fs_ncyl); - sblock->fs_cpg = swab_long (sblock->fs_cpg); - sblock->fs_ipg = swab_long (sblock->fs_ipg); - sblock->fs_fpg = swab_long (sblock->fs_fpg); - sblock->fs_cstotal.cs_ndir = swab_long (sblock->fs_cstotal.cs_ndir); - sblock->fs_cstotal.cs_nbfree = swab_long (sblock->fs_cstotal.cs_nbfree); - sblock->fs_cstotal.cs_nifree = swab_long (sblock->fs_cstotal.cs_nifree); - sblock->fs_cstotal.cs_nffree = swab_long (sblock->fs_cstotal.cs_nffree); - /* fs_fmod, fs_clean, fs_ronly, fs_flags, fs_fsmnt are all char */ - sblock->fs_cgrotor = swab_long (sblock->fs_cgrotor); - sblock->fs_cpc = swab_long (sblock->fs_cpc); - sblock->fs_contigsumsize = swab_long (sblock->fs_contigsumsize); - sblock->fs_maxsymlinklen = swab_long (sblock->fs_maxsymlinklen); - sblock->fs_inodefmt = swab_long (sblock->fs_inodefmt); - sblock->fs_maxfilesize = swab_long_long (sblock->fs_maxfilesize); - sblock->fs_qbmask = swab_long_long (sblock->fs_qbmask); - sblock->fs_state = swab_long (sblock->fs_state); - sblock->fs_postblformat = swab_long (sblock->fs_postblformat); - sblock->fs_nrpos = swab_long (sblock->fs_nrpos); - sblock->fs_postbloff = swab_long (sblock->fs_postbloff); - sblock->fs_rotbloff = swab_long (sblock->fs_rotbloff); - sblock->fs_magic = swab_long (sblock->fs_magic); - - /* Tables */ - if (sblock->fs_postblformat == FS_42POSTBLFMT) - for (i = 0; i < 16; i++) - for (j = 0; j < 8; j++) - sblock->fs_opostbl[i][j] = swab_short (sblock->fs_opostbl[i][j]); - else - for (i = 0; i < sblock->fs_cpc; i++) - for (j = 0; j < sblock->fs_nrpos; j++) - fs_postbl(sblock, j)[i] - = swab_short (fs_postbl (sblock, j)[i]); - - /* The rot table is all chars */ -} - -void -swab_csums (struct csum *csum) -{ - int i; - - for (i = 0; i < sblock->fs_ncg; i++) - { - csum[i].cs_ndir = swab_long (csum[i].cs_ndir); - csum[i].cs_nbfree = swab_long (csum[i].cs_nbfree); - csum[i].cs_nifree = swab_long (csum[i].cs_nifree); - csum[i].cs_nffree = swab_long (csum[i].cs_nffree); - } -} - -void -get_hypermetadata (void) -{ - error_t err; - - if (!sblock) - sblock = malloc (SBSIZE); - - /* Free previous values. */ - if (zeroblock) - munmap ((caddr_t) zeroblock, sblock->fs_bsize); - if (csum) - free (csum); - - err = diskfs_catch_exception (); - assert_perror (err); - bcopy (disk_image + SBOFF, sblock, SBSIZE); - diskfs_end_catch_exception (); - - if ((swab_long (sblock->fs_magic)) == FS_MAGIC) - { - swab_disk = 1; - swab_sblock (sblock); - } - else - swab_disk = 0; - - if (sblock->fs_magic != FS_MAGIC) - { - fprintf (stderr, "Bad magic number %#lx (should be %#x)\n", - sblock->fs_magic, FS_MAGIC); - exit (1); - } - if (sblock->fs_bsize > 8192) - { - fprintf (stderr, "Block size %ld is too big (max is 8192 bytes)\n", - sblock->fs_bsize); - exit (1); - } - if (sblock->fs_bsize < sizeof (struct fs)) - { - fprintf (stderr, "Block size %ld is too small (min is %Zd bytes)\n", - sblock->fs_bsize, sizeof (struct fs)); - exit (1); - } - - if (sblock->fs_maxsymlinklen > (long)MAXSYMLINKLEN) - { - fprintf (stderr, "Max shortcut symlinklen %ld is too big (max is %ld)\n", - sblock->fs_maxsymlinklen, (long)MAXSYMLINKLEN); - exit (1); - } - - assert ((__vm_page_size % DEV_BSIZE) == 0); - assert ((sblock->fs_bsize % DEV_BSIZE) == 0); - assert (__vm_page_size <= sblock->fs_bsize); - - /* Examine the clean bit and force read-only if unclean. */ - ufs_clean = sblock->fs_clean; - if (! ufs_clean) - { - error (0, 0, - "%s: warning: FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck", - diskfs_disk_name); - if (! diskfs_readonly) - { - diskfs_readonly = 1; - error (0, 0, - "%s: MOUNTED READ-ONLY; MUST USE `fsysopts --writable'", - diskfs_disk_name); - } - } - - /* If this is an old filesystem, then we have some more - work to do; some crucial constants might not be set; we - are therefore forced to set them here. */ - - if (sblock->fs_npsect < sblock->fs_nsect) - sblock->fs_npsect = sblock->fs_nsect; - - if (sblock->fs_interleave < 1) - sblock->fs_interleave = 1; - - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sblock->fs_nrpos = 8; - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - quad_t sizepb = sblock->fs_bsize; - int i; - - oldformat = 1; - sblock->fs_maxfilesize = sblock->fs_bsize * NDADDR - 1; - for (i = 0; i < NIADDR; i++) - { - sizepb *= NINDIR (sblock); - sblock->fs_maxfilesize += sizepb; - } - sblock->fs_qbmask = ~sblock->fs_bmask; - sblock->fs_qfmask = ~sblock->fs_fmask; - } - - /* Find out if we support the 4.4 symlink/dirtype extension */ - if (sblock->fs_maxsymlinklen > 0) - direct_symlink_extension = 1; - else - direct_symlink_extension = 0; - - csum = malloc (fsaddr (sblock, howmany (sblock->fs_cssize, - sblock->fs_fsize))); - - assert (!diskfs_catch_exception ()); - bcopy (disk_image + fsaddr (sblock, sblock->fs_csaddr), - csum, - fsaddr (sblock, howmany (sblock->fs_cssize, sblock->fs_fsize))); - diskfs_end_catch_exception (); - - if (swab_disk) - swab_csums (csum); - - if (store->size < sblock->fs_size * sblock->fs_fsize) - { - fprintf (stderr, - "Disk size (%Ld) less than necessary " - "(superblock says we need %ld)\n", - store->size, sblock->fs_size * sblock->fs_fsize); - exit (1); - } - - zeroblock = mmap (0, sblock->fs_bsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - - /* If the filesystem has new features in it, don't pay attention to - the user's request not to use them. */ - if ((sblock->fs_inodefmt == FS_44INODEFMT - || direct_symlink_extension) - && compat_mode == COMPAT_BSD42) - { - compat_mode = COMPAT_BSD44; - error (0, 0, - "4.2 compat mode requested on 4.4 fs--switched to 4.4 mode"); - } -} - -/* Write the csum data. This isn't backed by a pager because it is - taken from ordinary data blocks and might not be an even number - of pages; in that case writing it through the pager would nuke whatever - pages came after it on the disk and were backed by file pagers. */ -error_t -diskfs_set_hypermetadata (int wait, int clean) -{ - error_t err; - - pthread_spin_lock (&alloclock); - - if (csum_dirty) - { - /* Copy into a page-aligned buffer to avoid bugs in kernel device - code. */ - void *buf = 0; - size_t read = 0; - size_t bufsize = round_page (fragroundup (sblock, sblock->fs_cssize)); - - err = store_read (store, - fsbtodb (sblock, sblock->fs_csaddr) - << log2_dev_blocks_per_dev_bsize, - bufsize, &buf, &read); - if (err) - return err; - else if (read != bufsize) - err = EIO; - else - { - size_t wrote; - bcopy (csum, buf, sblock->fs_cssize); - if (swab_disk) - swab_csums ((struct csum *)buf); - err = store_write (store, - fsbtodb (sblock, sblock->fs_csaddr) - << log2_dev_blocks_per_dev_bsize, - buf, bufsize, &wrote); - if (!err && wrote != bufsize) - err = EIO; - } - - munmap (buf, read); - - if (err) - { - pthread_spin_unlock (&alloclock); - return err; - } - - csum_dirty = 0; - } - - if (clean && ufs_clean && !sblock->fs_clean) - { - /* The filesystem is clean, so set the clean flag. */ - sblock->fs_clean = 1; - sblock_dirty = 1; - } - else if (!clean && sblock->fs_clean) - { - /* Clear the clean flag */ - sblock->fs_clean = 0; - sblock_dirty = 1; - wait = 1; /* must be synchronous */ - } - - pthread_spin_unlock (&alloclock); - - /* Update the superblock if necessary (clean bit was just set). */ - copy_sblock (); - - sync_disk (wait); - return 0; -} - -/* Copy the sblock into the disk */ -void -copy_sblock () -{ - error_t err; - - err = diskfs_catch_exception (); - assert_perror (err); - - pthread_spin_lock (&alloclock); - - if (sblock_dirty) - { - assert (! diskfs_readonly); - - if (sblock->fs_postblformat == FS_42POSTBLFMT - || oldformat - || swab_disk) - { - char sblockcopy[SBSIZE]; - struct fs *sbcopy = (struct fs *)sblockcopy; - bcopy (sblock, sblockcopy, SBSIZE); - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sbcopy->fs_nrpos = -1; - if (oldformat) - { - sbcopy->fs_maxfilesize = -1; - sbcopy->fs_qbmask = -1; - sbcopy->fs_qfmask = -1; - } - if (swab_disk) - swab_sblock (sbcopy); - bcopy (sbcopy, disk_image + SBOFF, SBSIZE); - } - else - bcopy (sblock, disk_image + SBOFF, SBSIZE); - record_poke (disk_image + SBOFF, SBSIZE); - sblock_dirty = 0; - } - - pthread_spin_unlock (&alloclock); - - diskfs_end_catch_exception (); -} - -void -diskfs_readonly_changed (int readonly) -{ - (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY); - - mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE)); - - if (readonly) - { - /* We know we are sync'd now. The superblock is marked as dirty - because we cleared the clean flag immediately after sync'ing. - But now we want to leave it marked clean and not touch it further. */ - sblock_dirty = 0; - return; - } - - strcpy (sblock->fs_fsmnt, "Hurd /"); /* XXX */ - - if (!sblock->fs_clean) - error (0, 0, "WARNING: UNCLEANED FILESYSTEM NOW WRITABLE"); -} diff --git a/ufs/inode.c b/ufs/inode.c deleted file mode 100644 index 066eb1e5..00000000 --- a/ufs/inode.c +++ /dev/null @@ -1,705 +0,0 @@ -/* Inode management routines - - Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2007 - Free Software Foundation, Inc. - - 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. */ - -#include "ufs.h" -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <netinet/in.h> -#include <fcntl.h> -#include <hurd/store.h> - -#define INOHSZ 512 -#if ((INOHSZ&(INOHSZ-1)) == 0) -#define INOHASH(ino) ((ino)&(INOHSZ-1)) -#else -#define INOHASH(ino) (((unsigned)(ino))%INOHSZ) -#endif - -static struct node *nodehash[INOHSZ]; -static error_t read_disknode (struct node *np); - -pthread_spinlock_t gennumberlock = PTHREAD_SPINLOCK_INITIALIZER; - -/* Initialize the inode hash table. */ -void -inode_init () -{ - int n; - for (n = 0; n < INOHSZ; n++) - nodehash[n] = 0; -} - -/* Fetch inode INUM, set *NPP to the node structure; - gain one user reference and lock the node. */ -error_t -diskfs_cached_lookup (ino_t inum, struct node **npp) -{ - struct disknode *dn; - struct node *np; - error_t err; - - pthread_spin_lock (&diskfs_node_refcnt_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->dn->number != inum) - continue; - - np->references++; - pthread_spin_unlock (&diskfs_node_refcnt_lock); - pthread_mutex_lock (&np->lock); - *npp = np; - return 0; - } - - dn = malloc (sizeof (struct disknode)); - - dn->number = inum; - dn->dirents = 0; - dn->dir_idx = 0; - - pthread_rwlock_init (&dn->allocptrlock, NULL); - pthread_mutex_init (&dn->waitlock, NULL); - pthread_cond_init (&dn->waitcond, NULL); - dn->dirty = 0; - dn->fileinfo = 0; - - np = diskfs_make_node (dn); - np->cache_id = inum; - - pthread_mutex_lock (&np->lock); - dn->hnext = nodehash[INOHASH(inum)]; - if (dn->hnext) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &nodehash[INOHASH(inum)]; - nodehash[INOHASH(inum)] = np; - pthread_spin_unlock (&diskfs_node_refcnt_lock); - - err = read_disknode (np); - - if (!diskfs_check_readonly () && !np->dn_stat.st_gen) - { - pthread_spin_lock (&gennumberlock); - if (++nextgennumber < diskfs_mtime->seconds) - nextgennumber = diskfs_mtime->seconds; - np->dn_stat.st_gen = nextgennumber; - pthread_spin_unlock (&gennumberlock); - np->dn_set_ctime = 1; - } - - if (err) - return err; - else - { - *npp = np; - return 0; - } -} - -/* Lookup node INUM (which must have a reference already) and return it - without allocating any new references. */ -struct node * -ifind (ino_t inum) -{ - struct node *np; - - pthread_spin_lock (&diskfs_node_refcnt_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->dn->number != inum) - continue; - - assert (np->references); - pthread_spin_unlock (&diskfs_node_refcnt_lock); - return np; - } - assert (0); -} - -/* The last reference to a node has gone away; drop - it from the hash table and clean all state in the dn structure. */ -void -diskfs_node_norefs (struct node *np) -{ - *np->dn->hprevp = np->dn->hnext; - if (np->dn->hnext) - np->dn->hnext->dn->hprevp = np->dn->hprevp; - if (np->dn->dirents) - free (np->dn->dirents); - assert (!np->dn->fileinfo); - free (np->dn); - free (np); -} - -/* The last hard reference to a node has gone away; arrange to have - all the weak references dropped that can be. */ -void -diskfs_try_dropping_softrefs (struct node *np) -{ - drop_pager_softrefs (np); -} - -/* The last hard reference to a node has gone away. */ -void -diskfs_lost_hardrefs (struct node *np) -{ -#ifdef notanymore - struct port_info *pi; - struct pager *p; - - /* Check and see if there is a pager which has only - one reference (ours). If so, then drop that reference, - breaking the cycle. The complexity in this routine - is all due to this cycle. */ - - if (np->dn->fileinfo) - { - pthread_spin_lock (&_libports_portrefcntlock); - pi = (struct port_info *) np->dn->fileinfo->p; - if (pi->refcnt == 1) - { - - /* The only way to get a new reference to the pager - in this state is to call diskfs_get_filemap; this - can't happen as long as we hold NP locked. So - we can safely unlock _libports_portrefcntlock for - the following call. */ - pthread_spin_unlock (&_libports_portrefcntlock); - - /* Right now the node is locked with no hard refs; - this is an anomalous situation. Before messing with - the reference count on the file pager, we have to - give ourselves a reference back so that we are really - allowed to hold the lock. Then we can do the - unreference. */ - p = np->dn->fileinfo->p; - np->dn->fileinfo = 0; - diskfs_nref (np); - pager_unreference (p); - - assert (np->references == 1 && np->light_references == 0); - - /* This will do the real deallocate. Whew. */ - diskfs_nput (np); - } - else - pthread_spin_unlock (&_libports_portrefcntlock); - } -#endif -} - -/* A new hard reference to a node has been created; it's now OK to - have unused weak references. */ -void -diskfs_new_hardrefs (struct node *np) -{ - allow_pager_softrefs (np); -} - -/* Read stat information out of the dinode. */ -static error_t -read_disknode (struct node *np) -{ - struct stat *st = &np->dn_stat; - struct dinode *di = dino (np->dn->number); - error_t err; - - err = diskfs_catch_exception (); - if (err) - return err; - - st->st_fstype = FSTYPE_UFS; - st->st_fsid = getpid (); /* This call is very cheap. */ - st->st_ino = np->dn->number; - st->st_gen = read_disk_entry (di->di_gen); - st->st_rdev = read_disk_entry(di->di_rdev); - st->st_mode = (((read_disk_entry (di->di_model) - | (read_disk_entry (di->di_modeh) << 16)) - & ~S_ITRANS) - | (di->di_trans ? S_IPTRANS : 0)); - st->st_nlink = read_disk_entry (di->di_nlink); - st->st_size = read_disk_entry (di->di_size); - st->st_atim.tv_sec = read_disk_entry (di->di_atime.tv_sec); - st->st_atim.tv_nsec = read_disk_entry (di->di_atime.tv_nsec); - st->st_mtim.tv_sec = read_disk_entry (di->di_mtime.tv_sec); - st->st_mtim.tv_nsec = read_disk_entry (di->di_mtime.tv_nsec); - st->st_ctim.tv_sec = read_disk_entry (di->di_ctime.tv_sec); - st->st_ctim.tv_nsec = read_disk_entry (di->di_ctime.tv_nsec); - st->st_blksize = sblock->fs_bsize; - st->st_blocks = read_disk_entry (di->di_blocks); - st->st_flags = read_disk_entry (di->di_flags); - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - st->st_uid = read_disk_entry (di->di_ouid); - st->st_gid = read_disk_entry (di->di_ogid); - st->st_author = st->st_uid; - np->author_tracks_uid = 1; - } - else - { - st->st_uid = read_disk_entry (di->di_uid); - st->st_gid = read_disk_entry (di->di_gid); - st->st_author = read_disk_entry (di->di_author); - if (st->st_author == -1) - st->st_author = st->st_uid; - } - - diskfs_end_catch_exception (); - if (!S_ISBLK (st->st_mode) && !S_ISCHR (st->st_mode)) - st->st_rdev = 0; - - if (S_ISLNK (st->st_mode) - && direct_symlink_extension - && st->st_size < sblock->fs_maxsymlinklen) - np->allocsize = 0; - else - { - if (lblkno (sblock, np->dn_stat.st_size) < NDADDR) - np->allocsize = fragroundup (sblock, st->st_size); - else - np->allocsize = blkroundup (sblock, st->st_size); - } - - return 0; -} - -error_t diskfs_node_reload (struct node *node) -{ - if (node->dn->dirents) - { - free (node->dn->dirents); - node->dn->dirents = 0; - } - flush_node_pager (node); - read_disknode (node); - return 0; -} - -/* Return 0 if NP's author can be changed to AUTHOR; otherwise return an - error code. */ -error_t -diskfs_validate_author_change (struct node *np, uid_t author) -{ - if (compat_mode == COMPAT_GNU) - return 0; - else - /* For non-hurd filesystems, the author & owner are the same. */ - return (author == np->dn_stat.st_uid) ? 0 : EINVAL; -} - -static void -write_node (struct node *np) -{ - struct stat *st = &np->dn_stat; - struct dinode *di = dino (np->dn->number); - error_t err; - - if (np->dn_stat_dirty) - { - assert (!diskfs_readonly); - - err = diskfs_catch_exception (); - if (err) - return; - - write_disk_entry (di->di_gen, st->st_gen); - - if (S_ISBLK (st->st_mode) || S_ISCHR (st->st_mode)) - write_disk_entry (di->di_rdev, st->st_rdev); - - /* We happen to know that the stat mode bits are the same - as the ufs mode bits. */ - - if (compat_mode == COMPAT_GNU) - { - mode_t mode = st->st_mode & ~S_ITRANS; - write_disk_entry (di->di_model, mode & 0xffff); - write_disk_entry (di->di_modeh, (mode >> 16) & 0xffff); - } - else - { - write_disk_entry (di->di_model, st->st_mode & 0xffff & ~S_ITRANS); - di->di_modeh = 0; - } - - if (compat_mode != COMPAT_BSD42) - { - write_disk_entry (di->di_uid, st->st_uid); - write_disk_entry (di->di_gid, st->st_gid); - } - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - write_disk_entry (di->di_ouid, st->st_uid & 0xffff); - write_disk_entry (di->di_ogid, st->st_gid & 0xffff); - } - else if (compat_mode == COMPAT_GNU) - write_disk_entry (di->di_author, st->st_author); - - write_disk_entry (di->di_nlink, st->st_nlink); - write_disk_entry (di->di_size, st->st_size); - write_disk_entry (di->di_atime.tv_sec, st->st_atim.tv_sec); - write_disk_entry (di->di_atime.tv_nsec, st->st_atim.tv_nsec); - write_disk_entry (di->di_mtime.tv_sec, st->st_mtim.tv_sec); - write_disk_entry (di->di_mtime.tv_nsec, st->st_mtim.tv_nsec); - write_disk_entry (di->di_ctime.tv_sec, st->st_ctim.tv_sec); - write_disk_entry (di->di_ctime.tv_nsec, st->st_ctim.tv_nsec); - write_disk_entry (di->di_blocks, st->st_blocks); - write_disk_entry (di->di_flags, st->st_flags); - - diskfs_end_catch_exception (); - np->dn_stat_dirty = 0; - record_poke (di, sizeof (struct dinode)); - } -} - -/* See if we should create a symlink by writing it directly into - the block pointer array. Returning EINVAL tells diskfs to do it - the usual way. */ -static error_t -create_symlink_hook (struct node *np, const char *target) -{ - int len = strlen (target); - error_t err; - struct dinode *di; - - if (!direct_symlink_extension) - return EINVAL; - - assert (compat_mode != COMPAT_BSD42); - - if (len >= sblock->fs_maxsymlinklen) - return EINVAL; - - err = diskfs_catch_exception (); - if (err) - return err; - - di = dino (np->dn->number); - bcopy (target, di->di_shortlink, len); - np->dn_stat.st_size = len; - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - record_poke (di, sizeof (struct dinode)); - - diskfs_end_catch_exception (); - return 0; -} -error_t (*diskfs_create_symlink_hook)(struct node *, const char *) - = create_symlink_hook; - -/* Check if this symlink is stored directly in the block pointer array. - Returning EINVAL tells diskfs to do it the usual way. */ -static error_t -read_symlink_hook (struct node *np, - char *buf) -{ - error_t err; - - if (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen) - return EINVAL; - - err = diskfs_catch_exception (); - if (err) - return err; - - bcopy ((dino (np->dn->number))->di_shortlink, buf, np->dn_stat.st_size); - - diskfs_set_node_atime (np); - - diskfs_end_catch_exception (); - return 0; -} -error_t (*diskfs_read_symlink_hook)(struct node *, char *) - = read_symlink_hook; - -error_t -diskfs_node_iterate (error_t (*fun)(struct node *)) -{ - struct node *np; - struct item {struct item *next; struct node *np;} *list = 0; - struct item *i; - error_t err; - int n; - - /* Acquire a reference on all the nodes in the hash table - and enter them into a list on the stack. */ - pthread_spin_lock (&diskfs_node_refcnt_lock); - for (n = 0; n < INOHSZ; n++) - for (np = nodehash[n]; np; np = np->dn->hnext) - { - np->references++; - i = alloca (sizeof (struct item)); - i->next = list; - i->np = np; - list = i; - } - pthread_spin_unlock (&diskfs_node_refcnt_lock); - - err = 0; - for (i = list; i; i = i->next) - { - if (!err) - { - pthread_mutex_lock (&i->np->lock); - err = (*fun)(i->np); - pthread_mutex_unlock (&i->np->lock); - } - diskfs_nrele (i->np); - } - return err; -} - -/* Write all active disknodes into the dinode pager. */ -void -write_all_disknodes () -{ - error_t - helper (struct node *np) - { - diskfs_set_node_times (np); - write_node (np); - return 0; - } - - diskfs_node_iterate (helper); -} - -void -diskfs_write_disknode (struct node *np, int wait) -{ - write_node (np); - if (wait) - sync_dinode (np->dn->number, 1); -} - -/* Implement the diskfs_set_statfs callback from the diskfs library; - see <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_set_statfs (struct statfs *st) -{ - st->f_type = FSTYPE_UFS; - st->f_bsize = sblock->fs_fsize; - st->f_blocks = sblock->fs_dsize; - st->f_bfree = (sblock->fs_cstotal.cs_nbfree * sblock->fs_frag - + sblock->fs_cstotal.cs_nffree); - st->f_bavail = ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100) - - (sblock->fs_dsize - st->f_bfree)); - if (st->f_bfree < ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100))) - st->f_bavail = 0; - st->f_files = sblock->fs_ncg * sblock->fs_ipg - 2; /* not 0 or 1 */ - st->f_ffree = sblock->fs_cstotal.cs_nifree; - st->f_fsid = getpid (); - st->f_namelen = 0; - st->f_favail = st->f_ffree; - st->f_frsize = sblock->fs_fsize; - return 0; -} - -/* Implement the diskfs_set_translator callback from the diskfs - library; see <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_set_translator (struct node *np, const char *name, u_int namelen, - struct protid *cred) -{ - daddr_t blkno; - error_t err; - char buf[sblock->fs_bsize]; - struct dinode *di; - - if (compat_mode != COMPAT_GNU) - return EOPNOTSUPP; - - if (namelen + sizeof (u_int) > sblock->fs_bsize) - return ENAMETOOLONG; - - err = diskfs_catch_exception (); - if (err) - return err; - - di = dino (np->dn->number); - blkno = read_disk_entry (di->di_trans); - - if (namelen && !blkno) - { - /* Allocate block for translator */ - err = ffs_alloc (np, 0, 0, sblock->fs_bsize, &blkno, cred); - if (err) - { - diskfs_end_catch_exception (); - return err; - } - write_disk_entry (di->di_trans, blkno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - else if (!namelen && blkno) - { - /* Clear block for translator going away. */ - ffs_blkfree (np, blkno, sblock->fs_bsize); - di->di_trans = 0; - record_poke (di, sizeof (struct dinode)); - np->dn_stat.st_blocks -= btodb (sblock->fs_bsize); - np->dn_stat.st_mode &= ~S_IPTRANS; - np->dn_set_ctime = 1; - } - - if (namelen) - { - bcopy (&namelen, buf, sizeof (u_int)); - bcopy (name, buf + sizeof (u_int), namelen); - - bcopy (buf, disk_image + fsaddr (sblock, blkno), sblock->fs_bsize); - sync_disk_blocks (blkno, sblock->fs_bsize, 1); - - np->dn_stat.st_mode |= S_IPTRANS; - np->dn_set_ctime = 1; - } - - diskfs_end_catch_exception (); - return err; -} - -/* Implement the diskfs_get_translator callback from the diskfs library. - See <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_get_translator (struct node *np, char **namep, u_int *namelen) -{ - error_t err; - daddr_t blkno; - u_int datalen; - const void *transloc; - - err = diskfs_catch_exception (); - if (err) - return err; - - blkno = read_disk_entry ((dino (np->dn->number))->di_trans); - assert (blkno); - transloc = disk_image + fsaddr (sblock, blkno); - - datalen = *(u_int *)transloc; - if (datalen > sblock->fs_bsize - sizeof (u_int)) - err = EFTYPE; - else - { - *namep = malloc (datalen); - if (*namep == NULL) - err = ENOMEM; - memcpy (*namep, transloc + sizeof (u_int), datalen); - } - - diskfs_end_catch_exception (); - - *namelen = datalen; - return 0; -} - -/* Called when all hard ports have gone away. */ -void -diskfs_shutdown_soft_ports () -{ - /* Should initiate termination of internally held pager ports - (the only things that should be soft) XXX */ -} - -/* Return a description of the storage of the file. */ -/* In STORAGE_DATA are the following, in network byte order: - - Inode number (4 bytes) - disk address of transator spec (4 bytes) - disk address of inode structure (4 bytes) - offset into inode block holding inode (4 bytes) */ -error_t -diskfs_S_file_get_storage_info (struct protid *cred, - mach_port_t **ports, - mach_msg_type_name_t *ports_type, - mach_msg_type_number_t *num_ports, - int **ints, mach_msg_type_number_t *num_ints, - off_t **offsets, - mach_msg_type_number_t *num_offsets, - char **data, mach_msg_type_number_t *data_len) -{ - error_t err; - struct node *np; - struct store *file_store; - struct store_run runs[NDADDR]; - size_t num_runs = 0; - - if (! cred) - return EOPNOTSUPP; - - np = cred->po->np; - pthread_mutex_lock (&np->lock); - - /* See if this file fits in the direct block pointers. If not, punt - for now. (Reading indir blocks is a pain, and I'm postponing - pain.) XXX */ - if (np->allocsize > NDADDR * sblock->fs_bsize) - { - pthread_mutex_unlock (&np->lock); - return EINVAL; - } - - err = diskfs_catch_exception (); - if (! err) - if (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen - || !S_ISLNK (np->dn_stat.st_mode)) - /* Copy the block pointers */ - { - int i; - struct store_run *run = runs; - struct dinode *di = dino (np->dn->number); - - for (i = 0; i < NDADDR; i++) - { - store_offset_t start = fsbtodb (sblock, read_disk_entry (di->di_db[i])); - store_offset_t length = - (((i + 1) * sblock->fs_bsize > np->allocsize) - ? np->allocsize - i * sblock->fs_bsize - : sblock->fs_bsize); - start <<= log2_dev_blocks_per_dev_bsize; - length <<= log2_dev_blocks_per_dev_bsize; - if (num_runs == 0 || run->start + run->length != start) - *run++ = (struct store_run){ start, length }; - else - run->length += length; - } - } - diskfs_end_catch_exception (); - - pthread_mutex_unlock (&np->lock); - - if (! err) - err = store_clone (store, &file_store); - if (! err) - { - err = store_remap (file_store, runs, num_runs, &file_store); - if (! err) - err = store_return (file_store, ports, num_ports, ints, num_ints, - offsets, num_offsets, data, data_len); - store_free (file_store); - } - *ports_type = MACH_MSG_TYPE_COPY_SEND; - - return err; -} diff --git a/ufs/main.c b/ufs/main.c deleted file mode 100644 index 9fc21f81..00000000 --- a/ufs/main.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Copyright (C) 1994,95,96,97,98,99,2002 Free Software Foundation, Inc. - - 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. */ - - -#include "ufs.h" -#include <stdarg.h> -#include <stdio.h> -#include <error.h> -#include <device/device.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <argz.h> -#include <argp.h> -#include <hurd/store.h> - -struct node *diskfs_root_node; - -struct store *store = 0; -struct store_parsed *store_parsed = 0; - -char *diskfs_disk_name = 0; - -/* Number of device blocks per DEV_BSIZE block. */ -unsigned log2_dev_blocks_per_dev_bsize = 0; - -/* Set diskfs_root_node to the root inode. */ -static void -warp_root (void) -{ - error_t err; - err = diskfs_cached_lookup (2, &diskfs_root_node); - assert (!err); - pthread_mutex_unlock (&diskfs_root_node->lock); -} - -/* XXX */ -pthread_mutex_t printf_lock = PTHREAD_MUTEX_INITIALIZER; -int printf (const char *fmt, ...) -{ - va_list arg; - int done; - va_start (arg, fmt); - pthread_mutex_lock (&printf_lock); - done = vprintf (fmt, arg); - pthread_mutex_unlock (&printf_lock); - va_end (arg); - return done; -} - -int diskfs_readonly; - -/* Ufs-specific options. XXX this should be moved so it can be done at - runtime as well as startup. */ -static const struct argp_option -options[] = -{ - {"compat", 'C', "FMT", 0, - "FMT may be GNU, 4.4, or 4.2, and determines which filesystem extensions" - " are written onto the disk (default is GNU)"}, - {0} -}; - -/* Parse a ufs-specific command line option. */ -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - enum compat_mode mode; - - case 'C': - if (strcasecmp (arg, "gnu") == 0) - mode = COMPAT_GNU; - else if (strcmp (arg, "4.4") == 0) - mode = COMPAT_BSD44; - else if (strcmp (arg, "4.2") == 0) - { - if (sblock - && (sblock->fs_inodefmt == FS_44INODEFMT - || direct_symlink_extension)) - { - argp_failure (state, 0, 0, - "4.2 compat mode requested on 4.4 fs"); - return EINVAL; - } - mode = COMPAT_BSD42; - } - else - { - argp_error (state, "%s: Unknown compatibility mode", arg); - return EINVAL; - } - - state->hook = (void *)mode; /* Save it for the end. */ - break; - - case ARGP_KEY_INIT: - state->child_inputs[0] = state->input; - state->hook = (void *)compat_mode; break; - case ARGP_KEY_SUCCESS: - compat_mode = (enum compat_mode)state->hook; break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -/* Add our startup arguments to the standard diskfs set. */ -static const struct argp_child startup_children[] = - {{&diskfs_store_startup_argp}, {0}}; -static struct argp startup_argp = {options, parse_opt, 0, 0, startup_children}; - -/* Similarly at runtime. */ -static const struct argp_child runtime_children[] = - {{&diskfs_std_runtime_argp}, {0}}; -static struct argp runtime_argp = {options, parse_opt, 0, 0, runtime_children}; - -struct argp *diskfs_runtime_argp = (struct argp *)&runtime_argp; - -/* Override the standard diskfs routine so we can add our own output. */ -error_t -diskfs_append_args (char **argz, size_t *argz_len) -{ - error_t err; - - /* Get the standard things. */ - err = diskfs_append_std_options (argz, argz_len); - - if (!err && compat_mode != COMPAT_GNU) - err = argz_add (argz, argz_len, - ((compat_mode == COMPAT_BSD42) - ? "--compat=4.2" - : "--compat=4.4")); - - if (! err) - err = store_parsed_append_args (store_parsed, argz, argz_len); - - return err; -} - -int -main (int argc, char **argv) -{ - mach_port_t bootstrap; - - /* Initialize the diskfs library, parse arguments, and open the store. - This starts the first diskfs thread for us. */ - store = diskfs_init_main (&startup_argp, argc, argv, - &store_parsed, &bootstrap); - - if (store->block_size > DEV_BSIZE) - error (4, 0, "%s: Bad device block size %zd (should be <= %d)", - diskfs_disk_name, store->block_size, DEV_BSIZE); - if (store->size < SBSIZE + SBOFF) - error (5, 0, "%s: Disk too small (%Ld bytes)", diskfs_disk_name, - store->size); - - log2_dev_blocks_per_dev_bsize = 0; - while ((1 << log2_dev_blocks_per_dev_bsize) < DEV_BSIZE) - log2_dev_blocks_per_dev_bsize++; - log2_dev_blocks_per_dev_bsize -= store->log2_block_size; - - /* Map the entire disk. */ - create_disk_pager (); - - get_hypermetadata (); - - inode_init (); - - /* Find our root node. */ - warp_root (); - - /* Now that we are all set up to handle requests, and diskfs_root_node is - set properly, it is safe to export our fsys control port to the - outside world. */ - diskfs_startup_diskfs (bootstrap, 0); - - /* SET HOST NAME */ - - /* And this thread is done with its work. */ - pthread_exit (NULL); - - return 0; -} - -error_t -diskfs_reload_global_state () -{ - flush_pokes (); - pager_flush (diskfs_disk_pager, 1); - get_hypermetadata (); - return 0; -} diff --git a/ufs/pager.c b/ufs/pager.c deleted file mode 100644 index 5d3e44ab..00000000 --- a/ufs/pager.c +++ /dev/null @@ -1,838 +0,0 @@ -/* Pager for ufs - Copyright (C) 1994, 1995, 1996, 1997, 1999 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. */ - -#include "ufs.h" -#include <strings.h> -#include <stdio.h> -#include <unistd.h> -#include <hurd/store.h> - -pthread_spinlock_t node2pagelock = PTHREAD_SPINLOCK_INITIALIZER; - -pthread_spinlock_t unlocked_pagein_lock = PTHREAD_SPINLOCK_INITIALIZER; - -#ifdef DONT_CACHE_MEMORY_OBJECTS -#define MAY_CACHE 0 -#else -#define MAY_CACHE 1 -#endif - -struct port_bucket *pager_bucket; - -/* Mapped image of the disk. */ -void *disk_image; - -/* Find the location on disk of page OFFSET in pager UPI. Return the - disk address (in disk block) in *ADDR. If *NPLOCK is set on - return, then release that mutex after I/O on the data has - completed. Set DISKSIZE to be the amount of valid data on disk. - (If this is an unallocated block, then set *ADDR to zero.) - ISREAD is non-zero iff this is for a pagein. */ -static error_t -find_address (struct user_pager_info *upi, - vm_address_t offset, - daddr_t *addr, - int *disksize, - pthread_rwlock_t **nplock, - int isread) -{ - error_t err; - pthread_rwlock_t *lock; - - assert (upi->type == DISK || upi->type == FILE_DATA); - - if (upi->type == DISK) - { - *disksize = __vm_page_size; - *addr = offset / DEV_BSIZE; - *nplock = 0; - return 0; - } - else - { - struct iblock_spec indirs[NIADDR + 1]; - struct node *np; - - np = upi->np; - - if (isread) - { - try_again: - - /* If we should allow an unlocked pagein, do so. (This - still has a slight race; there could be a pageout in progress - which is blocked on NP->np->allocptrlock itself. In that - case the pagein that should proceed unimpeded is blocked - in the pager library waiting for the pageout to complete. - I think this is sufficiently rare to put it off for the time - being.) */ - - pthread_spin_lock (&unlocked_pagein_lock); - if (offset >= upi->allow_unlocked_pagein - && (offset + vm_page_size - <= upi->allow_unlocked_pagein + upi->unlocked_pagein_length)) - { - pthread_spin_unlock (&unlocked_pagein_lock); - *nplock = 0; - goto have_lock; - } - pthread_spin_unlock (&unlocked_pagein_lock); - - /* Block on the rwlock if necessary; but when we wake up, - don't acquire it; check again from the top. - This is mutated inline from rwlock.h. */ - lock = &np->dn->allocptrlock; - /* - TD - Why do we lock first? - To prevent this nigh-impossible scenario: - 1) trylock - writer has lock - 2) switch back to writer before we lock waitlock - 3) writer finishes: releases lock and broadcasts - 4) we wait for a condition that will never get broadcast - With this, either we get the lock, or we get the signal. - */ - pthread_mutex_lock (&np->dn->waitlock); - if (pthread_rwlock_tryrdlock (lock)) - { - /* - TD - we now don't block on the rwlock. Instead, we wait on a - condition that will be signalled when the lock is unlocked, - or when it is safe not to lock the page. We don't spin on an - invariant, as spurius wakeups can do no harm. - */ - pthread_cond_wait (&np->dn->waitcond, &np->dn->waitlock); - pthread_mutex_unlock (&np->dn->waitlock); - goto try_again; - } - pthread_mutex_unlock (&np->dn->waitlock); - *nplock = lock; - } - else - { - pthread_rwlock_rdlock (&np->dn->allocptrlock); - *nplock = &np->dn->allocptrlock; - } - - have_lock: - - if (offset >= np->allocsize) - { - if (*nplock) - pthread_rwlock_unlock (*nplock); - if (isread) - return EIO; - else - { - *addr = 0; - *disksize = 0; - return 0; - } - } - - if (offset + __vm_page_size > np->allocsize) - *disksize = np->allocsize - offset; - else - *disksize = __vm_page_size; - - err = fetch_indir_spec (np, lblkno (sblock, offset), indirs); - if (err && *nplock) - pthread_rwlock_unlock (*nplock); - else - { - if (indirs[0].bno) - *addr = (fsbtodb (sblock, indirs[0].bno) - + blkoff (sblock, offset) / DEV_BSIZE); - else - *addr = 0; - } - - return err; - } -} - - -/* Implement the pager_read_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_read_page (struct user_pager_info *pager, - vm_offset_t page, - vm_address_t *buf, - int *writelock) -{ - error_t err; - pthread_rwlock_t *nplock; - daddr_t addr; - int disksize; - - err = find_address (pager, page, &addr, &disksize, &nplock, 1); - if (err) - return err; - - if (addr) - { - size_t read = 0; - err = store_read (store, addr << log2_dev_blocks_per_dev_bsize, - disksize, (void **)buf, &read); - if (read != disksize) - err = EIO; - if (!err && disksize != __vm_page_size) - bzero ((void *)(*buf + disksize), __vm_page_size - disksize); - *writelock = 0; - } - else - { -#if 0 - printf ("Write-locked pagein Object %#x\tOffset %#x\n", pager, page); - fflush (stdout); -#endif - *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - *writelock = 1; - } - - if (nplock) - pthread_rwlock_unlock (nplock); - - return err; -} - -/* Implement the pager_write_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_write_page (struct user_pager_info *pager, - vm_offset_t page, - vm_address_t buf) -{ - daddr_t addr; - int disksize; - pthread_rwlock_t *nplock; - error_t err; - - err = find_address (pager, page, &addr, &disksize, &nplock, 0); - if (err) - return err; - - if (addr) - { - size_t wrote; - err = store_write (store, addr << log2_dev_blocks_per_dev_bsize, - (void *)buf, disksize, &wrote); - if (wrote != disksize) - err = EIO; - } - else - err = 0; - - if (nplock) - pthread_rwlock_unlock (nplock); - - return err; -} - -/* Implement the pager_unlock_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_unlock_page (struct user_pager_info *pager, - vm_offset_t address) -{ - struct node *np; - error_t err; - struct iblock_spec indirs[NIADDR + 1]; - daddr_t bno; - struct disknode *dn; - struct dinode *di; - - /* Zero an sblock->fs_bsize piece of disk starting at BNO, - synchronously. We do this on newly allocated indirect - blocks before setting the pointer to them to ensure that an - indirect block absolutely never points to garbage. */ - void zero_disk_block (int bno) - { - bzero (indir_block (bno), sblock->fs_bsize); - sync_disk_blocks (bno, sblock->fs_bsize, 1); - }; - - /* Problem--where to get cred values for allocation here? */ - -#if 0 - printf ("Unlock page request, Object %#x\tOffset %#x...", pager, address); - fflush (stdout); -#endif - - if (pager->type == DISK) - return 0; - - np = pager->np; - dn = np->dn; - di = dino (dn->number); - - pthread_rwlock_wrlock (&dn->allocptrlock); - - /* If this is the last block, we don't let it get unlocked. */ - if (address + __vm_page_size - > blkroundup (sblock, np->allocsize) - sblock->fs_bsize) - { - printf ("attempt to unlock at last block denied\n"); - fflush (stdout); - pthread_rwlock_unlock (&dn->allocptrlock); - /* Wake up any remaining sleeping readers. Wow, so much work.... */ - pthread_mutex_lock (&dn->waitlock); - pthread_cond_broadcast (&dn->waitcond); - pthread_mutex_unlock (&dn->waitlock); - return EIO; - } - - err = fetch_indir_spec (np, lblkno (sblock, address), indirs); - if (err) - { - pthread_rwlock_unlock (&dn->allocptrlock); - pthread_mutex_lock (&dn->waitlock); - pthread_cond_broadcast (&dn->waitcond); - pthread_mutex_unlock (&dn->waitlock); - return EIO; - } - - err = diskfs_catch_exception (); - if (err) - { - pthread_rwlock_unlock (&dn->allocptrlock); - pthread_mutex_lock (&dn->waitlock); - pthread_cond_broadcast (&dn->waitcond); - pthread_mutex_unlock (&dn->waitlock); - return EIO; - } - - /* See if we need a triple indirect block; fail if we do. */ - assert (indirs[0].offset == -1 - || indirs[1].offset == -1 - || indirs[2].offset == -1); - - /* Check to see if this block is allocated. */ - if (indirs[0].bno == 0) - { - size_t wrote; - - if (indirs[0].offset == -1) - { - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - lblkno (sblock, address), di->di_db), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - - assert (lblkno (sblock, address) < NDADDR); - err = store_write (store, - fsbtodb (sblock, bno) - << log2_dev_blocks_per_dev_bsize, - zeroblock, sblock->fs_bsize, &wrote); - if (!err && wrote != sblock->fs_bsize) - err = EIO; - if (err) - goto out; - - indirs[0].bno = bno; - write_disk_entry (di->di_db[lblkno (sblock, address)], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *siblock; - - /* We need to set siblock to the single indirect block - array; see if the single indirect block is allocated. */ - if (indirs[1].bno == 0) - { - if (indirs[1].offset == -1) - { - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - INDIR_SINGLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (di->di_ib[INDIR_SINGLE], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *diblock; - - /* We need to set diblock to the double indirect - block array; see if the double indirect block is - allocated. */ - if (indirs[2].bno == 0) - { - /* This assert because triple indirection is - not supported. */ - assert (indirs[2].offset == -1); - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, - address), - INDIR_DOUBLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[2].bno = bno; - write_disk_entry (di->di_ib[INDIR_DOUBLE], bno); - record_poke (di, sizeof (struct dinode)); - } - - diblock = indir_block (indirs[2].bno); - mark_indir_dirty (np, indirs[2].bno); - - /* Now we can allocate the single indirect block */ - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - indirs[1].offset, diblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (diblock[indirs[1].offset], bno); - record_poke (diblock, sblock->fs_bsize); - } - } - - siblock = indir_block (indirs[1].bno); - mark_indir_dirty (np, indirs[1].bno); - - /* Now we can allocate the data block. */ - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - indirs[0].offset, siblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - - err = store_write (store, - fsbtodb (sblock, bno) - << log2_dev_blocks_per_dev_bsize, - zeroblock, sblock->fs_bsize, &wrote); - if (!err && wrote != sblock->fs_bsize) - err = EIO; - if (err) - goto out; - - indirs[0].bno = bno; - write_disk_entry (siblock[indirs[0].offset], bno); - record_poke (siblock, sblock->fs_bsize); - } - } - - out: - diskfs_end_catch_exception (); - pthread_rwlock_unlock (&dn->allocptrlock); - pthread_mutex_lock (&dn->waitlock); - pthread_cond_broadcast (&dn->waitcond); - pthread_mutex_unlock (&dn->waitlock); - return err; -} - -void -pager_notify_evict (struct user_pager_info *pager, - vm_offset_t page) -{ - assert (!"unrequested notification on eviction"); -} - -/* Implement the pager_report_extent callback from the pager library. See - <hurd/pager.h> for the interface description. */ -inline error_t -pager_report_extent (struct user_pager_info *pager, - vm_address_t *offset, - vm_size_t *size) -{ - assert (pager->type == DISK || pager->type == FILE_DATA); - - *offset = 0; - - if (pager->type == DISK) - *size = store->size; - else - *size = pager->np->allocsize; - - return 0; -} - -/* Implement the pager_clear_user_data callback from the pager library. - See <hurd/pager.h> for the interface description. */ -void -pager_clear_user_data (struct user_pager_info *upi) -{ - /* XXX Do the right thing for the disk pager here too. */ - if (upi->type == FILE_DATA) - { - pthread_spin_lock (&node2pagelock); - if (upi->np->dn->fileinfo == upi) - upi->np->dn->fileinfo = 0; - pthread_spin_unlock (&node2pagelock); - diskfs_nrele_light (upi->np); - } - free (upi); -} - -void -pager_dropweak (struct user_pager_info *upi __attribute__ ((unused))) -{ -} - - - -/* Create the DISK pager. */ -void -create_disk_pager (void) -{ - struct user_pager_info *upi = malloc (sizeof (struct user_pager_info)); - - upi->type = DISK; - upi->np = 0; - pager_bucket = ports_create_bucket (); - diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0, store->size, - &disk_image); - upi->p = diskfs_disk_pager; -} - -/* This syncs a single file (NP) to disk. Wait for all I/O to complete - if WAIT is set. NP->lock must be held. */ -void -diskfs_file_update (struct node *np, - int wait) -{ - struct dirty_indir *d, *tmp; - struct user_pager_info *upi; - - pthread_spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - - if (upi) - { - pager_sync (upi->p, wait); - ports_port_deref (upi->p); - } - - for (d = np->dn->dirty; d; d = tmp) - { - sync_disk_blocks (d->bno, sblock->fs_bsize, wait); - tmp = d->next; - free (d); - } - np->dn->dirty = 0; - - diskfs_node_update (np, wait); -} - -/* Invalidate any pager data associated with NODE. */ -void -flush_node_pager (struct node *node) -{ - struct user_pager_info *upi; - struct disknode *dn = node->dn; - struct dirty_indir *dirty = dn->dirty; - - pthread_spin_lock (&node2pagelock); - upi = dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - - if (upi) - { - pager_flush (upi->p, 1); - ports_port_deref (upi->p); - } - - dn->dirty = 0; - - while (dirty) - { - struct dirty_indir *next = dirty->next; - free (dirty); - dirty = next; - } -} - -/* Call this to create a FILE_DATA pager and return a send right. - NP must be locked. PROT is the max protection desired. */ -mach_port_t -diskfs_get_filemap (struct node *np, vm_prot_t prot) -{ - struct user_pager_info *upi; - mach_port_t right; - - assert (S_ISDIR (np->dn_stat.st_mode) - || S_ISREG (np->dn_stat.st_mode) - || (S_ISLNK (np->dn_stat.st_mode) - && (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen))); - - pthread_spin_lock (&node2pagelock); - do - if (!np->dn->fileinfo) - { - upi = malloc (sizeof (struct user_pager_info)); - upi->type = FILE_DATA; - upi->np = np; - upi->max_prot = prot; - upi->allow_unlocked_pagein = 0; - upi->unlocked_pagein_length = 0; - diskfs_nref_light (np); - upi->p = pager_create (upi, pager_bucket, - MAY_CACHE, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi->p == 0) - { - diskfs_nrele_light (np); - free (upi); - pthread_spin_unlock (&node2pagelock); - return MACH_PORT_NULL; - } - np->dn->fileinfo = upi; - right = pager_get_port (np->dn->fileinfo->p); - ports_port_deref (np->dn->fileinfo->p); - } - else - { - np->dn->fileinfo->max_prot |= prot; - - /* Because NP->dn->fileinfo->p is not a real reference, - this might be nearly deallocated. If that's so, then - the port right will be null. In that case, clear here - and loop. The deallocation will complete separately. */ - right = pager_get_port (np->dn->fileinfo->p); - if (right == MACH_PORT_NULL) - np->dn->fileinfo = 0; - } - while (right == MACH_PORT_NULL); - - pthread_spin_unlock (&node2pagelock); - - mach_port_insert_right (mach_task_self (), right, right, - MACH_MSG_TYPE_MAKE_SEND); - - return right; -} - -/* Call this when we should turn off caching so that unused memory object - ports get freed. */ -void -drop_pager_softrefs (struct node *np) -{ - struct user_pager_info *upi; - - pthread_spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - - if (MAY_CACHE && upi) - pager_change_attributes (upi->p, 0, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi) - ports_port_deref (upi->p); -} - -/* Call this when we should turn on caching because it's no longer - important for unused memory object ports to get freed. */ -void -allow_pager_softrefs (struct node *np) -{ - struct user_pager_info *upi; - - pthread_spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - - if (MAY_CACHE && upi) - pager_change_attributes (upi->p, 1, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi) - ports_port_deref (upi->p); -} - -static void -block_caching () -{ - error_t block_cache (void *arg) - { - struct pager *p = arg; - - pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_DELAY, 1); - return 0; - } - - /* Loop through the pagers and turn off caching one by one, - synchronously. That should cause termination of each pager. */ - ports_bucket_iterate (pager_bucket, block_cache); -} - -static void -enable_caching () -{ - error_t enable_cache (void *arg) - { - struct pager *p = arg; - struct user_pager_info *upi = pager_get_upi (p); - - pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_DELAY, 0); - - /* It's possible that we didn't have caching on before, because - the user here is the only reference to the underlying node - (actually, that's quite likely inside this particular - routine), and if that node has no links. So dinkle the node - ref counting scheme here, which will cause caching to be - turned off, if that's really necessary. */ - if (upi->type == FILE_DATA) - { - diskfs_nref (upi->np); - diskfs_nrele (upi->np); - } - - return 0; - } - - ports_bucket_iterate (pager_bucket, enable_cache); -} - -/* Tell diskfs if there are pagers exported, and if none, then - prevent any new ones from showing up. */ -int -diskfs_pager_users () -{ - int npagers = ports_count_bucket (pager_bucket); - - if (npagers <= 1) - return 0; - - if (MAY_CACHE) - { - block_caching (); - - /* Give it a second; the kernel doesn't actually shutdown - immediately. XXX */ - sleep (1); - - npagers = ports_count_bucket (pager_bucket); - if (npagers <= 1) - return 0; - - /* Darn, there are actual honest users. Turn caching back on, - and return failure. */ - enable_caching (); - } - - ports_enable_bucket (pager_bucket); - - return 1; -} - -/* Return the bitwise or of the maximum prot parameter (the second arg to - diskfs_get_filemap) for all active user pagers. */ -vm_prot_t -diskfs_max_user_pager_prot () -{ - vm_prot_t max_prot = 0; - int npagers = ports_count_bucket (pager_bucket); - - if (npagers > 1) - /* More than just the disk pager. */ - { - error_t add_pager_max_prot (void *v_p) - { - struct pager *p = v_p; - struct user_pager_info *upi = pager_get_upi (p); - if (upi->type == FILE_DATA) - max_prot |= upi->max_prot; - /* Stop iterating if MAX_PROT is as filled as it's going to get. */ - return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); - } - - block_caching (); /* Make any silly pagers go away. */ - - /* Give it a second; the kernel doesn't actually shutdown - immediately. XXX */ - sleep (1); - - ports_bucket_iterate (pager_bucket, add_pager_max_prot); - - enable_caching (); - } - - ports_enable_bucket (pager_bucket); - - return max_prot; -} - -/* Call this to find out the struct pager * corresponding to the - FILE_DATA pager of inode IP. This should be used *only* as a subsequent - argument to register_memory_fault_area, and will be deleted when - the kernel interface is fixed. NP must be locked. */ -struct pager * -diskfs_get_filemap_pager_struct (struct node *np) -{ - /* This is safe because fileinfo can't be cleared; there must be - an active mapping for this to be called. */ - return np->dn->fileinfo->p; -} - -/* Shutdown all the pagers. */ -void -diskfs_shutdown_pager () -{ - error_t shutdown_one (void *arg) - { - struct pager *p = arg; - /* Don't ever shut down the disk pager. */ - if (p != diskfs_disk_pager) - pager_shutdown (p); - return 0; - } - - copy_sblock (); - write_all_disknodes (); - ports_bucket_iterate (pager_bucket, shutdown_one); - sync_disk (1); -} - -/* Sync all the pagers. */ -void -diskfs_sync_everything (int wait) -{ - error_t sync_one (void *arg) - { - struct pager *p = arg; - /* Make sure the disk pager is done last. */ - if (p != diskfs_disk_pager) - pager_sync (p, wait); - return 0; - } - - copy_sblock (); - write_all_disknodes (); - ports_bucket_iterate (pager_bucket, sync_one); - sync_disk (wait); -} diff --git a/ufs/pokeloc.c b/ufs/pokeloc.c deleted file mode 100644 index e1d5ffcb..00000000 --- a/ufs/pokeloc.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Remember where we've written the disk to speed up sync - Copyright (C) 1994, 1996 Free Software Foundation, Inc. - Written by Michael I. Bushnell. - - This file is part of the GNU Hurd. - - The GNU Hurd 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. - - The GNU Hurd 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. */ - -#include "ufs.h" - -struct pokeloc -{ - vm_offset_t offset; - vm_size_t length; - struct pokeloc *next; -}; - -struct pokeloc *pokelist; -pthread_spinlock_t pokelistlock = PTHREAD_SPINLOCK_INITIALIZER; - -/* Remember that data here on the disk has been modified. */ -void -record_poke (void *loc, vm_size_t length) -{ - struct pokeloc *pl = malloc (sizeof (struct pokeloc)); - vm_offset_t offset; - - offset = loc - disk_image; - pl->offset = trunc_page (offset); - pl->length = round_page (offset + length) - pl->offset; - - pthread_spin_lock (&pokelistlock); - pl->next = pokelist; - pokelist = pl; - pthread_spin_unlock (&pokelistlock); -} - -/* Get rid of any outstanding pokes. */ -void -flush_pokes () -{ - struct pokeloc *pl; - - pthread_spin_lock (&pokelistlock); - pl = pokelist; - pokelist = 0; - pthread_spin_unlock (&pokelistlock); - - while (pl) - { - struct pokeloc *next = pl->next; - free (pl); - pl = next; - } -} - -/* Sync all the modified pieces of disk */ -void -sync_disk (int wait) -{ - struct pokeloc *pl, *tmp; - - pthread_spin_lock (&pokelistlock); - for (pl = pokelist; pl; pl = tmp) - { - pager_sync_some (diskfs_disk_pager, pl->offset, pl->length, wait); - tmp = pl->next; - free (pl); - } - pokelist = 0; - pthread_spin_unlock (&pokelistlock); -} - diff --git a/ufs/sizes.c b/ufs/sizes.c deleted file mode 100644 index e3d51b7d..00000000 --- a/ufs/sizes.c +++ /dev/null @@ -1,736 +0,0 @@ -/* File growth and truncation - Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999 Free Software Foundation - -This file is part of the GNU Hurd. - -The GNU Hurd 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. - -The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Written by Michael I. Bushnell. */ - -#include "ufs.h" -#include <string.h> - -#ifdef DONT_CACHE_MEMORY_OBJECTS -#define MAY_CACHE 0 -#else -#define MAY_CACHE 1 -#endif - -static int indir_release (struct node *np, daddr_t bno, int level); -static void poke_pages (memory_object_t, vm_offset_t, vm_offset_t); - -/* Implement the diskfs_truncate callback; sse <hurd/diskfs.h> for the - interface description. */ -error_t -diskfs_truncate (struct node *np, - off_t length) -{ - int offset; - struct dinode *di = dino (np->dn->number); - volatile int blocksfreed = 0; - error_t err; - int i; - struct iblock_spec indirs[NIADDR + 1]; - volatile daddr_t lbn; - struct user_pager_info *upi; - - if (length >= np->dn_stat.st_size) - return 0; - - diskfs_check_readonly (); - assert (!diskfs_readonly); - - /* First check to see if this is a kludged symlink; if so - this is special. */ - if (direct_symlink_extension && S_ISLNK (np->dn_stat.st_mode) - && np->dn_stat.st_size < sblock->fs_maxsymlinklen) - { - error_t err; - - err = diskfs_catch_exception (); - if (err) - return err; - bzero ((char *)di->di_shortlink + length, np->dn_stat.st_size - length); - record_poke (di, sizeof (struct dinode)); - diskfs_end_catch_exception (); - np->dn_stat.st_size = length; - np->dn_set_ctime = np->dn_set_mtime = 1; - diskfs_node_update (np, 1); - return 0; - } - - /* If the file is not being trucated to a block boundary, - the zero the partial bit in the new last block. */ - offset = blkoff (sblock, length); - if (offset) - { - int bsize; /* size of new last block */ - int savesize = np->allocsize; - - np->allocsize = length; /* temporary */ - bsize = blksize (sblock, np, lblkno (sblock, length)); - np->allocsize = savesize; - diskfs_node_rdwr (np, zeroblock, length, bsize - offset, 1, 0, 0); - diskfs_file_update (np, 1); - } - - /* Now flush all the data past the new size from the kernel. - Also force any delayed copies of this data to take place - immediately. (We are implicitly changing the data to zeros - and doing it without the kernel's immediate knowledge; - accordingl we must help out the kernel thusly.) */ - pthread_spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - - if (upi) - { - mach_port_t obj; - - pager_change_attributes (upi->p, MAY_CACHE, - MEMORY_OBJECT_COPY_NONE, 1); - obj = diskfs_get_filemap (np, VM_PROT_READ | VM_PROT_WRITE); - if (obj != MACH_PORT_NULL) - { - /* XXX should cope with errors from diskfs_get_filemap */ - poke_pages (obj, round_page (length), round_page (np->allocsize)); - mach_port_deallocate (mach_task_self (), obj); - pager_flush_some (upi->p, round_page (length), - np->allocsize - length, 1); - } - ports_port_deref (upi->p); - } - - pthread_rwlock_wrlock (&np->dn->allocptrlock); - - /* Update the size on disk; fsck will finish freeing blocks if necessary - should we crash. */ - np->dn_stat.st_size = length; - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - diskfs_node_update (np, 1); - - /* Find out the location information for the last block to - be retained */ - lbn = lblkno (sblock, length - 1); - err = fetch_indir_spec (np, lbn, indirs); - /* err XXX */ - - /* We don't support triple indirs */ - assert (indirs[3].offset == -2); - - err = diskfs_catch_exception (); - /* err XXX */ - - /* BSD carefully finds out how far to clear; it's vastly simpler - to just clear everything after the new last block. */ - - /* Free direct blocks */ - if (indirs[0].offset < 0) - { - /* ...mapped from the inode. */ - for (i = lbn + 1; i < NDADDR; i++) - if (di->di_db[i]) - { - long bsize = blksize (sblock, np, i); - ffs_blkfree (np, read_disk_entry (di->di_db[i]), bsize); - di->di_db[i] = 0; - blocksfreed += btodb (bsize); - } - } - else - { - /* ... or mapped from sindir */ - if (indirs[1].bno) - { - daddr_t *sindir = indir_block (indirs[1].bno); - for (i = indirs[0].offset + 1; i < NINDIR (sblock); i++) - if (sindir[i]) - { - ffs_blkfree (np, read_disk_entry (sindir[i]), - sblock->fs_bsize); - sindir[i] = 0; - blocksfreed += btodb (sblock->fs_bsize); - } - record_poke (sindir, sblock->fs_bsize); - } - } - - /* Free single indirect blocks */ - if (indirs[1].offset < 0) - { - /* ...mapped from the inode */ - if (di->di_ib[INDIR_SINGLE] && indirs[1].offset == -2) - { - blocksfreed += indir_release (np, - read_disk_entry (di->di_ib - [INDIR_SINGLE]), - INDIR_SINGLE); - di->di_ib[INDIR_SINGLE] = 0; - } - } - else - { - /* ...or mapped from dindir */ - if (indirs[2].bno) - { - daddr_t *dindir = indir_block (indirs[2].bno); - for (i = indirs[1].offset + 1; i < NINDIR (sblock); i++) - if (dindir[i]) - { - blocksfreed += indir_release (np, - read_disk_entry (dindir[i]), - INDIR_SINGLE); - dindir[i] = 0; - } - record_poke (dindir, sblock->fs_bsize); - } - } - - /* Free double indirect block */ - assert (indirs[2].offset < 0); /* which must be mapped from the inode */ - if (indirs[2].offset == -2) - { - if (di->di_ib[INDIR_DOUBLE]) - { - blocksfreed += indir_release (np, - read_disk_entry (di->di_ib - [INDIR_DOUBLE]), - INDIR_DOUBLE); - di->di_ib[INDIR_DOUBLE] = 0; - } - } - - /* Finally, check to see if the new last direct block is - changing size; if so release any frags necessary. */ - if (lbn >= 0 && lbn < NDADDR && di->di_db[lbn]) - { - long oldspace, newspace; - daddr_t bn; - - bn = read_disk_entry (di->di_db[lbn]); - oldspace = blksize (sblock, np, lbn); - np->allocsize = fragroundup (sblock, length); - newspace = blksize (sblock, np, lbn); - - assert (newspace); - - if (oldspace - newspace) - { - bn += numfrags (sblock, newspace); - ffs_blkfree (np, bn, oldspace - newspace); - blocksfreed += btodb (oldspace - newspace); - } - } - else - { - if (lbn > NDADDR) - np->allocsize = blkroundup (sblock, length); - else - np->allocsize = fragroundup (sblock, length); - } - - record_poke (di, sizeof (struct dinode)); - - np->dn_stat.st_blocks -= blocksfreed; - np->dn_set_ctime = 1; - diskfs_node_update (np, 1); - - pthread_rwlock_unlock (&np->dn->allocptrlock); - /* Wake up any remaining sleeping readers. - This sequence of three calls is now necessary whenever we acquire a write - lock on allocptrlock. If we do not, we may leak some readers. */ - pthread_mutex_lock (&np->dn->waitlock); - pthread_cond_broadcast (&np->dn->waitcond); - pthread_mutex_unlock (&np->dn->waitlock); - - /* At this point the last block (as defined by np->allocsize) - might not be allocated. We need to allocate it to maintain - the rule that the last block of a file is always allocated. */ - - if (np->allocsize && indirs[0].bno == 0) - { - /* The strategy is to reduce LBN until we get one that's allocated; - then reduce allocsize accordingly, then call diskfs_grow. */ - - do - err = fetch_indir_spec (np, --lbn, indirs); - /* err XXX */ - while (indirs[0].bno == 0 && lbn >= 0); - - assert ((lbn + 1) * sblock->fs_bsize < np->allocsize); - np->allocsize = (lbn + 1) * sblock->fs_bsize; - - diskfs_grow (np, length, 0); - } - - diskfs_end_catch_exception (); - - /* Now we can permit delayed copies again. */ - pthread_spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - pthread_spin_unlock (&node2pagelock); - if (upi) - { - pager_change_attributes (upi->p, MAY_CACHE, - MEMORY_OBJECT_COPY_DELAY, 0); - ports_port_deref (upi->p); - } - - return err; -} - -/* Free indirect block BNO of level LEVEL; recursing if necessary - to free other indirect blocks. Return the number of disk - blocks freed. */ -static int -indir_release (struct node *np, daddr_t bno, int level) -{ - int count = 0; - daddr_t *addrs; - int i; - struct dirty_indir *d, *prev, *next; - - assert (bno); - - addrs = indir_block (bno); - for (i = 0; i < NINDIR (sblock); i++) - if (addrs[i]) - { - if (level == INDIR_SINGLE) - { - ffs_blkfree (np, read_disk_entry (addrs[i]), sblock->fs_bsize); - count += btodb (sblock->fs_bsize); - } - else - count += indir_release (np, read_disk_entry (addrs[i]), level - 1); - } - - /* Subtlety: this block is no longer necessary; the information - the kernel has cached corresponding to ADDRS is now unimportant. - Consider that if this block is allocated to a file, it will then - be double cached and the kernel might decide to write out - the disk_image version of the block. So we have to flush - the block from the kernel's memory, making sure we do it - synchronously--and BEFORE we attach it to the free list - with ffs_blkfree. */ - pager_flush_some (diskfs_disk_pager, fsaddr (sblock, bno), sblock->fs_bsize, 1); - - /* We should also take this block off the inode's list of - dirty indirect blocks if it's there. */ - prev = 0; - d = np->dn->dirty; - while (d) - { - next = d->next; - if (d->bno == bno) - { - if (prev) - prev->next = next; - else - np->dn->dirty = next; - free (d); - } - else - { - prev = d; - next = d->next; - } - d = next; - } - - /* Free designated block */ - ffs_blkfree (np, bno, sblock->fs_bsize); - count += btodb (sblock->fs_bsize); - - return count; -} - - -/* Offer data at BUF from START of LEN bytes of file NP. */ -void -offer_data (struct node *np, - off_t start, - size_t len, - vm_address_t buf) -{ - vm_address_t addr; - - len = round_page (len); - - assert (start % vm_page_size == 0); - - assert (np->dn->fileinfo); - for (addr = start; addr < start + len; addr += vm_page_size) - pager_offer_page (np->dn->fileinfo->p, 1, 0, addr, buf + (addr - start)); -} - -/* Logical block LBN of node NP has been extended with ffs_realloccg. - It used to be allocated at OLD_PBN and is now at NEW_PBN. The old - size was OLD_SIZE; it is now NEW_SIZE bytes long. Arrange for the data - on disk to be kept consistent, and free the old block if it has moved. - Return one iff we've actually moved data around on disk. */ -int -block_extended (struct node *np, - daddr_t lbn, - daddr_t old_pbn, - daddr_t new_pbn, - size_t old_size, - size_t new_size) -{ - /* Make sure that any pages of this block which just became allocated - don't get paged in from disk. */ - if (round_page (old_size) < round_page (new_size)) - offer_data (np, lbn * sblock->fs_bsize + round_page (old_size), - round_page (new_size) - round_page (old_size), - (vm_address_t)zeroblock); - - if (old_pbn != new_pbn) - { - memory_object_t mapobj; - error_t err; - vm_address_t mapaddr; - volatile int *pokeaddr; - - /* Map in this part of the file */ - mapobj = diskfs_get_filemap (np, VM_PROT_WRITE | VM_PROT_READ); - - /* XXX Should cope with errors from diskfs_get_filemap and back - out the operation here. */ - assert (mapobj); - - err = vm_map (mach_task_self (), &mapaddr, round_page (old_size), 0, 1, - mapobj, lbn * sblock->fs_bsize, 0, - VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, 0); - assert_perror (err); - - /* Allow these pageins to occur even though we're holding the lock */ - pthread_spin_lock (&unlocked_pagein_lock); - np->dn->fileinfo->allow_unlocked_pagein = lbn * sblock->fs_bsize; - np->dn->fileinfo->unlocked_pagein_length = round_page (old_size); - pthread_spin_unlock (&unlocked_pagein_lock); - - /* Make sure all waiting pageins see this change. */ - /* BDD - Is this sane? */ - /* TD - No... no it wasn't. But, it looked right. */ - /* - This new code should, SHOULD, behave as the original code did. - This will wake up all readers waiting on the lock. This code favors - strongly writers, but, as of making this change, pthreads favors - writers, and cthreads did favor writers. - */ - pthread_mutex_lock (&np->dn->waitlock); - pthread_cond_broadcast (&np->dn->waitcond); - pthread_mutex_unlock (&np->dn->waitlock); - - /* Force the pages in core and make sure they are dirty */ - for (pokeaddr = (int *)mapaddr; - pokeaddr < (int *) (mapaddr + round_page (old_size)); - pokeaddr += vm_page_size / sizeof (*pokeaddr)) - *pokeaddr = *pokeaddr; - - /* Turn off the special pagein permission */ - pthread_spin_lock (&unlocked_pagein_lock); - np->dn->fileinfo->allow_unlocked_pagein = 0; - np->dn->fileinfo->unlocked_pagein_length = 0; - pthread_spin_unlock (&unlocked_pagein_lock); - - /* Undo mapping */ - mach_port_deallocate (mach_task_self (), mapobj); - munmap ((caddr_t) mapaddr, round_page (old_size)); - - /* Now it's OK to free the old block */ - ffs_blkfree (np, old_pbn, old_size); - - /* Tell caller that we've moved data */ - return 1; - } - else - return 0; -} - - -/* Implement the diskfs_grow callback; see <hurd/diskfs.h> for the - interface description. */ -error_t -diskfs_grow (struct node *np, - off_t end, - struct protid *cred) -{ - daddr_t lbn, olbn; - int size, osize; - error_t err; - struct dinode *di = dino (np->dn->number); - mach_port_t pagerpt; - int need_sync = 0; - - /* Zero an sblock->fs_bsize piece of disk starting at BNO, - synchronously. We do this on newly allocated indirect - blocks before setting the pointer to them to ensure that an - indirect block absolutely never points to garbage. */ - void zero_disk_block (int bno) - { - bzero (indir_block (bno), sblock->fs_bsize); - sync_disk_blocks (bno, sblock->fs_bsize, 1); - }; - - /* Check to see if we don't actually have to do anything */ - if (end <= np->allocsize) - return 0; - - diskfs_check_readonly (); - assert (!diskfs_readonly); - - /* This reference will ensure that NP->dn->fileinfo stays allocated. */ - pagerpt = diskfs_get_filemap (np, VM_PROT_WRITE|VM_PROT_READ); - - if (pagerpt == MACH_PORT_NULL) - return errno; - - /* The new last block of the file. */ - lbn = lblkno (sblock, end - 1); - - /* This is the size of that block if it is in the NDADDR array. */ - size = fragroundup (sblock, blkoff (sblock, end)); - if (size == 0) - size = sblock->fs_bsize; - - pthread_rwlock_wrlock (&np->dn->allocptrlock); - - /* The old last block of the file. */ - olbn = lblkno (sblock, np->allocsize - 1); - - /* This is the size of that block if it is in the NDADDR array. */ - osize = fragroundup (sblock, blkoff (sblock, np->allocsize)); - if (osize == 0) - osize = sblock->fs_bsize; - - /* If this end point is a new block and the file currently - has a fragment, then expand the fragment to a full block. */ - if (np->allocsize && olbn < NDADDR && olbn < lbn) - { - if (osize < sblock->fs_bsize) - { - daddr_t old_pbn, bno; - err = ffs_realloccg (np, olbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - osize, sblock->fs_bsize, &bno, cred); - if (err) - goto out; - - old_pbn = read_disk_entry (di->di_db[olbn]); - - need_sync = block_extended (np, olbn, old_pbn, bno, - osize, sblock->fs_bsize); - - write_disk_entry (di->di_db[olbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - } - - if (lbn < NDADDR) - { - daddr_t bno, old_pbn = read_disk_entry (di->di_db[lbn]); - - if (old_pbn != 0) - { - /* The last block is already allocated. Therefore we - must be expanding the fragment. Make sure that's really - what we're up to. */ - assert (size > osize); - assert (lbn == olbn); - - err = ffs_realloccg (np, lbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - osize, size, &bno, cred); - if (err) - goto out; - - need_sync = block_extended (np, lbn, old_pbn, bno, osize, size); - - write_disk_entry (di->di_db[lbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - else - { - /* Allocate a new last block. */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - size, &bno, cred); - if (err) - goto out; - - - offer_data (np, lbn * sblock->fs_bsize, size, - (vm_address_t)zeroblock); - write_disk_entry (di->di_db[lbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - } - else - { - struct iblock_spec indirs[NIADDR + 1]; - daddr_t *siblock; - daddr_t bno; - - /* Count the number of levels of indirection. */ - err = fetch_indir_spec (np, lbn, indirs); - if (err) - goto out; - - /* Make sure we didn't miss the NDADDR case - above somehow. */ - assert (indirs[0].offset != -1); - - /* See if we need a triple indirect block; fail if so. */ - assert (indirs[1].offset == -1 || indirs[2].offset == -1); - - /* Check to see if this block is allocated. If it is - that's an error. */ - assert (indirs[0].bno == 0); - - /* We need to set SIBLOCK to the single indirect block - array; see if the single indirect block is allocated. */ - if (indirs[1].bno == 0) - { - /* Allocate it. */ - if (indirs[1].offset == -1) - { - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, INDIR_SINGLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (di->di_ib[INDIR_SINGLE], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *diblock; - - /* We need to set diblock to the double indirect block - array; see if the double indirect block is allocated. */ - if (indirs[2].bno == 0) - { - /* This assert because triple indirection is not - supported. */ - assert (indirs[2].offset == -1); - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, - INDIR_DOUBLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[2].bno = bno; - write_disk_entry (di->di_ib[INDIR_DOUBLE], bno); - record_poke (di, sizeof (struct dinode)); - } - - diblock = indir_block (indirs[2].bno); - mark_indir_dirty (np, indirs[2].bno); - - /* Now we can allocate the single indirect block */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, - indirs[1].offset, diblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (diblock[indirs[1].offset], bno); - record_poke (diblock, sblock->fs_bsize); - } - } - - siblock = indir_block (indirs[1].bno); - mark_indir_dirty (np, indirs[1].bno); - - /* Now we can allocate the data block. */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, indirs[0].offset, siblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - offer_data (np, lbn * sblock->fs_bsize, sblock->fs_bsize, - (vm_address_t)zeroblock); - indirs[0].bno = bno; - write_disk_entry (siblock[indirs[0].offset], bno); - record_poke (siblock, sblock->fs_bsize); - } - - out: - mach_port_deallocate (mach_task_self (), pagerpt); - if (!err) - { - int newallocsize; - if (lbn < NDADDR) - newallocsize = lbn * sblock->fs_bsize + size; - else - newallocsize = (lbn + 1) * sblock->fs_bsize; - assert (newallocsize > np->allocsize); - np->allocsize = newallocsize; - } - - pthread_rwlock_unlock (&np->dn->allocptrlock); - pthread_mutex_lock (&np->dn->waitlock); - pthread_cond_broadcast (&np->dn->waitcond); - pthread_mutex_unlock (&np->dn->waitlock); - - if (need_sync) - diskfs_file_update (np, 1); - - return err; -} - -/* Write something to each page from START to END inclusive of memory - object OBJ, but make sure the data doesns't actually change. */ -static void -poke_pages (memory_object_t obj, - vm_offset_t start, - vm_offset_t end) -{ - vm_address_t addr, poke; - vm_size_t len; - error_t err; - - while (start < end) - { - len = 8 * vm_page_size; - if (len > end - start) - len = end - start; - addr = 0; - err = vm_map (mach_task_self (), &addr, len, 0, 1, obj, start, 0, - VM_PROT_WRITE|VM_PROT_READ, VM_PROT_READ|VM_PROT_WRITE, 0); - if (!err) - { - for (poke = addr; poke < addr + len; poke += vm_page_size) - *(volatile int *)poke = *(volatile int *)poke; - munmap ((caddr_t) addr, len); - } - start += len; - } -} - diff --git a/ufs/subr.c b/ufs/subr.c deleted file mode 100644 index 2b356ddc..00000000 --- a/ufs/subr.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 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. - * - * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 - */ - -#include "ufs.h" - -#if 0 /* Not needed in GNU Hurd ufs. */ -/* - * Return buffer with the contents of block "offset" from the beginning of - * directory "ip". If "res" is non-zero, fill it in with a pointer to the - * remaining space in the directory. - */ -int -ffs_blkatoff(ap) - struct vop_blkatoff_args /* { - struct vnode *a_vp; - off_t a_offset; - char **a_res; - struct buf **a_bpp; - } */ *ap; -{ - struct inode *ip; - register struct fs *fs; - struct buf *bp; - daddr_t lbn; - int bsize, error; - - ip = VTOI(ap->a_vp); - fs = ip->i_fs; - lbn = lblkno(fs, ap->a_offset); - bsize = blksize(fs, ip, lbn); - - *ap->a_bpp = NULL; - if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { - brelse(bp); - return (error); - } - if (ap->a_res) - *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); - *ap->a_bpp = bp; - return (0); -} -#endif /* 0 */ - -/* - * 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; - } - } -} - -#if 0 /* Not needed in GNU Hurd ufs. */ -void -ffs_checkoverlap(bp, ip) - struct buf *bp; - struct inode *ip; -{ - register struct buf *ebp, *ep; - register daddr_t start, last; - struct vnode *vp; - - ebp = &buf[nbuf]; - start = bp->b_blkno; - last = start + btodb(bp->b_bcount) - 1; - for (ep = buf; ep < ebp; ep++) { - if (ep == bp || (ep->b_flags & B_INVAL) || - ep->b_vp == NULLVP) - continue; - if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL)) - continue; - if (vp != ip->i_devvp) - continue; - /* look for overlap */ - if (ep->b_bcount == 0 || ep->b_blkno > last || - ep->b_blkno + btodb(ep->b_bcount) <= start) - continue; - vprint("Disk overlap", vp); - (void)printf("\tstart %d, end %d overlap start %d, end %d\n", - start, last, ep->b_blkno, - ep->b_blkno + btodb(ep->b_bcount) - 1); - panic("Disk buffer overlap"); - } -} -#endif /* 0 */ - -/* - * block operations - * - * check if a block is available - */ -int -ffs_isblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - daddr_t h; -{ - unsigned char mask; - - switch ((int)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: - assert (0); - } -} - -/* - * take a block out of the map - */ -void -ffs_clrblock(fs, cp, h) - struct fs *fs; - u_char *cp; - daddr_t h; -{ - - switch ((int)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: - assert (0); - } -} - -/* - * put a block into the map - */ -void -ffs_setblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - daddr_t h; -{ - - switch ((int)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: - assert (0); - } -} - -/* Taken from 4.4 BSD sys/libkern/skpc.c: - @(#)skpc.c 8.1 (Berkeley) 6/10/93 -*/ -int -skpc(mask0, size, cp0) - int mask0; - int size; - char *cp0; -{ - register u_char *cp, *end, mask; - - mask = mask0; - cp = (u_char *)cp0; - for (end = &cp[size]; cp < end && *cp == mask; ++cp); - return (end - cp); -} - -/* Taken from 4.4 BSD sys/libkern/scanc.c: - @(#)scanc.c 8.1 (Berkeley) 6/10/93 -*/ -int -scanc(size, cp, table, mask0) - u_int size; - register u_char *cp, table[]; - int mask0; -{ - register u_char *end; - register u_char mask; - - mask = mask0; - for (end = &cp[size]; cp < end && (table[*cp] & mask) == 0; ++cp); - return (end - cp); -} diff --git a/ufs/tables.c b/ufs/tables.c deleted file mode 100644 index d345b9e4..00000000 --- a/ufs/tables.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Modified from BSD for GNU Hurd ufs server by Michael I. Bushnell. */ -/* - * Copyright (c) 1982, 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. - * - * @(#)ffs_tables.c 8.1 (Berkeley) 6/11/93 - */ - -#include <sys/types.h> -#include "fs.h" - -/* - * Bit patterns for identifying fragments in the block map - * used as ((map & around) == inside) - */ -int around[9] = { - 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff -}; -int inside[9] = { - 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe -}; - -/* - * Given a block map bit pattern, the frag tables tell whether a - * particular size fragment is available. - * - * used as: - * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] { - * at least one fragment of the indicated size is available - * } - * - * These tables are used by the scanc instruction on the VAX to - * quickly find an appropriate fragment. - */ -u_char fragtbl124[256] = { - 0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e, - 0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e, - 0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae, - 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, - 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, - 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, - 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, - 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, - 0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce, - 0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a, -}; - -u_char fragtbl8[256] = { - 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, - 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, - 0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, - 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, - 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c, - 0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c, - 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80, -}; - -/* - * The actual fragtbl array. - */ -u_char *fragtbl[MAXFRAG + 1] = { - 0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8, -}; diff --git a/ufs/ufs.h b/ufs/ufs.h deleted file mode 100644 index 0a79f560..00000000 --- a/ufs/ufs.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - Copyright (C) 1994, 1995, 1996, 1997, 1999 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. */ - -#include <mach.h> -#include <hurd.h> -#include <sys/mman.h> -#include <hurd/ports.h> -#include <hurd/pager.h> -#include <hurd/fshelp.h> -#include <hurd/iohelp.h> -#include <hurd/diskfs.h> -#include <sys/mman.h> -#include <assert.h> -#include <pthread.h> -#include <features.h> -#include "fs.h" -#include "dinode.h" - -#ifdef UFS_DEFINE_EI -#define UFS_EI -#else -#define UFS_EI __extern_inline -#endif - -/* Define this if memory objects should not be cached by the kernel. - Normally, don't define it, but defining it causes a much greater rate - of paging requests, which may be helpful in catching bugs. */ - -/* #undef DONT_CACHE_MEMORY_OBJECTS */ - -struct disknode -{ - ino_t number; - - int dir_idx; - - /* For a directory, this array holds the number of directory entries in - each DIRBLKSIZE piece of the directory. */ - int *dirents; - - /* Links on hash list. */ - struct node *hnext, **hprevp; - - pthread_rwlock_t allocptrlock; - pthread_mutex_t waitlock; - pthread_cond_t waitcond; - - struct dirty_indir *dirty; - - struct user_pager_info *fileinfo; -}; - -/* Identifies a particular block and where it's found - when interpreting indirect block structure. */ -struct iblock_spec -{ - /* Disk address of block */ - daddr_t bno; - - /* Offset in next block up; -1 if it's in the inode itself. */ - int offset; -}; - -/* Identifies an indirect block owned by this file which - might be dirty. */ -struct dirty_indir -{ - daddr_t bno; /* Disk address of block. */ - struct dirty_indir *next; -}; - -struct user_pager_info -{ - struct node *np; - enum pager_type - { - DISK, - FILE_DATA, - } type; - struct pager *p; - vm_prot_t max_prot; - - vm_offset_t allow_unlocked_pagein; - vm_size_t unlocked_pagein_length; -}; - -#include <hurd/diskfs-pager.h> - -/* The physical media. */ -extern struct store *store; -/* What the user specified. */ -extern struct store_parsed *store_parsed; - -/* Mapped image of the disk. */ -extern void *disk_image; - -extern void *zeroblock; - -extern struct fs *sblock; -extern struct csum *csum; -int sblock_dirty; -int csum_dirty; - -pthread_spinlock_t node2pagelock; - -pthread_spinlock_t alloclock; - -pthread_spinlock_t gennumberlock; -u_long nextgennumber; - -pthread_spinlock_t unlocked_pagein_lock; - -/* The compat_mode specifies whether or not we write - extensions onto the disk. */ -enum compat_mode -{ - COMPAT_GNU = 0, - COMPAT_BSD42 = 1, - COMPAT_BSD44 = 2, -} compat_mode; - -/* If this is set, then this filesystem has two extensions: - 1) directory entries include the type field. - 2) symlink targets might be written directly in the di_db field - of the dinode. */ -int direct_symlink_extension; - -/* If this is set, then the disk is byteswapped from native order. */ -int swab_disk; - -/* Number of device blocks per DEV_BSIZE block. */ -unsigned log2_dev_blocks_per_dev_bsize; - -/* Handy macros */ -#define DEV_BSIZE 512 -#define NBBY 8 -#define btodb(n) ((n) / DEV_BSIZE) -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY)) -#define fsaddr(fs,n) (fsbtodb(fs,n)*DEV_BSIZE) - - -/* Functions for looking inside disk_image */ - -extern struct dinode * dino (ino_t inum); -extern daddr_t * indir_block (daddr_t bno); -extern struct cg * cg_locate (int ncg); -extern void sync_disk_blocks (daddr_t blkno, size_t nbytes, int wait); -extern void sync_dinode (int inum, int wait); -extern short swab_short (short arg); -extern long swab_long (long arg); -extern long long swab_long_long (long long arg); - -#if defined(__USE_EXTERN_INLINES) || defined(UFS_DEFINE_EI) -/* Convert an inode number to the dinode on disk. */ -UFS_EI struct dinode * -dino (ino_t inum) -{ - return (struct dinode *) - (disk_image - + fsaddr (sblock, ino_to_fsba (sblock, inum)) - + ino_to_fsbo (sblock, inum) * sizeof (struct dinode)); -} - -/* Convert a indirect block number to a daddr_t table. */ -UFS_EI daddr_t * -indir_block (daddr_t bno) -{ - return (daddr_t *) (disk_image + fsaddr (sblock, bno)); -} - -/* Convert a cg number to the cylinder group. */ -UFS_EI struct cg * -cg_locate (int ncg) -{ - return (struct cg *) (disk_image + fsaddr (sblock, cgtod (sblock, ncg))); -} - -/* Sync part of the disk */ -UFS_EI void -sync_disk_blocks (daddr_t blkno, size_t nbytes, int wait) -{ - pager_sync_some (diskfs_disk_pager, fsaddr (sblock, blkno), nbytes, wait); -} - -/* Sync an disk inode */ -UFS_EI void -sync_dinode (int inum, int wait) -{ - sync_disk_blocks (ino_to_fsba (sblock, inum), sblock->fs_fsize, wait); -} - - -/* Functions for byte swapping */ -UFS_EI short -swab_short (short arg) -{ - return (((arg & 0xff) << 8) - | ((arg & 0xff00) >> 8)); -} - -UFS_EI long -swab_long (long arg) -{ - return (((long) swab_short (arg & 0xffff) << 16) - | swab_short ((arg & 0xffff0000) >> 16)); -} - -UFS_EI long long -swab_long_long (long long arg) -{ - return (((long long) swab_long (arg & 0xffffffff) << 32) - | swab_long ((arg & 0xffffffff00000000LL) >> 32)); -} -#endif /* Use extern inlines. */ - -/* Return ENTRY, after byteswapping it if necessary */ -#define read_disk_entry(entry) \ -({ \ - typeof (entry) ret; \ - if (!swab_disk || sizeof (entry) == 1) \ - ret = (entry); \ - else if (sizeof (entry) == 2) \ - ret = swab_short (entry); \ - else if (sizeof (entry) == 4) \ - ret = swab_long (entry); \ - else \ - abort (); \ - ret; \ -}) - -/* Execute A = B, but byteswap it along the way if necessary */ -#define write_disk_entry(a,b) \ -({ \ - if (!swab_disk || sizeof (a) == 1) \ - ((a) = (b)); \ - else if (sizeof (a) == 2) \ - ((a) = (swab_short (b))); \ - else if (sizeof (a) == 4) \ - ((a) = (swab_long (b))); \ - else \ - abort (); \ -}) - - - - - -/* From alloc.c: */ -error_t ffs_alloc (struct node *, daddr_t, daddr_t, int, daddr_t *, - struct protid *); -void ffs_blkfree(struct node *, daddr_t bno, long size); -daddr_t ffs_blkpref (struct node *, daddr_t, int, daddr_t *); -error_t ffs_realloccg(struct node *, daddr_t, daddr_t, - int, int, daddr_t *, struct protid *); - -/* From bmap.c */ -error_t fetch_indir_spec (struct node *, daddr_t, struct iblock_spec *); -void mark_indir_dirty (struct node *, daddr_t); - -/* From hyper.c: */ -void get_hypermetadata (void); -void copy_sblock (void); - -/* From inode.c: */ -struct node *ifind (ino_t ino); -void inode_init (void); -void write_all_disknodes (void); - -/* From pager.c: */ -void create_disk_pager (void); -void din_map (struct node *); -void sin_map (struct node *); -void sin_remap (struct node *, int); -void sin_unmap (struct node *); -void din_unmap (struct node *); -void drop_pager_softrefs (struct node *); -void allow_pager_softrefs (struct node *); -void flush_node_pager (struct node *); - -/* From subr.c: */ -void ffs_fragacct (struct fs *, int, long [], int); -int ffs_isblock(struct fs *, u_char *, daddr_t); -void ffs_clrblock(struct fs *, u_char *, daddr_t); -void ffs_setblock (struct fs *, u_char *, daddr_t); -int skpc (int, int, char *); -int scanc (u_int, u_char *, u_char [], int); - -/* From pokeloc.c: */ -void record_poke (void *, vm_size_t); -void sync_disk (int); -void flush_pokes (); diff --git a/ufs/xinl.c b/ufs/xinl.c deleted file mode 100644 index 7994a1f7..00000000 --- a/ufs/xinl.c +++ /dev/null @@ -1,2 +0,0 @@ -#define UFS_DEFINE_EI -#include "ufs.h" |