LOCAL_C void Test2() // // Reproduce old bugs // { test.Next(_L("Regression Protection")); RFile f1,f2; // TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite); test_KErrNone(r); r=f2.Replace(TheFs,_L("BIGFILE2.TST"),EFileWrite); test_KErrNone(r); // WriteCluster(f1,0); WriteCluster(f1,1); WriteCluster(f1,2); WriteCluster(f1,3); WriteCluster(f1,4); WriteCluster(f1,5); WriteCluster(f2,0); WriteCluster(f1,6); // SeekToCluster(f1,6); SeekToCluster(f1,4); // f1.Close(); f2.Close(); r=TheFs.Delete(_L("BIGFile1.tst")); test_KErrNone(r); r=TheFs.Delete(_L("BIGFile2.tst")); test_KErrNone(r); CheckDisk(); }
static NTSTATUS VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext) { ULONG eocMark; PDEVICE_EXTENSION DeviceExt; NTSTATUS Status = STATUS_SUCCESS; DPRINT("VfatMarkVolumeDirty(IrpContext %p)\n", IrpContext); DeviceExt = IrpContext->DeviceExt; if (!(DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY)) { Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { /* unset clean shutdown bit */ eocMark &= ~DeviceExt->CleanShutBitMask; Status = WriteCluster(DeviceExt, 1, eocMark); } } DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY; return Status; }
static NTSTATUS VfatMount (PVFAT_IRP_CONTEXT IrpContext) /* * FUNCTION: Mount the filesystem */ { PDEVICE_OBJECT DeviceObject = NULL; PDEVICE_EXTENSION DeviceExt = NULL; BOOLEAN RecognizedFS; NTSTATUS Status; PVFATFCB Fcb = NULL; PVFATFCB VolumeFcb = NULL; PVFATCCB Ccb = NULL; PDEVICE_OBJECT DeviceToMount; PVPB Vpb; UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$"); UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$"); ULONG HashTableSize; ULONG eocMark; FATINFO FatInfo; DPRINT("VfatMount(IrpContext %p)\n", IrpContext); ASSERT(IrpContext); if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject; Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb; Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo); if (!NT_SUCCESS(Status)) { goto ByeBye; } if (RecognizedFS == FALSE) { DPRINT("VFAT: Unrecognized Volume\n"); Status = STATUS_UNRECOGNIZED_VOLUME; goto ByeBye; } /* Use prime numbers for the table size */ if (FatInfo.FatType == FAT12) { HashTableSize = 4099; // 4096 = 4 * 1024 } else if (FatInfo.FatType == FAT16 || FatInfo.FatType == FATX16) { HashTableSize = 16411; // 16384 = 16 * 1024 } else { HashTableSize = 65537; // 65536 = 64 * 1024; } HashTableSize = FCB_HASH_TABLE_SIZE; DPRINT("VFAT: Recognized volume\n"); Status = IoCreateDevice(VfatGlobalData->DriverObject, ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize, NULL, FILE_DEVICE_DISK_FILE_SYSTEM, DeviceToMount->Characteristics, FALSE, &DeviceObject); if (!NT_SUCCESS(Status)) { goto ByeBye; } DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; DeviceExt = (PVOID) DeviceObject->DeviceExtension; RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize); DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG))); DeviceExt->HashTableSize = HashTableSize; /* use same vpb as device disk */ DeviceObject->Vpb = Vpb; DeviceToMount->Vpb = Vpb; Status = VfatMountDevice(DeviceExt, DeviceToMount); if (!NT_SUCCESS(Status)) { /* FIXME: delete device object */ goto ByeBye; } DPRINT("BytesPerSector: %d\n", DeviceExt->FatInfo.BytesPerSector); DPRINT("SectorsPerCluster: %d\n", DeviceExt->FatInfo.SectorsPerCluster); DPRINT("FATCount: %d\n", DeviceExt->FatInfo.FATCount); DPRINT("FATSectors: %d\n", DeviceExt->FatInfo.FATSectors); DPRINT("RootStart: %d\n", DeviceExt->FatInfo.rootStart); DPRINT("DataStart: %d\n", DeviceExt->FatInfo.dataStart); if (DeviceExt->FatInfo.FatType == FAT32) { DPRINT("RootCluster: %d\n", DeviceExt->FatInfo.RootCluster); } switch (DeviceExt->FatInfo.FatType) { case FAT12: DeviceExt->GetNextCluster = FAT12GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT12WriteCluster; DeviceExt->CleanShutBitMask = 0; break; case FAT16: case FATX16: DeviceExt->GetNextCluster = FAT16GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT16WriteCluster; DeviceExt->CleanShutBitMask = 0x8000; break; case FAT32: case FATX32: DeviceExt->GetNextCluster = FAT32GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT32WriteCluster; DeviceExt->CleanShutBitMask = 0x80000000; break; } if (DeviceExt->FatInfo.FatType == FATX16 || DeviceExt->FatInfo.FatType == FATX32) { DeviceExt->Flags |= VCB_IS_FATX; DeviceExt->GetNextDirEntry = FATXGetNextDirEntry; DeviceExt->BaseDateYear = 2000; } else { DeviceExt->GetNextDirEntry = FATGetNextDirEntry; DeviceExt->BaseDateYear = 1980; } DeviceExt->StorageDevice = DeviceToMount; DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; DPRINT("FsDeviceObject %p\n", DeviceObject); /* Initialize this resource early ... it's used in VfatCleanup */ ExInitializeResourceLite(&DeviceExt->DirResource); DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); Fcb = vfatNewFCB(DeviceExt, &NameU); if (Fcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); if (Ccb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } RtlZeroMemory(Ccb, sizeof (VFATCCB)); DeviceExt->FATFileObject->FsContext = Fcb; DeviceExt->FATFileObject->FsContext2 = Ccb; DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; DeviceExt->FATFileObject->PrivateCacheMap = NULL; DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb; Fcb->FileObject = DeviceExt->FATFileObject; Fcb->Flags |= FCB_IS_FAT; Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector; Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize; Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; CcInitializeCacheMap(DeviceExt->FATFileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), TRUE, &VfatGlobalData->CacheMgrCallbacks, Fcb); DeviceExt->LastAvailableCluster = 2; ExInitializeResourceLite(&DeviceExt->FatResource); InitializeListHead(&DeviceExt->FcbListHead); VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU); if (VolumeFcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } VolumeFcb->Flags = FCB_IS_VOLUME; VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector; VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize; VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize; DeviceExt->VolumeFcb = VolumeFcb; ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry); ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); /* read serial number */ DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID; /* read volume label */ ReadVolumeLabel(DeviceExt, DeviceObject->Vpb); /* read clean shutdown bit status */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { if (eocMark & DeviceExt->CleanShutBitMask) { /* unset clean shutdown bit */ eocMark &= ~DeviceExt->CleanShutBitMask; WriteCluster(DeviceExt, 1, eocMark); VolumeFcb->Flags |= VCB_CLEAR_DIRTY; } } VolumeFcb->Flags |= VCB_IS_DIRTY; FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT); Status = STATUS_SUCCESS; ByeBye: if (!NT_SUCCESS(Status)) { // cleanup if (DeviceExt && DeviceExt->FATFileObject) ObDereferenceObject (DeviceExt->FATFileObject); if (Fcb) vfatDestroyFCB(Fcb); if (Ccb) vfatDestroyCCB(Ccb); if (DeviceObject) IoDeleteDevice(DeviceObject); if (VolumeFcb) vfatDestroyFCB(VolumeFcb); } return Status; }
LOCAL_C void Test1() // // Test openning a large file // { test.Next(_L("Create interleaved files")); RFile f1,f2; // TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite); test_KErrNone(r); r=f2.Replace(TheFs,_L("BIGFILE2.TST"),EFileWrite); test_KErrNone(r); // TInt maxListLength=4; TInt i=0,k=0; TInt countf1=0; TInt countf2=0; for (k=0;k<maxListLength;k++) { for (i=0;i<maxListLength;i++) { TInt j; for (j=0;j<=i;j++) WriteCluster(f1,countf1++); for (j=0;j<=k;j++) WriteCluster(f2,countf2++); test.Printf(_L("Written %d to file1 %d to file2\n"),i+1,k+1); } } ExhaustiveTest(f1,countf1); ExhaustiveTest(f2,countf2); SeekToCluster(f1,1,10); SeekToCluster(f1,6,3); SeekToCluster(f1,8,4); SeekToCluster(f1,12,3); SeekToCluster(f1,23,32); SeekToCluster(f1,5,8); SeekToCluster(f1,7,9); SeekToCluster(f1,12,1); SeekToCluster(f1,2,32); SeekToCluster(f1,16,8); SeekToCluster(f1,9,5); SeekToCluster(f1,33,6); SeekToCluster(f1,13,7); SeekToCluster(f1,9,17); SeekToCluster(f1,4,5); SeekToCluster(f1,5,31); SeekToCluster(f1,11,10); SeekToCluster(f1,1,2); SeekToCluster(f1,5,5); f1.Close(); f2.Close(); r=TheFs.Delete(_L("BIGFile1.tst")); test_KErrNone(r); r=TheFs.Delete(_L("BIGFile2.tst")); test_KErrNone(r); CheckDisk(); }
LOCAL_C void Test3() // // Change file size while seeking // { test.Next(_L("Alter filesize")); RFile f1; TheSeed=917824; TInt i=0,j=0; // TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite); test_KErrNone(r); r=f1.SetSize(65534); test_KErrNone(r); for(i=0;i<=15;i++) WriteCluster(f1,i); for (j=0;j<100;j++) { TInt cluster1=Math::Rand(TheSeed)%15; TInt cluster2=Math::Rand(TheSeed)%15; SeekToCluster(f1,cluster2,cluster1); } test.Next(_L("Increase Size")); r=f1.SetSize(1048577); test_Value(r, r == KErrNone || r==KErrDiskFull); if (r==KErrDiskFull) { test.Printf(_L("File too big\n")); f1.Close(); return; } test.Next(_L("Test data still present")); for (j=0;j<200;j++) { TInt cluster1=Math::Rand(TheSeed)%15; TInt cluster2=Math::Rand(TheSeed)%15; SeekToCluster(f1,cluster2,cluster1); } TInt newPos=8192; r=f1.Seek(ESeekStart,newPos); test_KErrNone(r); test.Next(_L("Write more data")); for(i=16;i<83;i++) WriteCluster(f1,i); test.Next(_L("Seek to new data")); for (j=0;j<200;j++) { TInt cluster1=Math::Rand(TheSeed)%83; TInt cluster2=Math::Rand(TheSeed)%83; SeekToCluster(f1,cluster2,cluster1); } test.Next(_L("Reduce file size")); r=f1.SetSize(135000); test_KErrNone(r); test.Next(_L("Test data still present")); for (j=0;j<200;j++) { TInt cluster1=Math::Rand(TheSeed)%31; TInt cluster2=Math::Rand(TheSeed)%31; SeekToCluster(f1,cluster2,cluster1); } f1.Close(); }
USHORT usWriteEAS(PVOLINFO pVolInfo, ULONG ulDirCluster, PSZ pszFileName, PFEALIST pFEAL) { ULONG ulCluster, ulNextCluster; PBYTE pszEAName; PBYTE pWrite; USHORT rc; USHORT usClustersNeeded; DIRENTRY DirEntry; DIRENTRY DirNew; BOOL fCritical; PFEA pFea, pFeaEnd; if (pFEAL->cbList > MAX_EA_SIZE) return ERROR_EA_LIST_TOO_LONG; rc = GetEASName(pVolInfo, ulDirCluster, pszFileName, &pszEAName); if (rc) return rc; usClustersNeeded = (USHORT)pFEAL->cbList / pVolInfo->usClusterSize; if (pFEAL->cbList % pVolInfo->usClusterSize) usClustersNeeded++; ulCluster = FindPathCluster(pVolInfo, ulDirCluster, pszEAName, &DirEntry, NULL); if (!ulCluster || ulCluster == FAT_EOF) { BOOL fNew = FALSE; if (ulCluster == FAT_EOF) { fNew = TRUE; memset(&DirNew, 0, sizeof DirNew); DirNew.bAttr = FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY; DirNew.ulFileSize = pFEAL->cbList; } else memcpy(&DirNew, &DirEntry, sizeof DirEntry); ulCluster = MakeFatChain(pVolInfo, FAT_EOF, (ULONG)usClustersNeeded, NULL); if (ulCluster == FAT_EOF) { free(pszEAName); return ERROR_DISK_FULL; } DirNew.wCluster = LOUSHORT(ulCluster); DirNew.wClusterHigh = HIUSHORT(ulCluster); if (fNew) rc = MakeDirEntry(pVolInfo, ulDirCluster, &DirNew, pszEAName); else rc = ModifyDirectory(pVolInfo, ulDirCluster, MODIFY_DIR_UPDATE, &DirEntry, &DirNew, NULL, 0); if (rc) { free(pszEAName); return rc; } } else { memcpy(&DirNew, &DirEntry, sizeof (DIRENTRY)); DirNew.ulFileSize = pFEAL->cbList; rc = ModifyDirectory(pVolInfo, ulDirCluster, MODIFY_DIR_UPDATE, &DirEntry, &DirNew, NULL, 0); if (rc) { free(pszEAName); return rc; } } free(pszEAName); pWrite = (PBYTE)pFEAL; ulNextCluster = FAT_EOF; while (usClustersNeeded) { ulNextCluster = GetNextCluster(pVolInfo, ulCluster); if (!ulNextCluster) ulNextCluster = FAT_EOF; rc = WriteCluster(pVolInfo, ulCluster, pWrite, 0); if (rc) return rc; usClustersNeeded --; pWrite += pVolInfo->usClusterSize; if (usClustersNeeded) { if (ulNextCluster == FAT_EOF) ulCluster = MakeFatChain(pVolInfo, ulCluster, (ULONG)usClustersNeeded, NULL); else ulCluster = ulNextCluster; if (ulCluster == FAT_EOF) return ERROR_DISK_FULL; } } if (ulNextCluster != FAT_EOF) { SetNextCluster(pVolInfo, ulCluster, FAT_EOF); DeleteFatChain(pVolInfo, ulNextCluster); } pFea = pFEAL->list; pFeaEnd = (PFEA)((PBYTE)pFEAL + pFEAL->cbList); fCritical = FALSE; while (pFea < pFeaEnd) { if (pFea->fEA & FEA_NEEDEA) fCritical = TRUE; pFea = (PFEA)((PBYTE)pFea + sizeof (FEA) + (USHORT)pFea->cbName + 1 + pFea->cbValue); } if (fCritical) rc = MarkFileEAS(pVolInfo, ulDirCluster, pszFileName, FILE_HAS_CRITICAL_EAS); else rc = MarkFileEAS(pVolInfo, ulDirCluster, pszFileName, FILE_HAS_EAS); return rc; }
NTSTATUS NTAPI VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS Status; PLIST_ENTRY ListEntry; PDEVICE_EXTENSION DeviceExt; ULONG eocMark; DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp); FsRtlEnterFileSystem(); /* FIXME: block new mount requests */ if (DeviceObject == VfatGlobalData->DeviceObject) { Irp->IoStatus.Status = STATUS_SUCCESS; ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); ListEntry = VfatGlobalData->VolumeListHead.Flink; while (ListEntry != &VfatGlobalData->VolumeListHead) { DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry); ListEntry = ListEntry->Flink; ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY) { /* set clean shutdown bit */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { eocMark |= DeviceExt->CleanShutBitMask; if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark))) DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY; } } Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb); if (NT_SUCCESS(Status)) { Status = VfatDiskShutDown(DeviceExt); if (!NT_SUCCESS(Status)) DPRINT1("VfatDiskShutDown failed, status = %x\n", Status); } else { DPRINT1("VfatFlushVolume failed, status = %x\n", Status); } ExReleaseResourceLite(&DeviceExt->DirResource); /* FIXME: Unmount the logical volume */ if (!NT_SUCCESS(Status)) Irp->IoStatus.Status = Status; } ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); /* FIXME: Free all global acquired resources */ Status = Irp->IoStatus.Status; } else { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST; } Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FsRtlExitFileSystem(); return(Status); }
static NTSTATUS VfatDismountVolume( PVFAT_IRP_CONTEXT IrpContext) { PDEVICE_EXTENSION DeviceExt; PLIST_ENTRY NextEntry; PVFATFCB Fcb; PFILE_OBJECT FileObject; ULONG eocMark; NTSTATUS Status; DPRINT("VfatDismountVolume(%p)\n", IrpContext); DeviceExt = IrpContext->DeviceExt; FileObject = IrpContext->FileObject; /* We HAVE to be locked. Windows also allows dismount with no lock * but we're here mainly for 1st stage, so KISS */ if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED)) { return STATUS_ACCESS_DENIED; } /* Race condition? */ if (DeviceExt->Flags & VCB_DISMOUNT_PENDING) { return STATUS_VOLUME_DISMOUNTED; } /* Notify we'll dismount. Pass that point there's no reason we fail */ FsRtlNotifyVolumeEvent(IrpContext->Stack->FileObject, FSRTL_VOLUME_DISMOUNT); ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY) { /* Set clean shutdown bit */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { eocMark |= DeviceExt->CleanShutBitMask; if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark))) DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY; } } /* Flush volume & files */ VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext); /* Rebrowse the FCB in order to free them now */ while (!IsListEmpty(&DeviceExt->FcbListHead)) { NextEntry = RemoveHeadList(&DeviceExt->FcbListHead); Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry); vfatDestroyFCB(Fcb); } /* Mark we're being dismounted */ DeviceExt->Flags |= VCB_DISMOUNT_PENDING; #ifndef ENABLE_SWAPOUT IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED; #endif ExReleaseResourceLite(&DeviceExt->FatResource); /* Release a few resources and quit, we're done */ ExDeleteResourceLite(&DeviceExt->DirResource); ExDeleteResourceLite(&DeviceExt->FatResource); ObDereferenceObject(DeviceExt->FATFileObject); return STATUS_SUCCESS; }
exp bool CopyIn(const char* source, const char* dest) { DirectoryEntry* entry = 0; char* buffer = new char[bpb->bytesPerSector]; // Open file we're copying in std::ifstream inHandle(source, std::ios::in | std::ios::binary | std::ios::ate); if (!inHandle.is_open()) { LastError("CopyIn", "Failed to open source file"); return false; } // Get size of source file size_t inLength = (size_t)inHandle.tellg(); inHandle.seekg(std::ios::beg); // Convert the filename into DOS8.3 format char* dosName = new char[12]; ToDos83Name(dest, dosName); // Check if entry exists, if so, overwrite it entry = FindEntry(dosName, &directory); if (entry) { // Delete file Delete(dest); // Undelete entry entry->name[0] = dosName[0]; } // Create the directory entry if (!entry) { // Didn't delete file, make it entry = MakeEntry(dosName, ATTRIB_ARCHIVE, inLength, &directory); if (!entry) { LastError("CopyIn", "Failed to create directory entry"); delete[] dosName; delete[] buffer; return false; } } else { // Deleted file, find it entry = FindEntry(dosName, &directory); if (!entry) { LastError("CopyIn", "Somehow a file that was just undeleted can't be found..."); delete[] dosName; delete[] buffer; return false; } UpdateEntry(entry, 0, inLength); } // Write entry to disk DirectoryWrite(&directory); // Update FAT and then load each cluster and write it while updating the FAT FatEntry fatEntry; fatEntry.buffer = new char[bpb->bytesPerSector]; fatEntry.cluster = GetClusterFromEntry(entry); fatEntry.sector = GetFATSector(fatEntry.cluster); ReadSector(fatEntry.buffer, fatEntry.sector); UpdateFAT(&fatEntry, FindFreeCluster()); // Write to disk for (size_t i = 0; i < inLength; i += bpb->bytesPerSector) { memset(buffer, 0, bpb->bytesPerSector); if (!(i % bpb->bytesPerSector)) inHandle.read(buffer, bpb->bytesPerSector); else inHandle.read(buffer, i % bpb->bytesPerSector); WriteCluster(&fatEntry, buffer); } delete[] dosName; delete[] buffer; delete[] fatEntry.buffer; inHandle.close(); return true; }