Ultrix-3.1/src/cmd/mkfs.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* Make a file system prototype.
* usage: /etc/mkfs filsys proto/size [ [disk cpu] or [m n] ] [fsname volname]
*
* Modified for ULTRIX-11
*
* Fred Canter
*
* Due to file system changes (i.e., 1024 byte logical block size),
* the free list interleaving factors are now double the values in
* the table ((f_m+1)/2 and f_n/2), with the following exceptions:
*
* If the value of f_m is one.
* RQDX2 - RD52/RD53/RD54: f_m = 2 (j11 class CPUs only)
* RQDX3 - RD52/RD53/RD54: f_m = 7 " " "
*
* This means mkfs must know the type of disk controller.
* The operating system version of mkfs looks at ra_ctid in the kernel.
* The stand-alone version gets the controller type from a magic
* physical location (RQ_CTID = 0140006), where it is saved by the
* RA disk driver. Mkfs must zero this location before opening the disk.
*/
static char Sccsid[] = "@(#)mkfs.c 3.1 3/26/87";
#define NIPB (BSIZE/sizeof(struct dinode))
#define NINDIR (BSIZE/sizeof(daddr_t))
#define NDIRECT (BSIZE/sizeof(struct direct))
#ifndef STANDALONE
#define NORMAL 0
#define FATAL 1
#include <stdio.h>
#include <a.out.h>
#else
#include "/usr/sys/sas/sa_defs.h" /* exit status codes (NORMAL = 0, FATAL = 1) */
#endif
#include <sys/param.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/filsys.h>
#include <sys/fblk.h>
#include <sys/dir.h>
#ifndef STANDALONE
#include <sys/stat.h>
#include <sys/devmaj.h>
#include <sys/ra_info.h>
#else
#include "/usr/sys/sas/ra_saio.h" /* stand-alone RA disk defines */
#endif
#ifdef UCB_NKB
#define MAXFN 357 /* RA81 has 714 blocks per cylinder */
#define DEFFN 250 /* default value for blocks per cylinder */
#define DEFFM 5 /* default value for interleave factor (m) */
#else
#define MAXFN 714 /* RA81 has 714 blocks per cylinder */
#define DEFFN 500 /* default value for blocks per cylinder */
#define DEFFM 9 /* default value for interleave factor (m) */
#endif UCB_NKB
/*
* Following caused a "multiply defined"
* since itoo is defined in <param.h>
* Fred Canter
#ifndef UCB_NKB
#define itoo(x) (int)((x+15)&07)
#endif UCB_NKB
*
*/
#ifdef UCB_NKB
#define LADDR (NADDR-3)
#else
#define LADDR 10
#endif
time_t utime;
#ifndef STANDALONE
FILE *fin;
struct stat statb;
#else
int fin;
#endif
int fsi;
int fso;
char *charp;
char buf[BSIZE];
union {
struct fblk fb;
char pad1[BSIZE];
} fbuf;
#ifndef STANDALONE
struct exec head;
#endif
char string[50];
union {
struct filsys fs;
char pad2[BSIZE];
} filsys;
char *fsys;
char *proto;
char *mstrg;
char *nstrg;
char *dsktyp;
char *cputyp;
int f_n = DEFFN;
int f_m = DEFFM; /* was 3, that was much to small */
int error;
ino_t ino;
long getnum();
daddr_t alloc();
#ifndef STANDALONE
struct nlist nl[] =
{
{ "_ra_ctid" },
{ "" },
};
struct stat ra_statb;
int ra_cntlr = -1; /* MSCP cntlr #, -1 if none */
char ra_ctid[] = {0377, 0377, 0377, 0377};
#endif
struct { /* disk types by generic name */
char *dkname; /* disk type name, rp04, ra80, etc. */
int dkindx; /* index into FS param array */
} dktype[] = {
{ "rk05", 0 },
{ "rl01", 1 },
{ "rl02", 1 },
{ "rk06", 2 },
{ "rk07", 2 },
{ "rp02", 3 },
{ "rp03", 3 },
{ "rm02", 4 },
{ "rm03", 5 },
{ "rm05", 6 },
{ "rp04", 7 },
{ "rp05", 7 },
{ "rp06", 7 },
{ "ra60", 8 },
{ "ra80", 9 },
{ "ra81", 10 },
{ "rx33", 11 },
{ "rx50", 11 },
{ "rd31", 12 },
{ "rd32", 12 },
{ "rd51", 12 },
{ "rx02", 13 },
{ "rd52", 12 },
{ "rd53", 12 },
{ "rd54", 12 },
{ "rc25", 14 },
{ "ml11", 11 },
{ 0, -1 },
};
struct { /* File system parameters M/N by cpu tpye */
int fsp_cpu; /* CPU type, 23, 24, 70, etc. */
int fsp_m[15]; /* m - interleave factor */
int fsp_n[15]; /* n - blocks per cylinder */
} fsparam[] = {
/*
* FOREIGN - disk not expected on this CPU
* m/n are guess work.
*/
/*
* NOTE - for RC25 n = 62. 31 is the correct value but mkfs
* does not like odd numbers. 62 will work just fine!
*/
/*
* FOREIGN - rk06/7, rp02/3, rm02/3/5, rp04/5/6, ra60, ra80, ra81
*/
{ 23,
/* RD31/RD32/RD51/RX50/RX33/RX02 (m = 1) hardware does interleaving */
8, 13, 15, 8, 21, 31, 31, 21, 42, 31, 51, 1, 1, 1, 30,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 24,
7, 12, 14, 7, 20, 30, 30, 20, 42, 31, 51, 1, 1, 1, 30,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 34,
6, 11, 12, 6, 16, 24, 24, 16, 34, 25, 41, 1, 1, 1, 25,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 40,
6, 11, 12, 6, 16, 24, 24, 16, 34, 25, 41, 1, 1, 1, 25,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03, rm05, rx50, rd51, rd52
*/
{ 44,
4, 7, 8, 4, 11, 16, 16, 11, 23, 17, 28, 1, 1, 1, 17,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 45,
5, 9, 10, 5, 14, 21, 21, 14, 30, 22, 36, 1, 1, 1, 22,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rk06/7, rp02/3, rm02/3/5, rp04/5/6, ra60, ra80, ra81
* ****** (used 11/44 values for m/n) ******
*/
{ 53,
4, 7, 8, 4, 11, 16, 16, 11, 23, 17, 28, 1, 1, 1, 17,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 55,
5, 9, 10, 5, 14, 21, 21, 14, 30, 22, 36, 1, 1, 1, 22,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
*/
{ 60,
5, 9, 10, 5, 14, 21, 21, 14, 30, 22, 36, 1, 1, 1, 22,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rd51, rd52
*/
{ 70,
4, 6, 6, 4, 9, 13, 13, 9, 19, 14, 23, 1, 1, 1, 14,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rk06/7, rp02/3, rm02/3/5, rp04/5/6, ra60, ra80, ra81
* ****** (used 11/44 values for m/n) ******
*/
{ 73,
4, 7, 8, 4, 11, 16, 16, 11, 23, 17, 28, 1, 1, 1, 17,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rk06/7, rp02/3, rm02/3/5, rp04/5/6, ra60, ra80, ra81
* ****** (used 11/44 values for m/n) ******
* M is probably too high, but that's ok!
*/
{ 83,
4, 7, 8, 4, 11, 16, 16, 11, 23, 17, 28, 1, 1, 1, 17,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
/*
* FOREIGN - rm03/5, rd51, rd52
* ****** (used 11/70 values for m/n) ******
*/
{ 84,
4, 6, 6, 4, 9, 13, 13, 9, 19, 14, 23, 1, 1, 1, 14,
24, 20, 66, 200, 160, 160, 608, 418, 168, 434, 714, 10, 72, 13, 62,
},
{ 0 },
};
#ifdef STANDALONE
int argflag; /* 0=interactive, 1=called by SDLOAD, see prf.c */
#endif
main(argc, argv)
char *argv[];
{
int a3num, a4num;
int f, c, i, j;
long n;
int mem, maj, ct;
#ifndef STANDALONE
time(&utime);
if((argc < 3) || (argc > 7) || (argc == 4) || (argc == 6)) {
usage:
printf("\nusage: /etc/mkfs filsys proto/size");
printf(" [ [disk cpu] or [m n] ] [fsname volname]\n");
exit(FATAL);
}
fsys = argv[1];
proto = argv[2];
/*
* Find out whether arg3 and arg4 are alpha or numeric,
* this tells mkfs if they represent [disk cpu],
* [m n], and/or [filsys volume].
*/
if((argv[3][0] >= '0') && (argv[3][0] <= '9'))
a3num = 1;
else
a3num = 0;
if((argv[4][0] >= '0') && (argv[4][0] <= '9'))
a4num = 1;
else
a4num = 0;
/*
* Get ra_ctid (MSCP cntlr type ID) from kernel.
* If we can't find cntlr type, leave it blank so
* default f_m & f_n values will be used.
*/
while(1) {
if(nlist("/unix", nl) < 0)
break;
if(nl[0].n_value == 0)
break;
if((mem = open("/dev/mem", 0)) < 0)
break;
lseek(mem, (long)nl[0].n_value, 0);
read(mem, (char *)&ra_ctid, sizeof(ra_ctid));
break;
}
#else
{
static char protos[60];
static char mstrg[60];
static char nstrg[60];
static char dtstrg[60];
static char ctstrg[60];
static char fsname[60];
static char voln[60];
printf("File system size: ");
gets(protos);
proto = protos;
sf1:
printf("Disk type: ");
gets(dtstrg);
dsktyp = dtstrg;
if(*dsktyp == 0)
goto sf3; /* typed return, go ask for m/n */
for(i=0; dktype[i].dkname; i++)
if(strcmp(dktype[i].dkname, dsktyp) == 0)
break;
if(dktype[i].dkindx < 0)
goto sf1;
sf2:
printf("Processor type: ");
gets(ctstrg);
cputyp = atoi(ctstrg);
for(j=0; fsparam[j].fsp_cpu; j++)
if(fsparam[j].fsp_cpu == cputyp)
break;
if(fsparam[j].fsp_cpu == 0)
goto sf2;
f_m = fsparam[j].fsp_m[dktype[i].dkindx];
f_n = fsparam[j].fsp_n[dktype[i].dkindx];
#ifdef UCB_NKB
if(f_m != 1) {
f_m = (f_m + 1)/2;
if((f_n & 1) == 0)
f_n /= 2;
}
#endif UCB_NKB
if((f_m == 0) || (f_n == 0))
/* NOTREACHED */ printf("disk and cpu not compatible\n");
else
goto sf4;
sf3:
printf("Interleave factor: ");
gets(mstrg);
f_m = atoi(mstrg);
printf("Blocks per cylinder: ");
gets(nstrg);
f_n = atoi(nstrg);
sf4:
printf("File system name: ");
gets(fsname);
if(strlen(fsname) > 6)
goto sf4;
sf5:
printf("Volume name: ");
gets(voln);
if(strlen(voln) > 6)
goto sf5;
if(fsname[0] != '\0')
strncpy(filsys.fs.s_fname, fsname, 6);
if(voln[0] != '\0')
strncpy(filsys.fs.s_fpack, voln, 6);
if(f_n <= 0 || f_n > MAXFN)
f_n = DEFFN;
if(f_m <= 0 || f_m > f_n)
f_m = DEFFM; /* 3 was much too small */
}
#endif
#ifdef STANDALONE
{
char fsbuf[100];
RQ_CTID->r[0] = 0; /* clear magic loc, only once */
do {
printf("File system: ");
gets(fsbuf);
fso = open(fsbuf, 1);
fsi = open(fsbuf, 0);
if(argflag && ((fso < 0) || (fsi < 0)))
exit(FATAL);
} while (fso < 0 || fsi < 0);
/* adjust f_m for RD52/RD53/RD54, for faster Qbus CPUs */
while(1) {
if(*dsktyp == 0) /* user supplied f_m */
break;
if((cputyp!=53) && (cputyp!=73) && (cputyp!=83))
break; /* slower CPU */
if((strcmp(dsktyp, "rd52") == 0) ||
(strcmp(dsktyp, "rd53") == 0) ||
(strcmp(dsktyp, "rd54") == 0)) {
if(RQ_CTID->r[0] == RQDX1)
f_m = 2;
if(RQ_CTID->r[0] == RQDX3)
f_m = 7;
}
break;
}
}
fin = NULL;
argc = 0;
#else
fso = creat(fsys, 0666);
if(fso < 0) {
printf("%s: cannot create\n", fsys);
exit(FATAL);
}
fsi = open(fsys, 0);
if(fsi < 0) {
printf("%s: cannot open\n", fsys);
exit(FATAL);
}
fin = fopen(proto, "r");
/*
* Stat fsys, if it is a special file
* for an MSCP disk, get and save controller number.
* Cntlr # in bits 6 & 7 of minor device.
* Dont't need error checking!
*/
while(1) {
if(stat(fsys, &ra_statb) < 0)
break;
maj = (ra_statb.st_rdev >> 8) & 0377;
if(((ra_statb.st_mode&S_IFMT) == S_IFBLK) && (maj == RA_BMAJ))
ra_cntlr = (ra_statb.st_rdev >> 6) & 3;
if(((ra_statb.st_mode&S_IFMT) == S_IFCHR) && (maj == RA_RMAJ))
ra_cntlr = (ra_statb.st_rdev >> 6) & 3;
break;
}
#endif
if(fin == NULL) {
n = 0;
for(f=0; c=proto[f]; f++) {
if(c<'0' || c>'9') {
printf("%s: cannot open\n", proto);
exit(FATAL);
}
n = n*10 + (c-'0');
}
filsys.fs.s_fsize = n;
n = n/25;
if(n <= 0)
n = 1;
if(n > 65500/NIPB)
n = 65500/NIPB;
filsys.fs.s_isize = n + 2;
printf("isize = %D\n", n*NIPB);
charp = "d--777 0 0 $ ";
goto f3;
}
#ifndef STANDALONE
/*
* get name of boot load program
* and read onto block 0
* Fred Canter -- 8/12/85
* Boot block must begin with 0407 or 0240,
* ULTRIX-11 boot blocks begin with nop (0240).
* Size of boot block must be <= 512 bytes.
*/
getstr();
f = open(string, 0);
if(f < 0) {
printf("%s: cannot open\n", string);
goto f2;
}
read(f, (char *)&head, sizeof head);
if(head.a_magic == 0240) { /* ULTRIX-11 boot block */
fstat(f, &statb);
if(statb.st_size > 512L)
c = 513; /* make size test fail */
else
c = (int)statb.st_size;
lseek(f, 0L, 0);
} else if(head.a_magic == A_MAGIC1) {
c = head.a_text + head.a_data;
} else {
printf("%s: invalid boot block format\n", string);
goto f1;
}
if(c > 512) {
printf("%s: size exceeds 512 bytes\n", string);
goto f1;
}
for(j=0; j<BSIZE; j++)
buf[j] = 0;
read(f, buf, c);
wtfs((long)0, buf);
f1:
close(f);
/*
* get total disk size
* and inode block size
*/
f2:
filsys.fs.s_fsize = getnum();
n = getnum();
n /= NIPB;
filsys.fs.s_isize = n + 3;
#endif
f3:
if((argc != 5) && (argc != 7))
goto f5;
if(argc == 7) {
if((strlen(argv[5]) > 6) || (strlen(argv[6]) > 6)) {
printf("\nmkfs: fsname/volname 6 characters maximum\n");
#ifdef STANDALONE
exit(FATAL);
#else
goto usage;
#endif
}
strncpy(filsys.fs.s_fname, argv[5], 6);
strncpy(filsys.fs.s_fpack, argv[6], 6);
}
if(a3num && a4num) {
f_m = atoi(argv[3]);
f_n = atoi(argv[4]);
} else {
dsktyp = argv[3];
cputyp = atoi(argv[4]);
for(i=0; dktype[i].dkname; i++)
if(strcmp(dktype[i].dkname, dsktyp) == 0)
break;
if(dktype[i].dkindx < 0) {
printf("\nmkfs: Unknown disk type\n");
goto f4; /* use default m/n */
}
for(j=0; fsparam[j].fsp_cpu; j++)
if(fsparam[j].fsp_cpu == cputyp)
break;
if(fsparam[j].fsp_cpu == 0) {
printf("\nmkfs: Unknown cpu type\n");
goto f4; /* use default m/n */
}
f_m = fsparam[j].fsp_m[dktype[i].dkindx];
f_n = fsparam[j].fsp_n[dktype[i].dkindx];
#ifdef UCB_NKB
if(f_m != 1) {
f_m = (f_m + 1)/2;
if((f_n & 1) == 0)
f_n /= 2;
}
#endif UCB_NKB
if((f_m == 0) || (f_n == 0))
/* NOTREACHED */ printf("\nmkfs: disk and cpu not compatible\n");
}
f4:
if(f_n <= 0 || f_n > MAXFN)
f_n = DEFFN;
if(f_m <= 0 || f_m > f_n)
f_m = DEFFM; /* 3 was much too small */
f5:
#ifndef STANDALONE
/*
* Adjust f_m for RQDX - RD52/RD53/RD54 if faster Qbus CPU.
*/
while(1) {
if(ra_cntlr < 0)
break; /* no MSCP cntlr on system */
if((cputyp!=53) && (cputyp!=73) && (cputyp!=83))
break; /* not one of the faster Qbus CPUs */
if((a3num && a4num) || (dktype[i].dkindx < 0))
break; /* unknown disk, use default f_m */
if((strcmp(dsktyp, "rd52") == 0) ||
(strcmp(dsktyp, "rd53") == 0) ||
(strcmp(dsktyp, "rd54") == 0)) {
if(((ra_ctid[ra_cntlr] >> 4) & 017) == RQDX1)
f_m = 2;
if(((ra_ctid[ra_cntlr] >> 4) & 017) == RQDX3)
f_m = 7;
}
break;
}
#endif
filsys.fs.s_m = f_m;
filsys.fs.s_n = f_n;
printf("m/n = %d %d\n", f_m, f_n);
if(filsys.fs.s_isize >= filsys.fs.s_fsize) {
printf("%D/%u: bad ratio\n",filsys.fs.s_fsize,filsys.fs.s_isize-2);
exit(FATAL);
}
filsys.fs.s_magic[0] = S_0MAGIC;
filsys.fs.s_magic[1] = S_1MAGIC;
filsys.fs.s_magic[2] = S_2MAGIC;
filsys.fs.s_magic[3] = S_3MAGIC;
filsys.fs.s_tfree = 0;
filsys.fs.s_tinode = 0;
for(c=0; c<BSIZE; c++)
buf[c] = 0;
for(n=2; n!=filsys.fs.s_isize; n++) {
wtfs(n, buf);
filsys.fs.s_tinode += NIPB;
}
ino = 0;
bflist();
cfile((struct inode *)0);
filsys.fs.s_time = utime;
wtfs((long)1, (char *)&filsys);
exit(error);
}
cfile(par)
struct inode *par;
{
struct inode in;
int dbc, ibc;
char db[BSIZE];
daddr_t ib[NINDIR];
int i, f, c;
/*
* get mode, uid and gid
*/
getstr();
in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
for(i=3; i<6; i++) {
c = string[i];
if(c<'0' || c>'7') {
printf("%c/%s: bad octal mode digit\n", c, string);
error = FATAL;
c = 0;
}
in.i_mode |= (c-'0')<<(15-3*i);
}
in.i_uid = getnum();
in.i_gid = getnum();
/*
* general initialization prior to
* switching on format
*/
ino++;
in.i_number = ino;
for(i=0; i<BSIZE; i++)
db[i] = 0;
for(i=0; i<NINDIR; i++)
ib[i] = (daddr_t)0;
in.i_nlink = 1;
in.i_size = 0;
for(i=0; i<NADDR; i++)
in.i_addr[i] = (daddr_t)0;
if(par == (struct inode *)0) {
par = ∈
in.i_nlink--;
}
dbc = 0;
ibc = 0;
switch(in.i_mode&IFMT) {
case IFREG:
/*
* regular file
* contents is a file name
*/
getstr();
f = open(string, 0);
if(f < 0) {
printf("%s: cannot open\n", string);
error = FATAL;
break;
}
while((i=read(f, db, BSIZE)) > 0) {
in.i_size += i;
newblk(&dbc, db, &ibc, ib);
}
close(f);
break;
case IFBLK:
case IFCHR:
/*
* special file
* content is maj/min types
*/
i = getnum() & 0377;
f = getnum() & 0377;
in.i_addr[0] = (i<<8) | f;
break;
case IFDIR:
/*
* directory
* put in extra links
* call recursively until
* name of "$" found
*/
par->i_nlink++;
in.i_nlink++;
entry(in.i_number, ".", &dbc, db, &ibc, ib);
entry(par->i_number, "..", &dbc, db, &ibc, ib);
in.i_size = 2*sizeof(struct direct);
for(;;) {
getstr();
if(string[0]=='$' && string[1]=='\0')
break;
entry(ino+1, string, &dbc, db, &ibc, ib);
in.i_size += sizeof(struct direct);
cfile(&in);
}
break;
}
if(dbc != 0)
newblk(&dbc, db, &ibc, ib);
iput(&in, &ibc, ib);
}
gmode(c, s, m0, m1, m2, m3)
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, string);
error = FATAL;
return(0);
}
long
getnum()
{
int i, c;
long n;
getstr();
n = 0;
i = 0;
for(i=0; c=string[i]; i++) {
if(c<'0' || c>'9') {
printf("%s: bad number\n", string);
error = FATAL;
return((long)0);
}
n = n*10 + (c-'0');
}
return(n);
}
getstr()
{
int i, c;
loop:
switch(c=getch()) {
case ' ':
case '\t':
case '\n':
goto loop;
case '\0':
printf("EOF\n");
exit(FATAL);
case ':':
while(getch() != '\n');
goto loop;
}
i = 0;
do {
string[i++] = c;
c = getch();
} while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
string[i] = '\0';
}
rdfs(bno, bf)
daddr_t bno;
char *bf;
{
int n;
lseek(fsi, bno*BSIZE, 0);
n = read(fsi, bf, BSIZE);
if(n != BSIZE) {
printf("read error: %D\n", bno);
exit(FATAL);
}
}
wtfs(bno, bf)
daddr_t bno;
char *bf;
{
int n;
lseek(fso, bno*BSIZE, 0);
n = write(fso, bf, BSIZE);
if(n != BSIZE) {
printf("write error: %D\n", bno);
exit(FATAL);
}
}
daddr_t
alloc()
{
int i;
daddr_t bno;
filsys.fs.s_tfree--;
bno = filsys.fs.s_free[--filsys.fs.s_nfree];
if(bno == 0) {
printf("out of free space\n");
exit(FATAL);
}
if(filsys.fs.s_nfree <= 0) {
rdfs(bno, (char *)&fbuf);
filsys.fs.s_nfree = fbuf.fb.df_nfree;
for(i=0; i<NICFREE; i++)
filsys.fs.s_free[i] = fbuf.fb.df_free[i];
}
return(bno);
}
bfree(bno)
daddr_t bno;
{
int i;
if(bno != 0)
filsys.fs.s_tfree++;
if(filsys.fs.s_nfree >= NICFREE) {
fbuf.fb.df_nfree = filsys.fs.s_nfree;
for(i=0; i<NICFREE; i++)
fbuf.fb.df_free[i] = filsys.fs.s_free[i];
wtfs(bno, (char *)&fbuf);
filsys.fs.s_nfree = 0;
}
filsys.fs.s_free[filsys.fs.s_nfree++] = bno;
}
entry(inum, str, adbc, db, aibc, ib)
ino_t inum;
char *str;
int *adbc, *aibc;
char *db;
daddr_t *ib;
{
struct direct *dp;
int i;
dp = (struct direct *)db;
dp += *adbc;
(*adbc)++;
dp->d_ino = inum;
for(i=0; i<DIRSIZ; i++)
dp->d_name[i] = 0;
for(i=0; i<DIRSIZ; i++)
if((dp->d_name[i] = str[i]) == 0)
break;
if(*adbc >= NDIRECT)
newblk(adbc, db, aibc, ib);
}
newblk(adbc, db, aibc, ib)
int *adbc, *aibc;
char *db;
daddr_t *ib;
{
int i;
daddr_t bno;
bno = alloc();
wtfs(bno, db);
for(i=0; i<BSIZE; i++)
db[i] = 0;
*adbc = 0;
ib[*aibc] = bno;
(*aibc)++;
if(*aibc >= NINDIR) {
printf("indirect block full\n");
error = FATAL;
*aibc = 0;
}
}
getch()
{
#ifndef STANDALONE
if(charp)
#endif
return(*charp++);
#ifndef STANDALONE
return(getc(fin));
#endif
}
bflist()
{
struct inode in;
daddr_t ib[NINDIR];
int ibc;
char flg[MAXFN];
int adr[MAXFN];
int i, j;
daddr_t f, d;
for(i=0; i<f_n; i++)
flg[i] = 0;
i = 0;
for(j=0; j<f_n; j++) {
while(flg[i])
i = (i+1)%f_n;
adr[j] = i+1;
flg[i]++;
i = (i+f_m)%f_n;
}
ino++;
in.i_number = ino;
in.i_mode = IFREG;
in.i_uid = 0;
in.i_gid = 0;
in.i_nlink = 0;
in.i_size = 0;
for(i=0; i<NADDR; i++)
in.i_addr[i] = (daddr_t)0;
for(i=0; i<NINDIR; i++)
ib[i] = (daddr_t)0;
ibc = 0;
bfree((daddr_t)0);
d = filsys.fs.s_fsize-1;
/*
* Fred Canter -- 7/13/85
* Mkfs left the last block missing from the free list
* whenever d was an even multiple of f_n.
*/
if(d%f_n == 0)
d++;
while(d%f_n)
d++;
for(; d > 0; d -= f_n)
for(i=0; i<f_n; i++) {
f = d - adr[i];
if(f < filsys.fs.s_fsize && f >= filsys.fs.s_isize)
if(badblk(f)) {
if(ibc >= NINDIR) {
printf("too many bad blocks\n");
error = FATAL;
ibc = 0;
}
ib[ibc] = f;
ibc++;
} else
bfree(f);
}
iput(&in, &ibc, ib);
}
iput(ip, aibc, ib)
struct inode *ip;
int *aibc;
daddr_t *ib;
{
struct dinode *dp;
daddr_t d;
int i;
filsys.fs.s_tinode--;
d = itod(ip->i_number);
if(d >= filsys.fs.s_isize) {
if(error == NORMAL)
printf("ilist too small\n");
error = FATAL;
return;
}
rdfs(d, buf);
dp = (struct dinode *)buf;
dp += itoo(ip->i_number);
dp->di_mode = ip->i_mode;
dp->di_nlink = ip->i_nlink;
dp->di_uid = ip->i_uid;
dp->di_gid = ip->i_gid;
dp->di_size = ip->i_size;
dp->di_atime = utime;
dp->di_mtime = utime;
dp->di_ctime = utime;
switch(ip->i_mode&IFMT) {
case IFDIR:
case IFREG:
for(i=0; i<*aibc; i++) {
if(i >= LADDR)
break;
ip->i_addr[i] = ib[i];
}
if(*aibc >= LADDR) {
ip->i_addr[LADDR] = alloc();
for(i=0; i<NINDIR-LADDR; i++) {
ib[i] = ib[i+LADDR];
ib[i+LADDR] = (daddr_t)0;
}
wtfs(ip->i_addr[LADDR], (char *)ib);
}
case IFBLK:
case IFCHR:
ltol3(dp->di_addr, ip->i_addr, NADDR);
break;
default:
printf("bad mode %o\n", ip->i_mode);
exit(FATAL);
}
wtfs(d, buf);
}
badblk(bno)
daddr_t bno;
{
return(0);
}