1*5324Smckusic static char *sccsid = "@(#)mkfs.c 1.10 (Berkeley) 01/05/82"; 24234Smckusick 34234Smckusick /* 44234Smckusick * make file system for cylinder-group style file systems 54234Smckusick * 64234Smckusick * usage: mkfs fs proto 7*5324Smckusic * or: mkfs size [ bsize frag nsect ntrak cpg ] 84234Smckusick */ 94234Smckusick 10*5324Smckusic #define NDIRECT(fs) ((fs)->fs_bsize/sizeof(struct direct)) 114234Smckusick #define MAXFN 500 124234Smckusick 134234Smckusick #ifndef STANDALONE 144234Smckusick #include <stdio.h> 154234Smckusick #include <a.out.h> 164234Smckusick #endif 174234Smckusick 184234Smckusick #include "../h/param.h" 194234Smckusick #include "../h/inode.h" 204234Smckusick #include "../h/fs.h" 214234Smckusick #include "../h/dir.h" 224234Smckusick 234234Smckusick time_t utime; 244234Smckusick 254234Smckusick #ifndef STANDALONE 264234Smckusick FILE *fin; 274234Smckusick #else 284234Smckusick int fin; 294234Smckusick #endif 304234Smckusick 314234Smckusick int fsi; 324234Smckusick int fso; 334234Smckusick char *charp; 34*5324Smckusic char buf[MAXBSIZE]; 354234Smckusick #ifndef STANDALONE 364234Smckusick struct exec head; 374234Smckusick #endif 384234Smckusick char string[50]; 394234Smckusick 404234Smckusick union { 414234Smckusick struct fs fs; 42*5324Smckusic char pad[MAXBSIZE]; 434234Smckusick } fsun; 444234Smckusick #define sblock fsun.fs 454234Smckusick struct csum *fscs; 464234Smckusick 474234Smckusick union { 484234Smckusick struct cg cg; 49*5324Smckusic char pad[MAXBSIZE]; 504234Smckusick } cgun; 514234Smckusick #define acg cgun.cg 524234Smckusick 534234Smckusick char *fsys; 544234Smckusick char *proto; 554234Smckusick int error; 564234Smckusick ino_t ino = ROOTINO - 1; 574234Smckusick long getnum(); 584234Smckusick daddr_t alloc(); 594234Smckusick 604234Smckusick struct dinode zino[MAXIPG]; 614234Smckusick 624234Smckusick main(argc, argv) 63*5324Smckusic int argc; 64*5324Smckusic char *argv[]; 654234Smckusick { 664234Smckusick int f, c; 674234Smckusick long i,n; 684234Smckusick 694234Smckusick argc--, argv++; 704234Smckusick #ifndef STANDALONE 714234Smckusick time(&utime); 724234Smckusick if(argc < 2) { 73*5324Smckusic printf("usage: mkfs sblock proto/size [ bsize frag nsect ntrak cpg ]\n"); 744234Smckusick exit(1); 754234Smckusick } 764234Smckusick fsys = argv[0]; 774234Smckusick proto = argv[1]; 784234Smckusick #else 794234Smckusick { 804234Smckusick static char protos[60]; 814234Smckusick 824234Smckusick printf("file sys size: "); 834234Smckusick gets(protos); 844234Smckusick proto = protos; 854234Smckusick } 864234Smckusick #endif 874234Smckusick #ifdef STANDALONE 884234Smckusick { 894234Smckusick char fsbuf[100]; 904234Smckusick 914234Smckusick do { 924234Smckusick printf("file system: "); 934234Smckusick gets(fsbuf); 944234Smckusick fso = open(fsbuf, 1); 954234Smckusick fsi = open(fsbuf, 0); 964234Smckusick } while (fso < 0 || fsi < 0); 974234Smckusick } 984234Smckusick fin = NULL; 994234Smckusick argc = 0; 1004234Smckusick #else 1014234Smckusick fso = creat(fsys, 0666); 1024234Smckusick if(fso < 0) { 1034234Smckusick printf("%s: cannot create\n", fsys); 1044234Smckusick exit(1); 1054234Smckusick } 1064234Smckusick fsi = open(fsys, 0); 1074234Smckusick if(fsi < 0) { 1084234Smckusick printf("%s: cannot open\n", fsys); 1094234Smckusick exit(1); 1104234Smckusick } 1114234Smckusick fin = fopen(proto, "r"); 1124234Smckusick #endif 1134234Smckusick #ifndef STANDALONE 1144234Smckusick if (fin != NULL) { 1154234Smckusick getstr(); 1164234Smckusick f = open(string, 0); 1174234Smckusick if (f < 0) { 1184234Smckusick printf("%s: cannot open init\n", string); 1194234Smckusick goto noinit; 1204234Smckusick } 1214234Smckusick read(f, (char *)&head, sizeof head); 1224234Smckusick c = head.a_text + head.a_data; 123*5324Smckusic if (c > MAXBSIZE) 1244234Smckusick printf("%s: too big\n", string); 1254234Smckusick else { 1264234Smckusick read(f, buf, c); 127*5324Smckusic wtfs(BBLOCK, MAXBSIZE, buf); 1284234Smckusick } 1294234Smckusick close(f); 1304234Smckusick noinit: 131*5324Smckusic n = getnum(); 132*5324Smckusic sblock.fs_bsize = MAXBSIZE; 133*5324Smckusic sblock.fs_frag = MAXFRAG; 134*5324Smckusic sblock.fs_fsize = MAXBSIZE / MAXFRAG; 135*5324Smckusic sblock.fs_rotdelay = ROTDELAY; 136*5324Smckusic sblock.fs_minfree = MINFREE; 1374234Smckusick sblock.fs_ntrak = getnum(); 1384234Smckusick sblock.fs_nsect = getnum(); 1394234Smckusick sblock.fs_cpg = getnum(); 1404234Smckusick } else 1414234Smckusick #endif 1424234Smckusick { 1434234Smckusick charp = "d--777 0 0 $ "; 1444234Smckusick n = 0; 1454234Smckusick for (f=0; c=proto[f]; f++) { 1464234Smckusick if (c<'0' || c>'9') { 1474234Smckusick printf("%s: cannot open\n", proto); 1484234Smckusick exit(1); 1494234Smckusick } 1504234Smckusick n = n*10 + (c-'0'); 1514234Smckusick } 1524234Smckusick if (argc > 2) 153*5324Smckusic sblock.fs_bsize = atoi(argv[2]); 1544234Smckusick else 155*5324Smckusic sblock.fs_bsize = MAXBSIZE; 1564234Smckusick if (argc > 3) 157*5324Smckusic sblock.fs_fsize = atoi(argv[3]); 1584234Smckusick else 159*5324Smckusic sblock.fs_fsize = MAXBSIZE / MAXFRAG; 160*5324Smckusic if (argc > 4) 161*5324Smckusic sblock.fs_nsect = atoi(argv[4]); 162*5324Smckusic else 163*5324Smckusic sblock.fs_nsect = 32; 164*5324Smckusic if (argc > 5) 165*5324Smckusic sblock.fs_ntrak = atoi(argv[5]); 166*5324Smckusic else 1674234Smckusick sblock.fs_ntrak = 19; 168*5324Smckusic sblock.fs_frag = sblock.fs_bsize / sblock.fs_fsize; 169*5324Smckusic sblock.fs_rotdelay = ROTDELAY; 170*5324Smckusic sblock.fs_minfree = MINFREE; 1714234Smckusick } 1724234Smckusick /* 1734234Smckusick * Now have size for file system and nsect and ntrak. 1744234Smckusick * (And, if coming from prototype, cpg). 1754234Smckusick * Determine number of cylinders occupied by file system. 1764234Smckusick */ 177*5324Smckusic if (sblock.fs_fsize < DEV_BSIZE) { 178*5324Smckusic printf("fragment size %d is too small, minimum is %d\n", 179*5324Smckusic sblock.fs_fsize, DEV_BSIZE); 180*5324Smckusic exit(1); 181*5324Smckusic } 182*5324Smckusic if (sblock.fs_bsize < MINBSIZE) { 183*5324Smckusic printf("block size %d is too small, minimum is %d\n", 184*5324Smckusic sblock.fs_bsize, MINBSIZE); 185*5324Smckusic exit(1); 186*5324Smckusic } 187*5324Smckusic sblock.fs_size = n = dbtofsb(&sblock, n); 1884234Smckusick if (sblock.fs_ntrak <= 0) 1894234Smckusick printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1904234Smckusick if (sblock.fs_nsect <= 0) 1914234Smckusick printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 1924234Smckusick if (sblock.fs_size <= 0) 1934234Smckusick printf("preposterous size %d\n", sblock.fs_size), exit(1); 194*5324Smckusic if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG(&sblock) * NSPB(&sblock)) { 1954234Smckusick printf("cylinder too large (%d sectors)\n", 1964234Smckusick sblock.fs_ntrak * sblock.fs_nsect); 1974234Smckusick printf("maximum cylinder size: %d sectors\n", 198*5324Smckusic MAXBPG(&sblock) * NSPB(&sblock)); 1994234Smckusick exit(1); 2004234Smckusick } 201*5324Smckusic sblock.fs_ncyl = n * NSPF(&sblock) / (sblock.fs_nsect * sblock.fs_ntrak); 202*5324Smckusic if (n * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { 2034234Smckusick printf("%d sector(s) in last cylinder unused\n", 204*5324Smckusic n * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); 2054234Smckusick sblock.fs_ncyl++; 2064234Smckusick } 2074234Smckusick sblock.fs_magic = FS_MAGIC; 2084234Smckusick /* 2094234Smckusick * Validate specified/determined cpg. 2104234Smckusick */ 211*5324Smckusic #define CGTOOBIG(fs) \ 212*5324Smckusic ((fs).fs_nsect * (fs).fs_ntrak * (fs).fs_cpg/NSPB(&sblock) > MAXBPG(&sblock)) 213*5324Smckusic if (argc > 6 || fin) { 2144234Smckusick if (fin == NULL) 215*5324Smckusic sblock.fs_cpg = atoi(argv[6]); 2164234Smckusick if (CGTOOBIG(sblock)) { 2174234Smckusick printf("cylinder group too large (%d blocks); ", 218*5324Smckusic sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB(&sblock)); 219*5324Smckusic printf("max: %d blocks\n", MAXBPG(&sblock)); 2204234Smckusick exit(1); 2214234Smckusick } 2224234Smckusick if (sblock.fs_cpg > MAXCPG) { 2234234Smckusick printf("cylinder groups are limited to %d cylinders\n", 2244234Smckusick MAXCPG); 2254234Smckusick exit(1); 2264234Smckusick } 2274234Smckusick } else { 2284234Smckusick sblock.fs_cpg = DESCPG; 2294234Smckusick while (CGTOOBIG(sblock)) 2304234Smckusick --sblock.fs_cpg; 2314234Smckusick } 2324234Smckusick /* 2334234Smckusick * Compute/validate number of cylinder groups. 2344234Smckusick */ 2354234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2364234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2374234Smckusick sblock.fs_ncg++; 238*5324Smckusic if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF(&sblock)) { 2394234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2404234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2414234Smckusick printf("as this would would have cyl groups whose size\n"); 242*5324Smckusic printf("is not a multiple of %d; choke!\n", sblock.fs_fsize); 2434234Smckusick exit(1); 2444234Smckusick } 2454234Smckusick fscs = (struct csum *) 246*5324Smckusic calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), 247*5324Smckusic sblock.fs_bsize)); 2484234Smckusick /* 2494234Smckusick * Compute number of inode blocks per cylinder group. 2504234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 2514234Smckusick */ 252*5324Smckusic n = ((n * sblock.fs_fsize) / NBPI) / INOPB(&sblock); 2534234Smckusick if (n <= 0) 2544234Smckusick n = 1; 255*5324Smckusic sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB(&sblock); 256*5324Smckusic if (sblock.fs_ipg < INOPB(&sblock)) 257*5324Smckusic sblock.fs_ipg = INOPB(&sblock); 2584234Smckusick if (sblock.fs_ipg > MAXIPG) 2594234Smckusick sblock.fs_ipg = MAXIPG; 2604234Smckusick sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 261*5324Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / 262*5324Smckusic (sblock.fs_fsize / SECTSIZE); 263*5324Smckusic if (cgdmin(0,&sblock) >= sblock.fs_fpg) { 2644234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 265*5324Smckusic cgdmin(0,&sblock) / sblock.fs_frag, 266*5324Smckusic sblock.fs_fpg / sblock.fs_frag); 267*5324Smckusic exit(1); 268*5324Smckusic } 2694788Smckusic sblock.fs_cstotal.cs_nifree = sblock.fs_ipg * sblock.fs_ncg; 2704234Smckusick sblock.fs_cgsize = cgsize(&sblock); 271*5324Smckusic sblock.fs_csaddr = cgdmin(0, &sblock); 272*5324Smckusic sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum); 2734234Smckusick sblock.fs_sblkno = SBLOCK; 2744234Smckusick sblock.fs_fmod = 0; 2754234Smckusick sblock.fs_ronly = 0; 2764234Smckusick 2774234Smckusick /* 2784234Smckusick * Dump out information about file system. 2794234Smckusick */ 2804234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 281*5324Smckusic fsys, sblock.fs_size*NSPF(&sblock), sblock.fs_ncyl, 282*5324Smckusic sblock.fs_ntrak, sblock.fs_nsect); 2834234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 284*5324Smckusic (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 285*5324Smckusic sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 286*5324Smckusic sblock.fs_ipg); 2874234Smckusick /* 288*5324Smckusic printf("%7d size (%d blocks)\n", 289*5324Smckusic sblock.fs_size, sblock.fs_size / sblock.fs_frag); 2904234Smckusick printf("%7d cylinder groups\n", sblock.fs_ncg); 2914234Smckusick printf("%7d cylinder group block size\n", sblock.fs_cgsize); 2924234Smckusick printf("%7d tracks\n", sblock.fs_ntrak); 2934234Smckusick printf("%7d sectors\n", sblock.fs_nsect); 2944234Smckusick printf("%7d sectors per cylinder\n", sblock.fs_spc); 2954234Smckusick printf("%7d cylinders\n", sblock.fs_ncyl); 2964234Smckusick printf("%7d cylinders per group\n", sblock.fs_cpg); 297*5324Smckusic printf("%7d blocks per group\n", sblock.fs_fpg/sblock.fs_frag); 2984234Smckusick printf("%7d inodes per group\n", sblock.fs_ipg); 2994234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) { 3004234Smckusick printf("%7d cylinders in last group\n", 3014234Smckusick i = sblock.fs_ncyl % sblock.fs_cpg); 3024234Smckusick printf("%7d blocks in last group\n", 303*5324Smckusic i * sblock.fs_spc / NSPB(&sblock)); 3044234Smckusick } 3054234Smckusick */ 3064234Smckusick /* 3074234Smckusick * Now build the cylinders group blocks and 3084234Smckusick * then print out indices of cylinder groups forwarded 3094234Smckusick * past bad blocks or other obstructions. 3104234Smckusick */ 3114788Smckusic sblock.fs_cstotal.cs_ndir = 0; 3124788Smckusic sblock.fs_cstotal.cs_nbfree = 0; 3134788Smckusic sblock.fs_cstotal.cs_nifree = 0; 3144788Smckusic sblock.fs_cstotal.cs_nffree = 0; 3154652Smckusic sblock.fs_cgrotor = 0; 3164652Smckusic for (i = 0; i < NRPOS; i++) 3174652Smckusic sblock.fs_postbl[i] = -1; 318*5324Smckusic for (i = 0; i < sblock.fs_spc; i += (NSPF(&sblock) * sblock.fs_frag)) 3194652Smckusic /* void */; 320*5324Smckusic for (i -= (NSPF(&sblock) * sblock.fs_frag); 321*5324Smckusic i >= 0; 322*5324Smckusic i -= (NSPF(&sblock) * sblock.fs_frag)) { 3234652Smckusic c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect; 324*5324Smckusic sblock.fs_rotbl[i / (NSPF(&sblock) * sblock.fs_frag)] = 325*5324Smckusic sblock.fs_postbl[c]; 326*5324Smckusic sblock.fs_postbl[c] = i / (NSPF(&sblock) * sblock.fs_frag); 3274652Smckusic } 3284234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 3294234Smckusick initcg(c); 330*5324Smckusic if (sblock.fs_ncg == 1) 331*5324Smckusic printf("Warning, no super-block backups with only one cylinder group\n"); 332*5324Smckusic else 333*5324Smckusic printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 334*5324Smckusic SBLOCK, fsbtodb(&sblock, sblock.fs_fpg), 335*5324Smckusic SBLOCK + fsbtodb(&sblock, sblock.fs_fpg), 336*5324Smckusic SBLOCK + fsbtodb(&sblock, (sblock.fs_ncg - 1) * 337*5324Smckusic sblock.fs_fpg)); 3384234Smckusick /* 3394234Smckusick * Now construct the initial file system, and 3404234Smckusick * then write out the super-block. 3414234Smckusick */ 3424234Smckusick cfile((struct inode *)0); 3434234Smckusick sblock.fs_time = utime; 344*5324Smckusic wtfs(SBLOCK, MAXBSIZE, (char *)&sblock); 345*5324Smckusic for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 346*5324Smckusic wtfs(fsbtodb(&sblock, sblock.fs_csaddr + i / sblock.fs_fsize), 347*5324Smckusic sblock.fs_bsize, ((char *)fscs) + i); 3484234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 349*5324Smckusic wtfs(fsbtodb(&sblock, cgsblock(c, &sblock)), 350*5324Smckusic MAXBSIZE, (char *)&sblock); 3514234Smckusick #ifndef STANDALONE 3524234Smckusick exit(error); 3534234Smckusick #endif 3544234Smckusick } 3554234Smckusick 3564234Smckusick /* 3574234Smckusick * Initialize a cylinder group. 3584234Smckusick */ 3594234Smckusick initcg(c) 3604234Smckusick int c; 3614234Smckusick { 3624234Smckusick daddr_t cbase, d, dmin, dmax; 3634234Smckusick long i, j, s; 3644234Smckusick register struct csum *cs; 3654234Smckusick 3664234Smckusick /* 3674234Smckusick * Determine block bounds for cylinder group. 3684234Smckusick * Allow space for super block summary information in first 3694234Smckusick * cylinder group. 3704234Smckusick */ 3714234Smckusick cbase = cgbase(c,&sblock); 3724234Smckusick dmax = cbase + sblock.fs_fpg; 3734234Smckusick if (dmax > sblock.fs_size) 3744234Smckusick dmax = sblock.fs_size; 3754465Smckusic dmin = cgdmin(c,&sblock) - cbase; 3764234Smckusick d = cbase; 3774234Smckusick cs = fscs+c; 3784234Smckusick acg.cg_time = utime; 3794234Smckusick acg.cg_magic = CG_MAGIC; 3804234Smckusick acg.cg_cgx = c; 3814234Smckusick acg.cg_ncyl = sblock.fs_cpg; 3824234Smckusick acg.cg_niblk = sblock.fs_ipg; 3834234Smckusick acg.cg_ndblk = dmax - cbase; 3844788Smckusic acg.cg_cs.cs_ndir = 0; 3854788Smckusic acg.cg_cs.cs_nffree = 0; 3864788Smckusic acg.cg_cs.cs_nbfree = 0; 3874788Smckusic acg.cg_cs.cs_nifree = 0; 3884465Smckusic acg.cg_rotor = dmin; 3894465Smckusic acg.cg_frotor = dmin; 3904257Smckusic acg.cg_irotor = 0; 391*5324Smckusic for (i = 0; i < sblock.fs_frag; i++) { 3924465Smckusic acg.cg_frsum[i] = 0; 3934465Smckusic } 3944465Smckusic for (i = 0; i < sblock.fs_ipg; ) { 395*5324Smckusic for (j = INOPB(&sblock); j > 0; j--) { 3964234Smckusick clrbit(acg.cg_iused, i); 3974234Smckusick i++; 3984234Smckusick } 399*5324Smckusic acg.cg_cs.cs_nifree += INOPB(&sblock); 4004234Smckusick } 4014234Smckusick while (i < MAXIPG) { 4024234Smckusick clrbit(acg.cg_iused, i); 4034234Smckusick i++; 4044234Smckusick } 405*5324Smckusic lseek(fso, fsbtodb(&sblock, cgimin(c,&sblock)) * DEV_BSIZE, 0); 4064234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 4074234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 408*5324Smckusic printf("write error %D\n", tell(fso) / sblock.fs_bsize); 4094234Smckusick for (i = 0; i < MAXCPG; i++) 4104234Smckusick for (j = 0; j < NRPOS; j++) 4114234Smckusick acg.cg_b[i][j] = 0; 4124234Smckusick if (c == 0) { 413*5324Smckusic dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) * 414*5324Smckusic sblock.fs_frag; 4154234Smckusick } 416*5324Smckusic for (d = 0; d < dmin; d += sblock.fs_frag) 417*5324Smckusic clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 418*5324Smckusic while ((d+sblock.fs_frag) <= dmax - cbase) { 419*5324Smckusic setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 4204788Smckusic acg.cg_cs.cs_nbfree++; 421*5324Smckusic s = d * NSPF(&sblock); 422*5324Smckusic acg.cg_b[s / sblock.fs_spc] 423*5324Smckusic [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]++; 424*5324Smckusic d += sblock.fs_frag; 4254234Smckusick } 4264234Smckusick if (d < dmax - cbase) 4274251Smckusic for (; d < dmax - cbase; d++) { 4284251Smckusic setbit(acg.cg_free, d); 4294788Smckusic acg.cg_cs.cs_nffree++; 4304251Smckusic } 431*5324Smckusic for (; d < MAXBPG(&sblock); d++) 4324234Smckusick clrbit(acg.cg_free, d); 4334788Smckusic sblock.fs_dsize += acg.cg_ndblk - dmin; 4344788Smckusic sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 4354788Smckusic sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 4364788Smckusic sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 4374788Smckusic sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 4384788Smckusic *cs = acg.cg_cs; 439*5324Smckusic wtfs(fsbtodb(&sblock, cgtod(c, &sblock)), 440*5324Smckusic sblock.fs_bsize, (char *)&acg); 4414234Smckusick } 4424234Smckusick 4434234Smckusick cfile(par) 444*5324Smckusic struct inode *par; 4454234Smckusick { 4464234Smckusick struct inode in; 4474234Smckusick int dbc, ibc; 448*5324Smckusic char db[MAXBSIZE]; 449*5324Smckusic daddr_t ib[MAXBSIZE / sizeof(daddr_t)]; 4504234Smckusick int i, f, c; 4514234Smckusick 4524234Smckusick /* 4534234Smckusick * get mode, uid and gid 4544234Smckusick */ 4554234Smckusick 4564234Smckusick getstr(); 4574234Smckusick in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 4584234Smckusick in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 4594234Smckusick in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 4604234Smckusick for(i=3; i<6; i++) { 4614234Smckusick c = string[i]; 4624234Smckusick if(c<'0' || c>'7') { 4634234Smckusick printf("%c/%s: bad octal mode digit\n", c, string); 4644234Smckusick error = 1; 4654234Smckusick c = 0; 4664234Smckusick } 4674234Smckusick in.i_mode |= (c-'0')<<(15-3*i); 4684234Smckusick } 4694234Smckusick in.i_uid = getnum(); 4704234Smckusick in.i_gid = getnum(); 4714251Smckusic in.i_atime = utime; 4724251Smckusic in.i_mtime = utime; 4734251Smckusic in.i_ctime = utime; 4744234Smckusick 4754234Smckusick /* 4764234Smckusick * general initialization prior to 4774234Smckusick * switching on format 4784234Smckusick */ 4794234Smckusick 4804234Smckusick ino++; 4814234Smckusick in.i_number = ino; 482*5324Smckusic for(i=0; i<sblock.fs_bsize; i++) 4834234Smckusick db[i] = 0; 484*5324Smckusic for(i=0; i<NINDIR(&sblock); i++) 4854234Smckusick ib[i] = (daddr_t)0; 4864234Smckusick in.i_nlink = 1; 4874234Smckusick in.i_size = 0; 4884234Smckusick for(i=0; i<NDADDR; i++) 4894251Smckusic in.i_db[i] = (daddr_t)0; 4904234Smckusick for(i=0; i<NIADDR; i++) 4914251Smckusic in.i_ib[i] = (daddr_t)0; 4924234Smckusick if(par == (struct inode *)0) { 4934234Smckusick par = ∈ 4944234Smckusick in.i_nlink--; 4954234Smckusick } 4964234Smckusick dbc = 0; 4974234Smckusick ibc = 0; 4984234Smckusick switch(in.i_mode&IFMT) { 4994234Smckusick 5004234Smckusick case IFREG: 5014234Smckusick /* 5024234Smckusick * regular file 5034234Smckusick * contents is a file name 5044234Smckusick */ 5054234Smckusick 5064234Smckusick getstr(); 5074234Smckusick f = open(string, 0); 5084234Smckusick if(f < 0) { 5094234Smckusick printf("%s: cannot open\n", string); 5104234Smckusick error = 1; 5114234Smckusick break; 5124234Smckusick } 513*5324Smckusic while((i = read(f, db, sblock.fs_bsize)) > 0) { 5144234Smckusick in.i_size += i; 515*5324Smckusic newblk(&dbc, db, &ibc, ib, 516*5324Smckusic ibc < NDADDR ? i : sblock.fs_bsize, 0); 5174234Smckusick } 5184234Smckusick close(f); 5194234Smckusick break; 5204234Smckusick 5214234Smckusick case IFBLK: 5224234Smckusick case IFCHR: 5234234Smckusick /* 5244234Smckusick * special file 5254234Smckusick * content is maj/min types 5264234Smckusick */ 5274234Smckusick 5284234Smckusick i = getnum() & 0377; 5294234Smckusick f = getnum() & 0377; 5304251Smckusic in.i_rdev = makedev(i, f); 5314234Smckusick break; 5324234Smckusick 5334234Smckusick case IFDIR: 5344234Smckusick /* 5354234Smckusick * directory 5364234Smckusick * put in extra links 5374234Smckusick * call recursively until 5384234Smckusick * name of "$" found 5394234Smckusick */ 5404234Smckusick 5414234Smckusick par->i_nlink++; 5424234Smckusick in.i_nlink++; 5434234Smckusick entry(in.i_number, ".", &dbc, db, &ibc, ib); 5444234Smckusick entry(par->i_number, "..", &dbc, db, &ibc, ib); 5454234Smckusick in.i_size = 2*sizeof(struct direct); 5464234Smckusick for(;;) { 5474234Smckusick getstr(); 5484234Smckusick if(string[0]=='$' && string[1]=='\0') 5494234Smckusick break; 550*5324Smckusic if (in.i_size >= sblock.fs_bsize * NDADDR) { 5514234Smckusick printf("can't handle direct of > %d entries\n", 552*5324Smckusic NDIRECT(&sblock) * NDADDR); 5534234Smckusick exit(1); 5544234Smckusick } 5554234Smckusick entry(ino+1, string, &dbc, db, &ibc, ib); 5564234Smckusick in.i_size += sizeof(struct direct); 5574234Smckusick cfile(&in); 5584234Smckusick } 559*5324Smckusic newblk(&dbc, db, &ibc, ib, roundup(dbc, sblock.fs_fsize), 560*5324Smckusic IFDIR); 5614234Smckusick break; 5624234Smckusick } 5634234Smckusick iput(&in, &ibc, ib); 5644234Smckusick } 5654234Smckusick 5664234Smckusick gmode(c, s, m0, m1, m2, m3) 567*5324Smckusic char c, *s; 568*5324Smckusic int m0, m1, m2, m3; 5694234Smckusick { 5704234Smckusick int i; 5714234Smckusick 5724234Smckusick for(i=0; s[i]; i++) 5734234Smckusick if(c == s[i]) 5744234Smckusick return((&m0)[i]); 5754234Smckusick printf("%c/%s: bad mode\n", c, string); 5764234Smckusick error = 1; 5774234Smckusick return(0); 5784234Smckusick } 5794234Smckusick 5804234Smckusick long 5814234Smckusick getnum() 5824234Smckusick { 5834234Smckusick int i, c; 5844234Smckusick long n; 5854234Smckusick 5864234Smckusick getstr(); 5874234Smckusick n = 0; 5884234Smckusick i = 0; 5894234Smckusick for(i=0; c=string[i]; i++) { 5904234Smckusick if(c<'0' || c>'9') { 5914234Smckusick printf("%s: bad number\n", string); 5924234Smckusick error = 1; 5934234Smckusick return((long)0); 5944234Smckusick } 5954234Smckusick n = n*10 + (c-'0'); 5964234Smckusick } 5974234Smckusick return(n); 5984234Smckusick } 5994234Smckusick 6004234Smckusick getstr() 6014234Smckusick { 6024234Smckusick int i, c; 6034234Smckusick 6044234Smckusick loop: 6054234Smckusick switch(c=getch()) { 6064234Smckusick 6074234Smckusick case ' ': 6084234Smckusick case '\t': 6094234Smckusick case '\n': 6104234Smckusick goto loop; 6114234Smckusick 6124234Smckusick case '\0': 6134234Smckusick printf("EOF\n"); 6144234Smckusick exit(1); 6154234Smckusick 6164234Smckusick case ':': 6174234Smckusick while(getch() != '\n'); 6184234Smckusick goto loop; 6194234Smckusick 6204234Smckusick } 6214234Smckusick i = 0; 6224234Smckusick 6234234Smckusick do { 6244234Smckusick string[i++] = c; 6254234Smckusick c = getch(); 6264234Smckusick } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 6274234Smckusick string[i] = '\0'; 6284234Smckusick } 6294234Smckusick 6304234Smckusick rdfs(bno, size, bf) 631*5324Smckusic daddr_t bno; 632*5324Smckusic int size; 633*5324Smckusic char *bf; 6344234Smckusick { 6354234Smckusick int n; 6364234Smckusick 637*5324Smckusic lseek(fsi, bno * DEV_BSIZE, 0); 6384234Smckusick n = read(fsi, bf, size); 6394234Smckusick if(n != size) { 6404234Smckusick printf("read error: %ld\n", bno); 6414234Smckusick exit(1); 6424234Smckusick } 6434234Smckusick } 6444234Smckusick 6454234Smckusick wtfs(bno, size, bf) 646*5324Smckusic daddr_t bno; 647*5324Smckusic int size; 648*5324Smckusic char *bf; 6494234Smckusick { 6504234Smckusick int n; 6514234Smckusick 652*5324Smckusic lseek(fso, bno * DEV_BSIZE, 0); 6534234Smckusick n = write(fso, bf, size); 6544234Smckusick if(n != size) { 6554234Smckusick printf("write error: %D\n", bno); 6564234Smckusick exit(1); 6574234Smckusick } 6584234Smckusick } 6594234Smckusick 6604234Smckusick daddr_t 6614427Smckusic alloc(size, mode) 6624427Smckusic int size; 6634427Smckusic int mode; 6644234Smckusick { 6654234Smckusick int c, i, s, frag; 6664234Smckusick daddr_t d; 6674234Smckusick 6684234Smckusick c = 0; 669*5324Smckusic rdfs(fsbtodb(&sblock, cgtod(0,&sblock)), 670*5324Smckusic sblock.fs_cgsize, (char *)&acg); 6714788Smckusic if (acg.cg_cs.cs_nbfree == 0) { 6724234Smckusick printf("first cylinder group ran out of space\n"); 6734234Smckusick return (0); 6744234Smckusick } 675*5324Smckusic for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 676*5324Smckusic if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag)) 6774234Smckusick goto goth; 6784234Smckusick printf("internal error: can't find block in cyl 0\n"); 6794234Smckusick return (0); 6804234Smckusick goth: 681*5324Smckusic clrblock(&sblock, acg.cg_free, d / sblock.fs_frag); 6824788Smckusic acg.cg_cs.cs_nbfree--; 6834788Smckusic sblock.fs_cstotal.cs_nbfree--; 6844234Smckusick fscs[0].cs_nbfree--; 6854427Smckusic if (mode & IFDIR) { 6864788Smckusic acg.cg_cs.cs_ndir++; 6874788Smckusic sblock.fs_cstotal.cs_ndir++; 6884427Smckusic fscs[0].cs_ndir++; 6894427Smckusic } 690*5324Smckusic s = d * NSPF(&sblock); 691*5324Smckusic acg.cg_b[s / sblock.fs_spc] 692*5324Smckusic [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]--; 693*5324Smckusic if (size != sblock.fs_bsize) { 694*5324Smckusic frag = howmany(size, sblock.fs_fsize); 695*5324Smckusic fscs[0].cs_nffree += sblock.fs_frag - frag; 696*5324Smckusic sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 697*5324Smckusic acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 698*5324Smckusic acg.cg_frsum[sblock.fs_frag - frag]++; 699*5324Smckusic for (i = frag; i < sblock.fs_frag; i++) 7004234Smckusick setbit(acg.cg_free, d+i); 7014234Smckusick } 702*5324Smckusic wtfs(fsbtodb(&sblock, cgtod(0,&sblock)), 703*5324Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 7044234Smckusick return (d); 7054234Smckusick } 7064234Smckusick 7074234Smckusick entry(inum, str, adbc, db, aibc, ib) 708*5324Smckusic ino_t inum; 709*5324Smckusic char *str; 710*5324Smckusic int *adbc, *aibc; 711*5324Smckusic char *db; 712*5324Smckusic daddr_t *ib; 7134234Smckusick { 7144234Smckusick struct direct *dp; 7154234Smckusick int i; 7164234Smckusick 717*5324Smckusic if (*adbc == NDIRECT(&sblock)) 718*5324Smckusic newblk(adbc, db, aibc, ib, sblock.fs_bsize, 0); 7194234Smckusick dp = (struct direct *)db; 7204234Smckusick dp += *adbc; 7214234Smckusick (*adbc)++; 7224234Smckusick dp->d_ino = inum; 723*5324Smckusic for(i=0; i < DIRSIZ; i++) 7244234Smckusick dp->d_name[i] = 0; 725*5324Smckusic for(i=0; i < DIRSIZ; i++) 7264234Smckusick if((dp->d_name[i] = str[i]) == 0) 7274234Smckusick break; 7284234Smckusick } 7294234Smckusick 7304427Smckusic newblk(adbc, db, aibc, ib, size, mode) 7314427Smckusic int *adbc, *aibc; 7324427Smckusic char *db; 7334427Smckusic daddr_t *ib; 7344427Smckusic int size; 7354427Smckusic int mode; 7364234Smckusick { 7374234Smckusick int i; 7384234Smckusick daddr_t bno; 7394234Smckusick 7404427Smckusic bno = alloc(size, mode); 741*5324Smckusic wtfs(fsbtodb(&sblock, bno), size, db); 742*5324Smckusic for(i = 0; i < size; i++) 7434234Smckusick db[i] = 0; 7444234Smckusick *adbc = 0; 7454234Smckusick ib[*aibc] = bno; 7464234Smckusick (*aibc)++; 747*5324Smckusic if(*aibc >= NINDIR(&sblock)) { 7484234Smckusick printf("indirect block full\n"); 7494234Smckusick error = 1; 7504234Smckusick *aibc = 0; 7514234Smckusick } 7524234Smckusick } 7534234Smckusick 7544234Smckusick getch() 7554234Smckusick { 7564234Smckusick 7574234Smckusick #ifndef STANDALONE 7584234Smckusick if(charp) 7594234Smckusick #endif 7604234Smckusick return(*charp++); 7614234Smckusick #ifndef STANDALONE 7624234Smckusick return(getc(fin)); 7634234Smckusick #endif 7644234Smckusick } 7654234Smckusick 7664234Smckusick iput(ip, aibc, ib) 767*5324Smckusic struct inode *ip; 768*5324Smckusic int *aibc; 769*5324Smckusic daddr_t *ib; 7704234Smckusick { 7714234Smckusick struct dinode *dp; 7724234Smckusick daddr_t d; 7734234Smckusick int i, c = ip->i_number / sblock.fs_ipg; 7744234Smckusick 775*5324Smckusic rdfs(fsbtodb(&sblock, cgtod(c,&sblock)), 776*5324Smckusic sblock.fs_cgsize, (char *)&acg); 7774788Smckusic acg.cg_cs.cs_nifree--; 7784234Smckusick setbit(acg.cg_iused, ip->i_number); 779*5324Smckusic wtfs(fsbtodb(&sblock, cgtod(c,&sblock)), 780*5324Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 7814788Smckusic sblock.fs_cstotal.cs_nifree--; 7824234Smckusick fscs[0].cs_nifree--; 7834234Smckusick if(ip->i_number >= sblock.fs_ipg) { 7844234Smckusick printf("mkfs: cant handle more than one cg of inodes (yet)\n"); 7854234Smckusick exit(1); 7864234Smckusick } 7874234Smckusick if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 7884234Smckusick if(error == 0) 7894234Smckusick printf("ilist too small\n"); 7904234Smckusick error = 1; 7914234Smckusick return; 7924234Smckusick } 7934234Smckusick d = itod(ip->i_number,&sblock); 794*5324Smckusic rdfs(fsbtodb(&sblock, d), sblock.fs_bsize, buf); 795*5324Smckusic for(i = 0; i < *aibc; i++) { 7964251Smckusic if(i >= NDADDR) 7974251Smckusic break; 7984251Smckusic ip->i_db[i] = ib[i]; 7994251Smckusic } 8004251Smckusic if(*aibc >= NDADDR) { 801*5324Smckusic ip->i_ib[0] = alloc(sblock.fs_bsize, 0); 802*5324Smckusic for(i=0; i<NINDIR(&sblock)-NDADDR; i++) { 8034251Smckusic ib[i] = ib[i+NDADDR]; 8044251Smckusic ib[i+NDADDR] = (daddr_t)0; 8054234Smckusick } 806*5324Smckusic wtfs(fsbtodb(&sblock, ip->i_ib[0]), sblock.fs_bsize, 807*5324Smckusic (char *)ib); 8084234Smckusick } 809*5324Smckusic ((struct dinode *)buf + itoo(ip->i_number, &sblock))->di_ic = ip->i_ic; 810*5324Smckusic wtfs(fsbtodb(&sblock, d), sblock.fs_bsize, buf); 8114234Smckusick } 812*5324Smckusic 813*5324Smckusic /* 814*5324Smckusic * block operations 815*5324Smckusic */ 816*5324Smckusic 817*5324Smckusic isblock(fs, cp, h) 818*5324Smckusic struct fs *fs; 819*5324Smckusic unsigned char *cp; 820*5324Smckusic int h; 821*5324Smckusic { 822*5324Smckusic unsigned char mask; 823*5324Smckusic 824*5324Smckusic switch (fs->fs_frag) { 825*5324Smckusic case 8: 826*5324Smckusic return (cp[h] == 0xff); 827*5324Smckusic case 4: 828*5324Smckusic mask = 0x0f << ((h & 0x1) << 2); 829*5324Smckusic return ((cp[h >> 1] & mask) == mask); 830*5324Smckusic case 2: 831*5324Smckusic mask = 0x03 << ((h & 0x3) << 1); 832*5324Smckusic return ((cp[h >> 2] & mask) == mask); 833*5324Smckusic case 1: 834*5324Smckusic mask = 0x01 << (h & 0x7); 835*5324Smckusic return ((cp[h >> 3] & mask) == mask); 836*5324Smckusic default: 837*5324Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 838*5324Smckusic return; 839*5324Smckusic } 840*5324Smckusic } 841*5324Smckusic 842*5324Smckusic clrblock(fs, cp, h) 843*5324Smckusic struct fs *fs; 844*5324Smckusic unsigned char *cp; 845*5324Smckusic int h; 846*5324Smckusic { 847*5324Smckusic switch ((fs)->fs_frag) { 848*5324Smckusic case 8: 849*5324Smckusic cp[h] = 0; 850*5324Smckusic return; 851*5324Smckusic case 4: 852*5324Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 853*5324Smckusic return; 854*5324Smckusic case 2: 855*5324Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 856*5324Smckusic return; 857*5324Smckusic case 1: 858*5324Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 859*5324Smckusic return; 860*5324Smckusic default: 861*5324Smckusic fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 862*5324Smckusic return; 863*5324Smckusic } 864*5324Smckusic } 865*5324Smckusic 866*5324Smckusic setblock(fs, cp, h) 867*5324Smckusic struct fs *fs; 868*5324Smckusic unsigned char *cp; 869*5324Smckusic int h; 870*5324Smckusic { 871*5324Smckusic switch (fs->fs_frag) { 872*5324Smckusic case 8: 873*5324Smckusic cp[h] = 0xff; 874*5324Smckusic return; 875*5324Smckusic case 4: 876*5324Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 877*5324Smckusic return; 878*5324Smckusic case 2: 879*5324Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 880*5324Smckusic return; 881*5324Smckusic case 1: 882*5324Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 883*5324Smckusic return; 884*5324Smckusic default: 885*5324Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 886*5324Smckusic return; 887*5324Smckusic } 888*5324Smckusic } 889