BSD 4_2 development
[unix-history] / usr / src / undoc / copyout.c
CommitLineData
8ed973d0
C
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
15struct buf *bread();
16struct buf b;
17char bc[BSIZE];
18int bflag;
19
20main(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
80int bused;
81
82struct buf *
83bread(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
98brelse(bp)
99struct buf *bp;
100{
101
102 if (bp != &b)
103 abort();
104 bused = 0;
105}
106
107struct buf *vbmap();
108/*
109 * Initialize the page tables for paging from an inode,
110 * by scouring up the indirect blocks in order.
111 */
112vinizfod(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 */
152struct buf *
153vbmap(ip, bn)
154register struct inode *ip;
155daddr_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
213noblk:
214 return ((struct buf *)0);
215}
216
217imin(a,b)
218{
219 return (a<b?a:b);
220}
221
222panic(cp)
223{
224 printf(cp);
225 abort();
226}
227
228char vmmap[1];
229char version[1];