Skip to content

Commit e03ee38

Browse files
committed
Bug fixes and feature updates
When updating the timestamps on a directory, the current and parent directory entries are now properly updated as well. New directories can now be added to a disk image.
1 parent e5ef60b commit e03ee38

File tree

15 files changed

+455
-84
lines changed

15 files changed

+455
-84
lines changed

DiskImageTool/DiskImage/DirectoryBase.vb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@
114114
End If
115115
End Sub
116116

117+
Public MustOverride Function AddDirectory(DirectoryData() As Byte, UseLFN As Boolean, LFNFileName As String, Optional Index As Integer = -1) As Integer Implements IDirectory.AddDirectory
118+
117119
Public MustOverride Function AddFile(FilePath As String, LFN As Boolean, Optional Index As Integer = -1) As Integer Implements IDirectory.AddFile
118120

119121
Public Function AdjustIndexForLFN(Index As Integer) As Integer

DiskImageTool/DiskImage/DirectoryEntry.vb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,6 @@
325325
Return Not (IsDirectory() OrElse IsVolumeName() OrElse HasInvalidStartingCluster() OrElse HasInvalidFileSize()) AndAlso StartingCluster > 1
326326
End Function
327327

328-
Public Function IsValidVolumeName() As Boolean
329-
Return IsVolumeName() AndAlso Not (IsHidden() OrElse IsSystem() OrElse IsDirectory() OrElse IsDeleted()) AndAlso StartingCluster = 0
330-
End Function
331-
332328
Public Function RemoveLFN() As Boolean
333329
Return ParentDirectory.RemoveLFN(_Index)
334330
End Function
@@ -454,7 +450,7 @@
454450
Return True
455451
End Function
456452

457-
Private Sub InitSubDirectory()
453+
Public Sub InitSubDirectory()
458454
If IsValidDirectory() AndAlso Not IsLink() AndAlso Not IsDeleted() Then
459455
_SubDirectory = New SubDirectory(_RootDirectory, Me)
460456
Else

DiskImageTool/DiskImage/DirectoryEntryBase.vb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Namespace DiskImage
66
Public Const CHAR_DELETED As Byte = &HE5
77
Public Const DIRECTORY_ENTRY_SIZE As Byte = 32
88
Public Shared ReadOnly EmptyDirectoryEntry() As Byte = {&HE5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
9+
Public Shared ReadOnly CurrentDirectoryEntry() As Byte = {&H2E, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20}
10+
Public Shared ReadOnly ParentDirectoryEntry() As Byte = {&H2E, &H2E, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20}
911

1012
Private Const CHAR_EMPTY As Byte = &H0
1113
Private Const CHAR_SPACE As Byte = &H20
@@ -99,6 +101,11 @@ Namespace DiskImage
99101
_Offset = 0
100102
End Sub
101103

104+
Sub New(Data() As Byte)
105+
_FileBytes = New ByteArray(Data)
106+
_Offset = 0
107+
End Sub
108+
102109
Sub New(FileBytes As IByteArray, Offset As UInteger)
103110
_FileBytes = FileBytes
104111
_Offset = Offset
@@ -190,6 +197,20 @@ Namespace DiskImage
190197
End Set
191198
End Property
192199

200+
Public Property FileNameWithExtension() As Byte()
201+
Get
202+
Return _FileBytes.GetBytes(_Offset + DirectoryEntryOffsets.FileName, DirectoryEntrySizes.FileName + DirectoryEntrySizes.Extension)
203+
End Get
204+
Set
205+
If _FileBytes.SetBytes(Value, _Offset + DirectoryEntryOffsets.FileName, DirectoryEntrySizes.FileName + DirectoryEntrySizes.Extension, CHAR_SPACE) Then
206+
_IsBlankCache = Nothing
207+
_VolumeNameIsCached = False
208+
_FileNameIsCached = False
209+
_HasInvalidFileNameCache = Nothing
210+
End If
211+
End Set
212+
End Property
213+
193214
Public Property FileSize() As UInteger
194215
Get
195216
Return _FileBytes.GetBytesInteger(_Offset + DirectoryEntryOffsets.FileSize)
@@ -326,6 +347,10 @@ Namespace DiskImage
326347
LastWriteTime = 0
327348
End Sub
328349

350+
Public Function Clone() As DirectoryEntryBase
351+
Return New DirectoryEntryBase(Data)
352+
End Function
353+
329354
Public Function GetCreationDate() As ExpandedDate
330355
If Not _CreationDateIsCached Then
331356
_CreationDateCache = ExpandDate(CreationDate, CreationTime, CreationMillisecond)
@@ -413,7 +438,7 @@ Namespace DiskImage
413438

414439
Public Function GetVolumeName() As String
415440
If Not _VolumeNameIsCached Then
416-
_VolumeNameCache = (CodePage437ToUnicode(FileName) & CodePage437ToUnicode(Extension)).TrimEnd(" ")
441+
_VolumeNameCache = CodePage437ToUnicode(FileNameWithExtension).TrimEnd(" ")
417442
_VolumeNameIsCached = True
418443
End If
419444

@@ -517,6 +542,10 @@ Namespace DiskImage
517542
Return (Attributes And AttributeFlags.System) > 0
518543
End Function
519544

545+
Public Function IsValidVolumeName() As Boolean
546+
Return IsVolumeName() AndAlso Not (IsHidden() OrElse IsSystem() OrElse IsDirectory() OrElse IsDeleted()) AndAlso StartingCluster = 0
547+
End Function
548+
520549
Public Function IsVolumeName() As Boolean
521550
Return (Attributes And AttributeFlags.VolumeName) > 0
522551
End Function

DiskImageTool/DiskImage/Interfaces/IDirectory.vb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
ReadOnly Property IsRootDirectory As Boolean
88
ReadOnly Property ParentEntry As DirectoryEntry
99
ReadOnly Property SectorChain As List(Of UInteger)
10+
Function AddDirectory(DirectoryData() As Byte, UseLFN As Boolean, LFNFileName As String, Optional Index As Integer = -1) As Integer
1011
Function AddFile(FilePath As String, LFN As Boolean, Optional Index As Integer = -1) As Integer
1112
Function GetAvailableFileName(FileName As String, Optional CurrentIndex As Integer = -1) As String
1213
Function GetContent() As Byte()

DiskImageTool/DiskImage/RootDirectory.vb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@
5252
End Get
5353
End Property
5454

55+
Public Overrides Function AddDirectory(DirectoryData() As Byte, UseLFN As Boolean, LFNFileName As String, Optional Index As Integer = -1) As Integer Implements IDirectory.AddDirectory
56+
Dim Data = InitializeAddDirectory(Me, UseLFN, LFNFileName, Index)
57+
58+
If Data.ClusterList Is Nothing Then
59+
Return -1
60+
End If
61+
62+
Dim UseTransaction As Boolean = Disk.BeginTransaction
63+
64+
ProcessAddDirectory(Me, DirectoryData, Data)
65+
66+
If UseTransaction Then
67+
Disk.EndTransaction()
68+
End If
69+
70+
Return Data.EntriesNeeded
71+
End Function
72+
5573
Public Overrides Function AddFile(FilePath As String, WindowsAdditions As Boolean, Optional Index As Integer = -1) As Integer Implements IDirectory.AddFile
5674
Dim Data = InitializeAddFile(Me, FilePath, WindowsAdditions, Index)
5775

DiskImageTool/DiskImage/SubDirectory.vb

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,37 @@
2525
End Get
2626
End Property
2727

28+
Public Overrides Function AddDirectory(DirectoryData() As Byte, UseLFN As Boolean, LFNFileName As String, Optional Index As Integer = -1) As Integer Implements IDirectory.AddDirectory
29+
Dim Data = InitializeAddDirectory(Me, UseLFN, LFNFileName, Index)
30+
31+
If Data.ClusterList Is Nothing Then
32+
Return -1
33+
End If
34+
35+
Dim Cluster As UShort
36+
If Data.RequiresExpansion Then
37+
Cluster = Disk.FAT.GetNextFreeCluster(Data.ClusterList, True)
38+
39+
If Cluster = 0 Then
40+
Return -1
41+
End If
42+
End If
43+
44+
Dim UseTransaction As Boolean = Disk.BeginTransaction
45+
46+
If Data.RequiresExpansion Then
47+
ExpandDirectorySize(Cluster)
48+
End If
49+
50+
ProcessAddDirectory(Me, DirectoryData, Data)
51+
52+
If UseTransaction Then
53+
Disk.EndTransaction()
54+
End If
55+
56+
Return Data.EntriesNeeded
57+
End Function
58+
2859
Public Overrides Function AddFile(FilePath As String, WindowsAdditions As Boolean, Optional Index As Integer = -1) As Integer Implements IDirectory.AddFile
2960
Dim Data = InitializeAddFile(Me, FilePath, WindowsAdditions, Index)
3061

@@ -107,6 +138,39 @@
107138
Return GetDataFromChain(Disk.Image.Data, SectorChain)
108139
End Function
109140

141+
Public Sub Initialize()
142+
Dim ClusterSize = Disk.BPB.BytesPerCluster
143+
Dim Entry As DirectoryEntryBase
144+
145+
For Each Cluster In ParentEntry.FATChain.Clusters
146+
Dim OffsetStart As UInteger = Disk.BPB.ClusterToOffset(Cluster)
147+
148+
Dim Buffer = New Byte(ClusterSize - 1) {}
149+
Disk.Image.SetBytes(Buffer, OffsetStart)
150+
Next
151+
152+
Entry = New DirectoryEntryBase With {
153+
.StartingCluster = ParentEntry.StartingCluster,
154+
.FileNameWithExtension = DirectoryEntryBase.CurrentDirectoryEntry
155+
}
156+
Entry.Attributes = MyBitConverter.ToggleBit(Entry.Attributes, DirectoryEntry.AttributeFlags.Directory, True)
157+
SetEntryDates(Entry)
158+
DirectoryEntries.Item(0).Data = Entry.Data
159+
160+
Dim StartingCluster As UShort = 0
161+
If ParentEntry.ParentDirectory.ParentEntry IsNot Nothing Then
162+
StartingCluster = ParentEntry.ParentDirectory.ParentEntry.StartingCluster
163+
End If
164+
165+
Entry = New DirectoryEntryBase With {
166+
.StartingCluster = StartingCluster,
167+
.FileNameWithExtension = DirectoryEntryBase.ParentDirectoryEntry
168+
}
169+
Entry.Attributes = MyBitConverter.ToggleBit(Entry.Attributes, DirectoryEntry.AttributeFlags.Directory, True)
170+
SetEntryDates(Entry)
171+
DirectoryEntries.Item(1).Data = Entry.Data
172+
End Sub
173+
110174
Public Function ReduceDirectorySize() As Boolean
111175
If ClusterChain.Count < 2 Then
112176
Return False
@@ -205,6 +269,16 @@
205269
Return Result
206270
End Function
207271

272+
Public Sub UpdateLinkDates()
273+
Dim Entry As DirectoryEntryBase
274+
275+
For i = 0 To 1
276+
Entry = DirectoryEntries.Item(i).Clone
277+
SetEntryDates(Entry)
278+
DirectoryEntries.Item(i).Data = Entry.Data
279+
Next i
280+
End Sub
281+
208282
Private Sub InitializeDirectoryData()
209283
DirectoryEntries.Clear()
210284

@@ -231,5 +305,14 @@
231305

232306
Return True
233307
End Function
308+
309+
Private Sub SetEntryDates(Entry As DirectoryEntryBase)
310+
Entry.LastAccessDate = ParentEntry.LastAccessDate
311+
Entry.LastWriteDate = ParentEntry.LastWriteDate
312+
Entry.LastWriteTime = ParentEntry.LastWriteTime
313+
Entry.CreationDate = ParentEntry.CreationDate
314+
Entry.CreationTime = ParentEntry.CreationTime
315+
Entry.CreationMillisecond = ParentEntry.CreationMillisecond
316+
End Sub
234317
End Class
235318
End Namespace

DiskImageTool/DiskImage/Utility.vb

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
Namespace DiskImage
1+
Imports System.IO
2+
3+
Namespace DiskImage
4+
Public Structure AddDirectoryData
5+
Dim Index As Integer
6+
Dim EntriesNeeded As Integer
7+
Dim ShortFileName As String
8+
Dim ClusterList As SortedSet(Of UShort)
9+
Dim UseLFN As Boolean
10+
Dim LFNEntries As List(Of Byte())
11+
Dim RequiresExpansion As Boolean
12+
End Structure
13+
214
Public Structure AddFileData
315
Dim FilePath As String
416
Dim WindowsAdditions As Boolean
@@ -362,6 +374,38 @@
362374
Return Entries
363375
End Function
364376

377+
Public Function InitializeAddDirectory(Directory As DirectoryBase, UseLFN As Boolean, LFNFileName As String, Index As Integer) As AddDirectoryData
378+
Dim ClustersRequired As UShort = 1
379+
380+
Dim AddDirectoryData As AddDirectoryData
381+
382+
AddDirectoryData.Index = Index
383+
AddDirectoryData.UseLFN = UseLFN
384+
If UseLFN Then
385+
AddDirectoryData.ShortFileName = Directory.GetAvailableFileName(LFNFileName)
386+
AddDirectoryData.LFNEntries = GetLFNDirectoryEntries(LFNFileName, AddDirectoryData.ShortFileName)
387+
AddDirectoryData.EntriesNeeded = AddDirectoryData.LFNEntries.Count + 1
388+
Else
389+
AddDirectoryData.ShortFileName = ""
390+
AddDirectoryData.LFNEntries = Nothing
391+
AddDirectoryData.EntriesNeeded = 1
392+
End If
393+
394+
395+
AddDirectoryData.RequiresExpansion = Directory.Data.AvailableEntryCount < AddDirectoryData.EntriesNeeded
396+
If AddDirectoryData.RequiresExpansion Then
397+
ClustersRequired += 1
398+
End If
399+
400+
If AddDirectoryData.RequiresExpansion And Directory.IsRootDirectory Then
401+
AddDirectoryData.ClusterList = Nothing
402+
Else
403+
AddDirectoryData.ClusterList = Directory.Disk.FAT.GetFreeClusters(ClustersRequired)
404+
End If
405+
406+
Return AddDirectoryData
407+
End Function
408+
365409
Public Function InitializeAddFile(Directory As DirectoryBase, FilePath As String, WindowsAdditions As Boolean, Index As Integer) As AddFileData
366410
Dim FileInfo = New IO.FileInfo(FilePath)
367411
Dim ClustersRequired As UShort = Math.Ceiling(FileInfo.Length / Directory.Disk.BPB.BytesPerCluster)
@@ -415,6 +459,42 @@
415459
Return UpdateLFNData
416460
End Function
417461

462+
Public Sub ProcessAddDirectory(Directory As DirectoryBase, DirectoryData() As Byte, Data As AddDirectoryData)
463+
Dim EntryCount = Directory.DirectoryEntries.Count - Directory.Data.AvailableEntryCount
464+
Dim Entries As List(Of DirectoryEntry)
465+
466+
If Data.Index > -1 Then
467+
Data.Index = Directory.AdjustIndexForLFN(Data.Index)
468+
Directory.ShiftEntries(Data.Index, EntryCount, Data.EntriesNeeded)
469+
Entries = Directory.GetEntries(Data.Index, Data.EntriesNeeded)
470+
Else
471+
Entries = Directory.GetEntries(EntryCount, Data.EntriesNeeded)
472+
End If
473+
474+
Dim Cluster = Directory.Disk.FAT.GetNextFreeCluster(Data.ClusterList, True)
475+
Directory.Disk.FATTables.UpdateTableEntry(Cluster, FAT12.FAT_LAST_CLUSTER_END)
476+
477+
Dim Entry = New DirectoryEntryBase(DirectoryData) With {
478+
.StartingCluster = Cluster
479+
}
480+
If Data.UseLFN Then
481+
Entry.SetFileName(Data.ShortFileName)
482+
End If
483+
484+
Dim DirectoryEntry = Entries(Entries.Count - 1)
485+
DirectoryEntry.Data = Entry.Data
486+
DirectoryEntry.InitFatChain()
487+
DirectoryEntry.InitSubDirectory()
488+
489+
If Data.UseLFN Then
490+
ProcessLFNEntries(Entries, Data.LFNEntries)
491+
End If
492+
493+
Directory.UpdateEntryCounts()
494+
495+
DirectoryEntry.SubDirectory.Initialize()
496+
End Sub
497+
418498
Public Sub ProcessAddFile(Directory As DirectoryBase, Data As AddFileData)
419499
Dim EntryCount = Directory.DirectoryEntries.Count - Directory.Data.AvailableEntryCount
420500
Dim Entries As List(Of DirectoryEntry)

DiskImageTool/DiskImageTool.vbproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<ProductName>DiskImageTool</ProductName>
3232
<PublisherName>Digitoxin</PublisherName>
3333
<ApplicationRevision>0</ApplicationRevision>
34-
<ApplicationVersion>2.0.0.%2a</ApplicationVersion>
34+
<ApplicationVersion>2.01.0.%2a</ApplicationVersion>
3535
<UseApplicationTrust>false</UseApplicationTrust>
3636
<PublishWizardCompleted>true</PublishWizardCompleted>
3737
<BootstrapperEnabled>true</BootstrapperEnabled>

0 commit comments

Comments
 (0)