|
|
1.1 root 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];
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.