1*4251Smckusic static char *sccsid = "@(#)mkfs.c 1.2 (Berkeley) 08/28/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 #define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) 144234Smckusick #define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) 154234Smckusick #define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) 164234Smckusick 174234Smckusick #ifndef STANDALONE 184234Smckusick #include <stdio.h> 194234Smckusick #include <a.out.h> 204234Smckusick #endif 214234Smckusick 224234Smckusick #include "../h/param.h" 234234Smckusick #include "../h/inode.h" 244234Smckusick #include "../h/fs.h" 254234Smckusick #include "../h/dir.h" 264234Smckusick 274234Smckusick time_t utime; 284234Smckusick 294234Smckusick #ifndef STANDALONE 304234Smckusick FILE *fin; 314234Smckusick #else 324234Smckusick int fin; 334234Smckusick #endif 344234Smckusick 354234Smckusick int fsi; 364234Smckusick int fso; 374234Smckusick char *charp; 384234Smckusick char buf[BSIZE]; 394234Smckusick #ifndef STANDALONE 404234Smckusick struct exec head; 414234Smckusick #endif 424234Smckusick char string[50]; 434234Smckusick 444234Smckusick union { 454234Smckusick struct fs fs; 464234Smckusick char pad[BSIZE]; 474234Smckusick } fsun; 484234Smckusick #define sblock fsun.fs 494234Smckusick struct csum *fscs; 504234Smckusick 514234Smckusick union { 524234Smckusick struct cg cg; 534234Smckusick char pad[BSIZE]; 544234Smckusick } cgun; 554234Smckusick #define acg cgun.cg 564234Smckusick 574234Smckusick #define howmany(x, y) (((x)+((y)-1))/(y)) 584234Smckusick #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 594234Smckusick 604234Smckusick char *fsys; 614234Smckusick char *proto; 624234Smckusick int error; 634234Smckusick ino_t ino = ROOTINO - 1; 644234Smckusick long getnum(); 654234Smckusick daddr_t alloc(); 664234Smckusick 674234Smckusick struct dinode zino[MAXIPG]; 684234Smckusick 694234Smckusick main(argc, argv) 704234Smckusick char *argv[]; 714234Smckusick { 724234Smckusick int f, c; 734234Smckusick long i,n; 744234Smckusick 754234Smckusick argc--, argv++; 764234Smckusick #ifndef STANDALONE 774234Smckusick time(&utime); 784234Smckusick if(argc < 2) { 794234Smckusick printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n"); 804234Smckusick exit(1); 814234Smckusick } 824234Smckusick fsys = argv[0]; 834234Smckusick proto = argv[1]; 844234Smckusick #else 854234Smckusick { 864234Smckusick static char protos[60]; 874234Smckusick 884234Smckusick printf("file sys size: "); 894234Smckusick gets(protos); 904234Smckusick proto = protos; 914234Smckusick } 924234Smckusick #endif 934234Smckusick #ifdef STANDALONE 944234Smckusick { 954234Smckusick char fsbuf[100]; 964234Smckusick 974234Smckusick do { 984234Smckusick printf("file system: "); 994234Smckusick gets(fsbuf); 1004234Smckusick fso = open(fsbuf, 1); 1014234Smckusick fsi = open(fsbuf, 0); 1024234Smckusick } while (fso < 0 || fsi < 0); 1034234Smckusick } 1044234Smckusick fin = NULL; 1054234Smckusick argc = 0; 1064234Smckusick #else 1074234Smckusick fso = creat(fsys, 0666); 1084234Smckusick if(fso < 0) { 1094234Smckusick printf("%s: cannot create\n", fsys); 1104234Smckusick exit(1); 1114234Smckusick } 1124234Smckusick fsi = open(fsys, 0); 1134234Smckusick if(fsi < 0) { 1144234Smckusick printf("%s: cannot open\n", fsys); 1154234Smckusick exit(1); 1164234Smckusick } 1174234Smckusick fin = fopen(proto, "r"); 1184234Smckusick #endif 1194234Smckusick #ifndef STANDALONE 1204234Smckusick if (fin != NULL) { 1214234Smckusick getstr(); 1224234Smckusick f = open(string, 0); 1234234Smckusick if (f < 0) { 1244234Smckusick printf("%s: cannot open init\n", string); 1254234Smckusick goto noinit; 1264234Smckusick } 1274234Smckusick read(f, (char *)&head, sizeof head); 1284234Smckusick c = head.a_text + head.a_data; 1294234Smckusick if (c > BSIZE) 1304234Smckusick printf("%s: too big\n", string); 1314234Smckusick else { 1324234Smckusick read(f, buf, c); 1334234Smckusick wtfs(BBLOCK, BSIZE, buf); 1344234Smckusick } 1354234Smckusick close(f); 1364234Smckusick noinit: 1374234Smckusick n = sblock.fs_size = getnum(); 1384234Smckusick sblock.fs_ntrak = getnum(); 1394234Smckusick sblock.fs_nsect = getnum(); 1404234Smckusick sblock.fs_cpg = getnum(); 1414234Smckusick } else 1424234Smckusick #endif 1434234Smckusick { 1444234Smckusick charp = "d--777 0 0 $ "; 1454234Smckusick n = 0; 1464234Smckusick for (f=0; c=proto[f]; f++) { 1474234Smckusick if (c<'0' || c>'9') { 1484234Smckusick printf("%s: cannot open\n", proto); 1494234Smckusick exit(1); 1504234Smckusick } 1514234Smckusick n = n*10 + (c-'0'); 1524234Smckusick } 1534234Smckusick sblock.fs_size = n; 1544234Smckusick if (argc > 2) 1554234Smckusick sblock.fs_nsect = atoi(argv[2]); 1564234Smckusick else 1574234Smckusick sblock.fs_nsect = 32; 1584234Smckusick if (argc > 3) 1594234Smckusick sblock.fs_ntrak = atoi(argv[3]); 1604234Smckusick else 1614234Smckusick sblock.fs_ntrak = 19; 1624234Smckusick } 1634234Smckusick /* 1644234Smckusick * Now have size for file system and nsect and ntrak. 1654234Smckusick * (And, if coming from prototype, cpg). 1664234Smckusick * Determine number of cylinders occupied by file system. 1674234Smckusick */ 1684234Smckusick if (sblock.fs_ntrak <= 0) 1694234Smckusick printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1704234Smckusick if (sblock.fs_nsect <= 0) 1714234Smckusick printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 1724234Smckusick if (sblock.fs_size <= 0) 1734234Smckusick printf("preposterous size %d\n", sblock.fs_size), exit(1); 1744234Smckusick if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) { 1754234Smckusick printf("cylinder too large (%d sectors)\n", 1764234Smckusick sblock.fs_ntrak * sblock.fs_nsect); 1774234Smckusick printf("maximum cylinder size: %d sectors\n", 1784234Smckusick MAXBPG * NSPB); 1794234Smckusick exit(1); 1804234Smckusick } 1814234Smckusick sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak); 1824234Smckusick if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { 1834234Smckusick printf("%d sector(s) in last cylinder unused\n", 1844234Smckusick n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); 1854234Smckusick sblock.fs_ncyl++; 1864234Smckusick } 1874234Smckusick sblock.fs_magic = FS_MAGIC; 1884234Smckusick /* 1894234Smckusick * Validate specified/determined cpg. 1904234Smckusick */ 1914234Smckusick #define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG) 1924234Smckusick if (argc > 4 || fin) { 1934234Smckusick if (fin == NULL) 1944234Smckusick sblock.fs_cpg = atoi(argv[4]); 1954234Smckusick if (CGTOOBIG(sblock)) { 1964234Smckusick printf("cylinder group too large (%d blocks); ", 1974234Smckusick sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB); 1984234Smckusick printf("max: %d blocks\n", MAXBPG); 1994234Smckusick exit(1); 2004234Smckusick } 2014234Smckusick if (sblock.fs_cpg > MAXCPG) { 2024234Smckusick printf("cylinder groups are limited to %d cylinders\n", 2034234Smckusick MAXCPG); 2044234Smckusick exit(1); 2054234Smckusick } 2064234Smckusick } else { 2074234Smckusick sblock.fs_cpg = DESCPG; 2084234Smckusick while (CGTOOBIG(sblock)) 2094234Smckusick --sblock.fs_cpg; 2104234Smckusick } 2114234Smckusick /* 2124234Smckusick * Compute/validate number of cylinder groups. 2134234Smckusick */ 2144234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2154234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2164234Smckusick sblock.fs_ncg++; 2174234Smckusick if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) { 2184234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2194234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2204234Smckusick printf("as this would would have cyl groups whose size\n"); 2214234Smckusick printf("is not a multiple of %d; choke!\n", FSIZE); 2224234Smckusick exit(1); 2234234Smckusick } 2244234Smckusick fscs = (struct csum *) 2254234Smckusick calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE)); 2264234Smckusick /* 2274234Smckusick * Compute number of inode blocks per cylinder group. 2284234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 2294234Smckusick */ 2304234Smckusick n = ((n * BSIZE) / NBPI) / INOPB; 2314234Smckusick if (n <= 0) 2324234Smckusick n = 1; 2334234Smckusick if (n > 65500/INOPB) 2344234Smckusick n = 65500/INOPB; 2354234Smckusick sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB; 2364234Smckusick if (sblock.fs_ipg < INOPB) 2374234Smckusick sblock.fs_ipg = INOPB; 2384234Smckusick if (sblock.fs_ipg > MAXIPG) 2394234Smckusick sblock.fs_ipg = MAXIPG; 2404234Smckusick while (sblock.fs_ipg * sblock.fs_ncyl > 65500) 2414234Smckusick sblock.fs_ipg -= INOPB; 2424234Smckusick sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 2434234Smckusick sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512); 2444234Smckusick if (cgdmin(0,&sblock) >= sblock.fs_fpg) 2454234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 2464234Smckusick cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1); 2474234Smckusick sblock.fs_nifree = sblock.fs_ipg * sblock.fs_ncg; 2484234Smckusick sblock.fs_cgsize = cgsize(&sblock); 2494234Smckusick sblock.fs_cssize = cssize(&sblock); 2504234Smckusick sblock.fs_sblkno = SBLOCK; 2514234Smckusick sblock.fs_fmod = 0; 2524234Smckusick sblock.fs_ronly = 0; 2534234Smckusick 2544234Smckusick /* 2554234Smckusick * Dump out information about file system. 2564234Smckusick */ 2574234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 2584234Smckusick fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect); 2594234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 2604234Smckusick (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg, 2614234Smckusick (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg); 2624234Smckusick /* 2634234Smckusick printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG); 2644234Smckusick printf("%7d cylinder groups\n", sblock.fs_ncg); 2654234Smckusick printf("%7d cylinder group block size\n", sblock.fs_cgsize); 2664234Smckusick printf("%7d tracks\n", sblock.fs_ntrak); 2674234Smckusick printf("%7d sectors\n", sblock.fs_nsect); 2684234Smckusick printf("%7d sectors per cylinder\n", sblock.fs_spc); 2694234Smckusick printf("%7d cylinders\n", sblock.fs_ncyl); 2704234Smckusick printf("%7d cylinders per group\n", sblock.fs_cpg); 2714234Smckusick printf("%7d blocks per group\n", sblock.fs_fpg/FRAG); 2724234Smckusick printf("%7d inodes per group\n", sblock.fs_ipg); 2734234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) { 2744234Smckusick printf("%7d cylinders in last group\n", 2754234Smckusick i = sblock.fs_ncyl % sblock.fs_cpg); 2764234Smckusick printf("%7d blocks in last group\n", 2774234Smckusick i * sblock.fs_spc / NSPB); 2784234Smckusick } 2794234Smckusick */ 2804234Smckusick /* 2814234Smckusick * Now build the cylinders group blocks and 2824234Smckusick * then print out indices of cylinder groups forwarded 2834234Smckusick * past bad blocks or other obstructions. 2844234Smckusick */ 2854234Smckusick sblock.fs_nffree = 0; 2864234Smckusick sblock.fs_nbfree = 0; 2874234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 2884234Smckusick initcg(c); 2894234Smckusick printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 2904234Smckusick SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg, 2914234Smckusick SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg); 2924234Smckusick /* 2934234Smckusick * Now construct the initial file system, and 2944234Smckusick * then write out the super-block. 2954234Smckusick */ 2964234Smckusick cfile((struct inode *)0); 2974234Smckusick sblock.fs_time = utime; 2984234Smckusick wtfs(SBLOCK, BSIZE, (char *)&sblock); 2994234Smckusick for (i = 0; i < cssize(&sblock); i += BSIZE) 3004234Smckusick wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i); 3014234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 3024234Smckusick wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock); 3034234Smckusick #ifndef STANDALONE 3044234Smckusick exit(error); 3054234Smckusick #endif 3064234Smckusick } 3074234Smckusick 3084234Smckusick /* 3094234Smckusick * Initialize a cylinder group. 3104234Smckusick */ 3114234Smckusick initcg(c) 3124234Smckusick int c; 3134234Smckusick { 3144234Smckusick daddr_t cbase, d, dmin, dmax; 3154234Smckusick long i, j, s; 3164234Smckusick register struct csum *cs; 3174234Smckusick 3184234Smckusick /* 3194234Smckusick * Determine block bounds for cylinder group. 3204234Smckusick * Allow space for super block summary information in first 3214234Smckusick * cylinder group. 3224234Smckusick */ 3234234Smckusick cbase = cgbase(c,&sblock); 3244234Smckusick dmax = cbase + sblock.fs_fpg; 3254234Smckusick if (dmax > sblock.fs_size) 3264234Smckusick dmax = sblock.fs_size; 3274234Smckusick d = cbase; 3284234Smckusick cs = fscs+c; 3294234Smckusick cs->cs_ndir = 0; 3304234Smckusick acg.cg_time = utime; 3314234Smckusick acg.cg_magic = CG_MAGIC; 3324234Smckusick acg.cg_cgx = c; 3334234Smckusick acg.cg_ncyl = sblock.fs_cpg; 3344234Smckusick acg.cg_niblk = sblock.fs_ipg; 3354234Smckusick acg.cg_ndblk = dmax - cbase; 3364234Smckusick acg.cg_ndir = 0; 3374234Smckusick acg.cg_nffree = 0; 3384234Smckusick acg.cg_nbfree = 0; 3394234Smckusick acg.cg_nifree = 0; 3404234Smckusick acg.cg_rotor = 0; 3414234Smckusick i = 0; 3424234Smckusick d = cgimin(c,&sblock); 3434234Smckusick while (i < sblock.fs_ipg) { 3444234Smckusick for (j = INOPB; j > 0; j--) { 3454234Smckusick clrbit(acg.cg_iused, i); 3464234Smckusick i++; 3474234Smckusick } 3484234Smckusick acg.cg_nifree += INOPB; 3494234Smckusick d++; 3504234Smckusick } 3514234Smckusick while (i < MAXIPG) { 3524234Smckusick clrbit(acg.cg_iused, i); 3534234Smckusick i++; 3544234Smckusick } 3554234Smckusick lseek(fso, cgimin(c,&sblock)*FSIZE, 0); 3564234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 3574234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 3584234Smckusick printf("write error %D\n", tell(fso) / BSIZE); 3594234Smckusick for (i = 0; i < MAXCPG; i++) 3604234Smckusick for (j = 0; j < NRPOS; j++) 3614234Smckusick acg.cg_b[i][j] = 0; 3624234Smckusick dmin = cgdmin(c,&sblock) - cbase; 3634234Smckusick if (c == 0) { 3644234Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 3654234Smckusick } 3664234Smckusick for (d = 0; d < dmin; d += FRAG) 3674234Smckusick clrblock(acg.cg_free, d/FRAG); 3684234Smckusick while ((d+FRAG) <= dmax - cbase) { 369*4251Smckusic setblock(acg.cg_free, d/FRAG); 370*4251Smckusic acg.cg_nbfree++; 371*4251Smckusic s = d * NSPF; 372*4251Smckusic acg.cg_b[s/sblock.fs_spc] 373*4251Smckusic [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 3744234Smckusick d += FRAG; 3754234Smckusick } 3764234Smckusick if (d < dmax - cbase) 377*4251Smckusic for (; d < dmax - cbase; d++) { 378*4251Smckusic setbit(acg.cg_free, d); 379*4251Smckusic acg.cg_nffree++; 380*4251Smckusic } 3814234Smckusick for (; d < MAXBPG; d++) 3824234Smckusick clrbit(acg.cg_free, d); 3834234Smckusick sblock.fs_nffree += acg.cg_nffree; 3844234Smckusick sblock.fs_nbfree += acg.cg_nbfree; 3854234Smckusick cs->cs_nifree = acg.cg_nifree; 3864234Smckusick cs->cs_nbfree = acg.cg_nbfree; 3874234Smckusick wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg); 3884234Smckusick } 3894234Smckusick 3904234Smckusick cfile(par) 3914234Smckusick struct inode *par; 3924234Smckusick { 3934234Smckusick struct inode in; 3944234Smckusick int dbc, ibc; 3954234Smckusick char db[BSIZE]; 3964234Smckusick daddr_t ib[NINDIR]; 3974234Smckusick int i, f, c; 3984234Smckusick 3994234Smckusick /* 4004234Smckusick * get mode, uid and gid 4014234Smckusick */ 4024234Smckusick 4034234Smckusick getstr(); 4044234Smckusick in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 4054234Smckusick in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 4064234Smckusick in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 4074234Smckusick for(i=3; i<6; i++) { 4084234Smckusick c = string[i]; 4094234Smckusick if(c<'0' || c>'7') { 4104234Smckusick printf("%c/%s: bad octal mode digit\n", c, string); 4114234Smckusick error = 1; 4124234Smckusick c = 0; 4134234Smckusick } 4144234Smckusick in.i_mode |= (c-'0')<<(15-3*i); 4154234Smckusick } 4164234Smckusick in.i_uid = getnum(); 4174234Smckusick in.i_gid = getnum(); 418*4251Smckusic in.i_atime = utime; 419*4251Smckusic in.i_mtime = utime; 420*4251Smckusic in.i_ctime = utime; 4214234Smckusick 4224234Smckusick /* 4234234Smckusick * general initialization prior to 4244234Smckusick * switching on format 4254234Smckusick */ 4264234Smckusick 4274234Smckusick ino++; 4284234Smckusick in.i_number = ino; 4294234Smckusick for(i=0; i<BSIZE; i++) 4304234Smckusick db[i] = 0; 4314234Smckusick for(i=0; i<NINDIR; i++) 4324234Smckusick ib[i] = (daddr_t)0; 4334234Smckusick in.i_nlink = 1; 4344234Smckusick in.i_size = 0; 4354234Smckusick for(i=0; i<NDADDR; i++) 436*4251Smckusic in.i_db[i] = (daddr_t)0; 4374234Smckusick for(i=0; i<NIADDR; i++) 438*4251Smckusic in.i_ib[i] = (daddr_t)0; 4394234Smckusick if(par == (struct inode *)0) { 4404234Smckusick par = ∈ 4414234Smckusick in.i_nlink--; 4424234Smckusick } 4434234Smckusick dbc = 0; 4444234Smckusick ibc = 0; 4454234Smckusick switch(in.i_mode&IFMT) { 4464234Smckusick 4474234Smckusick case IFREG: 4484234Smckusick /* 4494234Smckusick * regular file 4504234Smckusick * contents is a file name 4514234Smckusick */ 4524234Smckusick 4534234Smckusick getstr(); 4544234Smckusick f = open(string, 0); 4554234Smckusick if(f < 0) { 4564234Smckusick printf("%s: cannot open\n", string); 4574234Smckusick error = 1; 4584234Smckusick break; 4594234Smckusick } 4604234Smckusick while((i=read(f, db, BSIZE)) > 0) { 4614234Smckusick in.i_size += i; 4624234Smckusick newblk(&dbc, db, &ibc, ib, i); 4634234Smckusick } 4644234Smckusick close(f); 4654234Smckusick break; 4664234Smckusick 4674234Smckusick case IFBLK: 4684234Smckusick case IFCHR: 4694234Smckusick /* 4704234Smckusick * special file 4714234Smckusick * content is maj/min types 4724234Smckusick */ 4734234Smckusick 4744234Smckusick i = getnum() & 0377; 4754234Smckusick f = getnum() & 0377; 476*4251Smckusic in.i_rdev = makedev(i, f); 4774234Smckusick break; 4784234Smckusick 4794234Smckusick case IFDIR: 4804234Smckusick /* 4814234Smckusick * directory 4824234Smckusick * put in extra links 4834234Smckusick * call recursively until 4844234Smckusick * name of "$" found 4854234Smckusick */ 4864234Smckusick 4874234Smckusick par->i_nlink++; 4884234Smckusick in.i_nlink++; 4894234Smckusick entry(in.i_number, ".", &dbc, db, &ibc, ib); 4904234Smckusick entry(par->i_number, "..", &dbc, db, &ibc, ib); 4914234Smckusick in.i_size = 2*sizeof(struct direct); 4924234Smckusick for(;;) { 4934234Smckusick getstr(); 4944234Smckusick if(string[0]=='$' && string[1]=='\0') 4954234Smckusick break; 4964234Smckusick if (in.i_size >= FSIZE) { 4974234Smckusick printf("can't handle direct of > %d entries\n", 4984234Smckusick NDIRECT/FRAG); 4994234Smckusick exit(1); 5004234Smckusick } 5014234Smckusick entry(ino+1, string, &dbc, db, &ibc, ib); 5024234Smckusick in.i_size += sizeof(struct direct); 5034234Smckusick cfile(&in); 5044234Smckusick } 5054234Smckusick break; 5064234Smckusick } 5074234Smckusick if(dbc != 0) 5084234Smckusick newblk(&dbc, db, &ibc, ib, roundup(dbc,FSIZE)); 5094234Smckusick iput(&in, &ibc, ib); 5104234Smckusick } 5114234Smckusick 5124234Smckusick gmode(c, s, m0, m1, m2, m3) 5134234Smckusick char c, *s; 5144234Smckusick { 5154234Smckusick int i; 5164234Smckusick 5174234Smckusick for(i=0; s[i]; i++) 5184234Smckusick if(c == s[i]) 5194234Smckusick return((&m0)[i]); 5204234Smckusick printf("%c/%s: bad mode\n", c, string); 5214234Smckusick error = 1; 5224234Smckusick return(0); 5234234Smckusick } 5244234Smckusick 5254234Smckusick long 5264234Smckusick getnum() 5274234Smckusick { 5284234Smckusick int i, c; 5294234Smckusick long n; 5304234Smckusick 5314234Smckusick getstr(); 5324234Smckusick n = 0; 5334234Smckusick i = 0; 5344234Smckusick for(i=0; c=string[i]; i++) { 5354234Smckusick if(c<'0' || c>'9') { 5364234Smckusick printf("%s: bad number\n", string); 5374234Smckusick error = 1; 5384234Smckusick return((long)0); 5394234Smckusick } 5404234Smckusick n = n*10 + (c-'0'); 5414234Smckusick } 5424234Smckusick return(n); 5434234Smckusick } 5444234Smckusick 5454234Smckusick getstr() 5464234Smckusick { 5474234Smckusick int i, c; 5484234Smckusick 5494234Smckusick loop: 5504234Smckusick switch(c=getch()) { 5514234Smckusick 5524234Smckusick case ' ': 5534234Smckusick case '\t': 5544234Smckusick case '\n': 5554234Smckusick goto loop; 5564234Smckusick 5574234Smckusick case '\0': 5584234Smckusick printf("EOF\n"); 5594234Smckusick exit(1); 5604234Smckusick 5614234Smckusick case ':': 5624234Smckusick while(getch() != '\n'); 5634234Smckusick goto loop; 5644234Smckusick 5654234Smckusick } 5664234Smckusick i = 0; 5674234Smckusick 5684234Smckusick do { 5694234Smckusick string[i++] = c; 5704234Smckusick c = getch(); 5714234Smckusick } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 5724234Smckusick string[i] = '\0'; 5734234Smckusick } 5744234Smckusick 5754234Smckusick rdfs(bno, size, bf) 5764234Smckusick daddr_t bno; 5774234Smckusick int size; 5784234Smckusick char *bf; 5794234Smckusick { 5804234Smckusick int n; 5814234Smckusick 5824234Smckusick lseek(fsi, bno*FSIZE, 0); 5834234Smckusick n = read(fsi, bf, size); 5844234Smckusick if(n != size) { 5854234Smckusick printf("read error: %ld\n", bno); 5864234Smckusick exit(1); 5874234Smckusick } 5884234Smckusick } 5894234Smckusick 5904234Smckusick wtfs(bno, size, bf) 5914234Smckusick daddr_t bno; 5924234Smckusick int size; 5934234Smckusick char *bf; 5944234Smckusick { 5954234Smckusick int n; 5964234Smckusick 5974234Smckusick lseek(fso, bno*FSIZE, 0); 5984234Smckusick n = write(fso, bf, size); 5994234Smckusick if(n != size) { 6004234Smckusick printf("write error: %D\n", bno); 6014234Smckusick exit(1); 6024234Smckusick } 6034234Smckusick } 6044234Smckusick 6054234Smckusick daddr_t 6064234Smckusick alloc(size) 6074234Smckusick int size; 6084234Smckusick { 6094234Smckusick int c, i, s, frag; 6104234Smckusick daddr_t d; 6114234Smckusick 6124234Smckusick c = 0; 6134234Smckusick rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 6144234Smckusick if (acg.cg_nbfree == 0) { 6154234Smckusick printf("first cylinder group ran out of space\n"); 6164234Smckusick return (0); 6174234Smckusick } 6184234Smckusick for (d = 0; d < acg.cg_ndblk; d += FRAG) 6194234Smckusick if (isblock(acg.cg_free, d/FRAG)) 6204234Smckusick goto goth; 6214234Smckusick printf("internal error: can't find block in cyl 0\n"); 6224234Smckusick return (0); 6234234Smckusick goth: 6244234Smckusick clrblock(acg.cg_free, d/FRAG); 6254234Smckusick acg.cg_nbfree--; 6264234Smckusick sblock.fs_nbfree--; 6274234Smckusick fscs[0].cs_nbfree--; 6284234Smckusick s = d * NSPF; 6294234Smckusick acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--; 6304234Smckusick if (size != BSIZE) { 6314234Smckusick frag = howmany(size, FSIZE); 6324234Smckusick acg.cg_nffree += FRAG - frag; 6334234Smckusick sblock.fs_nffree += FRAG - frag; 6344234Smckusick for (i = frag; i < FRAG; i++) 6354234Smckusick setbit(acg.cg_free, d+i); 6364234Smckusick } 6374234Smckusick wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 6384234Smckusick return (d); 6394234Smckusick } 6404234Smckusick 6414234Smckusick entry(inum, str, adbc, db, aibc, ib) 6424234Smckusick ino_t inum; 6434234Smckusick char *str; 6444234Smckusick int *adbc, *aibc; 6454234Smckusick char *db; 6464234Smckusick daddr_t *ib; 6474234Smckusick { 6484234Smckusick struct direct *dp; 6494234Smckusick int i; 6504234Smckusick 6514234Smckusick dp = (struct direct *)db; 6524234Smckusick dp += *adbc; 6534234Smckusick (*adbc)++; 6544234Smckusick dp->d_ino = inum; 6554234Smckusick for(i=0; i<DIRSIZ; i++) 6564234Smckusick dp->d_name[i] = 0; 6574234Smckusick for(i=0; i<DIRSIZ; i++) 6584234Smckusick if((dp->d_name[i] = str[i]) == 0) 6594234Smckusick break; 6604234Smckusick if(*adbc >= NDIRECT) 6614234Smckusick newblk(adbc, db, aibc, ib, BSIZE); 6624234Smckusick } 6634234Smckusick 6644234Smckusick newblk(adbc, db, aibc, ib, size) 6654234Smckusick int *adbc, *aibc; 6664234Smckusick char *db; 6674234Smckusick daddr_t *ib; 6684234Smckusick int size; 6694234Smckusick { 6704234Smckusick int i; 6714234Smckusick daddr_t bno; 6724234Smckusick 6734234Smckusick bno = alloc(size); 6744234Smckusick wtfs(bno, size, db); 6754234Smckusick for(i=0; i<size; i++) 6764234Smckusick db[i] = 0; 6774234Smckusick *adbc = 0; 6784234Smckusick ib[*aibc] = bno; 6794234Smckusick (*aibc)++; 6804234Smckusick if(*aibc >= NINDIR) { 6814234Smckusick printf("indirect block full\n"); 6824234Smckusick error = 1; 6834234Smckusick *aibc = 0; 6844234Smckusick } 6854234Smckusick } 6864234Smckusick 6874234Smckusick getch() 6884234Smckusick { 6894234Smckusick 6904234Smckusick #ifndef STANDALONE 6914234Smckusick if(charp) 6924234Smckusick #endif 6934234Smckusick return(*charp++); 6944234Smckusick #ifndef STANDALONE 6954234Smckusick return(getc(fin)); 6964234Smckusick #endif 6974234Smckusick } 6984234Smckusick 6994234Smckusick iput(ip, aibc, ib) 7004234Smckusick struct inode *ip; 7014234Smckusick int *aibc; 7024234Smckusick daddr_t *ib; 7034234Smckusick { 7044234Smckusick struct dinode *dp; 7054234Smckusick daddr_t d; 7064234Smckusick int i, c = ip->i_number / sblock.fs_ipg; 7074234Smckusick 7084234Smckusick rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 7094234Smckusick acg.cg_nifree--; 7104234Smckusick setbit(acg.cg_iused, ip->i_number); 7114234Smckusick wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 7124234Smckusick sblock.fs_nifree--; 7134234Smckusick fscs[0].cs_nifree--; 7144234Smckusick if(ip->i_number >= sblock.fs_ipg) { 7154234Smckusick printf("mkfs: cant handle more than one cg of inodes (yet)\n"); 7164234Smckusick exit(1); 7174234Smckusick } 7184234Smckusick if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 7194234Smckusick if(error == 0) 7204234Smckusick printf("ilist too small\n"); 7214234Smckusick error = 1; 7224234Smckusick return; 7234234Smckusick } 7244234Smckusick d = itod(ip->i_number,&sblock); 7254234Smckusick rdfs(d, BSIZE, buf); 726*4251Smckusic for(i=0; i<*aibc; i++) { 727*4251Smckusic if(i >= NDADDR) 728*4251Smckusic break; 729*4251Smckusic ip->i_db[i] = ib[i]; 730*4251Smckusic } 731*4251Smckusic if(*aibc >= NDADDR) { 732*4251Smckusic ip->i_ib[0] = alloc(BSIZE); 733*4251Smckusic for(i=0; i<NINDIR-NDADDR; i++) { 734*4251Smckusic ib[i] = ib[i+NDADDR]; 735*4251Smckusic ib[i+NDADDR] = (daddr_t)0; 7364234Smckusick } 737*4251Smckusic wtfs(ip->i_ib[0], (char *)ib); 7384234Smckusick } 739*4251Smckusic ((struct dinode *)buf+itoo(ip->i_number))->di_ic = ip->i_ic; 7404234Smckusick wtfs(d, BSIZE, buf); 7414234Smckusick } 742