private static void DeleteFile(string fileName, FileStream fStream, FAT12_BOOT_SECTOR bootSector, FAT12_MOUNT_INFO mountInfo) { byte[] buf = new byte[512]; FAT12_FILE_ENTRY fat12FileEntry; /* Get 8.3 directory name */ char[] DosFileName = new char[12]; ToDosFileName(fileName, ref DosFileName); DosFileName[11] = '\0'; /* 16 entries per sector, 14 sectors total */ for (int sector = 0; sector < 14; sector++) { /* Read in sector */ fStream.Seek((mountInfo.rootOffset + sector) * 512, SeekOrigin.Begin); fStream.Read(buf, 0, 512); /* Get file info */ GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); int count = 0; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } for (int i = 0; i < 16; i++) { /* Get current filename */ char[] name = new char[12]; unsafe { for (int j = 0; j < 11; j++) name[j] = (char)fat12FileEntry.Filename[j]; } name[11] = '\0'; /* Find a match? */ if (String.Compare(String.Concat(DosFileName), String.Concat(name)) == 0) { FreeClusterChain(fat12FileEntry.FirstCluster, fStream); unsafe { fat12FileEntry.Filename[0] = 0xE5; fStream.Seek((mountInfo.rootOffset + sector) * 512 + (count * sizeof(FAT12_FILE_ENTRY)), SeekOrigin.Begin); Marshal.StructureToPtr(fat12FileEntry, pinnedBuf.AddrOfPinnedObject(), true); fStream.Write(buf, 0, sizeof(FAT12_FILE_ENTRY)); } return; } count++; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } } pinnedBuf.Free(); } return; }
private static FAT12_FILE_ENTRY? OpenSubDirectory(string fileName, FileStream fStream, FAT12_MOUNT_INFO mountInfo, FAT12_FILE_ENTRY? curFile) { byte[] buf = new byte[512]; FAT12_FILE_ENTRY fat12FileEntry; /* Get 8.3 directory name */ char[] DosFileName = new char[12]; ToDosFileName(fileName, ref DosFileName); DosFileName[11] = '\0'; /* 16 entries per sector, 14 sectors total */ for (int sector = 0; sector < 14; sector++) { /* Read in sector */ fStream.Seek(mountInfo.rootOffset + sector, SeekOrigin.Begin); fStream.Read(buf, 0, 512); /* Get file info */ GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); int count = 0; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } for (int i = 0; i < 16; i++) { /* Get current filename */ char[] name = new char[12]; unsafe { for (int j = 0; j < 11; j++) name[j] = (char)fat12FileEntry.Filename[j]; } name[11] = '\0'; /* Find a match? */ if (String.Compare(DosFileName.ToString(), name.ToString()) == 0) { /* Found it, set up file info */ /* strcpy(file.name, DirectoryName); */ /* file.currentCluster = directory->FirstCluster; */ return fat12FileEntry; } count++; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } } pinnedBuf.Free(); } return null; }
static void SaveFileToDiskImage(string fileName, FileStream fStream, FAT12_BOOT_SECTOR bootSector, FAT12_MOUNT_INFO mountInfo) { /* First delete the file if it exists */ DeleteFile(fileName, fStream, bootSector, mountInfo); byte[] buf = new byte[512]; FAT12_FILE_ENTRY fat12FileEntry; /* Get 8.3 directory name */ char[] DosFileName = new char[12]; ToDosFileName(fileName, ref DosFileName); DosFileName[11] = '\0'; /* 16 entries per sector, 14 sectors total */ for (int sector = 0; sector < 14; sector++) { /* Read in sector */ fStream.Seek((mountInfo.rootOffset + sector) * 512, SeekOrigin.Begin); fStream.Read(buf, 0, 512); /* Get file info */ GCHandle pinnedBuf = GCHandle.Alloc(buf, GCHandleType.Pinned); int count = 0; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } for (int i = 0; i < 16; i++) { /* I'm looking for an entry beginning with \0 or 0xE5 */ unsafe { if (fat12FileEntry.Filename[0] == '\0' || fat12FileEntry.Filename[0] == 0xE5) { /* Found a blank file entry */ for (int j = 0; j < 8; j++) fat12FileEntry.Filename[j] = (byte)DosFileName[j]; for (int j = 0; j < 3; j++) fat12FileEntry.Ext[j] = (byte)DosFileName[j + 8]; fat12FileEntry.Attrib = 0; /* TODO: Set the date and times */ fat12FileEntry.DateCreated = 0; fat12FileEntry.DateLastAccessed = 0; fat12FileEntry.LastModDate = 0; fat12FileEntry.LastModTime = 0; fat12FileEntry.TimeCreated = 0; fat12FileEntry.TimeCreatedMs = 0; fat12FileEntry.FileSize = 0; fat12FileEntry.FirstCluster = GetFirstFreeCluster(fStream, 2); UInt16 currentCluster = fat12FileEntry.FirstCluster; FileStream inputFile = new FileStream(fileName, FileMode.Open); byte[] inputBuffer = new byte[512]; int readBytes = 0; while ((readBytes = inputFile.Read(inputBuffer, 0, 512)) > 0) { fat12FileEntry.FileSize += (uint)readBytes; fStream.Seek((31 + currentCluster) * 512, SeekOrigin.Begin); fStream.Write(inputBuffer, 0, readBytes); if (fStream.Length > fat12FileEntry.FileSize) { /* Allocate next block */ UInt16 nextBlock = GetFirstFreeCluster(fStream, (UInt16)(currentCluster + 1)); MarkBlockChain(fStream, currentCluster, nextBlock); currentCluster = nextBlock; } } MarkBlockChain(fStream, currentCluster, 0xFFF); fStream.Seek((mountInfo.rootOffset + sector) * 512 + (count * sizeof(FAT12_FILE_ENTRY)), SeekOrigin.Begin); Marshal.StructureToPtr(fat12FileEntry, pinnedBuf.AddrOfPinnedObject(), true); fStream.Write(buf, 0, sizeof(FAT12_FILE_ENTRY)); return; } count++; unsafe { fat12FileEntry = (FAT12_FILE_ENTRY)Marshal.PtrToStructure(pinnedBuf.AddrOfPinnedObject() + (count * sizeof(FAT12_FILE_ENTRY)), typeof(FAT12_FILE_ENTRY)); } } } pinnedBuf.Free(); } }
static void Main(string[] args) { string imageFileName = args[0]; FileInfo image = new FileInfo(imageFileName); FileStream fStream; if (image.Exists) fStream = image.Open(FileMode.Open, FileAccess.ReadWrite); else fStream = createNewFloppyImage(image); FAT12_BOOT_SECTOR bootSector = LoadBootSector(fStream); FAT12_MOUNT_INFO mount_info = new FAT12_MOUNT_INFO(); mount_info.numSectors = bootSector.Bpb.NumSectors; mount_info.fatOffset = 1; mount_info.fatSize = bootSector.Bpb.SectorsPerFat; mount_info.fatEntrySize = 8; mount_info.numRootEntries = bootSector.Bpb.NumDirEntries; mount_info.rootOffset = (uint)(bootSector.Bpb.NumberOfFats * bootSector.Bpb.SectorsPerFat) + 1; mount_info.rootSize = (uint)(bootSector.Bpb.NumDirEntries * 32) / bootSector.Bpb.BytesPerSector; for (int i = 1; i < args.Length; i++) { SaveFileToDiskImage(args[i], fStream, bootSector, mount_info); } }