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