Mercurial > hg > Members > innparusu > xv6-rpi
comparison src/tools/mkfs.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children | 397e74cbf14e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
1 #include <stdio.h> | |
2 #include <unistd.h> | |
3 #include <stdlib.h> | |
4 #include <string.h> | |
5 #include <fcntl.h> | |
6 #include <assert.h> | |
7 | |
8 #define stat xv6_stat // avoid clash with host struct stat | |
9 #include "types.h" | |
10 #include "fs.h" | |
11 #include "stat.h" | |
12 #include "param.h" | |
13 | |
14 #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) | |
15 | |
16 int nblocks = 985; | |
17 int nlog = LOGSIZE; | |
18 int ninodes = 200; | |
19 int size = 1024; | |
20 | |
21 int fsfd; | |
22 struct superblock sb; | |
23 char zeroes[512]; | |
24 uint freeblock; | |
25 uint usedblocks; | |
26 uint bitblocks; | |
27 uint freeinode = 1; | |
28 | |
29 void balloc(int); | |
30 void wsect(uint, void*); | |
31 void winode(uint, struct dinode*); | |
32 void rinode(uint inum, struct dinode *ip); | |
33 void rsect(uint sec, void *buf); | |
34 uint ialloc(ushort type); | |
35 void iappend(uint inum, void *p, int n); | |
36 | |
37 // convert to intel byte order | |
38 ushort | |
39 xshort(ushort x) | |
40 { | |
41 ushort y; | |
42 uchar *a = (uchar*)&y; | |
43 a[0] = x; | |
44 a[1] = x >> 8; | |
45 return y; | |
46 } | |
47 | |
48 uint | |
49 xint(uint x) | |
50 { | |
51 uint y; | |
52 uchar *a = (uchar*)&y; | |
53 a[0] = x; | |
54 a[1] = x >> 8; | |
55 a[2] = x >> 16; | |
56 a[3] = x >> 24; | |
57 return y; | |
58 } | |
59 | |
60 int | |
61 main(int argc, char *argv[]) | |
62 { | |
63 int i, cc, fd; | |
64 uint rootino, inum, off; | |
65 struct dirent de; | |
66 char buf[512]; | |
67 struct dinode din; | |
68 | |
69 | |
70 static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); | |
71 | |
72 if(argc < 2){ | |
73 fprintf(stderr, "Usage: mkfs fs.img files...\n"); | |
74 exit(1); | |
75 } | |
76 | |
77 assert((512 % sizeof(struct dinode)) == 0); | |
78 assert((512 % sizeof(struct dirent)) == 0); | |
79 | |
80 fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); | |
81 if(fsfd < 0){ | |
82 perror(argv[1]); | |
83 exit(1); | |
84 } | |
85 | |
86 sb.size = xint(size); | |
87 sb.nblocks = xint(nblocks); // so whole disk is size sectors | |
88 sb.ninodes = xint(ninodes); | |
89 sb.nlog = xint(nlog); | |
90 | |
91 bitblocks = size/(512*8) + 1; | |
92 usedblocks = ninodes / IPB + 3 + bitblocks; | |
93 freeblock = usedblocks; | |
94 | |
95 printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks, | |
96 bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog); | |
97 | |
98 assert(nblocks + usedblocks + nlog == size); | |
99 | |
100 for(i = 0; i < nblocks + usedblocks + nlog; i++) | |
101 wsect(i, zeroes); | |
102 | |
103 memset(buf, 0, sizeof(buf)); | |
104 memmove(buf, &sb, sizeof(sb)); | |
105 wsect(1, buf); | |
106 | |
107 rootino = ialloc(T_DIR); | |
108 assert(rootino == ROOTINO); | |
109 | |
110 bzero(&de, sizeof(de)); | |
111 de.inum = xshort(rootino); | |
112 strcpy(de.name, "."); | |
113 iappend(rootino, &de, sizeof(de)); | |
114 | |
115 bzero(&de, sizeof(de)); | |
116 de.inum = xshort(rootino); | |
117 strcpy(de.name, ".."); | |
118 iappend(rootino, &de, sizeof(de)); | |
119 | |
120 for(i = 2; i < argc; i++){ | |
121 assert(index(argv[i], '/') == 0); | |
122 | |
123 if((fd = open(argv[i], 0)) < 0){ | |
124 perror(argv[i]); | |
125 exit(1); | |
126 } | |
127 | |
128 // Skip leading _ in name when writing to file system. | |
129 // The binaries are named _rm, _cat, etc. to keep the | |
130 // build operating system from trying to execute them | |
131 // in place of system binaries like rm and cat. | |
132 if(argv[i][0] == '_') | |
133 ++argv[i]; | |
134 | |
135 inum = ialloc(T_FILE); | |
136 | |
137 bzero(&de, sizeof(de)); | |
138 de.inum = xshort(inum); | |
139 strncpy(de.name, argv[i], DIRSIZ); | |
140 iappend(rootino, &de, sizeof(de)); | |
141 | |
142 while((cc = read(fd, buf, sizeof(buf))) > 0) | |
143 iappend(inum, buf, cc); | |
144 | |
145 close(fd); | |
146 } | |
147 | |
148 // fix size of root inode dir | |
149 rinode(rootino, &din); | |
150 off = xint(din.size); | |
151 off = ((off/BSIZE) + 1) * BSIZE; | |
152 din.size = xint(off); | |
153 winode(rootino, &din); | |
154 | |
155 balloc(usedblocks); | |
156 | |
157 exit(0); | |
158 } | |
159 | |
160 void | |
161 wsect(uint sec, void *buf) | |
162 { | |
163 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ | |
164 perror("lseek"); | |
165 exit(1); | |
166 } | |
167 if(write(fsfd, buf, 512) != 512){ | |
168 perror("write"); | |
169 exit(1); | |
170 } | |
171 } | |
172 | |
173 uint | |
174 i2b(uint inum) | |
175 { | |
176 return (inum / IPB) + 2; | |
177 } | |
178 | |
179 void | |
180 winode(uint inum, struct dinode *ip) | |
181 { | |
182 char buf[512]; | |
183 uint bn; | |
184 struct dinode *dip; | |
185 | |
186 bn = i2b(inum); | |
187 rsect(bn, buf); | |
188 dip = ((struct dinode*)buf) + (inum % IPB); | |
189 *dip = *ip; | |
190 wsect(bn, buf); | |
191 } | |
192 | |
193 void | |
194 rinode(uint inum, struct dinode *ip) | |
195 { | |
196 char buf[512]; | |
197 uint bn; | |
198 struct dinode *dip; | |
199 | |
200 bn = i2b(inum); | |
201 rsect(bn, buf); | |
202 dip = ((struct dinode*)buf) + (inum % IPB); | |
203 *ip = *dip; | |
204 } | |
205 | |
206 void | |
207 rsect(uint sec, void *buf) | |
208 { | |
209 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ | |
210 perror("lseek"); | |
211 exit(1); | |
212 } | |
213 if(read(fsfd, buf, 512) != 512){ | |
214 perror("read"); | |
215 exit(1); | |
216 } | |
217 } | |
218 | |
219 uint | |
220 ialloc(ushort type) | |
221 { | |
222 uint inum = freeinode++; | |
223 struct dinode din; | |
224 | |
225 bzero(&din, sizeof(din)); | |
226 din.type = xshort(type); | |
227 din.nlink = xshort(1); | |
228 din.size = xint(0); | |
229 winode(inum, &din); | |
230 return inum; | |
231 } | |
232 | |
233 void | |
234 balloc(int used) | |
235 { | |
236 uchar buf[512]; | |
237 int i; | |
238 | |
239 printf("balloc: first %d blocks have been allocated\n", used); | |
240 assert(used < 512*8); | |
241 bzero(buf, 512); | |
242 for(i = 0; i < used; i++){ | |
243 buf[i/8] = buf[i/8] | (0x1 << (i%8)); | |
244 } | |
245 printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3); | |
246 wsect(ninodes / IPB + 3, buf); | |
247 } | |
248 | |
249 #define min(a, b) ((a) < (b) ? (a) : (b)) | |
250 | |
251 void | |
252 iappend(uint inum, void *xp, int n) | |
253 { | |
254 char *p = (char*)xp; | |
255 uint fbn, off, n1; | |
256 struct dinode din; | |
257 char buf[512]; | |
258 uint indirect[NINDIRECT]; | |
259 uint x; | |
260 | |
261 rinode(inum, &din); | |
262 | |
263 off = xint(din.size); | |
264 while(n > 0){ | |
265 fbn = off / 512; | |
266 assert(fbn < MAXFILE); | |
267 if(fbn < NDIRECT){ | |
268 if(xint(din.addrs[fbn]) == 0){ | |
269 din.addrs[fbn] = xint(freeblock++); | |
270 usedblocks++; | |
271 } | |
272 x = xint(din.addrs[fbn]); | |
273 } else { | |
274 if(xint(din.addrs[NDIRECT]) == 0){ | |
275 // printf("allocate indirect block\n"); | |
276 din.addrs[NDIRECT] = xint(freeblock++); | |
277 usedblocks++; | |
278 } | |
279 // printf("read indirect block\n"); | |
280 rsect(xint(din.addrs[NDIRECT]), (char*)indirect); | |
281 if(indirect[fbn - NDIRECT] == 0){ | |
282 indirect[fbn - NDIRECT] = xint(freeblock++); | |
283 usedblocks++; | |
284 wsect(xint(din.addrs[NDIRECT]), (char*)indirect); | |
285 } | |
286 x = xint(indirect[fbn-NDIRECT]); | |
287 } | |
288 n1 = min(n, (fbn + 1) * 512 - off); | |
289 rsect(x, buf); | |
290 bcopy(p, buf + off - (fbn * 512), n1); | |
291 wsect(x, buf); | |
292 n -= n1; | |
293 off += n1; | |
294 p += n1; | |
295 } | |
296 din.size = xint(off); | |
297 winode(inum, &din); | |
298 } |