1*4234Smckusick static char *sccsid = "@(#)mkfs.c 1.1 (Berkeley) 08/26/81"; 2*4234Smckusick 3*4234Smckusick /* 4*4234Smckusick * make file system for cylinder-group style file systems 5*4234Smckusick * 6*4234Smckusick * usage: mkfs fs proto 7*4234Smckusick * or: mkfs size [ nsect ntrak cpg ] 8*4234Smckusick */ 9*4234Smckusick 10*4234Smckusick #define NDIRECT (BSIZE/sizeof(struct direct)) 11*4234Smckusick #define MAXFN 500 12*4234Smckusick 13*4234Smckusick #define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) 14*4234Smckusick #define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) 15*4234Smckusick #define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) 16*4234Smckusick 17*4234Smckusick #ifndef STANDALONE 18*4234Smckusick #include <stdio.h> 19*4234Smckusick #include <a.out.h> 20*4234Smckusick #endif 21*4234Smckusick 22*4234Smckusick #include "../h/param.h" 23*4234Smckusick #include "../h/ino.h" 24*4234Smckusick #include "../h/inode.h" 25*4234Smckusick #include "../h/fs.h" 26*4234Smckusick #include "../h/dir.h" 27*4234Smckusick 28*4234Smckusick time_t utime; 29*4234Smckusick 30*4234Smckusick #ifndef STANDALONE 31*4234Smckusick FILE *fin; 32*4234Smckusick #else 33*4234Smckusick int fin; 34*4234Smckusick #endif 35*4234Smckusick 36*4234Smckusick int fsi; 37*4234Smckusick int fso; 38*4234Smckusick char *charp; 39*4234Smckusick char buf[BSIZE]; 40*4234Smckusick #ifndef STANDALONE 41*4234Smckusick struct exec head; 42*4234Smckusick #endif 43*4234Smckusick char string[50]; 44*4234Smckusick 45*4234Smckusick union { 46*4234Smckusick struct fs fs; 47*4234Smckusick char pad[BSIZE]; 48*4234Smckusick } fsun; 49*4234Smckusick #define sblock fsun.fs 50*4234Smckusick struct csum *fscs; 51*4234Smckusick 52*4234Smckusick union { 53*4234Smckusick struct cg cg; 54*4234Smckusick char pad[BSIZE]; 55*4234Smckusick } cgun; 56*4234Smckusick #define acg cgun.cg 57*4234Smckusick 58*4234Smckusick #define howmany(x, y) (((x)+((y)-1))/(y)) 59*4234Smckusick #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 60*4234Smckusick 61*4234Smckusick char *fsys; 62*4234Smckusick char *proto; 63*4234Smckusick int error; 64*4234Smckusick ino_t ino = ROOTINO - 1; 65*4234Smckusick long getnum(); 66*4234Smckusick daddr_t alloc(); 67*4234Smckusick 68*4234Smckusick struct dinode zino[MAXIPG]; 69*4234Smckusick 70*4234Smckusick main(argc, argv) 71*4234Smckusick char *argv[]; 72*4234Smckusick { 73*4234Smckusick int f, c; 74*4234Smckusick long i,n; 75*4234Smckusick 76*4234Smckusick argc--, argv++; 77*4234Smckusick #ifndef STANDALONE 78*4234Smckusick time(&utime); 79*4234Smckusick if(argc < 2) { 80*4234Smckusick printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n"); 81*4234Smckusick exit(1); 82*4234Smckusick } 83*4234Smckusick fsys = argv[0]; 84*4234Smckusick proto = argv[1]; 85*4234Smckusick #else 86*4234Smckusick { 87*4234Smckusick static char protos[60]; 88*4234Smckusick 89*4234Smckusick printf("file sys size: "); 90*4234Smckusick gets(protos); 91*4234Smckusick proto = protos; 92*4234Smckusick } 93*4234Smckusick #endif 94*4234Smckusick #ifdef STANDALONE 95*4234Smckusick { 96*4234Smckusick char fsbuf[100]; 97*4234Smckusick 98*4234Smckusick do { 99*4234Smckusick printf("file system: "); 100*4234Smckusick gets(fsbuf); 101*4234Smckusick fso = open(fsbuf, 1); 102*4234Smckusick fsi = open(fsbuf, 0); 103*4234Smckusick } while (fso < 0 || fsi < 0); 104*4234Smckusick } 105*4234Smckusick fin = NULL; 106*4234Smckusick argc = 0; 107*4234Smckusick #else 108*4234Smckusick fso = creat(fsys, 0666); 109*4234Smckusick if(fso < 0) { 110*4234Smckusick printf("%s: cannot create\n", fsys); 111*4234Smckusick exit(1); 112*4234Smckusick } 113*4234Smckusick fsi = open(fsys, 0); 114*4234Smckusick if(fsi < 0) { 115*4234Smckusick printf("%s: cannot open\n", fsys); 116*4234Smckusick exit(1); 117*4234Smckusick } 118*4234Smckusick fin = fopen(proto, "r"); 119*4234Smckusick #endif 120*4234Smckusick #ifndef STANDALONE 121*4234Smckusick if (fin != NULL) { 122*4234Smckusick getstr(); 123*4234Smckusick f = open(string, 0); 124*4234Smckusick if (f < 0) { 125*4234Smckusick printf("%s: cannot open init\n", string); 126*4234Smckusick goto noinit; 127*4234Smckusick } 128*4234Smckusick read(f, (char *)&head, sizeof head); 129*4234Smckusick c = head.a_text + head.a_data; 130*4234Smckusick if (c > BSIZE) 131*4234Smckusick printf("%s: too big\n", string); 132*4234Smckusick else { 133*4234Smckusick read(f, buf, c); 134*4234Smckusick wtfs(BBLOCK, BSIZE, buf); 135*4234Smckusick } 136*4234Smckusick close(f); 137*4234Smckusick noinit: 138*4234Smckusick n = sblock.fs_size = getnum(); 139*4234Smckusick sblock.fs_ntrak = getnum(); 140*4234Smckusick sblock.fs_nsect = getnum(); 141*4234Smckusick sblock.fs_cpg = getnum(); 142*4234Smckusick } else 143*4234Smckusick #endif 144*4234Smckusick { 145*4234Smckusick charp = "d--777 0 0 $ "; 146*4234Smckusick n = 0; 147*4234Smckusick for (f=0; c=proto[f]; f++) { 148*4234Smckusick if (c<'0' || c>'9') { 149*4234Smckusick printf("%s: cannot open\n", proto); 150*4234Smckusick exit(1); 151*4234Smckusick } 152*4234Smckusick n = n*10 + (c-'0'); 153*4234Smckusick } 154*4234Smckusick sblock.fs_size = n; 155*4234Smckusick if (argc > 2) 156*4234Smckusick sblock.fs_nsect = atoi(argv[2]); 157*4234Smckusick else 158*4234Smckusick sblock.fs_nsect = 32; 159*4234Smckusick if (argc > 3) 160*4234Smckusick sblock.fs_ntrak = atoi(argv[3]); 161*4234Smckusick else 162*4234Smckusick sblock.fs_ntrak = 19; 163*4234Smckusick } 164*4234Smckusick /* 165*4234Smckusick * Now have size for file system and nsect and ntrak. 166*4234Smckusick * (And, if coming from prototype, cpg). 167*4234Smckusick * Determine number of cylinders occupied by file system. 168*4234Smckusick */ 169*4234Smckusick if (sblock.fs_ntrak <= 0) 170*4234Smckusick printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 171*4234Smckusick if (sblock.fs_nsect <= 0) 172*4234Smckusick printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 173*4234Smckusick if (sblock.fs_size <= 0) 174*4234Smckusick printf("preposterous size %d\n", sblock.fs_size), exit(1); 175*4234Smckusick if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) { 176*4234Smckusick printf("cylinder too large (%d sectors)\n", 177*4234Smckusick sblock.fs_ntrak * sblock.fs_nsect); 178*4234Smckusick printf("maximum cylinder size: %d sectors\n", 179*4234Smckusick MAXBPG * NSPB); 180*4234Smckusick exit(1); 181*4234Smckusick } 182*4234Smckusick sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak); 183*4234Smckusick if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { 184*4234Smckusick printf("%d sector(s) in last cylinder unused\n", 185*4234Smckusick n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); 186*4234Smckusick sblock.fs_ncyl++; 187*4234Smckusick } 188*4234Smckusick sblock.fs_magic = FS_MAGIC; 189*4234Smckusick /* 190*4234Smckusick * Validate specified/determined cpg. 191*4234Smckusick */ 192*4234Smckusick #define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG) 193*4234Smckusick if (argc > 4 || fin) { 194*4234Smckusick if (fin == NULL) 195*4234Smckusick sblock.fs_cpg = atoi(argv[4]); 196*4234Smckusick if (CGTOOBIG(sblock)) { 197*4234Smckusick printf("cylinder group too large (%d blocks); ", 198*4234Smckusick sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB); 199*4234Smckusick printf("max: %d blocks\n", MAXBPG); 200*4234Smckusick exit(1); 201*4234Smckusick } 202*4234Smckusick if (sblock.fs_cpg > MAXCPG) { 203*4234Smckusick printf("cylinder groups are limited to %d cylinders\n", 204*4234Smckusick MAXCPG); 205*4234Smckusick exit(1); 206*4234Smckusick } 207*4234Smckusick } else { 208*4234Smckusick sblock.fs_cpg = DESCPG; 209*4234Smckusick while (CGTOOBIG(sblock)) 210*4234Smckusick --sblock.fs_cpg; 211*4234Smckusick } 212*4234Smckusick /* 213*4234Smckusick * Compute/validate number of cylinder groups. 214*4234Smckusick */ 215*4234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 216*4234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 217*4234Smckusick sblock.fs_ncg++; 218*4234Smckusick if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) { 219*4234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 220*4234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 221*4234Smckusick printf("as this would would have cyl groups whose size\n"); 222*4234Smckusick printf("is not a multiple of %d; choke!\n", FSIZE); 223*4234Smckusick exit(1); 224*4234Smckusick } 225*4234Smckusick fscs = (struct csum *) 226*4234Smckusick calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE)); 227*4234Smckusick /* 228*4234Smckusick * Compute number of inode blocks per cylinder group. 229*4234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 230*4234Smckusick */ 231*4234Smckusick n = ((n * BSIZE) / NBPI) / INOPB; 232*4234Smckusick if (n <= 0) 233*4234Smckusick n = 1; 234*4234Smckusick if (n > 65500/INOPB) 235*4234Smckusick n = 65500/INOPB; 236*4234Smckusick sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB; 237*4234Smckusick if (sblock.fs_ipg < INOPB) 238*4234Smckusick sblock.fs_ipg = INOPB; 239*4234Smckusick if (sblock.fs_ipg > MAXIPG) 240*4234Smckusick sblock.fs_ipg = MAXIPG; 241*4234Smckusick while (sblock.fs_ipg * sblock.fs_ncyl > 65500) 242*4234Smckusick sblock.fs_ipg -= INOPB; 243*4234Smckusick sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 244*4234Smckusick sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512); 245*4234Smckusick if (cgdmin(0,&sblock) >= sblock.fs_fpg) 246*4234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 247*4234Smckusick cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1); 248*4234Smckusick sblock.fs_nifree = sblock.fs_ipg * sblock.fs_ncg; 249*4234Smckusick sblock.fs_cgsize = cgsize(&sblock); 250*4234Smckusick sblock.fs_cssize = cssize(&sblock); 251*4234Smckusick sblock.fs_sblkno = SBLOCK; 252*4234Smckusick sblock.fs_fmod = 0; 253*4234Smckusick sblock.fs_ronly = 0; 254*4234Smckusick 255*4234Smckusick /* 256*4234Smckusick * Dump out information about file system. 257*4234Smckusick */ 258*4234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 259*4234Smckusick fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect); 260*4234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 261*4234Smckusick (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg, 262*4234Smckusick (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg); 263*4234Smckusick /* 264*4234Smckusick printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG); 265*4234Smckusick printf("%7d cylinder groups\n", sblock.fs_ncg); 266*4234Smckusick printf("%7d cylinder group block size\n", sblock.fs_cgsize); 267*4234Smckusick printf("%7d tracks\n", sblock.fs_ntrak); 268*4234Smckusick printf("%7d sectors\n", sblock.fs_nsect); 269*4234Smckusick printf("%7d sectors per cylinder\n", sblock.fs_spc); 270*4234Smckusick printf("%7d cylinders\n", sblock.fs_ncyl); 271*4234Smckusick printf("%7d cylinders per group\n", sblock.fs_cpg); 272*4234Smckusick printf("%7d blocks per group\n", sblock.fs_fpg/FRAG); 273*4234Smckusick printf("%7d inodes per group\n", sblock.fs_ipg); 274*4234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) { 275*4234Smckusick printf("%7d cylinders in last group\n", 276*4234Smckusick i = sblock.fs_ncyl % sblock.fs_cpg); 277*4234Smckusick printf("%7d blocks in last group\n", 278*4234Smckusick i * sblock.fs_spc / NSPB); 279*4234Smckusick } 280*4234Smckusick */ 281*4234Smckusick /* 282*4234Smckusick * Now build the cylinders group blocks and 283*4234Smckusick * then print out indices of cylinder groups forwarded 284*4234Smckusick * past bad blocks or other obstructions. 285*4234Smckusick */ 286*4234Smckusick sblock.fs_nffree = 0; 287*4234Smckusick sblock.fs_nbfree = 0; 288*4234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 289*4234Smckusick initcg(c); 290*4234Smckusick printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 291*4234Smckusick SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg, 292*4234Smckusick SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg); 293*4234Smckusick /* 294*4234Smckusick * Now construct the initial file system, and 295*4234Smckusick * then write out the super-block. 296*4234Smckusick */ 297*4234Smckusick cfile((struct inode *)0); 298*4234Smckusick sblock.fs_time = utime; 299*4234Smckusick wtfs(SBLOCK, BSIZE, (char *)&sblock); 300*4234Smckusick for (i = 0; i < cssize(&sblock); i += BSIZE) 301*4234Smckusick wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i); 302*4234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 303*4234Smckusick wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock); 304*4234Smckusick #ifndef STANDALONE 305*4234Smckusick exit(error); 306*4234Smckusick #endif 307*4234Smckusick } 308*4234Smckusick 309*4234Smckusick /* 310*4234Smckusick * Initialize a cylinder group. 311*4234Smckusick */ 312*4234Smckusick initcg(c) 313*4234Smckusick int c; 314*4234Smckusick { 315*4234Smckusick daddr_t cbase, d, dmin, dmax; 316*4234Smckusick long i, j, s; 317*4234Smckusick register struct csum *cs; 318*4234Smckusick 319*4234Smckusick /* 320*4234Smckusick * Determine block bounds for cylinder group. 321*4234Smckusick * Allow space for super block summary information in first 322*4234Smckusick * cylinder group. 323*4234Smckusick */ 324*4234Smckusick cbase = cgbase(c,&sblock); 325*4234Smckusick dmax = cbase + sblock.fs_fpg; 326*4234Smckusick if (dmax > sblock.fs_size) 327*4234Smckusick dmax = sblock.fs_size; 328*4234Smckusick d = cbase; 329*4234Smckusick cs = fscs+c; 330*4234Smckusick tryagain: 331*4234Smckusick for (i = cgdmin(c,&sblock) - FRAG; i >= 0; i -= FRAG) 332*4234Smckusick if (badblk(d)) { 333*4234Smckusick d += i + FRAG; 334*4234Smckusick if (d + sblock.fs_ipg/INOPB >= dmax) { 335*4234Smckusick printf("bad blocks: cyl grp %d unusable\n", c); 336*4234Smckusick exit(1); 337*4234Smckusick } 338*4234Smckusick goto tryagain; 339*4234Smckusick } 340*4234Smckusick cs->cs_ndir = 0; 341*4234Smckusick acg.cg_time = utime; 342*4234Smckusick acg.cg_magic = CG_MAGIC; 343*4234Smckusick acg.cg_cgx = c; 344*4234Smckusick acg.cg_ncyl = sblock.fs_cpg; 345*4234Smckusick acg.cg_niblk = sblock.fs_ipg; 346*4234Smckusick acg.cg_ndblk = dmax - cbase; 347*4234Smckusick acg.cg_ndir = 0; 348*4234Smckusick acg.cg_nffree = 0; 349*4234Smckusick acg.cg_nbfree = 0; 350*4234Smckusick acg.cg_nifree = 0; 351*4234Smckusick acg.cg_rotor = 0; 352*4234Smckusick i = 0; 353*4234Smckusick d = cgimin(c,&sblock); 354*4234Smckusick while (i < sblock.fs_ipg) { 355*4234Smckusick for (j = INOPB; j > 0; j--) { 356*4234Smckusick clrbit(acg.cg_iused, i); 357*4234Smckusick i++; 358*4234Smckusick } 359*4234Smckusick acg.cg_nifree += INOPB; 360*4234Smckusick d++; 361*4234Smckusick } 362*4234Smckusick while (i < MAXIPG) { 363*4234Smckusick clrbit(acg.cg_iused, i); 364*4234Smckusick i++; 365*4234Smckusick } 366*4234Smckusick lseek(fso, cgimin(c,&sblock)*FSIZE, 0); 367*4234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 368*4234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 369*4234Smckusick printf("write error %D\n", tell(fso) / BSIZE); 370*4234Smckusick for (i = 0; i < MAXCPG; i++) 371*4234Smckusick for (j = 0; j < NRPOS; j++) 372*4234Smckusick acg.cg_b[i][j] = 0; 373*4234Smckusick dmin = cgdmin(c,&sblock) - cbase; 374*4234Smckusick if (c == 0) { 375*4234Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 376*4234Smckusick } 377*4234Smckusick for (d = 0; d < dmin; d += FRAG) 378*4234Smckusick clrblock(acg.cg_free, d/FRAG); 379*4234Smckusick while ((d+FRAG) <= dmax - cbase) { 380*4234Smckusick if (badblk(cbase+d)) 381*4234Smckusick clrblock(acg.cg_free, d/FRAG); 382*4234Smckusick else { 383*4234Smckusick setblock(acg.cg_free, d/FRAG); 384*4234Smckusick acg.cg_nbfree++; 385*4234Smckusick s = d * NSPF; 386*4234Smckusick acg.cg_b[s/sblock.fs_spc] 387*4234Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 388*4234Smckusick } 389*4234Smckusick d += FRAG; 390*4234Smckusick } 391*4234Smckusick if (d < dmax - cbase) 392*4234Smckusick if (badblk(d)) 393*4234Smckusick for (; d < dmax - cbase; d++) 394*4234Smckusick clrbit(acg.cg_free, d); 395*4234Smckusick else 396*4234Smckusick for (; d < dmax - cbase; d++) { 397*4234Smckusick setbit(acg.cg_free, d); 398*4234Smckusick acg.cg_nffree++; 399*4234Smckusick } 400*4234Smckusick for (; d < MAXBPG; d++) 401*4234Smckusick clrbit(acg.cg_free, d); 402*4234Smckusick sblock.fs_nffree += acg.cg_nffree; 403*4234Smckusick sblock.fs_nbfree += acg.cg_nbfree; 404*4234Smckusick cs->cs_nifree = acg.cg_nifree; 405*4234Smckusick cs->cs_nbfree = acg.cg_nbfree; 406*4234Smckusick wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg); 407*4234Smckusick } 408*4234Smckusick 409*4234Smckusick cfile(par) 410*4234Smckusick struct inode *par; 411*4234Smckusick { 412*4234Smckusick struct inode in; 413*4234Smckusick int dbc, ibc; 414*4234Smckusick char db[BSIZE]; 415*4234Smckusick daddr_t ib[NINDIR]; 416*4234Smckusick int i, f, c; 417*4234Smckusick 418*4234Smckusick /* 419*4234Smckusick * get mode, uid and gid 420*4234Smckusick */ 421*4234Smckusick 422*4234Smckusick getstr(); 423*4234Smckusick in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 424*4234Smckusick in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 425*4234Smckusick in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 426*4234Smckusick for(i=3; i<6; i++) { 427*4234Smckusick c = string[i]; 428*4234Smckusick if(c<'0' || c>'7') { 429*4234Smckusick printf("%c/%s: bad octal mode digit\n", c, string); 430*4234Smckusick error = 1; 431*4234Smckusick c = 0; 432*4234Smckusick } 433*4234Smckusick in.i_mode |= (c-'0')<<(15-3*i); 434*4234Smckusick } 435*4234Smckusick in.i_uid = getnum(); 436*4234Smckusick in.i_gid = getnum(); 437*4234Smckusick 438*4234Smckusick /* 439*4234Smckusick * general initialization prior to 440*4234Smckusick * switching on format 441*4234Smckusick */ 442*4234Smckusick 443*4234Smckusick ino++; 444*4234Smckusick in.i_number = ino; 445*4234Smckusick for(i=0; i<BSIZE; i++) 446*4234Smckusick db[i] = 0; 447*4234Smckusick for(i=0; i<NINDIR; i++) 448*4234Smckusick ib[i] = (daddr_t)0; 449*4234Smckusick in.i_nlink = 1; 450*4234Smckusick in.i_size = 0; 451*4234Smckusick for(i=0; i<NDADDR; i++) 452*4234Smckusick in.i_un.i_f.i_db[i] = (daddr_t)0; 453*4234Smckusick for(i=0; i<NIADDR; i++) 454*4234Smckusick in.i_un.i_f.i_ib[i] = (daddr_t)0; 455*4234Smckusick if(par == (struct inode *)0) { 456*4234Smckusick par = ∈ 457*4234Smckusick in.i_nlink--; 458*4234Smckusick } 459*4234Smckusick dbc = 0; 460*4234Smckusick ibc = 0; 461*4234Smckusick switch(in.i_mode&IFMT) { 462*4234Smckusick 463*4234Smckusick case IFREG: 464*4234Smckusick /* 465*4234Smckusick * regular file 466*4234Smckusick * contents is a file name 467*4234Smckusick */ 468*4234Smckusick 469*4234Smckusick getstr(); 470*4234Smckusick f = open(string, 0); 471*4234Smckusick if(f < 0) { 472*4234Smckusick printf("%s: cannot open\n", string); 473*4234Smckusick error = 1; 474*4234Smckusick break; 475*4234Smckusick } 476*4234Smckusick while((i=read(f, db, BSIZE)) > 0) { 477*4234Smckusick in.i_size += i; 478*4234Smckusick newblk(&dbc, db, &ibc, ib, i); 479*4234Smckusick } 480*4234Smckusick close(f); 481*4234Smckusick break; 482*4234Smckusick 483*4234Smckusick case IFBLK: 484*4234Smckusick case IFCHR: 485*4234Smckusick /* 486*4234Smckusick * special file 487*4234Smckusick * content is maj/min types 488*4234Smckusick */ 489*4234Smckusick 490*4234Smckusick i = getnum() & 0377; 491*4234Smckusick f = getnum() & 0377; 492*4234Smckusick in.i_un.i_d.i_rdev = makedev(i, f); 493*4234Smckusick break; 494*4234Smckusick 495*4234Smckusick case IFDIR: 496*4234Smckusick /* 497*4234Smckusick * directory 498*4234Smckusick * put in extra links 499*4234Smckusick * call recursively until 500*4234Smckusick * name of "$" found 501*4234Smckusick */ 502*4234Smckusick 503*4234Smckusick par->i_nlink++; 504*4234Smckusick in.i_nlink++; 505*4234Smckusick entry(in.i_number, ".", &dbc, db, &ibc, ib); 506*4234Smckusick entry(par->i_number, "..", &dbc, db, &ibc, ib); 507*4234Smckusick in.i_size = 2*sizeof(struct direct); 508*4234Smckusick for(;;) { 509*4234Smckusick getstr(); 510*4234Smckusick if(string[0]=='$' && string[1]=='\0') 511*4234Smckusick break; 512*4234Smckusick if (in.i_size >= FSIZE) { 513*4234Smckusick printf("can't handle direct of > %d entries\n", 514*4234Smckusick NDIRECT/FRAG); 515*4234Smckusick exit(1); 516*4234Smckusick } 517*4234Smckusick entry(ino+1, string, &dbc, db, &ibc, ib); 518*4234Smckusick in.i_size += sizeof(struct direct); 519*4234Smckusick cfile(&in); 520*4234Smckusick } 521*4234Smckusick break; 522*4234Smckusick } 523*4234Smckusick if(dbc != 0) 524*4234Smckusick newblk(&dbc, db, &ibc, ib, roundup(dbc,FSIZE)); 525*4234Smckusick iput(&in, &ibc, ib); 526*4234Smckusick } 527*4234Smckusick 528*4234Smckusick gmode(c, s, m0, m1, m2, m3) 529*4234Smckusick char c, *s; 530*4234Smckusick { 531*4234Smckusick int i; 532*4234Smckusick 533*4234Smckusick for(i=0; s[i]; i++) 534*4234Smckusick if(c == s[i]) 535*4234Smckusick return((&m0)[i]); 536*4234Smckusick printf("%c/%s: bad mode\n", c, string); 537*4234Smckusick error = 1; 538*4234Smckusick return(0); 539*4234Smckusick } 540*4234Smckusick 541*4234Smckusick long 542*4234Smckusick getnum() 543*4234Smckusick { 544*4234Smckusick int i, c; 545*4234Smckusick long n; 546*4234Smckusick 547*4234Smckusick getstr(); 548*4234Smckusick n = 0; 549*4234Smckusick i = 0; 550*4234Smckusick for(i=0; c=string[i]; i++) { 551*4234Smckusick if(c<'0' || c>'9') { 552*4234Smckusick printf("%s: bad number\n", string); 553*4234Smckusick error = 1; 554*4234Smckusick return((long)0); 555*4234Smckusick } 556*4234Smckusick n = n*10 + (c-'0'); 557*4234Smckusick } 558*4234Smckusick return(n); 559*4234Smckusick } 560*4234Smckusick 561*4234Smckusick getstr() 562*4234Smckusick { 563*4234Smckusick int i, c; 564*4234Smckusick 565*4234Smckusick loop: 566*4234Smckusick switch(c=getch()) { 567*4234Smckusick 568*4234Smckusick case ' ': 569*4234Smckusick case '\t': 570*4234Smckusick case '\n': 571*4234Smckusick goto loop; 572*4234Smckusick 573*4234Smckusick case '\0': 574*4234Smckusick printf("EOF\n"); 575*4234Smckusick exit(1); 576*4234Smckusick 577*4234Smckusick case ':': 578*4234Smckusick while(getch() != '\n'); 579*4234Smckusick goto loop; 580*4234Smckusick 581*4234Smckusick } 582*4234Smckusick i = 0; 583*4234Smckusick 584*4234Smckusick do { 585*4234Smckusick string[i++] = c; 586*4234Smckusick c = getch(); 587*4234Smckusick } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 588*4234Smckusick string[i] = '\0'; 589*4234Smckusick } 590*4234Smckusick 591*4234Smckusick rdfs(bno, size, bf) 592*4234Smckusick daddr_t bno; 593*4234Smckusick int size; 594*4234Smckusick char *bf; 595*4234Smckusick { 596*4234Smckusick int n; 597*4234Smckusick 598*4234Smckusick lseek(fsi, bno*FSIZE, 0); 599*4234Smckusick n = read(fsi, bf, size); 600*4234Smckusick if(n != size) { 601*4234Smckusick printf("read error: %ld\n", bno); 602*4234Smckusick exit(1); 603*4234Smckusick } 604*4234Smckusick } 605*4234Smckusick 606*4234Smckusick wtfs(bno, size, bf) 607*4234Smckusick daddr_t bno; 608*4234Smckusick int size; 609*4234Smckusick char *bf; 610*4234Smckusick { 611*4234Smckusick int n; 612*4234Smckusick 613*4234Smckusick lseek(fso, bno*FSIZE, 0); 614*4234Smckusick n = write(fso, bf, size); 615*4234Smckusick if(n != size) { 616*4234Smckusick printf("write error: %D\n", bno); 617*4234Smckusick exit(1); 618*4234Smckusick } 619*4234Smckusick } 620*4234Smckusick 621*4234Smckusick daddr_t 622*4234Smckusick alloc(size) 623*4234Smckusick int size; 624*4234Smckusick { 625*4234Smckusick int c, i, s, frag; 626*4234Smckusick daddr_t d; 627*4234Smckusick 628*4234Smckusick c = 0; 629*4234Smckusick rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 630*4234Smckusick if (acg.cg_nbfree == 0) { 631*4234Smckusick printf("first cylinder group ran out of space\n"); 632*4234Smckusick return (0); 633*4234Smckusick } 634*4234Smckusick for (d = 0; d < acg.cg_ndblk; d += FRAG) 635*4234Smckusick if (isblock(acg.cg_free, d/FRAG)) 636*4234Smckusick goto goth; 637*4234Smckusick printf("internal error: can't find block in cyl 0\n"); 638*4234Smckusick return (0); 639*4234Smckusick goth: 640*4234Smckusick clrblock(acg.cg_free, d/FRAG); 641*4234Smckusick acg.cg_nbfree--; 642*4234Smckusick sblock.fs_nbfree--; 643*4234Smckusick fscs[0].cs_nbfree--; 644*4234Smckusick s = d * NSPF; 645*4234Smckusick acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--; 646*4234Smckusick if (size != BSIZE) { 647*4234Smckusick frag = howmany(size, FSIZE); 648*4234Smckusick acg.cg_nffree += FRAG - frag; 649*4234Smckusick sblock.fs_nffree += FRAG - frag; 650*4234Smckusick for (i = frag; i < FRAG; i++) 651*4234Smckusick setbit(acg.cg_free, d+i); 652*4234Smckusick } 653*4234Smckusick wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 654*4234Smckusick return (d); 655*4234Smckusick } 656*4234Smckusick 657*4234Smckusick entry(inum, str, adbc, db, aibc, ib) 658*4234Smckusick ino_t inum; 659*4234Smckusick char *str; 660*4234Smckusick int *adbc, *aibc; 661*4234Smckusick char *db; 662*4234Smckusick daddr_t *ib; 663*4234Smckusick { 664*4234Smckusick struct direct *dp; 665*4234Smckusick int i; 666*4234Smckusick 667*4234Smckusick dp = (struct direct *)db; 668*4234Smckusick dp += *adbc; 669*4234Smckusick (*adbc)++; 670*4234Smckusick dp->d_ino = inum; 671*4234Smckusick for(i=0; i<DIRSIZ; i++) 672*4234Smckusick dp->d_name[i] = 0; 673*4234Smckusick for(i=0; i<DIRSIZ; i++) 674*4234Smckusick if((dp->d_name[i] = str[i]) == 0) 675*4234Smckusick break; 676*4234Smckusick if(*adbc >= NDIRECT) 677*4234Smckusick newblk(adbc, db, aibc, ib, BSIZE); 678*4234Smckusick } 679*4234Smckusick 680*4234Smckusick newblk(adbc, db, aibc, ib, size) 681*4234Smckusick int *adbc, *aibc; 682*4234Smckusick char *db; 683*4234Smckusick daddr_t *ib; 684*4234Smckusick int size; 685*4234Smckusick { 686*4234Smckusick int i; 687*4234Smckusick daddr_t bno; 688*4234Smckusick 689*4234Smckusick bno = alloc(size); 690*4234Smckusick wtfs(bno, size, db); 691*4234Smckusick for(i=0; i<size; i++) 692*4234Smckusick db[i] = 0; 693*4234Smckusick *adbc = 0; 694*4234Smckusick ib[*aibc] = bno; 695*4234Smckusick (*aibc)++; 696*4234Smckusick if(*aibc >= NINDIR) { 697*4234Smckusick printf("indirect block full\n"); 698*4234Smckusick error = 1; 699*4234Smckusick *aibc = 0; 700*4234Smckusick } 701*4234Smckusick } 702*4234Smckusick 703*4234Smckusick getch() 704*4234Smckusick { 705*4234Smckusick 706*4234Smckusick #ifndef STANDALONE 707*4234Smckusick if(charp) 708*4234Smckusick #endif 709*4234Smckusick return(*charp++); 710*4234Smckusick #ifndef STANDALONE 711*4234Smckusick return(getc(fin)); 712*4234Smckusick #endif 713*4234Smckusick } 714*4234Smckusick 715*4234Smckusick iput(ip, aibc, ib) 716*4234Smckusick struct inode *ip; 717*4234Smckusick int *aibc; 718*4234Smckusick daddr_t *ib; 719*4234Smckusick { 720*4234Smckusick struct dinode *dp; 721*4234Smckusick daddr_t d; 722*4234Smckusick int i, c = ip->i_number / sblock.fs_ipg; 723*4234Smckusick 724*4234Smckusick rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 725*4234Smckusick acg.cg_nifree--; 726*4234Smckusick setbit(acg.cg_iused, ip->i_number); 727*4234Smckusick wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 728*4234Smckusick sblock.fs_nifree--; 729*4234Smckusick fscs[0].cs_nifree--; 730*4234Smckusick if(ip->i_number >= sblock.fs_ipg) { 731*4234Smckusick printf("mkfs: cant handle more than one cg of inodes (yet)\n"); 732*4234Smckusick exit(1); 733*4234Smckusick } 734*4234Smckusick if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 735*4234Smckusick if(error == 0) 736*4234Smckusick printf("ilist too small\n"); 737*4234Smckusick error = 1; 738*4234Smckusick return; 739*4234Smckusick } 740*4234Smckusick d = itod(ip->i_number,&sblock); 741*4234Smckusick rdfs(d, BSIZE, buf); 742*4234Smckusick dp = (struct dinode *)buf; 743*4234Smckusick dp += itoo(ip->i_number); 744*4234Smckusick 745*4234Smckusick dp->di_mode = ip->i_mode; 746*4234Smckusick dp->di_nlink = ip->i_nlink; 747*4234Smckusick dp->di_uid = ip->i_uid; 748*4234Smckusick dp->di_gid = ip->i_gid; 749*4234Smckusick dp->di_size = ip->i_size; 750*4234Smckusick dp->di_atime = utime; 751*4234Smckusick dp->di_mtime = utime; 752*4234Smckusick dp->di_ctime = utime; 753*4234Smckusick 754*4234Smckusick switch(ip->i_mode&IFMT) { 755*4234Smckusick 756*4234Smckusick case IFDIR: 757*4234Smckusick case IFREG: 758*4234Smckusick for(i=0; i<*aibc; i++) { 759*4234Smckusick if(i >= NDADDR) 760*4234Smckusick break; 761*4234Smckusick ip->i_un.i_f.i_db[i] = ib[i]; 762*4234Smckusick } 763*4234Smckusick if(*aibc >= NDADDR) { 764*4234Smckusick ip->i_un.i_f.i_ib[0] = alloc(BSIZE); 765*4234Smckusick for(i=0; i<NINDIR-NDADDR; i++) { 766*4234Smckusick ib[i] = ib[i+NDADDR]; 767*4234Smckusick ib[i+NDADDR] = (daddr_t)0; 768*4234Smckusick } 769*4234Smckusick wtfs(ip->i_un.i_f.i_ib[0], (char *)ib); 770*4234Smckusick } 771*4234Smckusick 772*4234Smckusick case IFBLK: 773*4234Smckusick case IFCHR: 774*4234Smckusick ltol3(dp->di_addr, ip->i_un.i_f.i_db, NDADDR+NIADDR); 775*4234Smckusick break; 776*4234Smckusick 777*4234Smckusick default: 778*4234Smckusick printf("bad mode %o\n", ip->i_mode); 779*4234Smckusick exit(1); 780*4234Smckusick } 781*4234Smckusick wtfs(d, BSIZE, buf); 782*4234Smckusick } 783*4234Smckusick 784*4234Smckusick badblk(bno) 785*4234Smckusick daddr_t bno; 786*4234Smckusick { 787*4234Smckusick 788*4234Smckusick return(0); 789*4234Smckusick } 790