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