00001 #include <stdio.h>
00002 #include <unistd.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <fcntl.h>
00006 #include <assert.h>
00007 #include "types.h"
00008 #include "fs.h"
00009 #include "stat.h"
00010
00011 int nblocks = 995;
00012 int ninodes = 200;
00013 int size = 1024;
00014
00015 int fsfd;
00016 struct superblock sb;
00017 char zeroes[512];
00018 uint freeblock;
00019 uint usedblocks;
00020 uint bitblocks;
00021 uint freeinode = 1;
00022
00023 void balloc(int);
00024 void wsect(uint, void*);
00025 void winode(uint, struct dinode*);
00026 void rinode(uint inum, struct dinode *ip);
00027 void rsect(uint sec, void *buf);
00028 uint ialloc(ushort type);
00029 void iappend(uint inum, void *p, int n);
00030
00031
00032 ushort
00033 xshort(ushort x)
00034 {
00035 ushort y;
00036 uchar *a = (uchar*) &y;
00037 a[0] = x;
00038 a[1] = x >> 8;
00039 return y;
00040 }
00041
00042 uint
00043 xint(uint x)
00044 {
00045 uint y;
00046 uchar *a = (uchar*) &y;
00047 a[0] = x;
00048 a[1] = x >> 8;
00049 a[2] = x >> 16;
00050 a[3] = x >> 24;
00051 return y;
00052 }
00053
00054 int
00055 main(int argc, char *argv[])
00056 {
00057 int i, cc, fd;
00058 uint rootino, inum, off;
00059 struct dirent de;
00060 char buf[512];
00061 struct dinode din;
00062
00063 if(argc < 2){
00064 fprintf(stderr, "Usage: mkfs fs.img files...\n");
00065 exit(1);
00066 }
00067
00068 assert((512 % sizeof(struct dinode)) == 0);
00069 assert((512 % sizeof(struct dirent)) == 0);
00070
00071 fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
00072 if(fsfd < 0){
00073 perror(argv[1]);
00074 exit(1);
00075 }
00076
00077 sb.size = xint(size);
00078 sb.nblocks = xint(nblocks);
00079 sb.ninodes = xint(ninodes);
00080
00081 bitblocks = size/(512*8) + 1;
00082 usedblocks = ninodes / IPB + 3 + bitblocks;
00083 freeblock = usedblocks;
00084
00085 printf("used %d (bit %d ninode %lu) free %u total %d\n", usedblocks,
00086 bitblocks, ninodes/IPB + 1, freeblock, nblocks+usedblocks);
00087
00088 assert(nblocks + usedblocks == size);
00089
00090 for(i = 0; i < nblocks + usedblocks; i++)
00091 wsect(i, zeroes);
00092
00093 wsect(1, &sb);
00094
00095 rootino = ialloc(T_DIR);
00096 assert(rootino == ROOTINO);
00097
00098 bzero(&de, sizeof(de));
00099 de.inum = xshort(rootino);
00100 strcpy(de.name, ".");
00101 iappend(rootino, &de, sizeof(de));
00102
00103 bzero(&de, sizeof(de));
00104 de.inum = xshort(rootino);
00105 strcpy(de.name, "..");
00106 iappend(rootino, &de, sizeof(de));
00107
00108 for(i = 2; i < argc; i++){
00109 assert(index(argv[i], '/') == 0);
00110
00111 if((fd = open(argv[i], 0)) < 0){
00112 perror(argv[i]);
00113 exit(1);
00114 }
00115
00116
00117
00118
00119
00120 if(argv[i][0] == '_')
00121 ++argv[i];
00122
00123 inum = ialloc(T_FILE);
00124
00125 bzero(&de, sizeof(de));
00126 de.inum = xshort(inum);
00127 strncpy(de.name, argv[i], DIRSIZ);
00128 iappend(rootino, &de, sizeof(de));
00129
00130 while((cc = read(fd, buf, sizeof(buf))) > 0)
00131 iappend(inum, buf, cc);
00132
00133 close(fd);
00134 }
00135
00136
00137 rinode(rootino, &din);
00138 off = xint(din.size);
00139 off = ((off/BSIZE) + 1) * BSIZE;
00140 din.size = xint(off);
00141 winode(rootino, &din);
00142
00143 balloc(usedblocks);
00144
00145 exit(0);
00146 }
00147
00148 void
00149 wsect(uint sec, void *buf)
00150 {
00151 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
00152 perror("lseek");
00153 exit(1);
00154 }
00155 if(write(fsfd, buf, 512) != 512){
00156 perror("write");
00157 exit(1);
00158 }
00159 }
00160
00161 uint
00162 i2b(uint inum)
00163 {
00164 return (inum / IPB) + 2;
00165 }
00166
00167 void
00168 winode(uint inum, struct dinode *ip)
00169 {
00170 char buf[512];
00171 uint bn;
00172 struct dinode *dip;
00173
00174 bn = i2b(inum);
00175 rsect(bn, buf);
00176 dip = ((struct dinode*) buf) + (inum % IPB);
00177 *dip = *ip;
00178 wsect(bn, buf);
00179 }
00180
00181 void
00182 rinode(uint inum, struct dinode *ip)
00183 {
00184 char buf[512];
00185 uint bn;
00186 struct dinode *dip;
00187
00188 bn = i2b(inum);
00189 rsect(bn, buf);
00190 dip = ((struct dinode*) buf) + (inum % IPB);
00191 *ip = *dip;
00192 }
00193
00194 void
00195 rsect(uint sec, void *buf)
00196 {
00197 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
00198 perror("lseek");
00199 exit(1);
00200 }
00201 if(read(fsfd, buf, 512) != 512){
00202 perror("read");
00203 exit(1);
00204 }
00205 }
00206
00207 uint
00208 ialloc(ushort type)
00209 {
00210 uint inum = freeinode++;
00211 struct dinode din;
00212
00213 bzero(&din, sizeof(din));
00214 din.type = xshort(type);
00215 din.nlink = xshort(1);
00216 din.size = xint(0);
00217 winode(inum, &din);
00218 return inum;
00219 }
00220
00221 void
00222 balloc(int used)
00223 {
00224 uchar buf[512];
00225 int i;
00226
00227 printf("balloc: first %d blocks have been allocated\n", used);
00228 assert(used < 512);
00229 bzero(buf, 512);
00230 for(i = 0; i < used; i++) {
00231 buf[i/8] = buf[i/8] | (0x1 << (i%8));
00232 }
00233 printf("balloc: write bitmap block at sector %lu\n", ninodes/IPB + 3);
00234 wsect(ninodes / IPB + 3, buf);
00235 }
00236
00237 #define min(a, b) ((a) < (b) ? (a) : (b))
00238
00239 void
00240 iappend(uint inum, void *xp, int n)
00241 {
00242 char *p = (char*) xp;
00243 uint fbn, off, n1;
00244 struct dinode din;
00245 char buf[512];
00246 uint indirect[NINDIRECT];
00247 uint x;
00248
00249 rinode(inum, &din);
00250
00251 off = xint(din.size);
00252 while(n > 0){
00253 fbn = off / 512;
00254 assert(fbn < MAXFILE);
00255 if(fbn < NDIRECT) {
00256 if(xint(din.addrs[fbn]) == 0) {
00257 din.addrs[fbn] = xint(freeblock++);
00258 usedblocks++;
00259 }
00260 x = xint(din.addrs[fbn]);
00261 } else {
00262 if(xint(din.addrs[NDIRECT]) == 0) {
00263
00264 din.addrs[NDIRECT] = xint(freeblock++);
00265 usedblocks++;
00266 }
00267
00268 rsect(xint(din.addrs[NDIRECT]), (char*) indirect);
00269 if(indirect[fbn - NDIRECT] == 0) {
00270 indirect[fbn - NDIRECT] = xint(freeblock++);
00271 usedblocks++;
00272 wsect(xint(din.addrs[NDIRECT]), (char*) indirect);
00273 }
00274 x = xint(indirect[fbn-NDIRECT]);
00275 }
00276 n1 = min(n, (fbn + 1) * 512 - off);
00277 rsect(x, buf);
00278 bcopy(p, buf + off - (fbn * 512), n1);
00279 wsect(x, buf);
00280 n -= n1;
00281 off += n1;
00282 p += n1;
00283 }
00284 din.size = xint(off);
00285 winode(inum, &din);
00286 }