00001 #include <stddef.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <string.h>
00005 #include <assert.h>
00006 #include <iostream>
00007 
00008 #include "ubixfs.h"
00009 #include "btree.h"
00010 
00011 using namespace std;
00012 
00013 UbixFS::UbixFS(void) { 
00014   device = NULL;
00015   freeBlockList = NULL;
00016   superBlock = NULL;
00017   root = NULL;
00018 } 
00019 
00020 
00021 UbixFS::UbixFS(device_t * dev) {
00022   device = dev;
00023   freeBlockList = NULL;
00024   superBlock = NULL;
00025   root = NULL;
00026 } 
00027 
00028 void
00029 UbixFS::printSuperBlock(void) {
00030   printf("superBlock->name........... %s\n", superBlock->name);
00031   printf("superBlock->magic1......... %X\n", superBlock->magic1);
00032   printf("superBlock->fsByteOrder.... %d\n", superBlock->fsByteOrder);
00033   printf("superBlock->blockSize...... %d\n", superBlock->blockSize);
00034   printf("superBlock->blockShift..... %d\n", superBlock->blockShift);
00035   printf("superBlock->numBlocks...... %lld\n", superBlock->numBlocks);
00036   printf("superBlock->usedBlocks..... %lld\n", superBlock->usedBlocks);
00037   printf("superBlock->batSectors..... %d\n", superBlock->batSectors);
00038   printf("superBlock->inodeCount..... %d\n", superBlock->inodeCount);
00039   printf("superBlock->magic2......... %X\n", superBlock->magic2);
00040   printf("superBlock->blocksPerAG.... %d\n", superBlock->blocksPerAG);
00041   printf("superBlock->AGShift........ %d\n", superBlock->AGShift);
00042   printf("superBlock->numAGs......... %d\n", superBlock->numAGs);
00043   printf("superBlock->lastUsedAG..... %d\n", superBlock->lastUsedAG);
00044   printf("superBlock->flags.......... %X\n", superBlock->flags);
00045   printf("superBlock->magic3......... %X\n", superBlock->magic3);
00046   return;
00047 } 
00048 
00049 int 
00050 UbixFS::vfs_init(void) {
00051 assert(device);
00052   size_t result;
00053   cout << "vfs_init()" << endl;
00054   assert(device);
00055 
00056   if (device == NULL) return -1;
00057   if (superBlock != NULL) delete superBlock;
00058   superBlock = new diskSuperBlock;
00059 assert(superBlock);
00060   if (superBlock == NULL) return -1;
00061 
00062   
00063 cout << "reading in superBlock" << endl;
00064   device->read(device, superBlock, device->sectors-1, 1);
00065 cout << "done" << endl;
00066 
00067   assert(superBlock->magic1 == UBIXFS_MAGIC1);
00068   assert(superBlock->magic2 == UBIXFS_MAGIC2);
00069   assert(superBlock->magic3 == UBIXFS_MAGIC3);
00070   assert(strcmp(superBlock->name, "UbixFS") == 0);
00071   assert((1 << superBlock->blockShift) == superBlock->blockSize);
00072   assert((unsigned)(1 << superBlock->AGShift) == superBlock->blocksPerAG);
00073   assert(superBlock->flags == UBIXFS_CLEAN);
00074 
00075   if (freeBlockList != NULL) delete [] freeBlockList;
00076   freeBlockList = new signed char[superBlock->batSectors*512];
00077 assert(freeBlockList);
00078   memset(freeBlockList, 0, superBlock->batSectors*512);
00079 
00080   device->read(device, 
00081                freeBlockList, 
00082                device->sectors - superBlock->batSectors-1,
00083                superBlock->batSectors
00084               ); 
00085 
00086   root = new fileDescriptor;
00087   assert(root);
00088   memset(root, 0, sizeof(fileDescriptor));
00089 cout << "allocating root dir inode" << endl;
00090   root->inode = new ubixfsInode;
00091   memset(root->inode, 0, sizeof(ubixfsInode));
00092 cout << "root dir inode starting sector: " << 
00093                ((superBlock->rootDir.AG << superBlock->AGShift) 
00094                + superBlock->rootDir.start) * (superBlock->blockSize / 512)
00095      << endl;
00096 
00097 cout << "reading in root dir inode" << endl;
00098   
00099   device->read(device,
00100                root->inode,
00101                ((superBlock->rootDir.AG << superBlock->AGShift) 
00102                  + superBlock->rootDir.start) * (superBlock->blockSize / 512),
00103                sizeof(ubixfsInode) / 512
00104               );
00105 cout << "done" << endl;
00106   ubixfsInode * rootInode = static_cast<ubixfsInode *>(root->inode);
00107   assert(rootInode);
00108 
00109   
00110 
00111   rootInode->data.btPtr = new bTree(this, root);
00112   rootInode->data.btPtr->Info();
00113   printSuperBlock();
00114   return 0;
00115 } 
00116 
00117 int
00118 UbixFS::vfs_format(device_t * dev) {
00119   cout << "vfs_format()" << endl;
00120   char sector[512];
00121   uInt32 blocks, batSect, batSize;
00122   if (dev == NULL) return -1; 
00123 
00124   
00125   memset(§or, 0x0, sizeof(sector));
00126  
00127   
00128   cout << "dev->sectors: " << dev->sectors << endl;
00129   cout << "clearing device...";
00130 
00131   for (unsigned int i = 0; i < dev->sectors; i++) {
00132     dev->write(dev, §or, i, 1);
00133   } 
00134 
00135   cout << "done" << endl;
00136 
00137   
00138 
00139   diskSuperBlock *sb = new diskSuperBlock;
00140   if (sb == NULL) return -1;
00141   memset(sb, 0, sizeof(diskSuperBlock));
00142 
00143   
00144 
00145   blocks = (dev->sectors-1) / 8;     
00146   batSize = (dev->sectors-1) % 8;    
00147   
00148   
00149 
00150   while ((batSize * 4096) < blocks) {
00151     batSize += 8;
00152     --blocks;
00153   } 
00154  
00155   
00156   batSect = blocks * 8;
00157 
00158   strcpy(sb->name, "UbixFS");
00159   sb->magic1 = UBIXFS_MAGIC1;
00160   sb->fsByteOrder = 0;
00161   sb->blockSize = 4096;
00162   sb->blockShift = 12;
00163   sb->numBlocks = blocks;
00164   sb->usedBlocks = 2;  
00165   sb->inodeCount = 1;
00166   sb->inodeSize = 4096;
00167   sb->magic2 = UBIXFS_MAGIC2;
00168   sb->blocksPerAG = 2048;
00169   sb->AGShift = 11;
00170   sb->numAGs = (sb->numBlocks+2047) / 2048;
00171   sb->lastUsedAG = 0;
00172 
00173   
00174   
00175   sb->batSectors = batSize;
00176 
00177   sb->flags = 0x434C454E; 
00178   sb->logBlocks.AG = 0;
00179   sb->logBlocks.start = 0;
00180   sb->logBlocks.len = 0;
00181   sb->logStart = 0;
00182   sb->logEnd = 0;
00183   sb->magic3 = UBIXFS_MAGIC3;
00184   sb->indicies.AG = 0;
00185   sb->indicies.start = 0;
00186   sb->indicies.len = 0;
00187 
00188   sb->rootDir.AG = 0;
00189   sb->rootDir.start = 0;
00190   sb->rootDir.len = 1;
00191 
00192   
00193 
00194   dev->write(dev, sb, dev->sectors-1, 1);
00195 
00196   
00197   memset(§or, 0, sizeof(sector));
00198   sector[0] = (1 << 7) | (1 << 6);
00199 
00200   
00201 
00202   dev->write(dev, §or, batSect, 1);
00203   
00204   sector[0] = 0;
00205 
00206   
00207 
00208   for (unsigned int i = 1; i < batSize; i++) {
00209     dev->write(dev, §or, (batSect)+i, 1);
00210   } 
00211 
00212   
00213 
00214   
00215   assert(sb->blockSize);
00216   assert((unsigned)sb->blockSize >= sizeof(bTreeHeader));
00217 
00218   bTreeHeader * bth = new bTreeHeader;
00219   assert(bth);
00220   memset(bth, 0, sizeof(bTreeHeader));
00221 
00222   bth->firstDeleted = -1;
00223   bth->firstNodeOffset = -1;
00224   bth->treeDepth = 1;
00225   bth->treeWidth = 0;
00226   bth->treeLeafCount = 0;
00227 
00228   
00229 
00230   ubixfsInode * inode = new ubixfsInode;
00231   assert(inode);
00232   if (inode == NULL) return -1;
00233   memset(inode, 0, sizeof(ubixfsInode));
00234 
00235   inode->magic1 = UBIXFS_INODE_MAGIC;
00236 
00237   
00238   inode->inodeNum.AG = 0;
00239   inode->inodeNum.start = 0;
00240   inode->inodeNum.len = 1;
00241 
00242   
00243   inode->parent.iAddr.AG = 0;
00244   inode->parent.iAddr.start = 0;
00245   inode->parent.iAddr.len = 0;
00246 
00247   
00248   inode->blocks.direct[0].AG = 0;
00249   inode->blocks.direct[0].start = 1;
00250   inode->blocks.direct[0].len = 1;
00251    
00252   inode->blocks.maxDirectRange = sizeof(bTreeHeader);
00253   inode->blocks.size = sizeof(bTreeHeader);
00254 
00255   strcpy(inode->name, "/");
00256   inode->uid = getuid();
00257   inode->gid = getgid();
00258   
00259   inode->flags = INODE_DIRECTORY;
00260   
00261   
00262   
00263 
00264   inode->attributes.AG = 0;
00265   inode->attributes.start = 0;
00266   inode->attributes.len = 0;
00267 
00268   inode->inodeSize = sb->inodeSize;
00269 
00270   
00271 
00272 
00273 
00274 
00275 
00276   inode->next.offset = 0;
00277   inode->prev.offset = 0;
00278 
00279   
00280 
00281   dev->write(dev, 
00282              inode, 
00283              ((inode->inodeNum.AG << sb->AGShift) +
00284               inode->inodeNum.start) * (sb->blockSize / 512),
00285              sb->inodeSize / 512
00286             ); 
00287 
00288   
00289 
00290   dev->write(dev, 
00291              bth, 
00292              ((inode->blocks.direct[0].AG << sb->AGShift) + 
00293               inode->blocks.direct[0].start) * (sb->blockSize / 512),
00294              sb->blockSize / 512
00295             ); 
00296 
00297   delete inode;
00298   delete bth;
00299   delete sb;
00300   cout << "format complete" << endl;
00301   return 0;
00302 } 
00303 
00304 void *
00305 UbixFS::vfs_mknod(const char *path, mode_t mode) {
00306   return mknod(path, 0, mode);  
00307 } 
00308 
00309 int
00310 UbixFS::vfs_open(const char * filename, fileDescriptor * fd, int flags, ...) {
00311   if (filename == NULL || fd == NULL) return -1;
00312   flags = flags;
00313   fd->inode = NULL;
00314   fd->offset = 0;
00315   fd->size = 0;
00316   
00317   return 0;
00318 } 
00319 
00320 size_t
00321 UbixFS::vfs_read(fileDescriptor * fd, void * data, off_t offset, size_t size) {
00322   
00323   unsigned int i;
00324   off_t sum, startingBlock;
00325   size_t runSize, sectorCount, totalSize, bSize; 
00326   ubixfsInode * inode = NULL;
00327 
00328   if (fd == NULL || data == NULL) return ~0;
00329 
00330   if (size == 0) return 0; 
00331    
00332   assert(device);
00333   assert(superBlock);
00334 
00335   inode = static_cast<ubixfsInode *>(fd->inode);
00336 
00337   assert(inode);
00338 
00339   bSize = superBlock->blockSize;
00340 
00341   totalSize = sum = i = 0;
00342   
00343   while (size > 0) {
00344 
00345     
00346 
00347 
00348 
00349     
00350     do {
00351       if (offset >= sum && offset < sum + inode->blocks.direct[i].len * bSize)          break;
00352 
00353       sum += inode->blocks.direct[i++].len * bSize;
00354      
00355     } while (i < NUM_DIRECT_BLOCKS);
00356 
00357     startingBlock = (inode->blocks.direct[i].AG << superBlock->AGShift) + 
00358                      inode->blocks.direct[i].start + ((offset - sum) / bSize);
00359 
00360     runSize = inode->blocks.direct[i].len * bSize;
00361 
00362     
00363     startingBlock *= (bSize / 512);
00364     
00365 
00366     if (runSize >= size) {
00367       runSize = size;
00368       size = 0;
00369     } else { 
00370       size -= runSize;
00371     } 
00372 
00373     sectorCount = runSize / 512;
00374   
00375     cout << "device->read(device, data, " << startingBlock << ", ";
00376     cout << sectorCount << ");" << endl; 
00377 
00378     device->read(device, data, startingBlock, sectorCount);
00379 
00380     (uInt8 *)data += runSize;
00381     totalSize += runSize;
00382   } 
00383   return totalSize;
00384 } 
00385 
00386 size_t
00387 UbixFS::vfs_write(fileDescriptor * fd, void * data, off_t offset, size_t size) {
00388   
00389   unsigned int i, whichBlocks;
00390   off_t sum, startingBlock, EORPos, maxRange;
00391   size_t runSize, runRemainder, sectorCount, totalSize, bSize; 
00392   ubixfsInode * inode = NULL;
00393   blockRun br;
00394 
00395   if (fd == NULL || data == NULL) return ~0;
00396 
00397   if (size == 0) return 0; 
00398 
00399   assert(device);
00400   assert(superBlock);
00401 
00402   inode = static_cast<ubixfsInode *>(fd->inode);
00403 
00404   assert(inode);
00405 
00406   bSize = superBlock->blockSize;
00407   assert(bSize != 0);
00408 
00409   totalSize = sum = i = whichBlocks = 0;
00410 
00411   EORPos = offset + size;  
00412   maxRange = inode->blocks.maxDirectRange;
00413 
00414   if (inode->blocks.maxIndirectRange > maxRange) {
00415     maxRange = inode->blocks.maxIndirectRange;
00416     whichBlocks = 1;
00417   }
00418 
00419   if (inode->blocks.maxDoubleIndirectRange > maxRange) {
00420     maxRange = inode->blocks.maxDoubleIndirectRange;
00421     whichBlocks = 2;
00422   } 
00423   
00424   if (EORPos > maxRange) {
00425     
00426 
00427 
00428 
00429 
00430     switch (whichBlocks) {
00431       case 0:
00432         while (i < NUM_DIRECT_BLOCKS && inode->blocks.direct[i].len != 0) ++i;
00433         
00434         break;
00435       case 1:
00436       case 2:
00437         assert(false);  
00438         break;
00439       default:
00440         assert(false);  
00441     } 
00442 
00443     
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451     br.AG = inode->inodeNum.AG;        
00452     br.start = 0;                      
00453 
00454     
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478     br.len = ((EORPos - maxRange + (bSize-1)) / bSize);
00479 
00480     if (br.len < 8) br.len = 8;  
00481 
00482     br = getFreeBlock(br);
00483     assert(br.len > 0);
00484     switch (whichBlocks) {
00485       case 0:
00486         inode->blocks.direct[i] = br;
00487         inode->blocks.maxDirectRange += br.len * bSize;
00488         break;
00489       case 1:
00490         assert(false); 
00491         inode->blocks.maxIndirectRange += br.len * bSize;
00492         break;
00493       case 2:
00494         assert(false); 
00495         inode->blocks.maxDoubleIndirectRange += br.len * bSize;
00496         break;
00497       default:   
00498         assert(false); 
00499     } 
00500 
00501     inode->blocks.size = EORPos;
00502   } 
00503 
00504 
00505   runRemainder = size % 512;
00506   size -= runRemainder;
00507 
00508   totalSize = sum = i = 0;
00509 
00510   while (size > 0) {
00511 
00512     
00513 
00514 
00515 
00516     
00517     do {
00518       if (offset >= sum && offset < sum + inode->blocks.direct[i].len * bSize)
00519         break;
00520 
00521       sum += inode->blocks.direct[i++].len * bSize;
00522 
00523     } while (i < NUM_DIRECT_BLOCKS);
00524 
00525     startingBlock = (inode->blocks.direct[i].AG << superBlock->AGShift) +
00526                      inode->blocks.direct[i].start + ((offset - sum) / bSize);
00527 
00528     runSize = inode->blocks.direct[i].len * bSize;
00529 
00530     
00531     startingBlock *= (bSize / 512);
00532     
00533 
00534     if (runSize >= size) {
00535       runSize = size;
00536       size = 0;
00537     } else {
00538       size -= runSize;
00539     } 
00540 
00541     sectorCount = runSize / 512;
00542 
00543     cout << "device->write(device, data, " << startingBlock << ", ";
00544     cout << sectorCount << ");" << endl;
00545 
00546     device->write(device, data, startingBlock, sectorCount);
00547 
00548     (uInt8 *)data += runSize;
00549     totalSize += runSize;
00550   } 
00551 
00552   assert(runRemainder != 0);  
00553   return totalSize;
00554 } 
00555 
00556 int
00557 UbixFS::vfs_stop(void) {
00558   if (vfs_sync() != 0) return -1;
00559 
00560   
00561   
00562 
00563   if (root != NULL) {
00564     ubixfsInode * rootInode = static_cast<ubixfsInode *>(root->inode);
00565     delete rootInode->data.btPtr; 
00566     delete rootInode;
00567     root->inode = NULL;
00568     
00569   } 
00570 
00571   delete root;
00572   delete [] freeBlockList;
00573   delete superBlock;
00574 
00575   freeBlockList = NULL;
00576   superBlock = NULL; 
00577   root = NULL;
00578 
00579   
00580 
00581 
00582 
00583   
00584   return 0;
00585 } 
00586 
00587 int
00588 UbixFS::vfs_sync(void) {
00589   if (device == NULL || superBlock == NULL || freeBlockList == NULL) return -1;
00590   device->write(device, 
00591                 freeBlockList, 
00592                 device->sectors - superBlock->batSectors - 1, 
00593                 superBlock->batSectors
00594                );
00595   device->write(device, superBlock, device->sectors-1, 1);
00596   return 0;
00597 } 
00598 
00599 void
00600 UbixFS::setFreeBlock(blockRun ibr) {
00601   signed char * ptr;
00602   
00603   if (superBlock == NULL || freeBlockList == NULL) return;
00604   if (ibr.len == 0) return;
00605   ptr = freeBlockList + ((ibr.AG << superBlock->AGShift) >> 3);
00606   ptr += ibr.start >> 3;
00607 
00608   if (ibr.start % 8 != 0) {
00609     
00610     ibr.len -= ibr.start % 8;
00611   } 
00612 
00613 } 
00614 
00615 blockRun
00616 UbixFS::getFreeBlock(blockRun ibr) {
00617   signed char * ptr;
00618   signed char * holdPtr;
00619   int32 count, holdCount;
00620 
00621   blockRun obr = {0, 0, 0};  
00622 
00623   
00624   if (device == NULL || freeBlockList == NULL || superBlock == NULL) return obr;
00625 
00626   if (ibr.len == 0) return obr;
00627 
00628   if (ibr.len > superBlock->numBlocks) return obr;
00629 
00630   if (ibr.len == 1) return getFreeBlock(ibr.AG);
00631   
00632 
00633 
00634 
00635 
00636 
00637 
00638   count = (ibr.AG << superBlock->AGShift);
00639 
00640   
00641 
00642 
00643 
00644 
00645 
00646 
00647 
00648   ptr = freeBlockList + (count >> 3);
00649 
00650 rescan:
00651   
00652   while (*ptr != 0) {
00653     ++ptr;
00654     count += 8;
00655     if (count+8 > superBlock->numBlocks) {
00656       ptr = freeBlockList;
00657       count = 0;
00658     } 
00659   } 
00660 
00661   holdPtr = ptr;
00662   holdCount = count;
00663 
00664   for (unsigned short i = 0; i < ((ibr.len+7) / 8); i++) {
00665     ++ptr;
00666     count += 8;
00667     if (count+8 > superBlock->numBlocks) {
00668       ptr = freeBlockList;
00669       count = 0;
00670       goto rescan;
00671     } 
00672     if (*ptr != 0) goto rescan;
00673   } 
00674 
00675   
00676 
00677   obr.AG = holdCount / superBlock->blocksPerAG;
00678   obr.start = holdCount % superBlock->blocksPerAG;
00679   obr.len = ibr.len;
00680 
00681   for (unsigned short i = 0; i < (ibr.len / 8); i++) {
00682     *holdPtr = -1;
00683     ++holdPtr;
00684   } 
00685 
00686   if (ibr.len % 8 != 0) *holdPtr = (-1 << (8-(ibr.len % 8)));
00687 
00688   superBlock->usedBlocks += ibr.len;   
00689   return obr;
00690 } 
00691 
00692 blockRun
00693 UbixFS::getFreeBlock(uInt32 AG) {
00694   
00695   blockRun br;
00696   signed char * ptr;
00697   int32 count;
00698   int32 subCount = 128;
00699 
00700   br.AG = 0;
00701   br.start = 0;
00702   br.len = 0;
00703   
00704   if (device == NULL || freeBlockList == NULL || superBlock == NULL) return br;
00705 
00706   
00707   if (superBlock->numBlocks == superBlock->usedBlocks) return br;
00708 
00709   
00710 
00711 
00712 
00713 
00714 
00715 
00716   count = (AG << superBlock->AGShift);
00717 
00718   
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726   ptr = freeBlockList + (count >> 3);
00727 
00728   
00729 
00730 rescan:
00731   while (*ptr == -1) { 
00732     ++ptr;
00733     count += 8;
00734     if (count+8 > superBlock->numBlocks) break;
00735   } 
00736 
00737   subCount = 128;
00738 
00739   do {
00740     if ((*ptr & subCount) == 0) break;
00741     subCount >>= 1;
00742     ++count;
00743     if (count == superBlock->numBlocks) {
00744       count = 0;
00745       ptr = freeBlockList;
00746       goto rescan;
00747     } 
00748   } while(subCount > 1);
00749 
00750   *ptr |= subCount;           
00751   ++superBlock->usedBlocks;   
00752 
00753   br.AG = count / superBlock->blocksPerAG; 
00754   br.start = count % superBlock->blocksPerAG;
00755   br.len = 1;
00756   return br;               
00757 } 
00758 
00759 uInt32
00760 UbixFS::getNextAG(void) {
00761 
00762   if (superBlock->lastUsedAG == superBlock->numAGs) 
00763     superBlock->lastUsedAG = 0;
00764   else
00765     superBlock->lastUsedAG++;
00766   return superBlock->lastUsedAG;
00767 
00768 } 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 blockRun
00777 UbixFS::getFreeBlock(void) {
00778   return getFreeBlock(getNextAG());
00779 } 
00780 
00781 blockRun
00782 UbixFS::get8FreeBlocks(uInt32 AG) {
00783   
00784   blockRun br;
00785   signed char * ptr;
00786   signed char * endPtr;
00787   int32 count;
00788 
00789   br.AG = 0;
00790   br.start = 0;
00791   br.len = 0;
00792 
00793   if (device == NULL || freeBlockList == NULL || superBlock == NULL) return br;
00794 
00795   
00796   if (superBlock->usedBlocks+8 > superBlock->numBlocks) return br;
00797 
00798   
00799 
00800 
00801 
00802 
00803 
00804 
00805   count = (AG << superBlock->AGShift);
00806 
00807   ptr = freeBlockList + (count >> 3);
00808   
00809   endPtr = freeBlockList + (superBlock->numBlocks >> 3);
00810 
00811   bool secondTime = false;
00812   while (*ptr != 0) {
00813     ++ptr;
00814     count += 8;
00815     if (ptr == endPtr) {
00816       if (secondTime) 
00817         return br; 
00818       else 
00819         secondTime = true;
00820 
00821       count = 0;
00822       ptr = freeBlockList;      
00823     } 
00824   } 
00825 
00826   *ptr = -1;   
00827 
00828   br.AG = count / superBlock->blocksPerAG;
00829   br.start = count % superBlock->blocksPerAG;
00830   br.len = 8;
00831   return br;
00832 } 
00833 
00834 void *
00835 UbixFS::mknod(const char *filename, ubixfsInode * parent, mode_t mode) {
00836   ubixfsInode * inode = NULL;
00837 
00838   inode = new ubixfsInode;
00839   assert(inode);
00840   if (inode == NULL) return NULL;
00841   memset(inode, 0, sizeof(ubixfsInode));
00842 
00843   inode->magic1 = UBIXFS_INODE_MAGIC;
00844 
00845   
00846 
00847 
00848 
00849 
00850 
00851   if (parent == NULL) {
00852     inode->inodeNum = getFreeBlock();
00853     inode->parent.iAddr.AG = 0;
00854     inode->parent.iAddr.start = 0;
00855     inode->parent.iAddr.len = 0;
00856   } else {
00857     inode->inodeNum = getFreeBlock(parent->inodeNum.AG);
00858     inode->parent.iAddr = parent->inodeNum;
00859   } 
00860    
00861   strncpy(inode->name, filename, MAX_FILENAME_LENGTH);
00862 
00863   inode->uid = getuid();
00864   inode->gid = getgid();
00865   
00866   inode->flags = mode;
00867   
00868   
00869   inode->inodeSize = superBlock->inodeSize;
00870 
00871   inode->attributes.AG = 0;
00872   inode->attributes.start = 0;
00873   inode->attributes.len = 0;
00874 
00875   
00876 
00877   
00878 
00879 
00880 
00881 
00882 
00883   inode->next.offset = 0;
00884   inode->prev.offset = 0;
00885   inode->refCount = 0;
00886   ++superBlock->inodeCount;
00887   return inode;
00888 } 
00889 
00890 int
00891 UbixFS::vfs_mkdir(const char * path, mode_t mode) {
00892   char name[MAX_FILENAME_LENGTH];
00893   unsigned int start, end, len, nameStart;
00894   ubixfsInode * dir = static_cast<ubixfsInode *>(root->inode);
00895   ubixfsInode * inode = NULL;
00896 
00897   assert(path);                     
00898   assert(*path);                    
00899 
00900   memset(&name, 0, sizeof(name));
00901   
00902   len = strlen(path);
00903 
00904   assert(path[0] == '/');           
00905   assert(len > 1);                  
00906 
00907   
00908   if (path[len-1] == '/') --len;
00909 
00910   assert(len > 1);                  
00911 
00912   nameStart = len-1;
00913 
00914   assert(path[nameStart] != '/');   
00915 
00916   
00917 
00918 
00919 
00920 
00921 
00922 
00923   while (path[nameStart] != '/') --nameStart;
00924   ++nameStart;
00925   assert(len - nameStart > 0);
00926 
00927   
00928 
00929 
00930 
00931 
00932 
00933 
00934 
00935   start = end = 1;   
00936   while (end < nameStart) {
00937     do { ++end; } while(path[end] != '/');
00938 
00939     assert(end-start+1 < sizeof(name));
00940     
00941     strncpy(name, &path[start], end-start+1);
00942     cout << name << endl;
00943     dir = dir->data.btPtr->Find(name);
00944     assert(dir);
00945     assert(dir->flags & INODE_DIRECTORY == INODE_DIRECTORY);
00946     start = ++end;
00947   }
00948 
00949   strncpy(name, &path[nameStart], len - nameStart);
00950   inode = (ubixfsInode *)mknod(name, dir, mode | INODE_DIRECTORY);
00951 
00952   
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960   assert(dir->data.btPtr->Insert(inode->name, inode));
00961 
00962   return 0;
00963 } 
00964 
00965 void 
00966 UbixFS::printFreeBlockList(uInt32 AG) {
00967   unsigned int j;
00968   if (superBlock == NULL || freeBlockList == NULL) return;
00969   printf("AG = %d\n", AG);
00970   for (unsigned int i = 0; i < superBlock->blocksPerAG / 8; i++) {
00971     j = 128;
00972     signed char foo = freeBlockList[(AG << superBlock->AGShift)+i];
00973     while (j > 0) {
00974       if ((foo & j) == j) 
00975         printf("1");
00976       else
00977         printf("0");    
00978       j >>= 1;
00979  
00980     }
00981   } 
00982   printf("\n");
00983   return;
00984 } 
00985 
00986 UbixFS::~UbixFS(void) {
00987   delete [] freeBlockList;
00988   return;
00989 }