1*4788Smckusic static char *sccsid = "@(#)mkfs.c 1.9 (Berkeley) 11/07/81"; 24234Smckusick 34234Smckusick /* 44234Smckusick * make file system for cylinder-group style file systems 54234Smckusick * 64234Smckusick * usage: mkfs fs proto 74234Smckusick * or: mkfs size [ nsect ntrak cpg ] 84234Smckusick */ 94234Smckusick 104234Smckusick #define NDIRECT (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; 344234Smckusick char buf[BSIZE]; 354234Smckusick #ifndef STANDALONE 364234Smckusick struct exec head; 374234Smckusick #endif 384234Smckusick char string[50]; 394234Smckusick 404234Smckusick union { 414234Smckusick struct fs fs; 424234Smckusick char pad[BSIZE]; 434234Smckusick } fsun; 444234Smckusick #define sblock fsun.fs 454234Smckusick struct csum *fscs; 464234Smckusick 474234Smckusick union { 484234Smckusick struct cg cg; 494234Smckusick char pad[BSIZE]; 504234Smckusick } cgun; 514234Smckusick #define acg cgun.cg 524234Smckusick 534234Smckusick #define howmany(x, y) (((x)+((y)-1))/(y)) 544234Smckusick #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 554234Smckusick 564234Smckusick char *fsys; 574234Smckusick char *proto; 584234Smckusick int error; 594234Smckusick ino_t ino = ROOTINO - 1; 604234Smckusick long getnum(); 614234Smckusick daddr_t alloc(); 624234Smckusick 634234Smckusick struct dinode zino[MAXIPG]; 644234Smckusick 654234Smckusick main(argc, argv) 664234Smckusick char *argv[]; 674234Smckusick { 684234Smckusick int f, c; 694234Smckusick long i,n; 704234Smckusick 714234Smckusick argc--, argv++; 724234Smckusick #ifndef STANDALONE 734234Smckusick time(&utime); 744234Smckusick if(argc < 2) { 754234Smckusick printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n"); 764234Smckusick exit(1); 774234Smckusick } 784234Smckusick fsys = argv[0]; 794234Smckusick proto = argv[1]; 804234Smckusick #else 814234Smckusick { 824234Smckusick static char protos[60]; 834234Smckusick 844234Smckusick printf("file sys size: "); 854234Smckusick gets(protos); 864234Smckusick proto = protos; 874234Smckusick } 884234Smckusick #endif 894234Smckusick #ifdef STANDALONE 904234Smckusick { 914234Smckusick char fsbuf[100]; 924234Smckusick 934234Smckusick do { 944234Smckusick printf("file system: "); 954234Smckusick gets(fsbuf); 964234Smckusick fso = open(fsbuf, 1); 974234Smckusick fsi = open(fsbuf, 0); 984234Smckusick } while (fso < 0 || fsi < 0); 994234Smckusick } 1004234Smckusick fin = NULL; 1014234Smckusick argc = 0; 1024234Smckusick #else 1034234Smckusick fso = creat(fsys, 0666); 1044234Smckusick if(fso < 0) { 1054234Smckusick printf("%s: cannot create\n", fsys); 1064234Smckusick exit(1); 1074234Smckusick } 1084234Smckusick fsi = open(fsys, 0); 1094234Smckusick if(fsi < 0) { 1104234Smckusick printf("%s: cannot open\n", fsys); 1114234Smckusick exit(1); 1124234Smckusick } 1134234Smckusick fin = fopen(proto, "r"); 1144234Smckusick #endif 1154234Smckusick #ifndef STANDALONE 1164234Smckusick if (fin != NULL) { 1174234Smckusick getstr(); 1184234Smckusick f = open(string, 0); 1194234Smckusick if (f < 0) { 1204234Smckusick printf("%s: cannot open init\n", string); 1214234Smckusick goto noinit; 1224234Smckusick } 1234234Smckusick read(f, (char *)&head, sizeof head); 1244234Smckusick c = head.a_text + head.a_data; 1254234Smckusick if (c > BSIZE) 1264234Smckusick printf("%s: too big\n", string); 1274234Smckusick else { 1284234Smckusick read(f, buf, c); 1294234Smckusick wtfs(BBLOCK, BSIZE, buf); 1304234Smckusick } 1314234Smckusick close(f); 1324234Smckusick noinit: 1334234Smckusick n = sblock.fs_size = getnum(); 1344234Smckusick sblock.fs_ntrak = getnum(); 1354234Smckusick sblock.fs_nsect = getnum(); 1364234Smckusick sblock.fs_cpg = getnum(); 1374234Smckusick } else 1384234Smckusick #endif 1394234Smckusick { 1404234Smckusick charp = "d--777 0 0 $ "; 1414234Smckusick n = 0; 1424234Smckusick for (f=0; c=proto[f]; f++) { 1434234Smckusick if (c<'0' || c>'9') { 1444234Smckusick printf("%s: cannot open\n", proto); 1454234Smckusick exit(1); 1464234Smckusick } 1474234Smckusick n = n*10 + (c-'0'); 1484234Smckusick } 1494234Smckusick sblock.fs_size = n; 1504234Smckusick if (argc > 2) 1514234Smckusick sblock.fs_nsect = atoi(argv[2]); 1524234Smckusick else 1534234Smckusick sblock.fs_nsect = 32; 1544234Smckusick if (argc > 3) 1554234Smckusick sblock.fs_ntrak = atoi(argv[3]); 1564234Smckusick else 1574234Smckusick sblock.fs_ntrak = 19; 1584234Smckusick } 1594234Smckusick /* 1604234Smckusick * Now have size for file system and nsect and ntrak. 1614234Smckusick * (And, if coming from prototype, cpg). 1624234Smckusick * Determine number of cylinders occupied by file system. 1634234Smckusick */ 1644234Smckusick if (sblock.fs_ntrak <= 0) 1654234Smckusick printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1664234Smckusick if (sblock.fs_nsect <= 0) 1674234Smckusick printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 1684234Smckusick if (sblock.fs_size <= 0) 1694234Smckusick printf("preposterous size %d\n", sblock.fs_size), exit(1); 1704234Smckusick if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) { 1714234Smckusick printf("cylinder too large (%d sectors)\n", 1724234Smckusick sblock.fs_ntrak * sblock.fs_nsect); 1734234Smckusick printf("maximum cylinder size: %d sectors\n", 1744234Smckusick MAXBPG * NSPB); 1754234Smckusick exit(1); 1764234Smckusick } 1774234Smckusick sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak); 1784234Smckusick if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { 1794234Smckusick printf("%d sector(s) in last cylinder unused\n", 1804234Smckusick n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); 1814234Smckusick sblock.fs_ncyl++; 1824234Smckusick } 1834234Smckusick sblock.fs_magic = FS_MAGIC; 1844234Smckusick /* 1854234Smckusick * Validate specified/determined cpg. 1864234Smckusick */ 1874234Smckusick #define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG) 1884234Smckusick if (argc > 4 || fin) { 1894234Smckusick if (fin == NULL) 1904234Smckusick sblock.fs_cpg = atoi(argv[4]); 1914234Smckusick if (CGTOOBIG(sblock)) { 1924234Smckusick printf("cylinder group too large (%d blocks); ", 1934234Smckusick sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB); 1944234Smckusick printf("max: %d blocks\n", MAXBPG); 1954234Smckusick exit(1); 1964234Smckusick } 1974234Smckusick if (sblock.fs_cpg > MAXCPG) { 1984234Smckusick printf("cylinder groups are limited to %d cylinders\n", 1994234Smckusick MAXCPG); 2004234Smckusick exit(1); 2014234Smckusick } 2024234Smckusick } else { 2034234Smckusick sblock.fs_cpg = DESCPG; 2044234Smckusick while (CGTOOBIG(sblock)) 2054234Smckusick --sblock.fs_cpg; 2064234Smckusick } 2074234Smckusick /* 2084234Smckusick * Compute/validate number of cylinder groups. 2094234Smckusick */ 2104234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2114234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2124234Smckusick sblock.fs_ncg++; 2134234Smckusick if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) { 2144234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2154234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2164234Smckusick printf("as this would would have cyl groups whose size\n"); 2174234Smckusick printf("is not a multiple of %d; choke!\n", FSIZE); 2184234Smckusick exit(1); 2194234Smckusick } 2204234Smckusick fscs = (struct csum *) 2214234Smckusick calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE)); 2224234Smckusick /* 2234234Smckusick * Compute number of inode blocks per cylinder group. 2244234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 2254234Smckusick */ 2264234Smckusick n = ((n * BSIZE) / NBPI) / INOPB; 2274234Smckusick if (n <= 0) 2284234Smckusick n = 1; 2294234Smckusick if (n > 65500/INOPB) 2304234Smckusick n = 65500/INOPB; 2314234Smckusick sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB; 2324234Smckusick if (sblock.fs_ipg < INOPB) 2334234Smckusick sblock.fs_ipg = INOPB; 2344234Smckusick if (sblock.fs_ipg > MAXIPG) 2354234Smckusick sblock.fs_ipg = MAXIPG; 2364234Smckusick while (sblock.fs_ipg * sblock.fs_ncyl > 65500) 2374234Smckusick sblock.fs_ipg -= INOPB; 2384234Smckusick sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 2394234Smckusick sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512); 2404234Smckusick if (cgdmin(0,&sblock) >= sblock.fs_fpg) 2414234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 2424234Smckusick cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1); 243*4788Smckusic sblock.fs_cstotal.cs_nifree = sblock.fs_ipg * sblock.fs_ncg; 2444234Smckusick sblock.fs_cgsize = cgsize(&sblock); 2454234Smckusick sblock.fs_cssize = cssize(&sblock); 2464234Smckusick sblock.fs_sblkno = SBLOCK; 2474234Smckusick sblock.fs_fmod = 0; 2484234Smckusick sblock.fs_ronly = 0; 2494234Smckusick 2504234Smckusick /* 2514234Smckusick * Dump out information about file system. 2524234Smckusick */ 2534234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 2544234Smckusick fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect); 2554234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 2564234Smckusick (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg, 2574234Smckusick (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg); 2584234Smckusick /* 2594234Smckusick printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG); 2604234Smckusick printf("%7d cylinder groups\n", sblock.fs_ncg); 2614234Smckusick printf("%7d cylinder group block size\n", sblock.fs_cgsize); 2624234Smckusick printf("%7d tracks\n", sblock.fs_ntrak); 2634234Smckusick printf("%7d sectors\n", sblock.fs_nsect); 2644234Smckusick printf("%7d sectors per cylinder\n", sblock.fs_spc); 2654234Smckusick printf("%7d cylinders\n", sblock.fs_ncyl); 2664234Smckusick printf("%7d cylinders per group\n", sblock.fs_cpg); 2674234Smckusick printf("%7d blocks per group\n", sblock.fs_fpg/FRAG); 2684234Smckusick printf("%7d inodes per group\n", sblock.fs_ipg); 2694234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) { 2704234Smckusick printf("%7d cylinders in last group\n", 2714234Smckusick i = sblock.fs_ncyl % sblock.fs_cpg); 2724234Smckusick printf("%7d blocks in last group\n", 2734234Smckusick i * sblock.fs_spc / NSPB); 2744234Smckusick } 2754234Smckusick */ 2764234Smckusick /* 2774234Smckusick * Now build the cylinders group blocks and 2784234Smckusick * then print out indices of cylinder groups forwarded 2794234Smckusick * past bad blocks or other obstructions. 2804234Smckusick */ 281*4788Smckusic sblock.fs_cstotal.cs_ndir = 0; 282*4788Smckusic sblock.fs_cstotal.cs_nbfree = 0; 283*4788Smckusic sblock.fs_cstotal.cs_nifree = 0; 284*4788Smckusic sblock.fs_cstotal.cs_nffree = 0; 2854652Smckusic sblock.fs_cgrotor = 0; 2864652Smckusic for (i = 0; i < NRPOS; i++) 2874652Smckusic sblock.fs_postbl[i] = -1; 2884652Smckusic for (i = 0; i < sblock.fs_spc; i += (NSPF * FRAG)) 2894652Smckusic /* void */; 2904652Smckusic for (i -= (NSPF * FRAG); i >= 0; i -= (NSPF * FRAG)) { 2914652Smckusic c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect; 2924652Smckusic sblock.fs_rotbl[i / (NSPF * FRAG)] = sblock.fs_postbl[c]; 2934652Smckusic sblock.fs_postbl[c] = i / (NSPF * FRAG); 2944652Smckusic } 2954234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 2964234Smckusick initcg(c); 2974234Smckusick printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 2984234Smckusick SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg, 2994234Smckusick SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg); 3004234Smckusick /* 3014234Smckusick * Now construct the initial file system, and 3024234Smckusick * then write out the super-block. 3034234Smckusick */ 3044234Smckusick cfile((struct inode *)0); 3054234Smckusick sblock.fs_time = utime; 3064234Smckusick wtfs(SBLOCK, BSIZE, (char *)&sblock); 3074234Smckusick for (i = 0; i < cssize(&sblock); i += BSIZE) 3084234Smckusick wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i); 3094234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 3104234Smckusick wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock); 3114234Smckusick #ifndef STANDALONE 3124234Smckusick exit(error); 3134234Smckusick #endif 3144234Smckusick } 3154234Smckusick 3164234Smckusick /* 3174234Smckusick * Initialize a cylinder group. 3184234Smckusick */ 3194234Smckusick initcg(c) 3204234Smckusick int c; 3214234Smckusick { 3224234Smckusick daddr_t cbase, d, dmin, dmax; 3234234Smckusick long i, j, s; 3244234Smckusick register struct csum *cs; 3254234Smckusick 3264234Smckusick /* 3274234Smckusick * Determine block bounds for cylinder group. 3284234Smckusick * Allow space for super block summary information in first 3294234Smckusick * cylinder group. 3304234Smckusick */ 3314234Smckusick cbase = cgbase(c,&sblock); 3324234Smckusick dmax = cbase + sblock.fs_fpg; 3334234Smckusick if (dmax > sblock.fs_size) 3344234Smckusick dmax = sblock.fs_size; 3354465Smckusic dmin = cgdmin(c,&sblock) - cbase; 3364234Smckusick d = cbase; 3374234Smckusick cs = fscs+c; 3384234Smckusick acg.cg_time = utime; 3394234Smckusick acg.cg_magic = CG_MAGIC; 3404234Smckusick acg.cg_cgx = c; 3414234Smckusick acg.cg_ncyl = sblock.fs_cpg; 3424234Smckusick acg.cg_niblk = sblock.fs_ipg; 3434234Smckusick acg.cg_ndblk = dmax - cbase; 344*4788Smckusic acg.cg_cs.cs_ndir = 0; 345*4788Smckusic acg.cg_cs.cs_nffree = 0; 346*4788Smckusic acg.cg_cs.cs_nbfree = 0; 347*4788Smckusic acg.cg_cs.cs_nifree = 0; 3484465Smckusic acg.cg_rotor = dmin; 3494465Smckusic acg.cg_frotor = dmin; 3504257Smckusic acg.cg_irotor = 0; 3514465Smckusic for (i = 0; i < FRAG; i++) { 3524465Smckusic acg.cg_frsum[i] = 0; 3534465Smckusic } 3544465Smckusic for (i = 0; i < sblock.fs_ipg; ) { 3554234Smckusick for (j = INOPB; j > 0; j--) { 3564234Smckusick clrbit(acg.cg_iused, i); 3574234Smckusick i++; 3584234Smckusick } 359*4788Smckusic acg.cg_cs.cs_nifree += INOPB; 3604234Smckusick } 3614234Smckusick while (i < MAXIPG) { 3624234Smckusick clrbit(acg.cg_iused, i); 3634234Smckusick i++; 3644234Smckusick } 3654234Smckusick lseek(fso, cgimin(c,&sblock)*FSIZE, 0); 3664234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 3674234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 3684234Smckusick printf("write error %D\n", tell(fso) / BSIZE); 3694234Smckusick for (i = 0; i < MAXCPG; i++) 3704234Smckusick for (j = 0; j < NRPOS; j++) 3714234Smckusick acg.cg_b[i][j] = 0; 3724234Smckusick if (c == 0) { 3734234Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 3744234Smckusick } 3754234Smckusick for (d = 0; d < dmin; d += FRAG) 3764234Smckusick clrblock(acg.cg_free, d/FRAG); 3774234Smckusick while ((d+FRAG) <= dmax - cbase) { 3784251Smckusic setblock(acg.cg_free, d/FRAG); 379*4788Smckusic acg.cg_cs.cs_nbfree++; 3804251Smckusic s = d * NSPF; 3814251Smckusic acg.cg_b[s/sblock.fs_spc] 3824251Smckusic [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 3834234Smckusick d += FRAG; 3844234Smckusick } 3854234Smckusick if (d < dmax - cbase) 3864251Smckusic for (; d < dmax - cbase; d++) { 3874251Smckusic setbit(acg.cg_free, d); 388*4788Smckusic acg.cg_cs.cs_nffree++; 3894251Smckusic } 3904234Smckusick for (; d < MAXBPG; d++) 3914234Smckusick clrbit(acg.cg_free, d); 392*4788Smckusic sblock.fs_dsize += acg.cg_ndblk - dmin; 393*4788Smckusic sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 394*4788Smckusic sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 395*4788Smckusic sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 396*4788Smckusic sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 397*4788Smckusic *cs = acg.cg_cs; 3984234Smckusick wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg); 3994234Smckusick } 4004234Smckusick 4014234Smckusick cfile(par) 4024234Smckusick struct inode *par; 4034234Smckusick { 4044234Smckusick struct inode in; 4054234Smckusick int dbc, ibc; 4064234Smckusick char db[BSIZE]; 4074234Smckusick daddr_t ib[NINDIR]; 4084234Smckusick int i, f, c; 4094234Smckusick 4104234Smckusick /* 4114234Smckusick * get mode, uid and gid 4124234Smckusick */ 4134234Smckusick 4144234Smckusick getstr(); 4154234Smckusick in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 4164234Smckusick in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 4174234Smckusick in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 4184234Smckusick for(i=3; i<6; i++) { 4194234Smckusick c = string[i]; 4204234Smckusick if(c<'0' || c>'7') { 4214234Smckusick printf("%c/%s: bad octal mode digit\n", c, string); 4224234Smckusick error = 1; 4234234Smckusick c = 0; 4244234Smckusick } 4254234Smckusick in.i_mode |= (c-'0')<<(15-3*i); 4264234Smckusick } 4274234Smckusick in.i_uid = getnum(); 4284234Smckusick in.i_gid = getnum(); 4294251Smckusic in.i_atime = utime; 4304251Smckusic in.i_mtime = utime; 4314251Smckusic in.i_ctime = utime; 4324234Smckusick 4334234Smckusick /* 4344234Smckusick * general initialization prior to 4354234Smckusick * switching on format 4364234Smckusick */ 4374234Smckusick 4384234Smckusick ino++; 4394234Smckusick in.i_number = ino; 4404234Smckusick for(i=0; i<BSIZE; i++) 4414234Smckusick db[i] = 0; 4424234Smckusick for(i=0; i<NINDIR; i++) 4434234Smckusick ib[i] = (daddr_t)0; 4444234Smckusick in.i_nlink = 1; 4454234Smckusick in.i_size = 0; 4464234Smckusick for(i=0; i<NDADDR; i++) 4474251Smckusic in.i_db[i] = (daddr_t)0; 4484234Smckusick for(i=0; i<NIADDR; i++) 4494251Smckusic in.i_ib[i] = (daddr_t)0; 4504234Smckusick if(par == (struct inode *)0) { 4514234Smckusick par = ∈ 4524234Smckusick in.i_nlink--; 4534234Smckusick } 4544234Smckusick dbc = 0; 4554234Smckusick ibc = 0; 4564234Smckusick switch(in.i_mode&IFMT) { 4574234Smckusick 4584234Smckusick case IFREG: 4594234Smckusick /* 4604234Smckusick * regular file 4614234Smckusick * contents is a file name 4624234Smckusick */ 4634234Smckusick 4644234Smckusick getstr(); 4654234Smckusick f = open(string, 0); 4664234Smckusick if(f < 0) { 4674234Smckusick printf("%s: cannot open\n", string); 4684234Smckusick error = 1; 4694234Smckusick break; 4704234Smckusick } 4714234Smckusick while((i=read(f, db, BSIZE)) > 0) { 4724234Smckusick in.i_size += i; 4734427Smckusic newblk(&dbc, db, &ibc, ib, ibc < NDADDR ? i : BSIZE, 0); 4744234Smckusick } 4754234Smckusick close(f); 4764234Smckusick break; 4774234Smckusick 4784234Smckusick case IFBLK: 4794234Smckusick case IFCHR: 4804234Smckusick /* 4814234Smckusick * special file 4824234Smckusick * content is maj/min types 4834234Smckusick */ 4844234Smckusick 4854234Smckusick i = getnum() & 0377; 4864234Smckusick f = getnum() & 0377; 4874251Smckusic in.i_rdev = makedev(i, f); 4884234Smckusick break; 4894234Smckusick 4904234Smckusick case IFDIR: 4914234Smckusick /* 4924234Smckusick * directory 4934234Smckusick * put in extra links 4944234Smckusick * call recursively until 4954234Smckusick * name of "$" found 4964234Smckusick */ 4974234Smckusick 4984234Smckusick par->i_nlink++; 4994234Smckusick in.i_nlink++; 5004234Smckusick entry(in.i_number, ".", &dbc, db, &ibc, ib); 5014234Smckusick entry(par->i_number, "..", &dbc, db, &ibc, ib); 5024234Smckusick in.i_size = 2*sizeof(struct direct); 5034234Smckusick for(;;) { 5044234Smckusick getstr(); 5054234Smckusick if(string[0]=='$' && string[1]=='\0') 5064234Smckusick break; 5074427Smckusic if (in.i_size >= BSIZE * NDADDR) { 5084234Smckusick printf("can't handle direct of > %d entries\n", 5094427Smckusic NDIRECT * NDADDR); 5104234Smckusick exit(1); 5114234Smckusick } 5124234Smckusick entry(ino+1, string, &dbc, db, &ibc, ib); 5134234Smckusick in.i_size += sizeof(struct direct); 5144234Smckusick cfile(&in); 5154234Smckusick } 5164427Smckusic newblk(&dbc, db, &ibc, ib, roundup(dbc, FSIZE), IFDIR); 5174234Smckusick break; 5184234Smckusick } 5194234Smckusick iput(&in, &ibc, ib); 5204234Smckusick } 5214234Smckusick 5224234Smckusick gmode(c, s, m0, m1, m2, m3) 5234234Smckusick char c, *s; 5244234Smckusick { 5254234Smckusick int i; 5264234Smckusick 5274234Smckusick for(i=0; s[i]; i++) 5284234Smckusick if(c == s[i]) 5294234Smckusick return((&m0)[i]); 5304234Smckusick printf("%c/%s: bad mode\n", c, string); 5314234Smckusick error = 1; 5324234Smckusick return(0); 5334234Smckusick } 5344234Smckusick 5354234Smckusick long 5364234Smckusick getnum() 5374234Smckusick { 5384234Smckusick int i, c; 5394234Smckusick long n; 5404234Smckusick 5414234Smckusick getstr(); 5424234Smckusick n = 0; 5434234Smckusick i = 0; 5444234Smckusick for(i=0; c=string[i]; i++) { 5454234Smckusick if(c<'0' || c>'9') { 5464234Smckusick printf("%s: bad number\n", string); 5474234Smckusick error = 1; 5484234Smckusick return((long)0); 5494234Smckusick } 5504234Smckusick n = n*10 + (c-'0'); 5514234Smckusick } 5524234Smckusick return(n); 5534234Smckusick } 5544234Smckusick 5554234Smckusick getstr() 5564234Smckusick { 5574234Smckusick int i, c; 5584234Smckusick 5594234Smckusick loop: 5604234Smckusick switch(c=getch()) { 5614234Smckusick 5624234Smckusick case ' ': 5634234Smckusick case '\t': 5644234Smckusick case '\n': 5654234Smckusick goto loop; 5664234Smckusick 5674234Smckusick case '\0': 5684234Smckusick printf("EOF\n"); 5694234Smckusick exit(1); 5704234Smckusick 5714234Smckusick case ':': 5724234Smckusick while(getch() != '\n'); 5734234Smckusick goto loop; 5744234Smckusick 5754234Smckusick } 5764234Smckusick i = 0; 5774234Smckusick 5784234Smckusick do { 5794234Smckusick string[i++] = c; 5804234Smckusick c = getch(); 5814234Smckusick } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 5824234Smckusick string[i] = '\0'; 5834234Smckusick } 5844234Smckusick 5854234Smckusick rdfs(bno, size, bf) 5864234Smckusick daddr_t bno; 5874234Smckusick int size; 5884234Smckusick char *bf; 5894234Smckusick { 5904234Smckusick int n; 5914234Smckusick 5924234Smckusick lseek(fsi, bno*FSIZE, 0); 5934234Smckusick n = read(fsi, bf, size); 5944234Smckusick if(n != size) { 5954234Smckusick printf("read error: %ld\n", bno); 5964234Smckusick exit(1); 5974234Smckusick } 5984234Smckusick } 5994234Smckusick 6004234Smckusick wtfs(bno, size, bf) 6014234Smckusick daddr_t bno; 6024234Smckusick int size; 6034234Smckusick char *bf; 6044234Smckusick { 6054234Smckusick int n; 6064234Smckusick 6074234Smckusick lseek(fso, bno*FSIZE, 0); 6084234Smckusick n = write(fso, bf, size); 6094234Smckusick if(n != size) { 6104234Smckusick printf("write error: %D\n", bno); 6114234Smckusick exit(1); 6124234Smckusick } 6134234Smckusick } 6144234Smckusick 6154234Smckusick daddr_t 6164427Smckusic alloc(size, mode) 6174427Smckusic int size; 6184427Smckusic int mode; 6194234Smckusick { 6204234Smckusick int c, i, s, frag; 6214234Smckusick daddr_t d; 6224234Smckusick 6234234Smckusick c = 0; 6244234Smckusick rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 625*4788Smckusic if (acg.cg_cs.cs_nbfree == 0) { 6264234Smckusick printf("first cylinder group ran out of space\n"); 6274234Smckusick return (0); 6284234Smckusick } 6294234Smckusick for (d = 0; d < acg.cg_ndblk; d += FRAG) 6304234Smckusick if (isblock(acg.cg_free, d/FRAG)) 6314234Smckusick goto goth; 6324234Smckusick printf("internal error: can't find block in cyl 0\n"); 6334234Smckusick return (0); 6344234Smckusick goth: 6354234Smckusick clrblock(acg.cg_free, d/FRAG); 636*4788Smckusic acg.cg_cs.cs_nbfree--; 637*4788Smckusic sblock.fs_cstotal.cs_nbfree--; 6384234Smckusick fscs[0].cs_nbfree--; 6394427Smckusic if (mode & IFDIR) { 640*4788Smckusic acg.cg_cs.cs_ndir++; 641*4788Smckusic sblock.fs_cstotal.cs_ndir++; 6424427Smckusic fscs[0].cs_ndir++; 6434427Smckusic } 6444234Smckusick s = d * NSPF; 6454234Smckusick acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--; 6464234Smckusick if (size != BSIZE) { 6474234Smckusick frag = howmany(size, FSIZE); 648*4788Smckusic fscs[0].cs_nffree += FRAG - frag; 649*4788Smckusic sblock.fs_cstotal.cs_nffree += FRAG - frag; 650*4788Smckusic acg.cg_cs.cs_nffree += FRAG - frag; 6514465Smckusic acg.cg_frsum[FRAG - frag]++; 6524234Smckusick for (i = frag; i < FRAG; i++) 6534234Smckusick setbit(acg.cg_free, d+i); 6544234Smckusick } 6554234Smckusick wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 6564234Smckusick return (d); 6574234Smckusick } 6584234Smckusick 6594234Smckusick entry(inum, str, adbc, db, aibc, ib) 6604234Smckusick ino_t inum; 6614234Smckusick char *str; 6624234Smckusick int *adbc, *aibc; 6634234Smckusick char *db; 6644234Smckusick daddr_t *ib; 6654234Smckusick { 6664234Smckusick struct direct *dp; 6674234Smckusick int i; 6684234Smckusick 6694427Smckusic if (*adbc == NDIRECT) 6704427Smckusic newblk(adbc, db, aibc, ib, BSIZE, 0); 6714234Smckusick dp = (struct direct *)db; 6724234Smckusick dp += *adbc; 6734234Smckusick (*adbc)++; 6744234Smckusick dp->d_ino = inum; 6754234Smckusick for(i=0; i<DIRSIZ; i++) 6764234Smckusick dp->d_name[i] = 0; 6774234Smckusick for(i=0; i<DIRSIZ; i++) 6784234Smckusick if((dp->d_name[i] = str[i]) == 0) 6794234Smckusick break; 6804234Smckusick } 6814234Smckusick 6824427Smckusic newblk(adbc, db, aibc, ib, size, mode) 6834427Smckusic int *adbc, *aibc; 6844427Smckusic char *db; 6854427Smckusic daddr_t *ib; 6864427Smckusic int size; 6874427Smckusic int mode; 6884234Smckusick { 6894234Smckusick int i; 6904234Smckusick daddr_t bno; 6914234Smckusick 6924427Smckusic bno = alloc(size, mode); 6934234Smckusick wtfs(bno, size, db); 6944234Smckusick for(i=0; i<size; i++) 6954234Smckusick db[i] = 0; 6964234Smckusick *adbc = 0; 6974234Smckusick ib[*aibc] = bno; 6984234Smckusick (*aibc)++; 6994234Smckusick if(*aibc >= NINDIR) { 7004234Smckusick printf("indirect block full\n"); 7014234Smckusick error = 1; 7024234Smckusick *aibc = 0; 7034234Smckusick } 7044234Smckusick } 7054234Smckusick 7064234Smckusick getch() 7074234Smckusick { 7084234Smckusick 7094234Smckusick #ifndef STANDALONE 7104234Smckusick if(charp) 7114234Smckusick #endif 7124234Smckusick return(*charp++); 7134234Smckusick #ifndef STANDALONE 7144234Smckusick return(getc(fin)); 7154234Smckusick #endif 7164234Smckusick } 7174234Smckusick 7184234Smckusick iput(ip, aibc, ib) 7194234Smckusick struct inode *ip; 7204234Smckusick int *aibc; 7214234Smckusick daddr_t *ib; 7224234Smckusick { 7234234Smckusick struct dinode *dp; 7244234Smckusick daddr_t d; 7254234Smckusick int i, c = ip->i_number / sblock.fs_ipg; 7264234Smckusick 7274234Smckusick rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 728*4788Smckusic acg.cg_cs.cs_nifree--; 7294234Smckusick setbit(acg.cg_iused, ip->i_number); 7304234Smckusick wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 731*4788Smckusic sblock.fs_cstotal.cs_nifree--; 7324234Smckusick fscs[0].cs_nifree--; 7334234Smckusick if(ip->i_number >= sblock.fs_ipg) { 7344234Smckusick printf("mkfs: cant handle more than one cg of inodes (yet)\n"); 7354234Smckusick exit(1); 7364234Smckusick } 7374234Smckusick if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 7384234Smckusick if(error == 0) 7394234Smckusick printf("ilist too small\n"); 7404234Smckusick error = 1; 7414234Smckusick return; 7424234Smckusick } 7434234Smckusick d = itod(ip->i_number,&sblock); 7444234Smckusick rdfs(d, BSIZE, buf); 7454251Smckusic for(i=0; i<*aibc; i++) { 7464251Smckusic if(i >= NDADDR) 7474251Smckusic break; 7484251Smckusic ip->i_db[i] = ib[i]; 7494251Smckusic } 7504251Smckusic if(*aibc >= NDADDR) { 7514427Smckusic ip->i_ib[0] = alloc(BSIZE, 0); 7524251Smckusic for(i=0; i<NINDIR-NDADDR; i++) { 7534251Smckusic ib[i] = ib[i+NDADDR]; 7544251Smckusic ib[i+NDADDR] = (daddr_t)0; 7554234Smckusick } 7564251Smckusic wtfs(ip->i_ib[0], (char *)ib); 7574234Smckusick } 7584251Smckusic ((struct dinode *)buf+itoo(ip->i_number))->di_ic = ip->i_ic; 7594234Smckusick wtfs(d, BSIZE, buf); 7604234Smckusick } 761