|
|
1.1 ! root 1: /* ! 2: * read a Berkeley `fast file system' ! 3: * quick, cheap hack ! 4: */ ! 5: ! 6: #include <stdio.h> ! 7: #include <sys/types.h> ! 8: #include <sys/stat.h> /* for file modes; they happen to match */ ! 9: #include "bsdffs.h" ! 10: ! 11: #include "rf.h" ! 12: #include <errno.h> ! 13: #include <libc.h> ! 14: ! 15: int fserrno; ! 16: static int devfd; ! 17: static Rfile *root; ! 18: static union { ! 19: char buf[SBSIZE]; ! 20: struct fs super; ! 21: } super; ! 22: #define sb (super.super) ! 23: static long firstblk; /* offset to beginning of filsys */ ! 24: static char *blk; ! 25: ! 26: typedef struct Fsfile { ! 27: long dir[NDADDR]; ! 28: long ind[NIADDR]; ! 29: } Fsfile; ! 30: #define fsp(f) ((Fsfile *)((f)->fs)) ! 31: ! 32: /* ! 33: * init: ! 34: * open the device ! 35: */ ! 36: ! 37: Rfile * ! 38: fsinit(argc, argv) ! 39: int argc; ! 40: char **argv; ! 41: { ! 42: register Rfile *f; ! 43: ! 44: if (argc <= 1) ! 45: rfpanic("no device specified\n"); ! 46: if ((devfd = open(argv[1], 0)) < 0) ! 47: rfpanic("%s: cannot open\n", argv[1]); ! 48: if (argc > 2) ! 49: firstblk = atol(argv[2]) * 512; ! 50: lseek(devfd, firstblk + SBLOCK, 0); ! 51: if (read(devfd, super.buf, SBSIZE) != SBSIZE) ! 52: rfpanic("can't read super block\n"); ! 53: if ((blk = malloc(sb.fs_bsize)) == NULL) ! 54: rfpanic("can't alloc %d for block buf\n", sb.fs_bsize); ! 55: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) ! 56: rfpanic("no mem for root\n"); ! 57: if ((f->fs = malloc(sizeof(Fsfile))) == NULL) ! 58: rfpanic("no mem for root\n"); ! 59: f->ino = ROOTINO; ! 60: fsstat(f); ! 61: root = f; ! 62: return (f); ! 63: } ! 64: ! 65: /* ! 66: * access a file ! 67: */ ! 68: ! 69: Rfile * ! 70: fswalk(df, name) ! 71: register Rfile *df; ! 72: char *name; ! 73: { ! 74: register Rfile *f; ! 75: int ino; ! 76: ! 77: if ((ino = dsearch(df, name)) == 0) { ! 78: fserrno = ENOENT; ! 79: return (NULL); ! 80: } ! 81: if (df == root) { /* "." and ".." magic */ ! 82: if (strcmp(name, ".") == 0) ! 83: return (df); ! 84: if (strcmp(name, "..") == 0) { ! 85: fserrno = 0; /* pseudo-error: popped out of root */ ! 86: return (NULL); ! 87: } ! 88: } ! 89: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) { ! 90: fserrno = ENOMEM; ! 91: return (NULL); ! 92: } ! 93: if ((f->fs = malloc(sizeof(Fsfile))) == NULL) { ! 94: free((char *)f); ! 95: fserrno = ENOMEM; ! 96: return (NULL); ! 97: } ! 98: f->ino = ino; ! 99: fsstat(f); ! 100: return (f); ! 101: } ! 102: ! 103: /* ! 104: * discard a file reference ! 105: */ ! 106: int ! 107: fsdone(f) ! 108: Rfile *f; ! 109: { ! 110: ! 111: free(f->fs); ! 112: free((char *)f); ! 113: return (0); ! 114: } ! 115: ! 116: /* ! 117: * return file status ! 118: */ ! 119: int ! 120: fsstat(f) ! 121: Rfile *f; ! 122: { ! 123: ! 124: getino(f); ! 125: return (0); ! 126: } ! 127: ! 128: /* ! 129: * read data ! 130: */ ! 131: int ! 132: fsread(f, off, buf, len) ! 133: register Rfile *f; ! 134: long off; ! 135: char *buf; ! 136: int len; ! 137: { ! 138: int rest; ! 139: long bno; ! 140: ! 141: switch (f->mode & S_IFMT) { ! 142: case S_IFREG: ! 143: case S_IFDIR: ! 144: break; ! 145: ! 146: default: ! 147: return (0); ! 148: } ! 149: if (off >= f->size) ! 150: return (0); ! 151: if (off + len > f->size) ! 152: len = f->size - off; ! 153: bno = off / sb.fs_bsize; ! 154: if (getlblk(f, bno, blk, f->size - bno*sb.fs_bsize) == 0) ! 155: return (-1); ! 156: rest = (bno + 1)*sb.fs_bsize - off; ! 157: if (len > rest) ! 158: len = rest; ! 159: memcpy(buf, blk + (off % sb.fs_bsize), len); ! 160: return (len); ! 161: } ! 162: ! 163: /* ! 164: * read a piece of a directory ! 165: */ ! 166: int ! 167: fsdirread(f, off, buf, len, offp) ! 168: register Rfile *f; ! 169: long off; ! 170: char *buf; ! 171: int len; ! 172: long *offp; ! 173: { ! 174: int stlen; ! 175: register struct direct *de; ! 176: struct direct *endblk; ! 177: char one[MAXNAMLEN+30]; ! 178: int n; ! 179: ! 180: stlen = len; ! 181: endblk = de = (struct direct *)&blk[sb.fs_bsize]; ! 182: for (; off < f->size; off += de->d_reclen, ! 183: de = (struct direct *)&blk[off%sb.fs_bsize]) { ! 184: if (de >= endblk) { ! 185: if (getlblk(f, off/sb.fs_bsize, blk, f->size - off) == 0) ! 186: break; ! 187: de = (struct direct *)&blk[off%sb.fs_bsize]; ! 188: } ! 189: if (de->d_reclen == 0) ! 190: break; ! 191: if (de->d_ino == 0) ! 192: continue; ! 193: sprintf(one, "%ld\t%s", de->d_ino, de->d_name); ! 194: n = strlen(one)+1; ! 195: if (n > len) ! 196: break; ! 197: memcpy(buf, one, n); ! 198: len -= n; ! 199: buf += n; ! 200: } ! 201: *offp = off; ! 202: return (stlen - len); ! 203: } ! 204: ! 205: /* ! 206: * fetch an i-node ! 207: * -- no sanity check for now ! 208: * -- magic inode-to-disk-block stuff here ! 209: */ ! 210: ! 211: int ! 212: getino(f) ! 213: register Rfile *f; ! 214: { ! 215: register struct icommon *dp; ! 216: register int cg; ! 217: register long ifrag; ! 218: register long ino; ! 219: ! 220: cg = f->ino / sb.fs_ipg; ! 221: ino = f->ino % sb.fs_ipg; ! 222: ifrag = cg*sb.fs_fpg + sb.fs_cgoffset*(cg&~sb.fs_cgmask) + sb.fs_iblkno; ! 223: ifrag += ino / (sb.fs_fsize/sizeof(struct icommon)); ! 224: lseek(devfd, firstblk + ifrag * sb.fs_fsize, 0); ! 225: if (read(devfd, blk, sb.fs_fsize) != sb.fs_fsize) { ! 226: /* print error */ ! 227: return (0); ! 228: } ! 229: dp = ((struct icommon *)blk) + (ino % (sb.fs_fsize/sizeof(struct icommon))); ! 230: switch (dp->i_mode & S_IFMT) { ! 231: case S_IFREG: ! 232: case S_IFDIR: ! 233: case S_IFBLK: ! 234: case S_IFCHR: ! 235: break; ! 236: ! 237: default: ! 238: return (0); /* unalloc or illegal */ ! 239: } ! 240: memcpy((char *)fsp(f)->dir, (char *)dp->i_db, NDADDR*sizeof(long)); ! 241: memcpy((char *)fsp(f)->ind, (char *)dp->i_ib, NIADDR*sizeof(long)); ! 242: f->dev = 0; ! 243: f->rdev = 0; /* well ... */ ! 244: f->mode = dp->i_mode; ! 245: f->nlink = dp->i_nlink; ! 246: f->uid = dp->i_uid; ! 247: f->gid = dp->i_gid; ! 248: f->size = dp->i_size; ! 249: f->tm = dp->i_mtime; ! 250: f->ta = dp->i_atime; ! 251: f->tc = dp->i_ctime; ! 252: return (1); ! 253: } ! 254: ! 255: /* ! 256: * look up a file ! 257: */ ! 258: ! 259: int ! 260: dsearch(f, name) ! 261: Rfile *f; ! 262: char *name; ! 263: { ! 264: register struct direct *de; ! 265: register struct direct *endblk; ! 266: register long b, size; ! 267: ! 268: endblk = (struct direct *)(blk + sb.fs_bsize); ! 269: for (b = 0, size = f->size; size > 0; b++, size -= sb.fs_bsize) { ! 270: if (getlblk(f, b, blk, size) == 0) ! 271: continue; ! 272: for (de = (struct direct *)blk; de < endblk; ! 273: de = (struct direct *)((char *)de + de->d_reclen)) { ! 274: if (de->d_reclen == 0) /* safety */ ! 275: break; ! 276: if (de->d_ino == 0) ! 277: continue; ! 278: if (strcmp(de->d_name, name) == 0) ! 279: return (de->d_ino); ! 280: } ! 281: } ! 282: return (0); ! 283: } ! 284: ! 285: /* ! 286: * read a block from a file ! 287: */ ! 288: long bmap(); ! 289: ! 290: getlblk(f, bno, buf, maxlen) ! 291: Rfile *f; ! 292: long bno; ! 293: char *buf; ! 294: int maxlen; ! 295: { ! 296: long dbno; ! 297: ! 298: if (maxlen > sb.fs_bsize) ! 299: maxlen = sb.fs_bsize; ! 300: if ((dbno = bmap(f, bno)) == 0) { ! 301: memset(buf, 0, maxlen); ! 302: return (1); ! 303: } ! 304: lseek(devfd, firstblk + dbno*sb.fs_fsize, 0); ! 305: if (read(devfd, buf, maxlen) != maxlen) { ! 306: fserrno = errno; ! 307: return (0); ! 308: } ! 309: return (1); ! 310: } ! 311: ! 312: /* ! 313: * logical to physical block ! 314: * only singly-indirect files for now ! 315: */ ! 316: ! 317: long ! 318: bmap(f, bno) ! 319: register Rfile *f; ! 320: long bno; ! 321: { ! 322: ! 323: if (bno < NDADDR) ! 324: return (fsp(f)->dir[bno]); ! 325: bno -= NDADDR; ! 326: if (bno >= sb.fs_nindir) ! 327: return (0); ! 328: lseek(devfd, firstblk + fsp(f)->ind[0] * sb.fs_fsize, 0); ! 329: if (read(devfd, blk, sb.fs_bsize) != sb.fs_bsize) ! 330: return (0); ! 331: return (((long *)blk)[bno]); ! 332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.