private static void LoadDirectoryContent(IDirectory direct, ExtPartInfo partInfo, Action <long> ntfSzAct, Func <bool> isCancel) { var dirStoken = direct.GetStoken(Constants.DirectoryKey_Ext); var fatFileInfo = dirStoken.GetInstance <ExtFileInfo>(Constants.FileStokenTag_ExtFileInfo) as ExtFileInfo; var filePtr = ExtX_Parse_Dir(partInfo.ExtUnmanagedManager.ExtManagerPtr, fatFileInfo.BlockListPtr); DealWithFileNode(direct, partInfo, filePtr, ntfSzAct, isCancel); }
public IFile ParseStream(Stream stream, string name, IProgressReporter reporter) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } var part = FileFactory.CreatePartition(Constants.PartitionKey_Ext); var stoken = part.GetStoken(Constants.PartitionKey_Ext); stoken.BaseStream = stream; stoken.Name = name; stoken.Size = stream.Length; stoken.TypeGuid = Constants.PartitionType_Ext; var extUnmanagedManager = new ExtUnmanagedManager(stream); var partInfo = new ExtPartInfo { ExtUnmanagedManager = extUnmanagedManager }; #if DEBUG //IntPtr stExt4Inode = ExtX_Get_InodeInfo(extUnmanagedManager.ExtManagerPtr, 113880); //129793 //var stBlockList = ExtX_Get_BlockList(extUnmanagedManager.ExtManagerPtr, stExt4Inode); //var stDirDntry = ExtX_Parse_Dir(extUnmanagedManager.ExtManagerPtr, stBlockList); //var dirEntry = stDirDntry.GetStructure<StDirEntry>(); //var cext4Entry = dirEntry.DirInfo.GetStructure<StExt4DirEntry>(); #endif //设定EXT分区详细信息; stoken.SetInstance(partInfo, Constants.PartitionStokenTag_ExtPartInfo); stoken.PartType = ServiceProvider.GetAllInstances <IPartitionType>().FirstOrDefault(p => p.GUID == Constants.PartitionType_Ext); if (partInfo.ExtUnmanagedManager.ExtManagerPtr == IntPtr.Zero) { extUnmanagedManager.Dispose(); throw new InvalidOperationException($"{nameof(extUnmanagedManager.ExtManagerPtr)} can't be nullptr."); } try { LoadPartInfo(partInfo); LoadPartContent(part, reporter); } catch (Exception ex) { LoggerService.WriteException(ex); } part.Disposing += OnPart_Disposing; return(part); }
private static void LoadPartInfo(ExtPartInfo partInfo) { if (partInfo == null) { throw new ArgumentNullException(nameof(partInfo)); } var stSuperBlockPtr = ExtX_SuperBlock(partInfo.ExtUnmanagedManager.ExtManagerPtr); if (stSuperBlockPtr == IntPtr.Zero) { //LoggerService.WriteCallerLine($"{nameof(stSuperBlockPtr)} can't be nullptr."); return; } else { partInfo.SuperBlock = new SuperBlock(stSuperBlockPtr.GetStructure <StSuperBlock>()); } var stGroupDescPtr = ExtX_GroupDesc(partInfo.ExtUnmanagedManager.ExtManagerPtr); if (stGroupDescPtr == IntPtr.Zero) { //LoggerService.WriteCallerLine($"{nameof(stGroupDescPtr)} can't be nullptr."); return; } else { var descIndex = 0; partInfo.Ext4GroupDescs = stGroupDescPtr.GetStructs <StExtGroupDesc>(p => p.Next)?. Select(p => { var desc = new ExtGroupDesc(p) { InternalDisplayName = $"{LanguageService.FindResourceString(Constants.DisplayName_ExtGroupDesc)}{++descIndex}" }; return(desc); }).ToArray() ?? null; } //stExt4INodePtr = ExtX_Get_InodeInfo( 2); //加载Inode,BlockList,Dir; //stBlockListPtr = Cflabqd_Get_BlockList(stExt4INodePtr); //加载Inode,BlockList,Dir; //stDirEntryPtr = Cflabqd_Parse_Dir(stBlockListPtr); //加载Inode,BlockList,Dir; }
/// <summary> /// 编辑目录/文件/其它的时间,簇列表等值; /// </summary> /// <param name="fileStoken2"></param> private static void EditFileStoken2( FileStokenBase2 fileStoken2, ExtPartInfo partInfo, ExtFileInfo extFileInfo) { if (fileStoken2 == null) { throw new ArgumentNullException(nameof(fileStoken2)); } if (extFileInfo == null) { throw new ArgumentNullException(nameof(extFileInfo)); } if (extFileInfo.BlockListPtr == null) { throw new InvalidOperationException($"{nameof(extFileInfo.BlockListPtr)} of {nameof(ExtFileInfo)} can't be nullptr."); } if (partInfo == null) { throw new ArgumentNullException(nameof(partInfo)); } fileStoken2.SetInstance(extFileInfo, Constants.FileStokenTag_ExtFileInfo); fileStoken2.Name = extFileInfo.StExt4DirEntry?.Name; fileStoken2.Size = extFileInfo.StExt4Inode?.Size ?? 0; fileStoken2.Deleted = extFileInfo.StDirEntry?.bDel ?? false; EditTime(fileStoken2, extFileInfo); #if DEBUG //if (fileStoken2.Name.StartsWith(".journal")) { //} #endif EditBlockGroups(fileStoken2, partInfo, extFileInfo); }
/// <summary> /// 编辑块组; /// </summary> /// <param name="fileStoken2"></param> /// <param name="partInfo"></param> /// <param name="extFileInfo"></param> private static void EditBlockGroups( FileStokenBase2 fileStoken2, ExtPartInfo partInfo, ExtFileInfo extFileInfo) { if (fileStoken2 == null) { throw new ArgumentNullException(nameof(fileStoken2)); } if (extFileInfo == null) { throw new ArgumentNullException(nameof(extFileInfo)); } //if (extFileInfo.BlockListPtr == null) { // throw new InvalidOperationException($"{nameof(extFileInfo.BlockListPtr)} of {nameof(ExtFileInfo)} can't be nullptr."); //} if (partInfo == null) { throw new ArgumentNullException(nameof(partInfo)); } if (extFileInfo.BlockList == null) { //LoggerService.WriteCallerLine($"{nameof(extFileInfo.BlockList)} can't be null."); return; } var blocks = extFileInfo.BlockList; var blockSize = partInfo.SuperBlock.StructInstance.BlockSize; if (blocks == null) { return; } //遍历,粘合,将连续的簇列表并入为一个块组; StBlockList?lastBlock = null; long firstClusterLBA = 0; int blockCount = 0; ulong lastBlockNum = 0; //重置局部变量;参数为本次(循环)最新的独立头块; void Reset(StBlockList block) { lastBlock = block; blockCount = (int)block.count; lastBlockNum = block.address; firstClusterLBA = (long)block.address * blockSize; } //压栈; void PushBlockGroup() { if (lastBlock == null) { return; } fileStoken2.BlockGroups.Add( BlockGroupFactory.CreateNewBlockGroup((long)lastBlock.Value.address, blockCount, blockSize, firstClusterLBA) ); } try { foreach (var cluster in blocks) { if (lastBlock == null) { Reset(cluster); continue; } //如果是连续的簇号则+1; if (cluster.address == lastBlockNum + 1) { lastBlockNum = cluster.address; blockCount++; } //否则,构造BlockGroup,插入新建链表,并重置; else { PushBlockGroup(); Reset(cluster); } } if (lastBlock != null) { PushBlockGroup(); } } catch (Exception ex) { LoggerService.WriteCallerLine(ex.Message); } }
/// <summary> /// 处理子文件/目录/其它加载; /// </summary> /// <param name="haveFileCollection"></param> /// <param name="filePtr">非托管文件节点指针</param> /// <param name="ntfSzAct"></param> /// <param name="isCancel"></param> private static void DealWithFileNode( IHaveFileCollection haveFileCollection, ExtPartInfo partInfo, IntPtr filePtr, Action <long> ntfSzAct, Func <bool> isCancel) { while (filePtr != IntPtr.Zero) { IFile file = null; FileStokenBase2 fileStoken2 = null; var stDirEntry = filePtr.GetStructure <StDirEntry>(); //压栈;避免使用continue导致死循环以及冗余代码; void Push() { if (file != null) { haveFileCollection.Children.Add(file); } filePtr = stDirEntry.Next; } if (stDirEntry.DirInfo == IntPtr.Zero) { Push(); continue; } var stExtDirEntry = stDirEntry.DirInfo.GetStructure <StExt4DirEntry>(); var stExtINodePtr = ExtX_Get_InodeInfo(partInfo.ExtUnmanagedManager.ExtManagerPtr, stExtDirEntry.inode); if (stExtINodePtr == IntPtr.Zero) { LoggerService.WriteCallerLine($"{nameof(stExtINodePtr)} can't be nullptr."); Push(); continue; } var stExtINode = stExtINodePtr.GetStructure <StExt4Inode>(); var stBlockListPtr = ExtX_Get_BlockList(partInfo.ExtUnmanagedManager.ExtManagerPtr, stExtINodePtr); if (stBlockListPtr == IntPtr.Zero) { //LoggerService.WriteCallerLine($"{nameof(stBlockListPtr)} can't be nullptr."); Push(); continue; } var extFileInfo = new ExtFileInfo { StDirEntry = stDirEntry, StExt4DirEntry = stExtDirEntry, BlockListPtr = stBlockListPtr, StExt4Inode = stExtINode }; if (stExtDirEntry.file_type == Ext4FileType.Directory) { var dir = FileFactory.CreateDirectory(Constants.DirectoryKey_Ext); var dirStoken = dir.GetStoken(Constants.DirectoryKey_Ext); dirStoken.TypeGuid = Constants.DirectoryType_Ext; file = dir; fileStoken2 = dirStoken; EditFileStoken2(fileStoken2, partInfo, extFileInfo); //当目录名为".."或者"."时,跳过加载子文件; //且所加载目录不能被删除; if (stExtDirEntry._name[0] != '.' && !stDirEntry.bDel) { LoadDirectoryContent(dir, partInfo, ntfSzAct, isCancel); } else if (stExtDirEntry._name[1] == '.') { dirStoken.IsBack = true; } else { dirStoken.IsLocalBackUp = true; } } else if (stExtDirEntry.file_type == Ext4FileType.RegularFile) { var regFile = FileFactory.CreateRegularFile(Constants.RegularFileKey_Ext); var regFileStoken = regFile.GetStoken(Constants.RegularFileKey_Ext); regFileStoken.TypeGuid = Constants.RegularFileType_Ext; file = regFile; fileStoken2 = regFileStoken; EditFileStoken2(fileStoken2, partInfo, extFileInfo); ntfSzAct?.Invoke(fileStoken2.Size); } Push(); if (isCancel?.Invoke() ?? false) { return; } } }