1: #include <stdio.h> 2: #include <sys/param.h> 3: #include <sys/systm.h> 4: #include <sys/dir.h> 5: #include <sys/user.h> 6: #include <sys/vm.h> 7: #include <sys/proc.h> 8: #include <sys/pte.h> 9: #include <sys/cmap.h> 10: #include <sys/inode.h> 11: #include <sys/buf.h> 12: #include <sys/text.h> 13: #include <sys/ino.h> 14: 15: struct buf *bread(); 16: struct buf b; 17: char bc[BSIZE]; 18: int bflag; 19: 20: main(argc, argv) 21: char *argv[]; 22: { 23: struct dinode di; 24: struct inode i; 25: struct proc p; 26: struct user u; 27: struct text x; 28: struct pte *pte; 29: int j,k,l; 30: 31: if (argc > 1 && !strcmp(argv[1], "-b")) 32: argc--, argv++, bflag++; 33: if (argc != 3) { 34: fprintf(stderr, "usage: copyout [ -b ] inum disk\n"); 35: exit(1); 36: } 37: close(0); 38: if (open(argv[2], 0) != 0) { 39: perror(argv[2]); 40: exit(1); 41: } 42: lseek(0, itod(atoi(argv[1])) * BSIZE + itoo(atoi(argv[1])) * sizeof (di), 0); 43: if (read(0, &di, sizeof (di)) != sizeof (di)) { 44: fprintf(stderr, "error reading inode "); 45: perror(argv[1]); 46: exit(1); 47: } 48: i.i_dev = 0; 49: i.i_number = atoi(argv[1]); 50: i.i_flag = ILOCK; 51: i.i_count = 1; 52: i.i_un.i_lastr = 0; 53: i.i_mode = di.di_mode; 54: i.i_nlink = di.di_nlink; 55: i.i_uid = di.di_uid; 56: i.i_size = di.di_size; 57: l3tol(i.i_un.i_addr, di.di_addr, NADDR); 58: p.p_textp = &x; 59: x.x_iptr = &i; 60: b.b_un.b_addr = bc; 61: pte = (struct pte *)calloc(btoc(i.i_size), sizeof (struct pte)); 62: if (pte == NULL) { 63: fprintf(stderr, "Not enough core for block pointers\n"); 64: exit(1); 65: } 66: vinizfod(&p, pte, 0, (btoc(i.i_size)+(CLSIZE-1)) / CLSIZE); 67: l = i.i_size; 68: for (j = 0; j < (btoc(i.i_size)+(CLSIZE-1)) / CLSIZE; j++) 69: if (bflag) 70: printf("#%d: block %d\n", j, pte[j].pg_pfnum); 71: else { 72: k = imin(l, BSIZE); 73: write(1, bread(0, pte[j].pg_pfnum)->b_un.b_words, k); 74: brelse(&b); 75: l -= BSIZE; 76: } 77: exit(0); 78: } 79: 80: int bused; 81: 82: struct buf * 83: bread(dev, blk) 84: { 85: 86: if (bused) 87: abort(); 88: bused = 1; 89: printf("getblk %x\n", blk); 90: lseek(0, blk * BSIZE, 0); 91: if (read(0, b.b_un.b_addr, BSIZE) != BSIZE) { 92: printf("block %d: ", blk); 93: perror("bread"); 94: } 95: return (&b); 96: } 97: 98: brelse(bp) 99: struct buf *bp; 100: { 101: 102: if (bp != &b) 103: abort(); 104: bused = 0; 105: } 106: 107: struct buf *vbmap(); 108: /* 109: * Initialize the page tables for paging from an inode, 110: * by scouring up the indirect blocks in order. 111: */ 112: vinizfod(p, pte, bstart, count) 113: struct proc *p; 114: register struct pte *pte; 115: daddr_t bstart; 116: int count; 117: { 118: register struct inode *ip = p->p_textp->x_iptr; 119: register int i; 120: struct buf *bp; 121: int indx; 122: register daddr_t *pp; 123: 124: while (count > 0) { 125: if (bstart < NADDR - 3) { 126: pte++->pg_pfnum = ip->i_un.i_addr[bstart]; 127: bstart++; 128: count--; 129: } else { 130: bp = vbmap(ip, bstart); 131: indx = (bstart - (NADDR - 3)) % NINDIR; 132: i = imin(NINDIR - indx, count); 133: bstart += i; 134: count -= i; 135: if (bp) { 136: pp = &bp->b_un.b_daddr[indx]; 137: do 138: pte++->pg_pfnum = *pp++; 139: while (--i > 0); 140: brelse(bp); 141: } else 142: pte += i; 143: } 144: } 145: } 146: 147: /* 148: * Vbmap returns a block full of indirect pointers for a given block offset 149: * in a file. It returns 0 if a missing address block was encountered, 150: * in which case the pages can be normal zfod pages. 151: */ 152: struct buf * 153: vbmap(ip, bn) 154: register struct inode *ip; 155: daddr_t bn; 156: { 157: register i; 158: struct buf *bp; 159: int j, sh; 160: daddr_t nb; 161: dev_t dev = ip->i_dev; 162: 163: if (bn < NADDR-3) 164: panic("vbmap"); 165: 166: /* 167: * addresses NADDR-3, NADDR-2, and NADDR-1 168: * have single, double, triple indirect blocks. 169: * the first step is to determine 170: * how many levels of indirection. 171: */ 172: sh = 0; 173: nb = 1; 174: bn -= NADDR-3; 175: for (j = 3; j > 0; j--) { 176: sh += NSHIFT; 177: nb <<= NSHIFT; 178: if(bn < nb) 179: break; 180: bn -= nb; 181: } 182: if (j == 0) 183: goto noblk; 184: 185: /* 186: * fetch the address from the inode 187: */ 188: nb = ip->i_un.i_addr[NADDR-j]; 189: 190: /* 191: * fetch through the indirect blocks 192: */ 193: for (;;) { 194: if (nb == 0) 195: return ((daddr_t)0); 196: bp = bread(dev, nb); 197: if (bp->b_flags & B_ERROR) { 198: brelse(bp); 199: goto noblk; 200: } 201: if (j == 3) 202: break; 203: j++; 204: sh -= NSHIFT; 205: i = (bn>>sh) & NMASK; 206: nb = bp->b_un.b_daddr[i]; 207: brelse(bp); 208: if (nb == 0) 209: goto noblk; 210: } 211: return (bp); 212: 213: noblk: 214: return ((struct buf *)0); 215: } 216: 217: imin(a,b) 218: { 219: return (a<b?a:b); 220: } 221: 222: panic(cp) 223: { 224: printf(cp); 225: abort(); 226: } 227: 228: char vmmap[1]; 229: char version[1];