/// <inheritdoc /> /// <summary> /// Sets the next cluster. /// </summary> /// <param name="cluster">The cluster.</param> /// <param name="nextCluster">The next cluster.</param> public void SetNextCluster(Cluster cluster, Cluster nextCluster) { lock (_fatLock) { // the only point is to avoid writing to virtual hard disk, which may be sparse and handle sparseness more or less efficiently... var fatPage = GetFatPage(cluster); var clusterIndex = (int)(cluster.Value % ClustersPerFatPage); var b = LittleEndian.GetBytes((UInt32)nextCluster.Value); var fatPageOffset = clusterIndex * sizeof(UInt32); if (b[0] == fatPage[fatPageOffset] && b[1] == fatPage[fatPageOffset + 1] && b[2] == fatPage[fatPageOffset + 2] && b[3] == fatPage[fatPageOffset + 3]) { return; } Buffer.BlockCopy(b, 0, fatPage, fatPageOffset, sizeof(Int32)); _fatPageDirty = true; if (!_options.HasAny(ExFatOptions.DelayWrite)) { FlushFatPage(); } } }
private void UpdateEntry(ExFatFilesystemEntry entry, FileAccess fileAccess, DataDescriptor dataDescriptor) { if (entry?.MetaEntry == null) { return; } DateTimeOffset?now = null; var file = (FileExFatDirectoryEntry)entry.MetaEntry.Primary; // if file was open for reading and the flag is set, the entry is updated if (fileAccess.HasAny(FileAccess.Read) && _options.HasAny(ExFatOptions.UpdateLastAccessTime)) { now = DateTimeOffset.Now; file.LastAccessDateTimeOffset.Value = now.Value; } // when it was open for writing, its characteristics may have changed, so we update them if (fileAccess.HasAny(FileAccess.Write)) { now = now ?? DateTimeOffset.Now; file.FileAttributes.Value |= ExFatFileAttributes.Archive; file.LastWriteDateTimeOffset.Value = now.Value; var stream = entry.MetaEntry.SecondaryStreamExtension; if (dataDescriptor.Contiguous) { stream.GeneralSecondaryFlags.Value |= ExFatGeneralSecondaryFlags.NoFatChain; } else { stream.GeneralSecondaryFlags.Value &= ~ExFatGeneralSecondaryFlags.NoFatChain; } stream.FirstCluster.Value = (UInt32)dataDescriptor.FirstCluster.Value; stream.ValidDataLength.Value = dataDescriptor.LogicalLength; stream.DataLength.Value = dataDescriptor.PhysicalLength; } // now has value only if it was used before, so we spare a flag :) if (now.HasValue) { Update(entry); } }