mkproto.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 589 行
C
589 行
#ifndef lintstatic char *sccsid = "@(#)mkproto.c 4.1 ULTRIX 7/2/90";#endif/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Make a file system prototype. * usage: mkproto filsys proto *//* * * Modification History * * * * 22 Aug 88 -- prs * * Added calculations of the blocks field of an on-disk * * inode. * * * * 1) - 15 Mar 85 -- funding * * Added named pipe support (re. System V named pipes) * */#define NPIPES /* 1 */#include <stdio.h>#include <sys/param.h>#include <sys/gnode.h>#include <sys/gnode_common.h>#include <ufs/ufs_inode.h>#include <sys/fs.h>#include <sys/dir.h>#define I_TO_UP(i) ((struct ufs_inode *)(&(i.g_in)))#define IP_TO_UP(i) ((struct ufs_inode *)(&(i->g_in)))union { struct fs fs; char fsx[SBSIZE];} ufs;#define sblock ufs.fsunion { struct cg cg; char cgx[MAXBSIZE];} ucg;#define acg ucg.cgstruct fs *fs;struct csum *fscs;int fso, fsi;FILE *proto;char token[BUFSIZ];int errs;int ino = 10;long getnum();char *strcpy();main(argc, argv) int argc; char *argv[];{ int i; if (argc != 3) { fprintf(stderr, "usage: mkproto filsys proto\n"); exit(1); } fso = open(argv[1], 1); fsi = open(argv[1], 0); if (fso < 0 || fsi < 0) { perror(argv[1]); exit(1); } fs = &sblock; rdfs(SBLOCK, SBSIZE, (char *)fs); fscs = (struct csum *)calloc(1, fs->fs_cssize); for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), (int)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize), ((char *)fscs) + i); proto = fopen(argv[2], "r"); descend((struct gnode *)0); wtfs(SBLOCK, SBSIZE, (char *)fs); for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)), (int)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - i : fs->fs_bsize), ((char *)fscs) + i); exit(errs);}descend(par) struct gnode *par;{ struct gnode in; int ibc = 0; int i, f, c; struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)]; daddr_t ib[MAXBSIZE / sizeof (daddr_t)]; char buf[MAXBSIZE]; getstr(); in.g_mode = gmode(token[0], "-bcdp", GFREG, GFBLK, GFCHR,/* 1 */ GFDIR, GFPORT); in.g_mode |= gmode(token[1], "-u", 0, GSUID, 0, 0, 0); /* 1 */ in.g_mode |= gmode(token[2], "-g", 0, GSGID, 0, 0, 0); /* 1 */ for (i = 3; i < 6; i++) { c = token[i]; if (c < '0' || c > '7') { printf("%c/%s: bad octal mode digit\n", c, token); errs++; c = 0; } in.g_mode |= (c-'0')<<(15-3*i); } in.g_uid = getnum(); in.g_gid = getnum(); for (i = 0; i < fs->fs_bsize; i++) buf[i] = 0; for (i = 0; i < NINDIR(fs); i++) ib[i] = (daddr_t)0; in.g_nlink = 1; in.g_size = 0; (I_TO_UP(in))->di_blocks = 0; for (i = 0; i < NDADDR; i++) (I_TO_UP(in))->di_db[i] = (daddr_t)0; for (i = 0; i < NIADDR; i++) (I_TO_UP(in))->di_ib[i] = (daddr_t)0; if (par != (struct gnode *)0) { ialloc(&in); } else { par = ∈ i = itod(fs, ROOTINO); rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos); dip = &inos[ROOTINO % INOPB(fs)]; in.g_number = ROOTINO; in.g_nlink = dip->di_nlink; in.g_size = dip->di_size; (I_TO_UP(in))->di_blocks = dip->di_blocks; (I_TO_UP(in))->di_db[0] = dip->di_db[0]; rdfs(fsbtodb(fs, (I_TO_UP(in))->di_db[0]), fs->fs_bsize, buf); } switch (in.g_mode&GFMT) { case GFREG: getstr(); f = open(token, 0); if (f < 0) { printf("%s: cannot open\n", token); errs++; break; } while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) { in.g_size += i; newblk(&in, buf, &ibc, ib, (int)blksize(fs, &in, ibc)); } close(f); break; case GFBLK: case GFCHR: /* * special file * content is maj/min types */ i = getnum() & 0377; f = getnum() & 0377; in.g_rdev = (i << 8) | f; break; case GFDIR: /* * directory * put in extra links * call recursively until * name of "$" found */ if (in.g_number != ROOTINO) { par->g_nlink++; in.g_nlink++; entry(&in, in.g_number, ".", buf); entry(&in, par->g_number, "..", buf); } for (;;) { getstr(); if (token[0]=='$' && token[1]=='\0') break; entry(&in, (ino_t)(ino+1), token, buf); descend(&in); } if (in.g_number != ROOTINO) newblk(&in, buf, &ibc, ib, (int)blksize(fs, &in, 0)); else wtfs(fsbtodb(fs, (I_TO_UP(in))->di_db[0]), (int)fs->fs_bsize, buf); break; } iput(&in, &ibc, ib);}/*ARGSUSED*/gmode(c, s, m0, m1, m2, m3, m4) /* 1 */ char c, *s;{ int i; for (i = 0; s[i]; i++) if (c == s[i]) return((&m0)[i]); printf("%c/%s: bad mode\n", c, token); errs++; return(0);}longgetnum(){ int i, c; long n; getstr(); n = 0; i = 0; for (i = 0; c=token[i]; i++) { if (c<'0' || c>'9') { printf("%s: bad number\n", token); errs++; return((long)0); } n = n*10 + (c-'0'); } return(n);}getstr(){ int i, c;loop: switch (c = getc(proto)) { case ' ': case '\t': case '\n': goto loop; case EOF: printf("Unexpected EOF\n"); exit(1); case ':': while (getc(proto) != '\n') ; goto loop; } i = 0; do { token[i++] = c; c = getc(proto); } while (c != ' ' && c != '\t' && c != '\n' && c != '\0'); token[i] = 0;}entry(ip, inum, str, buf) struct gnode *ip; ino_t inum; char *str; char *buf;{ register struct direct *dp, *odp; int oldsize, newsize, spacefree; odp = dp = (struct direct *)buf; while ((int)dp - (int)buf < ip->g_size) { odp = dp; dp = (struct direct *)((int)dp + dp->d_reclen); } if (odp != dp) oldsize = DIRSIZ(odp); else oldsize = 0; spacefree = odp->d_reclen - oldsize; dp = (struct direct *)((int)odp + oldsize); dp->d_ino = inum; dp->d_namlen = strlen(str); newsize = DIRSIZ(dp); if (spacefree >= newsize) { odp->d_reclen = oldsize; dp->d_reclen = spacefree; } else { dp = (struct direct *)((int)odp + odp->d_reclen); if ((int)dp - (int)buf >= fs->fs_bsize) { printf("directory too large\n"); exit(1); } dp->d_ino = inum; dp->d_namlen = strlen(str); dp->d_reclen = DIRBLKSIZ; } strcpy(dp->d_name, str); ip->g_size = (int)dp - (int)buf + newsize;}newblk(ip, buf, aibc, ib, size) struct gnode *ip; int *aibc; char *buf; daddr_t *ib; int size;{ int i; daddr_t bno; bno = alloc(size); wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf); for (i = 0; i < fs->fs_bsize; i++) buf[i] = 0; ib[(*aibc)++] = bno; if (*aibc >= NINDIR(fs)) { printf("indirect block full\n"); errs++; *aibc = 0; } (IP_TO_UP(ip))->di_blocks += btodb(size);}iput(ip, aibc, ib) struct gnode *ip; int *aibc; daddr_t *ib;{ daddr_t d; int i; struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; struct timeval utime; struct timezone uzone; gettimeofday(&utime,&uzone); ip->g_atime = ip->g_mtime = ip->g_ctime = utime; switch (ip->g_mode&GFMT) { case GFDIR: case GFREG: for (i = 0; i < *aibc; i++) { if (i >= NDADDR) break; (IP_TO_UP(ip))->di_db[i] = ib[i]; } if (*aibc > NDADDR) { (IP_TO_UP(ip))->di_ib[0] = alloc((int)fs->fs_bsize); (IP_TO_UP(ip))->di_blocks += btodb((int)fs->fs_bsize); for (i = 0; i < NINDIR(fs) - NDADDR; i++) { ib[i] = ib[i+NDADDR]; ib[i+NDADDR] = (daddr_t)0; } wtfs(fsbtodb(fs, (IP_TO_UP(ip))->di_ib[0]), (int)fs->fs_bsize, (char *)ib); } break; case GFBLK: case GFCHR: break; default: printf("bad mode %o\n", ip->g_mode); exit(1); } d = fsbtodb(fs, itod(fs, ip->g_number)); rdfs(d, (int)fs->fs_bsize, (char *)buf); buf[itoo(fs, ip->g_number)].di_ic = (IP_TO_UP(ip))->di_ic; wtfs(d, (int)fs->fs_bsize, (char *)buf);}daddr_talloc(size) int size;{ int i, frag; daddr_t d; static int cg = 0;again: rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, (char *)&acg); if (acg.cg_magic != CG_MAGIC) { printf("cg %d: bad magic number\n", cg); return (0); } if (acg.cg_cs.cs_nbfree == 0) { cg++; if (cg >= fs->fs_ncg) { printf("ran out of space\n"); return (0); } goto again; } for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) if (isblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag)) goto goth; printf("internal error: can't find block in cyl %d\n", cg); return (0);goth: clrblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag); acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; fscs[cg].cs_nbfree--; acg.cg_btot[cbtocylno(&sblock, d)]--; acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; if (size != sblock.fs_bsize) { frag = howmany(size, sblock.fs_fsize); fscs[cg].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(acg.cg_free, d + i); } wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, (char *)&acg); return (acg.cg_cgx * fs->fs_fpg + d);}/* * Allocate an gnode on the disk */ialloc(ip) register struct gnode *ip;{ struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; daddr_t d; int c; ip->g_number = ++ino; c = itog(&sblock, ip->g_number); rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, (char *)&acg); if (acg.cg_magic != CG_MAGIC) { printf("cg %d: bad magic number\n", c); exit(1); } if (ip->g_mode & GFDIR) { acg.cg_cs.cs_ndir++; sblock.fs_cstotal.cs_ndir++; fscs[c].cs_ndir++; } acg.cg_cs.cs_nifree--; setbit(acg.cg_iused, ip->g_number); wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, (char *)&acg); sblock.fs_cstotal.cs_nifree--; fscs[c].cs_nifree--; if(ip->g_number >= sblock.fs_ipg * sblock.fs_ncg) { printf("fsinit: gnode value out of range (%d).\n", ip->g_number); exit(1); } return (ip->g_number);}/* * read a block from the file system */rdfs(bno, size, bf) int bno, size; char *bf;{ int n; if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { printf("seek error: %ld\n", bno); perror("rdfs"); exit(1); } n = read(fsi, bf, size); if(n != size) { printf("read error: %ld\n", bno); perror("rdfs"); exit(1); }}/* * write a block to the file system */wtfs(bno, size, bf) int bno, size; char *bf;{ int n; lseek(fso, bno * DEV_BSIZE, 0); if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { printf("seek error: %ld\n", bno); perror("wtfs"); exit(1); } n = write(fso, bf, size); if(n != size) { printf("write error: %D\n", bno); perror("wtfs"); exit(1); }}/* * check if a block is available */isblock(fs, cp, h) struct fs *fs; unsigned char *cp; int h;{ unsigned char mask; switch (fs->fs_frag) { case 8: return (cp[h] == 0xff); case 4: mask = 0x0f << ((h & 0x1) << 2); return ((cp[h >> 1] & mask) == mask); case 2: mask = 0x03 << ((h & 0x3) << 1); return ((cp[h >> 2] & mask) == mask); case 1: mask = 0x01 << (h & 0x7); return ((cp[h >> 3] & mask) == mask); default: fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); return (0); } /*NOTREACHED*/}/* * take a block out of the map */clrblock(fs, cp, h) struct fs *fs; unsigned char *cp; int h;{ switch ((fs)->fs_frag) { case 8: cp[h] = 0; return; case 4: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); return; case 2: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); return; case 1: cp[h >> 3] &= ~(0x01 << (h & 0x7)); return; default: fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); return; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?