// ======================================================= void CExt2Part::readSuperBlock() { BEGIN; CExt2Super sb; int nRes; // init memset(&m_info, 0, sizeof(CInfoExt2Header)); // 0. go to the beginning of the super block nRes = fseek(m_fDeviceFile, 1024, SEEK_SET); if (nRes == -1) goto error_readSuperBlock; // 1. read and print important informations nRes = fread(&sb, sizeof(sb), 1, m_fDeviceFile); if (nRes != 1) goto error_readSuperBlock; // check partition has an ext2 file system if (sb.s_magic != Le16ToCpu(EXT2_SUPER_MAGIC)) goto error_readSuperBlock; // read and print important informations m_info.dwBlockSize = (EXT2_MIN_BLOCK_SIZE << Le32ToCpu(sb.s_log_block_size)); //sb.s_blocksize; //EXT2_BLOCK_SIZE(m_fs->super); showDebug(1, "blksize=%lu\n", m_info.dwBlockSize); m_info.dwFirstBlock = Le32ToCpu(sb.s_first_data_block); showDebug(1, "first=%lu\n", m_info.dwFirstBlock); m_info.dwTotalBlocksCount = Le32ToCpu(sb.s_blocks_count); showDebug(1, "total blocks=%lu\n", m_info.dwTotalBlocksCount); m_info.dwBlocksPerGroup = Le32ToCpu(sb.s_blocks_per_group); showDebug(1, "BlocksPerGroup=%lu\n", m_info.dwBlocksPerGroup); m_info.dwGroupsCount = (m_info.dwTotalBlocksCount - m_info.dwFirstBlock + m_info.dwBlocksPerGroup - 1) / Le32ToCpu(sb.s_blocks_per_group); showDebug(1, "groups=%lu\n", m_info.dwGroupsCount); m_info.dwLogicalBlocksPerExt2Block = m_info.dwBlockSize / LOGICAL_EXT2_BLKSIZE; showDebug(1, "m_info.dwLogicalBlocksPerExt2Block=%lu\n",m_info.dwLogicalBlocksPerExt2Block); showDebug(1, "logperblok=%lu\n", m_info.dwLogicalBlocksPerExt2Block); m_info.dwDescPerBlock = m_info.dwBlockSize / sizeof(CExt2GroupDesc); m_info.dwDescBlocks = (m_info.dwGroupsCount + m_info.dwDescPerBlock - 1) / m_info.dwDescPerBlock; //debugWin("m_info.dwDescBlocks=%lu",(DWORD)m_info.dwDescBlocks); // virtual blocks used in the abstract CFSBase m_header.qwBlocksCount = m_info.dwTotalBlocksCount * m_info.dwLogicalBlocksPerExt2Block; m_header.qwBlockSize = LOGICAL_EXT2_BLKSIZE; m_header.qwBitmapSize = ((m_header.qwBlocksCount+7) / 8)+16; m_header.qwUsedBlocks = (m_info.dwTotalBlocksCount - Le32ToCpu(sb.s_free_blocks_count)) * m_info.dwLogicalBlocksPerExt2Block; //debugWin("freeblks=%lu", sb.s_free_blocks_count); strncpy(m_header.szLabel, sb.s_volume_name, 64); // features m_info.dwFeatureCompat = Le32ToCpu(sb.s_feature_compat); m_info.dwFeatureIncompat = Le32ToCpu(sb.s_feature_incompat); m_info.dwFeatureRoCompat = Le32ToCpu(sb.s_feature_ro_compat); // misc infos m_info.dwRevLevel = Le32ToCpu(sb.s_rev_level); // Revision level memcpy(m_info.cUuid, sb.s_uuid, 16); // 128-bit uuid for volume //success_readSuperBlock: setSuperBlockInfos(true, true, m_header.qwUsedBlocks*m_header.qwBlockSize, ((QWORD)Le32ToCpu(sb.s_free_blocks_count)) * ((QWORD)m_info.dwBlockSize)); showDebug(1, "end success\n"); RETURN; error_readSuperBlock: g_interface -> ErrorReadingSuperblock(errno); THROW(ERR_WRONG_FS); }
// ======================================================= void CExt2Part::readBitmap(COptions *options) // FULLY WORKING { BEGIN; DWORD i, j; CExt2GroupDesc *desc; int nRes; DWORD dwBlocksInThisGroup; DWORD dwBootBlocks; char *cTempBitmap; DWORD dwBit, dwByte; DWORD dwExt2DataBlock; char *cPtr; int group = 0; // debug DWORD dwUsed; DWORD dwFree; dwBootBlocks = m_info.dwFirstBlock / m_info.dwLogicalBlocksPerExt2Block; //debugWin("dwBootBlocks=%lu and m_info.dwLogicalBlocksPerExt2Block=%lu",dwBootBlocks,m_info.dwLogicalBlocksPerExt2Block); cTempBitmap = new char[((m_info.dwTotalBlocksCount+7)/8)+4096]; if (!cTempBitmap) { showDebug(1, "CExt2Part::readBitmap(): Error 001\n"); goto error_readBitmap; } // init bitmap size nRes = m_bitmap.init(m_header.qwBitmapSize); showDebug(1, "m_bitmap.init(m_header.qwBitmapSize = %lu)\n", m_header.qwBitmapSize); if (nRes == -1) { showDebug(1, "CExt2Part::readBitmap(): Error 002\n"); goto error_readBitmap; } // load group descriptors desc = new CExt2GroupDesc[m_info.dwGroupsCount+m_info.dwDescPerBlock]; showDebug(1, "dwGroupsCount = %lu, m_info.dwDescPerBlock = %lu\n",m_info.dwGroupsCount, m_info.dwDescPerBlock); if (!desc) { showDebug(1, "CExt2Part::readBitmap(): Error 003\n"); goto error_readBitmap; } // for each descriptor BLOCK (not group descriptor!) showDebug(1, "readData m_info.dwBlockSize = %lu\n", m_info.dwBlockSize); for (cPtr=(char*)desc, i=0; i < m_info.dwDescBlocks; i++,cPtr+=m_info.dwBlockSize) { nRes = readData(cPtr, ((QWORD)m_info.dwBlockSize) * ((QWORD)(m_info.dwFirstBlock+1+i)), m_info.dwBlockSize); if (nRes == -1) { showDebug(1, "CExt2Part::readBitmap(): Error 004\n"); goto error_readBitmap; } } dwUsed=0; dwFree=0; showDebug(1, "m_info.dwBlocksPerGroup = %lu\n", m_info.dwBlocksPerGroup); for (i = 0; i < m_info.dwGroupsCount; i++) { if (m_info.dwFirstBlock+((i+1)*m_info.dwBlocksPerGroup) > m_info.dwTotalBlocksCount) dwBlocksInThisGroup = (m_info.dwTotalBlocksCount-m_info.dwFirstBlock) - (i*m_info.dwBlocksPerGroup); else dwBlocksInThisGroup = m_info.dwBlocksPerGroup; if (Le32ToCpu(desc[i].bg_block_bitmap)) { // -- read the bitmap block errno = 0; nRes = readData(cTempBitmap+(i*(m_info.dwBlocksPerGroup/8)), ((QWORD)m_info.dwBlockSize) * ((QWORD)Le32ToCpu(desc[i].bg_block_bitmap)), (m_info.dwBlocksPerGroup/8)); if (nRes == -1) { showDebug(1, "CExt2Part::readBitmap(): Error 005\n"); showDebug(1, "CExt2Part::readBitmap(): err=%d=%d\n", errno, strerror(errno)); goto error_readBitmap; } } else { memset(cTempBitmap+(i*(m_info.dwBlocksPerGroup/8)), 0, (m_info.dwBlocksPerGroup/8)); } } // convert bitmap to little endian DWORD *dwPtr; DWORD dwLen; dwLen = sizeof(cTempBitmap) / sizeof(DWORD); dwPtr = (DWORD *)cTempBitmap; for (i=0; i < dwLen; i++, dwPtr++) *dwPtr = CpuToLe32(*dwPtr); // bitmap is full of 0 at init, then we just have to // write 1 for used blocks // the boot block of 1024 bytes = used for (i=0; i < dwBootBlocks; i++) m_bitmap.setBit(i, true); dwUsed=0; dwFree=0; for (i=dwBootBlocks, dwExt2DataBlock=0; dwExt2DataBlock < ( m_info.dwTotalBlocksCount- m_info.dwFirstBlock); dwExt2DataBlock++) { dwBit = dwExt2DataBlock % 8; dwByte = (dwExt2DataBlock - dwBit) / 8; group = (dwExt2DataBlock/m_info.dwBlocksPerGroup); if ((cTempBitmap[dwByte] & (1 << dwBit)) != 0) { for (j=0; j < m_info.dwLogicalBlocksPerExt2Block; j++, i++) m_bitmap.setBit(i, true); showDebug(3, "m_bitmap.setBit(%1u, true), g = %i\n", (i/4), group); dwUsed++; } else { for (j=0; j < m_info.dwLogicalBlocksPerExt2Block; j++, i++) m_bitmap.setBit(i, false); showDebug(3, "m_bitmap.setBit(%1u, false), g = %i\n", (i/4), group); dwFree++; } } showDebug(1,"used=%lu\nfree=%lu\ntotal=%lu\n",dwUsed,dwFree,dwUsed+dwFree); calculateSpaceFromBitmap(); //success_readBitmap: delete []cTempBitmap; showDebug(1, "end success\n"); RETURN; // auccess error_readBitmap: delete []cTempBitmap; showDebug(1, "end error\n"); g_interface->msgBoxError(i18n("There was an error while reading the bitmap")); THROW(ERR_READ_BITMAP); }
// Load partition information from storage device. bool PartitionLoad(FS_CONTEXT* FsContext, uint8_t DriverId) { uint32_t RootDirSectors; uint32_t BootSecNum = 0; uint32_t FatSize; uint32_t TotalSectors; uint8_t IndexPtb; uint8_t SectorSizeMul; uint32_t temp2; uint8_t ExtBootEntry = 0; uint16_t BPBRsvSectCnt; uint8_t LogicDriverId = 1; uint8_t LoopFlag = 0; #ifdef FUNC_USB_EN if(FsContext->gFsInfo.DevID == DEV_ID_USB) { SectorSizeMul = (HostStorGetBlockSize() / SECTOR_SIZE); } else #endif { SectorSizeMul = 1; } // FS_DBG("SectorSizeMul: %d\n", (uint16_t)SectorSizeMul); while(1) { LoopFlag = 0; //read MBR //if(!ReadBlock(BootSecNum, (uint8_t*)(FsContext->FAT_BUFFER), 1)) if(RES_OK != disk_read(FsContext->gFsInfo.DevID, (uint8_t*)(FsContext->FAT_BUFFER), BootSecNum, 1)) { FS_DBG("ReadBlock() error!\n"); return FALSE; } FsContext->gFsInfo.CurrFATSecNum = BootSecNum; #ifndef CANCEL_COMMON_SIGNATURE_JUDGMENT if(*(uint16_t*)((FsContext->FAT_BUFFER) + SIGNATURE_OFFSET) != COMMON_SIGNATURE) //if 0x55aa { return FALSE; } #endif for(IndexPtb = 0; IndexPtb < 4; IndexPtb++) { PARTITION* pPart = &((PARTITION*)((FsContext->FAT_BUFFER) + PARTITION_OFFSET))[IndexPtb]; if((pPart->PartitionType == 0x05) //Extended partition && ((ExtBootEntry == 0) || (IndexPtb >= ExtBootEntry))) { BootSecNum += Le32ToCpu(pPart->FirstSectorNum); ExtBootEntry = IndexPtb + 1; // FS_DBG("Extended partition bootSecNum:%ld\n", (uint32_t)BootSecNum); LoopFlag = 1; break; } //check the partition type and get the boot sector num if(pPart->PartitionType == 0x04 || pPart->PartitionType == 0x06 || pPart->PartitionType == 0x0B || pPart->PartitionType == 0x0C || pPart->PartitionType == 0x01 || pPart->PartitionType == 0x0E) { if(DriverId <= 1 || LogicDriverId == DriverId) { BootSecNum += Le32ToCpu(pPart->FirstSectorNum); break; } LogicDriverId++; } } if(LoopFlag) { continue; } if((IndexPtb == 4) && ((ExtBootEntry > 0) && (ExtBootEntry < 4))) { //if extended parttion failed,try again. BootSecNum = 0; continue;//增加对第一分区为无效扩展分区设备的支持 } break; } if((DriverId > 1) && (LogicDriverId != DriverId)) { return FALSE; } //read DBR //if(!ReadBlock((BootSecNum * SectorSizeMul), (uint8_t*)(FsContext->FAT_BUFFER), 1)) if(RES_OK != disk_read(FsContext->gFsInfo.DevID, (uint8_t*)(FsContext->FAT_BUFFER), (BootSecNum * SectorSizeMul), 1)) { return FALSE; } FsContext->gFsInfo.CurrFATSecNum = (BootSecNum * SectorSizeMul); #ifndef CANCEL_COMMON_SIGNATURE_JUDGMENT if(*(uint16_t*)((FsContext->FAT_BUFFER) + SIGNATURE_OFFSET) != COMMON_SIGNATURE) //if 0x55aa { return FALSE; } #endif #define pzero_sector ((BOOT_SECTOR*)((FsContext->FAT_BUFFER))) //updata device information FsContext->gFsInfo.ClusterSize = pzero_sector->BPB_SecPerClus; //get first sector of FAT BPBRsvSectCnt = Le16ToCpu(pzero_sector->BPB_RsvdSecCnt); FsContext->gFsInfo.FatStart = BPBRsvSectCnt + BootSecNum; //get sectors of boot dir if(pzero_sector->BPB_RootEntCnt != 0) { RootDirSectors = (Le16ToCpu(pzero_sector->BPB_RootEntCnt) * 32 + SECTOR_SIZE - 1) / SECTOR_SIZE; } else { RootDirSectors = 0; } //get FAT size if(pzero_sector->BPB_FATSz16 != 0) { FatSize = Le16ToCpu(pzero_sector->BPB_FATSz16); } else { FatSize = Le32ToCpu(pzero_sector->BPB_FATSz32); } //get total cluster if(pzero_sector->BPB_TotSec16 != 0) { TotalSectors = Le16ToCpu(pzero_sector->BPB_TotSec16); } else { TotalSectors = Le32ToCpu(pzero_sector->BPB_TotSec32); } temp2 = (TotalSectors - (BPBRsvSectCnt + FatSize * pzero_sector->BPB_NumFATs + RootDirSectors)) / FsContext->gFsInfo.ClusterSize; // FS_DBG("temp2:%ld\n", (uint32_t)temp2); if(temp2 < 4085) { FS_DBG("FAT12\n"); FsContext->gFsInfo.IsCpatFS = FALSE; //FAT12 return TRUE; } else if(temp2 < 65525) { FS_DBG("FAT16\n"); FsContext->gFsInfo.FAT32 = 0; //FAT16 FsContext->gFsInfo.IsCpatFS = TRUE; } else { //FAT32设备BPB_RootEntCnt/BPB_TotSec16/BPB_FATSz16数值必须为零 if(memcmp((uint8_t*)((FsContext->FAT_BUFFER) + 0x36), "FAT16\0\0\0", 8) == 0) { //客户有一个U盘(USB启动盘),根据计算得出的簇数目应该为FAT32,实际为FAT16系统,为支持这一类设备,需要做此处理 FS_DBG("FAT16\n"); FsContext->gFsInfo.FAT32 = 0; } else { FS_DBG("FAT32\n"); FsContext->gFsInfo.FAT32 = 1; //FAT32 } FsContext->gFsInfo.IsCpatFS = TRUE; } FsContext->gFsInfo.DataStart = FsContext->gFsInfo.FatStart + (FatSize * pzero_sector->BPB_NumFATs) + RootDirSectors; //the first sector of data // get max cluster number in this drive. //FsContext->gFsInfo.MaxCluster = ((TotalSectors - FsContext->gFsInfo.DataStart) / FsContext->gFsInfo.ClusterSize) + 2; FsContext->gFsInfo.MaxCluster = temp2 + 2; //get the data start and boot dir start if(FsContext->gFsInfo.FAT32) { FsContext->gFsInfo.RootStart = FsContext->gFsInfo.DataStart + (Le32ToCpu(pzero_sector->BPB_RootClus) - 2) * FsContext->gFsInfo.ClusterSize; } else { FsContext->gFsInfo.RootStart = FsContext->gFsInfo.FatStart + FatSize * pzero_sector->BPB_NumFATs; //FAT16 the first sector of root dir } FsContext->gFsInfo.ClusterSize *= SectorSizeMul; // RootDirSectors *= SectorSizeMul; FsContext->gFsInfo.FatStart *= SectorSizeMul; FsContext->gFsInfo.DataStart *= SectorSizeMul; FsContext->gFsInfo.MaxSector = (BootSecNum + TotalSectors) * SectorSizeMul; FsContext->gFsInfo.RootStart *= SectorSizeMul; // FS_DBG("*************UDisk virtual params******************\n"); // FS_DBG("ClusterSize:%ld\n", (uint32_t)FsContext->gFsInfo.ClusterSize); // FS_DBG("RootDirSectors:%ld\n", (uint32_t)RootDirSectors); // FS_DBG("FatStart:%ld\n", (uint32_t)FsContext->gFsInfo.FatStart); // FS_DBG("RootStart:%ld\n", (uint32_t)FsContext->gFsInfo.RootStart); // FS_DBG("DataStart:%ld\n", (uint32_t)FsContext->gFsInfo.DataStart); // FS_DBG("MaxCluster:%ld\n", (uint32_t)FsContext->gFsInfo.MaxCluster); // FS_DBG("*****************************************************\n\n"); return TRUE; }