Commit | Line | Data |
---|---|---|
64d0f71e KT |
1 | # |
2 | /* | |
3 | */ | |
4 | ||
5 | #include "../param.h" | |
6 | #include "../conf.h" | |
7 | #include "../inode.h" | |
8 | #include "../user.h" | |
9 | #include "../buf.h" | |
10 | #include "../systm.h" | |
11 | ||
12 | /* | |
13 | * Bmap defines the structure of file system storage | |
14 | * by returning the physical block number on a device given the | |
15 | * inode and the logical block number in a file. | |
16 | * When convenient, it also leaves the physical | |
17 | * block number of the next block of the file in rablock | |
18 | * for use in read-ahead. | |
19 | */ | |
20 | bmap(ip, bn) | |
21 | struct inode *ip; | |
22 | int bn; | |
23 | { | |
24 | register *bp, *bap, nb; | |
25 | int *nbp, d, i; | |
26 | ||
27 | d = ip->i_dev; | |
28 | if(bn & ~077777) { | |
29 | u.u_error = EFBIG; | |
30 | return(0); | |
31 | } | |
32 | ||
33 | if((ip->i_mode&ILARG) == 0) { | |
34 | ||
35 | /* | |
36 | * small file algorithm | |
37 | */ | |
38 | ||
39 | if((bn & ~7) != 0) { | |
40 | ||
41 | /* | |
42 | * convert small to large | |
43 | */ | |
44 | ||
45 | if ((bp = alloc(d)) == NULL) | |
46 | return(NULL); | |
47 | bap = bp->b_addr; | |
48 | for(i=0; i<8; i++) { | |
49 | *bap++ = ip->i_addr[i]; | |
50 | ip->i_addr[i] = 0; | |
51 | } | |
52 | ip->i_addr[0] = bp->b_blkno; | |
53 | bdwrite(bp); | |
54 | ip->i_mode =| ILARG; | |
55 | goto large; | |
56 | } | |
57 | nb = ip->i_addr[bn]; | |
58 | if(nb == 0 && (bp = alloc(d)) != NULL) { | |
59 | bdwrite(bp); | |
60 | nb = bp->b_blkno; | |
61 | ip->i_addr[bn] = nb; | |
62 | ip->i_flag =| IUPD; | |
63 | } | |
64 | rablock = 0; | |
65 | if (bn<7) | |
66 | rablock = ip->i_addr[bn+1]; | |
67 | return(nb); | |
68 | } | |
69 | ||
70 | /* | |
71 | * large file algorithm | |
72 | */ | |
73 | ||
74 | large: | |
75 | i = bn>>8; | |
76 | if(bn & 0174000) | |
77 | i = 7; | |
78 | if((nb=ip->i_addr[i]) == 0) { | |
79 | ip->i_flag =| IUPD; | |
80 | if ((bp = alloc(d)) == NULL) | |
81 | return(NULL); | |
82 | ip->i_addr[i] = bp->b_blkno; | |
83 | } else | |
84 | bp = bread(d, nb); | |
85 | bap = bp->b_addr; | |
86 | ||
87 | /* | |
88 | * "huge" fetch of double indirect block | |
89 | */ | |
90 | ||
91 | if(i == 7) { | |
92 | i = ((bn>>8) & 0377) - 7; | |
93 | if((nb=bap[i]) == 0) { | |
94 | if((nbp = alloc(d)) == NULL) { | |
95 | brelse(bp); | |
96 | return(NULL); | |
97 | } | |
98 | bap[i] = nbp->b_blkno; | |
99 | bdwrite(bp); | |
100 | } else { | |
101 | brelse(bp); | |
102 | nbp = bread(d, nb); | |
103 | } | |
104 | bp = nbp; | |
105 | bap = bp->b_addr; | |
106 | } | |
107 | ||
108 | /* | |
109 | * normal indirect fetch | |
110 | */ | |
111 | ||
112 | i = bn & 0377; | |
113 | if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) { | |
114 | nb = nbp->b_blkno; | |
115 | bap[i] = nb; | |
116 | bdwrite(nbp); | |
117 | bdwrite(bp); | |
118 | } else | |
119 | brelse(bp); | |
120 | rablock = 0; | |
121 | if(i < 255) | |
122 | rablock = bap[i+1]; | |
123 | return(nb); | |
124 | } | |
125 | ||
126 | /* | |
127 | * Pass back c to the user at his location u_base; | |
128 | * update u_base, u_count, and u_offset. Return -1 | |
129 | * on the last character of the user's read. | |
130 | * u_base is in the user address space unless u_segflg is set. | |
131 | */ | |
132 | passc(c) | |
133 | char c; | |
134 | { | |
135 | ||
136 | if(u.u_segflg) | |
137 | *u.u_base = c; else | |
138 | if(subyte(u.u_base, c) < 0) { | |
139 | u.u_error = EFAULT; | |
140 | return(-1); | |
141 | } | |
142 | u.u_count--; | |
143 | if(++u.u_offset[1] == 0) | |
144 | u.u_offset[0]++; | |
145 | u.u_base++; | |
146 | return(u.u_count == 0? -1: 0); | |
147 | } | |
148 | ||
149 | /* | |
150 | * Pick up and return the next character from the user's | |
151 | * write call at location u_base; | |
152 | * update u_base, u_count, and u_offset. Return -1 | |
153 | * when u_count is exhausted. u_base is in the user's | |
154 | * address space unless u_segflg is set. | |
155 | */ | |
156 | cpass() | |
157 | { | |
158 | register c; | |
159 | ||
160 | if(u.u_count == 0) | |
161 | return(-1); | |
162 | if(u.u_segflg) | |
163 | c = *u.u_base; else | |
164 | if((c=fubyte(u.u_base)) < 0) { | |
165 | u.u_error = EFAULT; | |
166 | return(-1); | |
167 | } | |
168 | u.u_count--; | |
169 | if(++u.u_offset[1] == 0) | |
170 | u.u_offset[0]++; | |
171 | u.u_base++; | |
172 | return(c&0377); | |
173 | } | |
174 | ||
175 | /* | |
176 | * Routine which sets a user error; placed in | |
177 | * illegal entries in the bdevsw and cdevsw tables. | |
178 | */ | |
179 | nodev() | |
180 | { | |
181 | ||
182 | u.u_error = ENODEV; | |
183 | } | |
184 | ||
185 | /* | |
186 | * Null routine; placed in insignificant entries | |
187 | * in the bdevsw and cdevsw tables. | |
188 | */ | |
189 | nulldev() | |
190 | { | |
191 | } | |
192 | ||
193 | /* | |
194 | * copy count words from from to to. | |
195 | */ | |
196 | bcopy(from, to, count) | |
197 | int *from, *to; | |
198 | { | |
199 | register *a, *b, c; | |
200 | ||
201 | a = from; | |
202 | b = to; | |
203 | c = count; | |
204 | do | |
205 | *b++ = *a++; | |
206 | while(--c); | |
207 | } |