void parseCommand(char *command) { if (strcmp(command, "help") == 0) { putString("command list:\n"); putString("help -- display available command\n"); putString("clear -- clear the screen\n"); putString("exit -- halt the machine\n"); putString("date -- get date\n"); putString("time -- get time\n"); putString("asc -- load the custom asc program\n"); putString("test -- test program of system calls\n"); } else if (strcmp(command, "clear") == 0) clear(); else if (strcmp(command, "date") == 0) { putString(getDate()); putString("\n"); } else if (strcmp(command, "time") == 0) { putString(getTime()); putString("\n"); } else if (strcmp(command, "asc") == 0) loadSector(22, 2); else if (strcmp(command, "test") == 0) loadSector(24, 3); else if (strcmp(command, "exit") == 0) status = 0; }
/* 在文件系统中加载文件,文件大小写入size所指变量,返回bool值表示是否成功 */ bool loadFile(const char *path, uint32_t partitionFirstSector, uint32_t *size) { printString(" "); firstSector = partitionFirstSector; loadSector(firstSector + 2, superBlockBuffer); blockSize = (uint32_t) (1024 << superBlock->logBlockSize); sectorsPerBlock = blockSize / SECTOR_SIZE_512; if (superBlock->magic != EXT2_MAGIC_NUM) { printLine("incorrect ext2 magic number"); return false; } if (superBlock->revLevel < EXT2_DYNAMIC_REV) { printLine("reversion of this ext2 filesystem is too old"); return false; } if (blockSize > 0x10000) { printLine("block size is too large"); return false; } uint32_t targetInode = EXT2_INODE_ROOT; for (const char *nameEnd = path; *nameEnd != '\0';) { for (path = nameEnd; *path == '/'; ++path); for (nameEnd = path; *nameEnd != '/' && *nameEnd != '\0'; ++nameEnd); if (nameEnd == path) { break; } targetInode = findChild(targetInode, path, nameEnd - path); if (targetInode == EXT2_INODE_NULL) { printLine("can't find such file"); return false; } }; Ext2Inode inode = loadInode(targetInode); if ((inode.mode & EXT2_MODE_FT_MASK) != EXT2_MODE_FT_REG_FILE) { printLine("not a regular file"); return false; } else { printString("file found, size: "); printInt(inode.size); printString(" bytes ("); printStorageSize(inode.size); printLine(")"); } uint32_t blkCnt = inode.size / blockSize + (inode.size % blockSize != 0); for (uint32_t blockOffset = 0; blockOffset < blkCnt; ++blockOffset) { uint32_t block = getBlockIndex(&inode, blockOffset); if (!readFileSectorsToBuffer(lbaOfBlock(block), sectorsPerBlock)) { return false; } } *size = inode.size; return true; }
void load_sector(int n) { int head, cylinder, sector; sector = (n-1)%18+1; n = (n-1)/18; head = n/80; cylinder = n%80; loadSector(head, cylinder, sector); }
static Ext2Inode loadInode(uint32_t inodeIndex) { /* 先获取inode所在组,通过其获得inodeTable所在,最后定位到inode */ --inodeIndex; uint32_t grpNum = inodeIndex / superBlock->inodesPerGroup; uint32_t offsetInGrp = inodeIndex % superBlock->inodesPerGroup; uint32_t grpDescPerSct = (SECTOR_SIZE_512 / sizeof(Ext2BlockGroupDesc)); Ext2BlockGroupDesc bgdTable[grpDescPerSct]; uint8_t indTableBuf[SECTOR_SIZE_512]; loadSector(lbaOfBlock(superBlock->firstDataBlock + 1) + grpNum / grpDescPerSct, bgdTable); loadSector(lbaOfBlock(bgdTable[grpNum % grpDescPerSct].inodeTable) + offsetInGrp * superBlock->inodeSize / SECTOR_SIZE_512, indTableBuf); Ext2Inode *inode = (Ext2Inode *) &indTableBuf[ offsetInGrp * superBlock->inodeSize % SECTOR_SIZE_512]; return *inode; }
void SettingsManager::loadSettings(const MyGUI::UString& _fileName, bool _internal) { std::string _instance = "Editor"; MyGUI::xml::Document doc; if (_internal) { MyGUI::DataStreamHolder data = MyGUI::DataManager::getInstance().getData(_fileName); if (data.getData() != nullptr) { if (!doc.open(data.getData())) { MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError()); return; } } } else { if (!doc.open(_fileName)) { MYGUI_LOGGING(LogSection, Error, _instance << " : " << doc.getLastError()); return; } } MyGUI::xml::ElementPtr root = doc.getRoot(); if (!root || (root->getName() != "MyGUI")) { MYGUI_LOGGING(LogSection, Error, _instance << " : '" << _fileName << "', tag 'MyGUI' not found"); return; } std::string type; if (root->findAttribute("type", type)) { if (type == "Settings") { // берем детей и крутимся MyGUI::xml::ElementEnumerator field = root->getElementEnumerator(); while (field.next()) loadSector(field.current()); } } }
static uint32_t getBlockIndex(Ext2Inode *inode, uint32_t offset) { const uint32_t DIRECT_BLOCK_POINTER_COUNT = sizeof(inode->blockPointers) / sizeof(inode->blockPointers[0]); if (offset < DIRECT_BLOCK_POINTER_COUNT) { return inode->blockPointers[offset]; } /* 过程需要用到循环,blockPointer为当前得出的块指针 */ uint32_t blockPointer; /* recursion为寻找块号的迭代(循环)次数(0开始计数),对于可能为0,1,2 */ uint8_t recursion; /* 对于间接块指针,其中的一个item对应一个块,是为blocksPerItem[0]=1 * 而二阶间接块,则乘每个块中可以存储的块指针数目,三阶同理 * 而blocksPerItem[3]是为了代码的方便计算值,并不存在四阶间接块 */ uint32_t blocksPerItem[4]; blocksPerItem[0] = 1; blocksPerItem[1] = blockSize / sizeof(inode->blockPointers[0]); blocksPerItem[2] = blocksPerItem[1] * blocksPerItem[1]; blocksPerItem[3] = blocksPerItem[2] * blocksPerItem[1]; offset -= DIRECT_BLOCK_POINTER_COUNT; if (offset < blocksPerItem[1]) { blockPointer = inode->indirectBlockPointer; recursion = 0; } else { offset -= blocksPerItem[1]; if (offset < blocksPerItem[2]) { blockPointer = inode->doublyIndirectBlockPointer; recursion = 1; } else { offset -= blocksPerItem[2]; if (offset < blocksPerItem[3]) { blockPointer = inode->triplyIndirectBlockPointer; recursion = 2; } else { return INVALID_DATA_BLOCK; } } } /* 引入缓存提高效率,因为0扇区不可能被块指针指向,所以用来标记无缓存 */ static uint32_t caches[3][SECTOR_SIZE_512 / sizeof(uint32_t)]; static uint32_t itemsPerCache = sizeof(caches[0]) / sizeof(caches[0][0]); static uint32_t cachedSectors[3] = {0, 0, 0}; /* 每次只缓存一个扇区,其中包含的块指针项目数为itemsPerCache */ do { uint32_t sector = lbaOfBlock(blockPointer) + offset / blocksPerItem[recursion] / itemsPerCache; if (sector != cachedSectors[recursion]) { loadSector(cachedSectors[recursion] = sector, caches[recursion]); } blockPointer = caches[recursion][ offset / blocksPerItem[recursion] % itemsPerCache]; offset = offset % blocksPerItem[recursion]; } while (recursion-- > 0); return blockPointer; }
static uint32_t findChild( uint32_t dirInode, const char *childName, uint32_t nameLen) { Ext2Inode inode = loadInode(dirInode); if ((inode.mode & EXT2_MODE_FT_MASK) != EXT2_MODE_FT_DIR) { return EXT2_INODE_NULL; } /* 目录项一定占用整数个块,blkCnt */ uint32_t blkCnt = inode.size / blockSize + (inode.size % blockSize != 0); /* 一个目录项不可能跨块,但可能跨扇区,用第二个缓冲区作为副缓冲区 */ uint8_t buffers[2][SECTOR_SIZE_512]; uint32_t bufferedSector2 = 0; /* 当前的目录项和下一个目录项的指针 */ Ext2DirEntry *curEntry; Ext2DirEntry *nextEntry; /* 遍历目录文件的每一个块 */ for (uint32_t blockOffset = 0; blockOffset < blkCnt; ++blockOffset) { uint32_t block = getBlockIndex(&inode, blockOffset); if (block == INVALID_DATA_BLOCK) { return EXT2_INODE_NULL; } nextEntry = (Ext2DirEntry *) &buffers[0]; /* 遍历目录文件的每一个扇区 */ for (uint32_t sectorOffset = 0; sectorOffset < sectorsPerBlock;) { /* 副缓冲区本用作存储长文件名,但若其中有对应扇区,复制之,避免IO */ uint32_t sector = lbaOfBlock(block) + sectorOffset; if (sector == bufferedSector2) { for (uint32_t i = 0; i < SECTOR_SIZE_512; ++i) { buffers[0][i] = buffers[1][i]; } } else { loadSector(sector, buffers[0]); } /* 遍历目录项,不确定退出时机 */ for (;;) { /* 空目录项或者文件名不相等就直接跳过 */ if ((curEntry = nextEntry)->inode != EXT2_INODE_NULL && curEntry->nameLen == nameLen) { /* 如果文件名跨扇区,就要用副缓冲区延伸保存了 */ if (((uintptr_t) curEntry + offsetof(Ext2DirEntry, name) + curEntry->nameLen) >= (uintptr_t) &buffers[0] + SECTOR_SIZE_512) { bufferedSector2 = sector + 1; loadSector(bufferedSector2, buffers[1]); } /* 文件名一致就返回正确inode */ for (uint32_t i = 0; i < nameLen; ++i) { if (curEntry->name[i] != childName[i]) { break; } if (i == nameLen - 1) { return curEntry->inode; } } } /* next是nextEntry的uintptr_t形式表达 */ uintptr_t next = (uintptr_t) curEntry + curEntry->recLen; /* 下一个目录项是否超过扇区大小 */ if (next >= (uintptr_t) &buffers[0] + SECTOR_SIZE_512) { /* 是则要增加扇区偏移并且回滚nextEntry值,并结束当前扇区 */ uintptr_t offset = next - (uintptr_t) &buffers[0]; sectorOffset += offset / SECTOR_SIZE_512; next = (uintptr_t) &buffers[0] + offset % SECTOR_SIZE_512; nextEntry = (Ext2DirEntry *) next; break; } else { /* 否则继续在本扇区寻找 */ nextEntry = (Ext2DirEntry *) next; } } } } return EXT2_INODE_NULL; }