Xv6 with picoc & Linkage editor  v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
mkfs.c
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 
00008 #define stat xv6_stat  // avoid clash with host struct stat
00009 #include "types.h"
00010 #include "fs.h"
00011 #include "stat.h"
00012 #include "param.h"
00013 
00014 int nlog = LOGSIZE;
00015 int ninodes = 200;
00016 int size = 1024*32;
00017 int nblocks = 985;
00018 
00019 int fsfd;
00020 struct superblock sb;
00021 char zeroes[512];
00022 uint freeblock;
00023 uint usedblocks;
00024 uint bitblocks;
00025 uint freeinode = 1;
00026 
00027 
00028 
00029 void balloc(int);
00030 void wsect(uint, void*);
00031 void winode(uint, struct dinode*);
00032 void rinode(uint inum, struct dinode *ip);
00033 void rsect(uint sec, void *buf);
00034 uint ialloc(ushort type);
00035 void iappend(uint inum, void *p, int n);
00036 
00037 // convert to intel byte order
00038 ushort
00039 xshort(ushort x)
00040 {
00041   ushort y;
00042   uchar *a = (uchar*)&y;
00043   a[0] = x;
00044   a[1] = x >> 8;
00045   return y;
00046 }
00047 
00048 uint
00049 xint(uint x)
00050 {
00051   uint y;
00052   uchar *a = (uchar*)&y;
00053   a[0] = x;
00054   a[1] = x >> 8;
00055   a[2] = x >> 16;
00056   a[3] = x >> 24;
00057   return y;
00058 }
00059 
00060 // *added To create directories like bin , home
00061 void 
00062 adddir(char *name,uint* curino ,uint parino){
00063 
00064   uint inum;
00065   struct dirent de;
00066 
00067   *curino = inum = ialloc(T_DIR); 
00068   bzero(&de, sizeof(de));
00069   de.inum = xshort(inum);
00070   strcpy(de.name, name);
00071   iappend(parino, &de, sizeof(de));
00072 
00073   bzero(&de, sizeof(de));
00074   de.inum = xshort(inum);
00075   strcpy(de.name, ".");
00076   iappend(inum, &de, sizeof(de));
00077 
00078   bzero(&de, sizeof(de));
00079   de.inum = xshort(parino);
00080   strcpy(de.name, "..");
00081   iappend(inum, &de, sizeof(de));
00082 }
00083 int
00084 main(int argc, char *argv[])  // make file system using arguments given
00085 {
00086   int i, cc, fd;
00087   uint rootino, inum, off, binino, docino, tmp;
00088   struct dirent de;
00089   char buf[512];
00090   struct dinode din;
00091 
00092   if(argc < 2){
00093     fprintf(stderr, "Usage: mkfs fs.img files...\n");
00094     exit(1);
00095   }
00096 
00097   assert((512 % sizeof(struct dinode)) == 0);
00098   assert((512 % sizeof(struct dirent)) == 0);
00099 
00100   fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
00101   if(fsfd < 0){
00102     perror(argv[1]);
00103     exit(1);
00104   }
00105 
00106   sb.size = xint(size);
00107   sb.nblocks = xint(nblocks); // so whole disk is size sectors
00108   sb.ninodes = xint(ninodes);
00109   sb.nlog = xint(nlog);
00110 
00111   bitblocks = size/(512*8) + 1;
00112   usedblocks = ninodes / IPB + 3 + bitblocks;
00113   freeblock = usedblocks;
00114   nblocks = size - usedblocks - LOGSIZE;
00115 
00116   printf("used %d (bit %d ninode %zu) free %u log %u total %d and value of nblocks %d\n", usedblocks,
00117          bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog,nblocks);
00118 
00119   assert(nblocks + usedblocks + nlog == size);
00120 
00121   for(i = 0; i < nblocks + usedblocks + nlog; i++)
00122     wsect(i, zeroes);
00123 
00124   memset(buf, 0, sizeof(buf));
00125   memmove(buf, &sb, sizeof(sb));
00126   wsect(1, buf);
00127 
00128   rootino = ialloc(T_DIR);
00129   assert(rootino == ROOTINO);
00130 
00131   bzero(&de, sizeof(de));
00132   de.inum = xshort(rootino);
00133   strcpy(de.name, ".");
00134   iappend(rootino, &de, sizeof(de));
00135 
00136   bzero(&de, sizeof(de));
00137   de.inum = xshort(rootino);
00138   strcpy(de.name, "..");
00139   iappend(rootino, &de, sizeof(de));
00140 
00141   adddir("bin", &binino, rootino);
00142   adddir("doc", &docino, rootino);
00143   adddir("home", &inum, rootino);
00144 
00145 
00146   for(i = 2; i < argc; i++){ 
00147     assert(index(argv[i], '/') == 0);
00148     tmp = rootino;
00149     if((fd = open(argv[i], 0)) < 0){
00150       perror(argv[i]);
00151       exit(1);
00152     }
00153     
00154     // Skip leading _ in name when writing to file system.
00155     // The binaries are named _rm, _cat, etc. to keep the
00156     // build operating system from trying to execute them
00157     // in place of system binaries like rm and cat.
00158     if(argv[i][0] == '_'){
00159 //      if(argv[i][1] != 'i' )
00160         tmp = binino;
00161       ++argv[i];
00162     }
00163     else
00164       tmp = docino;
00165 
00166     inum = ialloc(T_FILE);
00167 
00168     bzero(&de, sizeof(de));
00169     de.inum = xshort(inum);
00170     strncpy(de.name, argv[i], DIRSIZ);
00171     iappend(tmp, &de, sizeof(de));
00172 
00173     while((cc = read(fd, buf, sizeof(buf))) > 0)
00174       iappend(inum, buf, cc);
00175 
00176     close(fd);
00177   }
00178 
00179   // fix size of root inode dir
00180   rinode(rootino, &din);
00181   off = xint(din.size);
00182   off = ((off/BSIZE) + 1) * BSIZE;
00183   din.size = xint(off);
00184   winode(rootino, &din);
00185 
00186   balloc(usedblocks);
00187 
00188   exit(0);
00189 }
00190 
00191 void
00192 wsect(uint sec, void *buf)    // writes data on given sector give sector number and buffer
00193 {
00194   if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
00195     perror("lseek");
00196     exit(1);
00197   }
00198   if(write(fsfd, buf, 512) != 512){
00199     perror("write");
00200     exit(1);
00201   }
00202 }
00203 
00204 uint
00205 i2b(uint inum)     // tells block number in which inode is stored  
00206 {
00207   return (inum / IPB) + 2; // why +2 ?
00208 }
00209 
00210 void
00211 winode(uint inum, struct dinode *ip)   // 
00212 {
00213   char buf[512];
00214   uint bn;
00215   struct dinode *dip;
00216 
00217   bn = i2b(inum);   // block in which inode will be stored  
00218   rsect(bn, buf);   // it will read  block into  buffer
00219   dip = ((struct dinode*)buf) + (inum % IPB); //  what is use of dip here  
00220   *dip = *ip;
00221   wsect(bn, buf); // write into sector pointer by buffer
00222 }
00223 
00224 void
00225 rinode(uint inum, struct dinode *ip)   // read buffer from it 
00226 {
00227   char buf[512];
00228   uint bn;
00229   struct dinode *dip;
00230 
00231   bn = i2b(inum);
00232   rsect(bn, buf);
00233   dip = ((struct dinode*)buf) + (inum % IPB);
00234   *ip = *dip;
00235 }
00236 
00237 void
00238 rsect(uint sec, void *buf)  // read sectors 
00239 {
00240   if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
00241     perror("lseek");
00242     exit(1);
00243   }
00244   if(read(fsfd, buf, 512) != 512){
00245     perror("read");
00246     exit(1);
00247   }
00248 }
00249 
00250 uint
00251 ialloc(ushort type)  // allocates inodes
00252 {
00253   uint inum = freeinode++;
00254   struct dinode din;
00255 
00256   bzero(&din, sizeof(din));
00257   din.type = xshort(type);
00258   din.nlink = xshort(1);
00259   din.size = xint(0);
00260   winode(inum, &din);
00261   return inum;
00262 }
00263  
00264 void            //need to make changes here as it will create problems 
00265 balloc(int used)  // allocate sector in bitmap mark it as 1 and write it back
00266 {
00267   uchar buf[512];
00268   int i,j;
00269 
00270   printf("balloc: first %d blocks have been allocated\n", used);
00271   assert(used < bitblocks*512*8);  //*changed
00272   bzero(buf, 512);  // make zero in buffer 
00273   for(j = 0; j < bitblocks ; j++){ //*changed for multiple bitmap blocks
00274     for(i = 0; i < 512*8 && (i+j*512*8) < used; i++){
00275       buf[i/8] = buf[i/8] | (0x1 << (i%8));  // make all used ones set 
00276     }
00277 //    printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3+j);
00278     wsect(ninodes / IPB + 3 + j, buf); // written back to fs
00279     bzero(buf, 512);
00280   }
00281   
00282 }
00283 
00284 #define min(a, b) ((a) < (b) ? (a) : (b))
00285 
00286 void
00287 iappend(uint inum, void *xp, int n)  // this function take 512 buffer writes into fs and do work if size greater thatn where to put buffer
00288 {
00289   char *p = (char*)xp;
00290   uint fbn, off, n1;
00291   struct dinode din;
00292   char buf[512];
00293   uint tmp,tmp1;
00294   uint indirect[NINDIRECT];
00295   uint indirect_w[NINDIRECT];  // for reading first indirect block
00296   uint dindirect[NINDIRECT];  // for rading second indiret block
00297   
00298   uint x;
00299 
00300   rinode(inum, &din);  // read inode i din
00301 
00302   off = xint(din.size); // offset set to current size
00303   while(n > 0){
00304     fbn = off / 512;  // calculate how many blocks already used
00305     assert(fbn < MAXFILE); 
00306     if(fbn < (NDIRECT-1)){  
00307       if(xint(din.addrs[fbn]) == 0){    // 
00308         din.addrs[fbn] = xint(freeblock++);  // free block count increased and usedblock count then it is written to fs
00309         usedblocks++;
00310       }
00311       x = xint(din.addrs[fbn]);
00312     } else if(fbn < (NDIRECT + NINDIRECT-1)){
00313       if(xint(din.addrs[NDIRECT-1]) == 0){
00314 //        printf("allocate indirect block %d\n", freeblock+1);
00315         din.addrs[NDIRECT-1] =  xint(freeblock++);
00316         usedblocks++;
00317       }
00318       // printf("read indirect block\n");
00319       rsect(xint(din.addrs[NDIRECT-1]), (char*)indirect);
00320       if(indirect[fbn - NDIRECT + 1] == 0){
00321         indirect[fbn - NDIRECT + 1] =  xint(freeblock++);
00322         usedblocks++;
00323         wsect(xint(din.addrs[NDIRECT-1]), (char*)indirect);
00324       }
00325       x = xint(indirect[fbn-NDIRECT+1]);
00326     }
00327 
00328 // for double indirect 
00329      else{
00330       if(xint(din.addrs[NDIRECT]) == 0){
00331 // allocate doub'le indirect blocks here 
00332         din.addrs[NDIRECT]  = xint(freeblock++);
00333         usedblocks++;
00334        }
00335         // get first indirect block then get the 2nd indirect block from other
00336       rsect(xint(din.addrs[NDIRECT]), (char*)indirect_w);
00337       tmp1 = (fbn-NINDIRECT-NDIRECT +1);
00338       tmp = tmp1/NINDIRECT;
00339       if(indirect_w[tmp] == 0){
00340         indirect_w[tmp] =  xint(freeblock++);
00341         usedblocks++;
00342         printf("Indirect 1st block allocated is %d\n",usedblocks-1);
00343         wsect(xint(din.addrs[NDIRECT]), (char*)indirect_w);
00344       }
00345 
00346       rsect(indirect_w[tmp], (char*)dindirect);
00347       if(dindirect[tmp1 % NINDIRECT] == 0){
00348         dindirect[tmp1 % NINDIRECT] =  xint(freeblock++);
00349         usedblocks++;
00350         wsect(indirect_w[tmp], (char*)dindirect);
00351       }
00352       x = xint(dindirect[tmp1 % NINDIRECT]);    
00353     }   
00354     
00355     n1 = min(n, (fbn + 1) * 512 - off);
00356     rsect(x, buf);
00357     bcopy(p, buf + off - (fbn * 512), n1);
00358     wsect(x, buf);
00359     n -= n1;
00360     off += n1;
00361     p += n1;
00362   }
00363   din.size = xint(off);
00364 //  printf("final check on %d %d\n", din.addrs[NDIRECT-1],din.addrs[NDIRECT]);
00365   winode(inum, &din);
00366 }
 All Data Structures