1: #if !defined(lint) && defined(DOSCCS) 2: char *sccsid = "@(#)mkfs.c 2.9 (2.11BSD) 1996/5/8"; 3: #endif 4: 5: /* 6: * Make a file system. Run by 'newfs' and not directly by users. 7: * usage: mkfs -s size -i byte/ino -n num -m num filsys 8: * 9: * NOTE: the size is specified in filesystem (1k) blocks NOT sectors. 10: * newfs does the conversion before running mkfs - if you run mkfs 11: * manually beware that the '-s' option means sectors to newfs but 12: * filesystem blocks to mkfs! 13: */ 14: 15: #include <sys/param.h> 16: /* 17: * Need to do the following to get the larger incore inode structure 18: * (the kernel might be built with the inode times external/mapped-out). 19: * See /sys/h/localtimes.h and /sys/conf. 20: */ 21: #undef EXTERNALITIMES 22: 23: #include <sys/file.h> 24: #include <sys/dir.h> 25: #include <sys/stat.h> 26: #include <sys/fs.h> 27: 28: #ifndef STANDALONE 29: #include <stdlib.h> 30: #include <stdio.h> 31: #include <sys/inode.h> 32: #else 33: #include "saio.h" 34: #endif 35: 36: #define UMASK 0755 37: #define MAXFN 750 38: 39: time_t utime; 40: 41: #ifdef STANDALONE 42: int fin; 43: char module[] = "Mkfs"; 44: extern char *ltoa(); 45: extern long atol(); 46: extern struct iob iob[]; 47: #endif 48: 49: int fsi; 50: int fso; 51: char buf[DEV_BSIZE]; 52: 53: union { 54: struct fblk fb; 55: char pad1[DEV_BSIZE]; 56: } fbuf; 57: 58: union { 59: struct fs fs; 60: char pad2[DEV_BSIZE]; 61: } filsys; 62: 63: u_int f_i = 4096; /* bytes/inode default */ 64: int f_n = 100; 65: int f_m = 2; 66: 67: daddr_t alloc(); 68: 69: main(argc,argv) 70: int argc; 71: char **argv; 72: { 73: register int c; 74: long n; 75: char *size = 0; 76: char *special; 77: #ifdef STANDALONE 78: struct disklabel *lp; 79: register struct partition *pp; 80: struct iob *io; 81: #endif 82: 83: #ifndef STANDALONE 84: time(&utime); 85: while ((c = getopt(argc, argv, "i:m:n:s:")) != EOF) 86: { 87: switch (c) 88: { 89: case 'i': 90: f_i = atoi(optarg); 91: break; 92: case 'm': 93: f_m = atoi(optarg); 94: break; 95: case 'n': 96: f_n = atoi(optarg); 97: break; 98: case 's': 99: size = optarg; 100: break; 101: default: 102: usage(); 103: break; 104: } 105: } 106: argc -= optind; 107: argv += optind; 108: if (argc != 1 || !size || !f_i || !f_m || !f_n) 109: usage(); 110: special = *argv; 111: 112: /* 113: * NOTE: this will fail if the device is currently mounted and the system 114: * is at securelevel 1 or higher. 115: * 116: * We do not get the partition information because 'newfs' has already 117: * done so and invoked us. This program should not be run manually unless 118: * you are absolutely sure you know what you are doing - use 'newfs' instead. 119: */ 120: fso = creat(special, 0666); 121: if (fso < 0) 122: err(1, "cannot create %s\n", special); 123: fsi = open(special, 0); 124: if (fsi < 0) 125: err(1, "cannot open %s\n", special); 126: #else 127: /* 128: * Something more modern than January 1, 1970 - the date that the new 129: * standalone mkfs worked. 1995/06/08 2121. 130: */ 131: utime = 802671684L; 132: printf("%s\n",module); 133: do { 134: printf("file system: "); 135: gets(buf); 136: fso = open(buf, 1); 137: fsi = open(buf, 0); 138: } while (fso < 0 || fsi < 0); 139: 140: /* 141: * If the underlying driver supports disklabels then do not make a file 142: * system unless: there is a valid label present, the specified partition 143: * is of type FS_V71K, and the size is not zero. 144: * 145: * The 'open' above will have already fetched the label if the driver supports 146: * labels - the check below will only fail if the driver doesn't do labels 147: * or if the drive blew up in the millisecond since the last read. 148: */ 149: io = &iob[fsi - 3]; 150: lp = &io->i_label; 151: pp = &lp->d_partitions[io->i_part]; 152: 153: if (devlabel(io, READLABEL) < 0) 154: { 155: /* 156: * The driver does not implement labels. The 'iob' structure still contains 157: * a label structure so initialize the items that will be looked at later. 158: */ 159: pp->p_size = 0; 160: lp->d_secpercyl = 0; 161: goto nolabels; 162: } 163: if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 164: dkcksum(lp)) 165: { 166: printf("'%s' is either unlabeled or the label is corrupt.\n", 167: buf); 168: printf("Since the driver for '%s' supports disklabels you\n", 169: buf); 170: printf("must use the standalone 'disklabel' before making\n"); 171: printf("a filesystem on '%s'\n", buf); 172: return; 173: } 174: if (pp->p_fstype != FS_V71K) 175: { 176: printf("%s is not a 2.11BSD (FS_V71K) partition.", buf); 177: return; 178: } 179: if (pp->p_size == 0) 180: { 181: printf("%s is a zero length partition.\n", buf); 182: return; 183: } 184: nolabels: 185: printf("file sys size [%D]: ", dbtofsb(pp->p_size)); 186: size = buf+128; 187: gets(size); 188: if (size[0] == '\0') 189: strcpy(size, ltoa(dbtofsb(pp->p_size))); 190: if (pp->p_size && atol(size) > pp->p_size) 191: { 192: printf("specified size larger than disklabel says.\n"); 193: return; 194: } 195: printf("bytes per inode [%u]: ", f_i); 196: gets(buf); 197: if (buf[0]) 198: f_i = atoi(buf); 199: printf("interleaving factor (m; %d default): ", f_m); 200: gets(buf); 201: if (buf[0]) 202: f_m = atoi(buf); 203: if (lp->d_secpercyl) 204: f_n = dbtofsb(lp->d_secpercyl); 205: printf("interleaving modulus (n; %d default): ", f_n); 206: gets(buf); 207: if (buf[0]) 208: f_n = atoi(buf); 209: #endif 210: 211: if (f_n <= 0 || f_n >= MAXFN) 212: f_n = MAXFN; 213: if (f_m <= 0 || f_m > f_n) 214: f_m = 3; 215: 216: n = atol(size); 217: if (!n) 218: { 219: printf("Can't make zero length filesystem\n"); 220: return; 221: } 222: filsys.fs.fs_fsize = n; 223: 224: /* 225: * Calculate number of blocks of inodes as follows: 226: * 227: * dbtob(n) = # of bytes in the filesystem 228: * dbtob(n) / f_i = # of inodes to allocate 229: * (dbtob(n) / f_i) / INOPB = # of fs blocks of inodes 230: * 231: * Pretty - isn't it? 232: */ 233: n = (dbtob(n) / f_i) / INOPB; 234: if (n <= 0) 235: n = 1; 236: if (n > 65500/INOPB) 237: n = 65500/INOPB; 238: filsys.fs.fs_isize = n + 2; 239: printf("isize = %D\n", n*INOPB); 240: 241: filsys.fs.fs_step = f_m; 242: filsys.fs.fs_cyl = f_n; 243: printf("m/n = %d %d\n", f_m, f_n); 244: if (filsys.fs.fs_isize >= filsys.fs.fs_fsize) 245: { 246: printf("%D/%D: bad ratio\n", filsys.fs.fs_fsize, filsys.fs.fs_isize-2); 247: exit(1); 248: } 249: filsys.fs.fs_tfree = 0; 250: filsys.fs.fs_tinode = 0; 251: bzero(buf, DEV_BSIZE); 252: for (n=2; n!=filsys.fs.fs_isize; n++) { 253: wtfs(n, buf); 254: filsys.fs.fs_tinode += INOPB; 255: } 256: 257: bflist(); 258: 259: fsinit(); 260: 261: filsys.fs.fs_time = utime; 262: wtfs((long)SBLOCK, (char *)&filsys.fs); 263: exit(0); 264: } 265: 266: /* 267: * initialize the file system 268: */ 269: struct inode node; 270: #define PREDEFDIR 3 271: struct direct root_dir[] = { 272: { ROOTINO, sizeof(struct direct), 1, "." }, 273: { ROOTINO, sizeof(struct direct), 2, ".." }, 274: { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 275: }; 276: struct direct lost_found_dir[] = { 277: { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 278: { ROOTINO, sizeof(struct direct), 2, ".." }, 279: { 0, DIRBLKSIZ, 0, 0 }, 280: }; 281: 282: fsinit() 283: { 284: register int i; 285: 286: /* 287: * initialize the node 288: */ 289: node.i_atime = utime; 290: node.i_mtime = utime; 291: node.i_ctime = utime; 292: /* 293: * create the lost+found directory 294: */ 295: (void)makedir(lost_found_dir, 2); 296: for (i = DIRBLKSIZ; i < DEV_BSIZE; i += DIRBLKSIZ) 297: bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 298: node.i_number = LOSTFOUNDINO; 299: node.i_mode = IFDIR | UMASK; 300: node.i_nlink = 2; 301: node.i_size = DEV_BSIZE; 302: node.i_db[0] = alloc(); 303: wtfs(node.i_db[0], buf); 304: iput(&node); 305: /* 306: * create the root directory 307: */ 308: node.i_number = ROOTINO; 309: node.i_mode = IFDIR | UMASK; 310: node.i_nlink = PREDEFDIR; 311: node.i_size = makedir(root_dir, PREDEFDIR); 312: node.i_db[0] = alloc(); 313: wtfs(node.i_db[0], buf); 314: iput(&node); 315: } 316: 317: /* 318: * construct a set of directory entries in "buf". 319: * return size of directory. 320: */ 321: makedir(protodir, entries) 322: register struct direct *protodir; 323: int entries; 324: { 325: char *cp; 326: int i, spcleft; 327: 328: spcleft = DIRBLKSIZ; 329: for (cp = buf, i = 0; i < entries - 1; i++) { 330: protodir[i].d_reclen = DIRSIZ(&protodir[i]); 331: bcopy(&protodir[i], cp, protodir[i].d_reclen); 332: cp += protodir[i].d_reclen; 333: spcleft -= protodir[i].d_reclen; 334: } 335: protodir[i].d_reclen = spcleft; 336: bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 337: return (DIRBLKSIZ); 338: } 339: 340: daddr_t 341: alloc() 342: { 343: register int i; 344: daddr_t bno; 345: 346: filsys.fs.fs_tfree--; 347: bno = filsys.fs.fs_free[--filsys.fs.fs_nfree]; 348: if(bno == 0) { 349: printf("out of free space\n"); 350: exit(1); 351: } 352: if(filsys.fs.fs_nfree <= 0) { 353: rdfs(bno, (char *)&fbuf); 354: filsys.fs.fs_nfree = fbuf.fb.df_nfree; 355: for(i=0; i<NICFREE; i++) 356: filsys.fs.fs_free[i] = fbuf.fb.df_free[i]; 357: } 358: return(bno); 359: } 360: 361: rdfs(bno, bf) 362: daddr_t bno; 363: char *bf; 364: { 365: int n; 366: 367: lseek(fsi, bno*DEV_BSIZE, 0); 368: n = read(fsi, bf, DEV_BSIZE); 369: if(n != DEV_BSIZE) { 370: printf("read error: %ld\n", bno); 371: exit(1); 372: } 373: } 374: 375: wtfs(bno, bf) 376: daddr_t bno; 377: char *bf; 378: { 379: int n; 380: 381: lseek(fso, bno*DEV_BSIZE, 0); 382: n = write(fso, bf, DEV_BSIZE); 383: if(n != DEV_BSIZE) { 384: printf("write error: %D\n", bno); 385: exit(1); 386: } 387: } 388: 389: bfree(bno) 390: daddr_t bno; 391: { 392: register int i; 393: 394: if (bno != 0) 395: filsys.fs.fs_tfree++; 396: if(filsys.fs.fs_nfree >= NICFREE) { 397: fbuf.fb.df_nfree = filsys.fs.fs_nfree; 398: for(i=0; i<NICFREE; i++) 399: fbuf.fb.df_free[i] = filsys.fs.fs_free[i]; 400: wtfs(bno, (char *)&fbuf); 401: filsys.fs.fs_nfree = 0; 402: } 403: filsys.fs.fs_free[filsys.fs.fs_nfree++] = bno; 404: } 405: 406: bflist() 407: { 408: struct inode in; 409: char flg[MAXFN]; 410: int adr[MAXFN]; 411: register int i, j; 412: daddr_t f, d; 413: 414: bzero(flg, sizeof flg); 415: i = 0; 416: for(j=0; j<f_n; j++) { 417: while(flg[i]) 418: i = (i+1)%f_n; 419: adr[j] = i+1; 420: flg[i]++; 421: i = (i+f_m)%f_n; 422: } 423: 424: bzero(&in, sizeof (in)); 425: in.i_number = 1; /* inode 1 is a historical hack */ 426: in.i_mode = IFREG; 427: bfree((daddr_t)0); 428: d = filsys.fs.fs_fsize-1; 429: while(d%f_n) 430: d++; 431: for(; d > 0; d -= f_n) 432: for(i=0; i<f_n; i++) { 433: f = d - adr[i]; 434: if(f < filsys.fs.fs_fsize && f >= filsys.fs.fs_isize) 435: bfree(f); 436: } 437: iput(&in); 438: } 439: 440: iput(ip) 441: register struct inode *ip; 442: { 443: struct dinode buf[INOPB]; 444: register struct dinode *dp; 445: daddr_t d; 446: 447: filsys.fs.fs_tinode--; 448: d = itod(ip->i_number); 449: if(d >= filsys.fs.fs_isize) { 450: printf("ilist too small\n"); 451: return; 452: } 453: rdfs(d, buf); 454: dp = (struct dinode *)buf; 455: dp += itoo(ip->i_number); 456: 457: dp->di_addr[0] = ip->i_addr[0]; 458: dp->di_ic1 = ip->i_ic1; 459: dp->di_ic2 = ip->i_ic2; 460: wtfs(d, buf); 461: } 462: 463: #ifndef STANDALONE 464: usage() 465: { 466: printf("usage: [-s size] [-i bytes/ino] [-n num] [-m num] special\n"); 467: exit(1); 468: /* NOTREACHED */ 469: } 470: #endif