1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: static char sccsid[] = "@(#)mkproto.c 5.1 (Berkeley) 5/28/85"; 12: #endif not lint 13: 14: /* 15: * Make a file system prototype. 16: * usage: mkproto filsys proto 17: * 18: * Files written to the new filesystem may be up to 4kb less than the 19: * max single indirect size: 256kb. 20: */ 21: #include <stdio.h> 22: #include <sys/param.h> 23: #undef EXTERNALITIMES /* Need full inode definiton */ 24: #include <sys/inode.h> 25: #include <sys/fs.h> 26: #include <sys/dir.h> 27: 28: union { 29: struct fs fs; 30: char fsx[DEV_BSIZE]; 31: } ufs; 32: #define sblock ufs.fs 33: struct fs *fs; 34: int fso, fsi; 35: FILE *proto; 36: char token[BUFSIZ]; 37: int errs; 38: ino_t ino = 10; 39: int flshroot; 40: long getnum(); 41: char *strcpy(); 42: daddr_t alloc(); 43: time_t time(); 44: 45: main(argc, argv) 46: int argc; 47: char *argv[]; 48: { 49: int i; 50: 51: if (argc != 3) { 52: fprintf(stderr, "usage: mkproto filsys proto\n"); 53: exit(1); 54: } 55: fso = open(argv[1], 1); 56: fsi = open(argv[1], 0); 57: if (fso < 0 || fsi < 0) { 58: perror(argv[1]); 59: exit(1); 60: } 61: fs = &sblock; 62: rdfs(SBLOCK, (char *)fs); 63: proto = fopen(argv[2], "r"); 64: descend((struct inode *)0); 65: wtfs(SBLOCK, (char *)fs); 66: exit(errs); 67: } 68: 69: descend(par) 70: struct inode *par; 71: { 72: struct inode in; 73: int ibc = 0, dbc = 0; 74: int i, f, c; 75: struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)]; 76: daddr_t ib[MAXBSIZE / sizeof (daddr_t)]; 77: char buf[MAXBSIZE]; 78: 79: getstr(); 80: in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 81: in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0); 82: in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0); 83: for (i = 3; i < 6; i++) { 84: c = token[i]; 85: if (c < '0' || c > '7') { 86: printf("%c/%s: bad octal mode digit\n", c, token); 87: errs++; 88: c = 0; 89: } 90: in.i_mode |= (c-'0')<<(15-3*i); 91: } 92: in.i_uid = getnum(); in.i_gid = getnum(); 93: in.i_nlink = 1; 94: in.i_size = 0; 95: bzero(in.i_addr, NADDR * sizeof (daddr_t)); 96: bzero(buf, sizeof (buf)); 97: bzero(ib, sizeof (ib)); 98: 99: if (par != (struct inode *)0) { 100: ialloc(&in); 101: } else { 102: par = ∈ 103: i = itod(ROOTINO); 104: rdfs((daddr_t) i, (char *)inos); 105: dip = &inos[itoo(ROOTINO)]; 106: in.i_number = ROOTINO; 107: in.i_nlink = dip->di_nlink; 108: in.i_size = dip->di_size; 109: in.i_db[0] = dip->di_addr[0]; 110: ib[0] = in.i_db[0]; /* rootino has 1st block assigned */ 111: ibc = 1; /* preserve it when iput is done */ 112: rdfs(in.i_db[0], buf); 113: flshroot = 1; 114: } 115: 116: switch (in.i_mode&IFMT) { 117: 118: case IFREG: 119: getstr(); 120: f = open(token, 0); 121: if (f < 0) { 122: printf("%s: cannot open\n", token); 123: errs++; 124: break; 125: } 126: while ((i = read(f, buf, DEV_BSIZE)) > 0) { 127: in.i_size += i; 128: newblk(buf, &ibc, ib, &dbc); 129: } 130: close(f); 131: break; 132: 133: case IFBLK: 134: case IFCHR: 135: /* 136: * special file 137: * content is maj/min types 138: */ 139: 140: i = getnum() & 0377; 141: f = getnum() & 0377; 142: in.i_rdev = (i << 8) | f; 143: break; 144: 145: case IFDIR: 146: /* 147: * directory 148: * put in extra links 149: * call recursively until 150: * name of "$" found 151: */ 152: 153: if (in.i_number != ROOTINO) { 154: par->i_nlink++; 155: in.i_nlink++; 156: entry(&in, in.i_number, ".", buf, &ibc, ib, &dbc); 157: entry(&in, par->i_number, "..", buf, &ibc, ib, &dbc); 158: } 159: for (;;) { 160: getstr(); 161: if (token[0]=='$' && token[1]=='\0') 162: break; 163: entry(&in, ino+1, token, buf, &ibc, ib, &dbc); 164: descend(&in); 165: } 166: if (dbc) { 167: if (in.i_number == ROOTINO && flshroot) 168: wtfs(in.i_db[0], buf); 169: else 170: newblk(buf, &ibc, ib, &dbc); 171: } 172: break; 173: } 174: iput(&in, &ibc, ib); 175: } 176: 177: /*ARGSUSED*/ 178: gmode(c, s, m0, m1, m2, m3) 179: char c, *s; 180: { 181: int i; 182: 183: for (i = 0; s[i]; i++) 184: if (c == s[i]) 185: return((&m0)[i]); 186: printf("%c/%s: bad mode\n", c, token); 187: errs++; 188: return(0); 189: } 190: 191: long 192: getnum() 193: { 194: int i, c; 195: long n; 196: 197: getstr(); 198: n = 0; 199: i = 0; 200: for (i = 0; c=token[i]; i++) { 201: if (c<'0' || c>'9') { 202: printf("%s: bad number\n", token); 203: errs++; 204: return((long)0); 205: } 206: n = n*10 + (c-'0'); 207: } 208: return(n); 209: } 210: 211: getstr() 212: { 213: int i, c; 214: 215: loop: 216: switch (c = getc(proto)) { 217: 218: case ' ': 219: case '\t': 220: case '\n': 221: goto loop; 222: 223: case EOF: 224: printf("Unexpected EOF\n"); 225: exit(1); 226: 227: case ':': 228: while (getc(proto) != '\n') 229: ; 230: goto loop; 231: 232: } 233: i = 0; 234: do { 235: token[i++] = c; 236: c = getc(proto); 237: } while (c != ' ' && c != '\t' && c != '\n' && c != '\0'); 238: token[i] = 0; 239: } 240: 241: entry(ip, inum, str, buf, aibc, ib, adbc) 242: struct inode *ip; 243: ino_t inum; 244: char *str; 245: char *buf; 246: int *aibc; 247: daddr_t *ib; 248: int *adbc; 249: { 250: register struct direct *dp, *odp; 251: int oldsize, newsize, spacefree; 252: u_short diroff = ip->i_size & DEV_BMASK; 253: 254: odp = dp = (struct direct *)buf; 255: while ((int)dp - (int)buf < diroff) { 256: odp = dp; 257: dp = (struct direct *)((int)dp + dp->d_reclen); 258: } 259: if (odp != dp) 260: oldsize = DIRSIZ(odp); 261: else 262: oldsize = 0; 263: spacefree = odp->d_reclen - oldsize; 264: dp = (struct direct *)((int)odp + oldsize); 265: dp->d_ino = inum; 266: dp->d_namlen = strlen(str); 267: newsize = DIRSIZ(dp); 268: if (spacefree >= newsize) { 269: odp->d_reclen = oldsize; 270: dp->d_reclen = spacefree; 271: } else { 272: dp = (struct direct *)((int)odp + odp->d_reclen); 273: if ((int)dp - (int)buf >= DEV_BSIZE) { 274: if (ip->i_number == ROOTINO && flshroot) { 275: flshroot = 0; 276: wtfs(ip->i_addr[0], buf); 277: bzero(buf, DEV_BSIZE); 278: } 279: else 280: newblk(buf, aibc, ib, adbc); 281: dp = (struct direct *)(&buf[DIRBLKSIZ]); 282: dp->d_reclen = DIRBLKSIZ; 283: dp = (struct direct *)buf; 284: } 285: dp->d_ino = inum; 286: dp->d_namlen = strlen(str); 287: dp->d_reclen = DIRBLKSIZ; 288: } 289: strcpy(dp->d_name, str); 290: ip->i_size = (int)dp - (int)buf + newsize; 291: (*adbc)++; 292: } 293: 294: newblk(buf, aibc, ib, adbc) 295: int *aibc; 296: char *buf; 297: daddr_t *ib; 298: int *adbc; 299: { 300: daddr_t bno; 301: 302: bno = alloc(); 303: wtfs(bno, buf); 304: bzero(buf, DEV_BSIZE); 305: ib[(*aibc)++] = bno; 306: if (*aibc >= NINDIR) { 307: printf("indirect block full\n"); 308: errs++; 309: *aibc = 0; 310: *adbc = 0; 311: } 312: } 313: 314: iput(ip, aibc, ib) 315: register struct inode *ip; 316: int *aibc; 317: daddr_t *ib; 318: { 319: daddr_t d; 320: register int i, off; 321: struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; 322: 323: ip->i_atime = ip->i_mtime = ip->i_ctime = time((long *)0); 324: switch (ip->i_mode&IFMT) { 325: 326: case IFDIR: 327: case IFREG: 328: for (i = 0; i < *aibc; i++) { 329: if (i >= NDADDR) 330: break; 331: ip->i_db[i] = ib[i]; 332: } 333: if (*aibc > NDADDR) { 334: ip->i_ib[0] = alloc(); 335: for (i = 0; i < NINDIR - NDADDR; i++) { 336: ib[i] = ib[i+NDADDR]; 337: ib[i+NDADDR] = (daddr_t)0; 338: } 339: wtfs(ip->i_ib[0], (char *)ib); 340: } 341: break; 342: 343: case IFBLK: 344: case IFCHR: 345: break; 346: 347: default: 348: printf("bad mode %o\n", ip->i_mode); 349: exit(1); 350: } 351: d = itod(ip->i_number); 352: off = itoo(ip->i_number); 353: rdfs(d, (char *)buf); 354: buf[off].di_ic2 = ip->i_ic2; 355: bcopy(ip->i_addr,buf[off].di_addr,NADDR*sizeof(daddr_t)); 356: buf[off].di_ic1 = ip->i_ic1; 357: wtfs(d, (char *)buf); 358: } 359: 360: daddr_t 361: alloc() 362: { 363: daddr_t bno; 364: register i; 365: union { 366: char data[DEV_BSIZE]; 367: struct fblk frees; 368: } fbuf; 369: 370: if (!sblock.fs_nfree || (bno=sblock.fs_free[--sblock.fs_nfree]) == 0) { 371: fprintf(stderr, "Out of space.\n"); 372: exit(1); 373: } 374: sblock.fs_tfree--; 375: if(sblock.fs_nfree == 0) { 376: rdfs(bno, fbuf.data); 377: sblock.fs_nfree = fbuf.frees.df_nfree; 378: for(i=0;i<NICFREE;i++) 379: sblock.fs_free[i] = fbuf.frees.df_free[i]; 380: } 381: return(bno); 382: } 383: 384: /* 385: * Allocate an inode on the disk 386: * 387: * This assumes a newly created filesystem in which fs_inode 388: * is zero filled and fs_ninode is zero. 389: */ 390: 391: ino_t 392: ialloc(ip) 393: register struct inode *ip; 394: { 395: 396: ip->i_number = ++ino; 397: return(ip->i_number); 398: } 399: 400: /* 401: * read a block from the file system 402: */ 403: rdfs(bno, bf) 404: daddr_t bno; 405: register char *bf; 406: { 407: register int n; 408: 409: if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 410: printf("seek error: %ld\n", bno); 411: perror("rdfs"); 412: exit(1); 413: } 414: n = read(fsi, bf, DEV_BSIZE); 415: if(n != DEV_BSIZE) { 416: printf("read error: %ld\n", bno); 417: perror("rdfs"); 418: exit(1); 419: } 420: } 421: 422: /* 423: * write a block to the file system 424: */ 425: wtfs(bno, bf) 426: daddr_t bno; 427: register char *bf; 428: { 429: register int n; 430: 431: if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 432: printf("seek error: %ld\n", bno); 433: perror("wtfs"); 434: exit(1); 435: } 436: n = write(fso, bf, DEV_BSIZE); 437: if(n != DEV_BSIZE) { 438: printf("write error: %D\n", bno); 439: perror("wtfs"); 440: exit(1); 441: } 442: }