/// <summary> /// Reads the file descriptor sector for a given file and verified that all sectors in the file segment list (and the file descriptor sector itself) /// are marked as free in the passed cluster allocation map. It then marks the clusters as marked. /// </summary> /// <param name="map">Cluster allocation map.</param> /// <param name="filedesc">Logical sector number of the file descriptor sector for the file.</param> /// <param name="clustersize">Cluster size for this filesystem.</param> /// <exception cref="FilesystemConsistencyException">Thrown if any cluster used for this file is already allocated.</exception> private void VerifyAndUpdateAllocationMap(OS9AllocationMap map, int filedesc, int clustersize) { var fileinfo = OS9FileInfo.Parse(ReadSector(filedesc), null); /* Verify that all sectors used by this file are marked as free in the cluster allocation map. */ if (map.IsAllocated(filedesc / clustersize)) { throw new FilesystemConsistencyException(String.Format("Sector {0} is in use by multiple files", filedesc)); } foreach (var segment in fileinfo.Segments) { int sector = segment.Lsn; for (int i = 0; i < segment.Size; i++) { if (map.IsAllocated(sector / clustersize)) { throw new FilesystemConsistencyException(String.Format("Sector {0} is in use by multiple files", sector)); } sector++; } } /* Mark all sectors as allocated. */ map.SetAllocated(filedesc / clustersize, true); foreach (var segment in fileinfo.Segments) { int sector = segment.Lsn; for (int i = 0; i < segment.Size; i++) { map.SetAllocated(sector / clustersize, true); sector++; } } }
/// <summary> /// Checks the filesystem consistency. /// </summary> /// <exception cref="FilesystemConsistencyException">Thrown if the filesystem is not consistent in a manner that makes write operations unsafe.</exception> public void Check() { if (IsDisposed) { throw new ObjectDisposedException(GetType().FullName); } ReadDiskHeader(); var allocmap = new OS9AllocationMap(DiskInfo.AllocationMapSize); // mirror the allocation map allocmap.SetAllocated(IdentificationSector / DiskInfo.ClusterSize, true); allocmap.SetAllocated(AllocationMapSector / DiskInfo.ClusterSize, true); var dirs = new Queue <int>(); // LSN of all directories found while traversing the file structure dirs.Enqueue(DiskInfo.RootDirectory); VerifyAndUpdateAllocationMap(allocmap, DiskInfo.RootDirectory, DiskInfo.ClusterSize); /* Traverse the directory hierarchy and update the cluster allocation map for all files encountered. */ while (dirs.Count > 0) { int lsn = dirs.Dequeue(); var files = ReadDirectory(lsn); foreach (var file in files) { if (file.IsValid && !String.Equals(file.Filename, ".") && !String.Equals(file.Filename, "..")) { VerifyAndUpdateAllocationMap(allocmap, file.Sector, DiskInfo.ClusterSize); var fileinfo = OS9FileInfo.Parse(ReadSector(file.Sector), file.Filename); if (fileinfo.IsDirectory) { dirs.Enqueue(file.Sector); } } } } /* Finally, verify that all clusters used by files found are actually marked as allocated in the disk cluster allocation map. */ for (int i = 0; i < AllocationMap.AllocationMapSize; i++) { if (allocmap.IsAllocated(i) && !AllocationMap.IsAllocated(i)) { throw new FilesystemConsistencyException(String.Format("Cluster {0} is in use by a file but not marked as allocated", i)); } } }
/// <summary> /// Reads the file descriptor sector for a given file and verified that all sectors in the file segment list (and the file descriptor sector itself) /// are marked as free in the passed cluster allocation map. It then marks the clusters as marked. /// </summary> /// <param name="map">Cluster allocation map.</param> /// <param name="filedesc">Logical sector number of the file descriptor sector for the file.</param> /// <param name="clustersize">Cluster size for this filesystem.</param> /// <exception cref="FilesystemConsistencyException">Thrown if any cluster used for this file is already allocated.</exception> private void VerifyAndUpdateAllocationMap(OS9AllocationMap map, int filedesc, int clustersize) { var fileinfo = OS9FileInfo.Parse(ReadSector(filedesc), null); /* Verify that all sectors used by this file are marked as free in the cluster allocation map. */ if (map.IsAllocated(filedesc/clustersize)) throw new FilesystemConsistencyException(String.Format("Sector {0} is in use by multiple files", filedesc)); foreach (var segment in fileinfo.Segments) { int sector = segment.Lsn; for (int i=0; i<segment.Size; i++) { if (map.IsAllocated(sector/clustersize)) throw new FilesystemConsistencyException(String.Format("Sector {0} is in use by multiple files", sector)); sector++; } } /* Mark all sectors as allocated. */ map.SetAllocated(filedesc/clustersize, true); foreach (var segment in fileinfo.Segments) { int sector = segment.Lsn; for (int i=0; i<segment.Size; i++) { map.SetAllocated(sector/clustersize, true); sector++; } } }
/// <summary> /// Checks the filesystem consistency. /// </summary> /// <exception cref="FilesystemConsistencyException">Thrown if the filesystem is not consistent in a manner that makes write operations unsafe.</exception> public void Check() { if (IsDisposed) throw new ObjectDisposedException(GetType().FullName); ReadDiskHeader(); var allocmap = new OS9AllocationMap(DiskInfo.AllocationMapSize); // mirror the allocation map allocmap.SetAllocated(IdentificationSector/DiskInfo.ClusterSize, true); allocmap.SetAllocated(AllocationMapSector/DiskInfo.ClusterSize, true); var dirs = new Queue<int>(); // LSN of all directories found while traversing the file structure dirs.Enqueue(DiskInfo.RootDirectory); VerifyAndUpdateAllocationMap(allocmap, DiskInfo.RootDirectory, DiskInfo.ClusterSize); /* Traverse the directory hierarchy and update the cluster allocation map for all files encountered. */ while (dirs.Count > 0) { int lsn = dirs.Dequeue(); var files = ReadDirectory(lsn); foreach (var file in files) { if (file.IsValid && !String.Equals(file.Filename, ".") && !String.Equals(file.Filename, "..")) { VerifyAndUpdateAllocationMap(allocmap, file.Sector, DiskInfo.ClusterSize); var fileinfo = OS9FileInfo.Parse(ReadSector(file.Sector), file.Filename); if (fileinfo.IsDirectory) { dirs.Enqueue(file.Sector); } } } } /* Finally, verify that all clusters used by files found are actually marked as allocated in the disk cluster allocation map. */ for (int i = 0; i < AllocationMap.AllocationMapSize; i++ ) { if (allocmap.IsAllocated(i) && !AllocationMap.IsAllocated(i)) { throw new FilesystemConsistencyException(String.Format("Cluster {0} is in use by a file but not marked as allocated", i)); } } }