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
|
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 }