Hello everyone,
Purpose
I'm in the midst of implementing the write portion of FAT 32 support for my kernel. Before I actually do port it and use my HDD driver, I wrote a Linux ver. by writing to a file (formatted as a FAT 32).
First concern
What I'm confused is how to create directories.
The root directory (info extracted from the first few sectors...), I can traverse through all the directory entries and find an empty one.
But from here, I'm confused. The documentation (from Microsoft) says the length (number of directory entries) is variable. So does that mean there is no limit as to how many directories can be created? What if I hit a cluster with data?
If that's not true, what do I need to consider? Is there a way to find out the limit?
Next concern
The next concern is filling the member of the directory entry that points to the first cluster of a non-zero file. If the first link to the cluster is not on the FAT itself, how would I go about allocating a cluster?
In short, I'm confused about how to create a file (in terms of allocating free clusters)
Next, performance is not of importance yet. So would the easiest way to allocate a link on the FAT to read every time I create a file?
Thanks everyone.
FAT 32 troubles (creating directories)
FAT 32 troubles (creating directories)
Last edited by mrkotfw on Thu Jan 26, 2012 4:15 am, edited 1 time in total.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: FAT 32 troubles (creating directories)
In FAT (and especially FAT32) directories are just like any other file; you follow cluster chains until you reach the end, and if you need more space you add another cluster to the chain. Similarly you can trim clusters when the directory shrinks.mrkotfw wrote:But from here, I'm confused. The documentation (from Microsoft) says the length (number of directory entries) is variable. So does that mean there is no limit as to how many directories can be created? What if I hit a cluster with data?
That also means that directory contents does not need to be in consecutive sectors - it typically works because its created as such and rarely changes.
The exception to this are the root directories on FAT12/FAT16 which have fixed sizes at formatting time - something to remember for later.
In generic terms, files are stored by getting a cluster index, reading it's content, then getting the next cluster index by indexing the FAT with the current cluster index.
Writing a file consists of finding an empty cluster (FAT will tell you which ones are empty) setting it to used, then write the data. If you need more than one cluster, allocate another one, and point the previous cluster's FAT entry to the new cluster.
If you paid attention, you'll see file size is stored twice: one accurate to the byte and one accurate to the cluster size.
Re: FAT 32 troubles (creating directories)
I see. I'm going to take this bit by bit (directories first). Also, I'm only going to support FAT 32. This FS is only provisional.Combuster wrote:In FAT (and especially FAT32) directories are just like any other file; you follow cluster chains until you reach the end, and if you need more space you add another cluster to the chain. Similarly you can trim clusters when the directory shrinks.mrkotfw wrote:But from here, I'm confused. The documentation (from Microsoft) says the length (number of directory entries) is variable. So does that mean there is no limit as to how many directories can be created? What if I hit a cluster with data?
That also means that directory contents does not need to be in consecutive sectors - it typically works because its created as such and rarely changes.
The exception to this are the root directories on FAT12/FAT16 which have fixed sizes at formatting time - something to remember for later.
In generic terms, files are stored by getting a cluster index, reading it's content, then getting the next cluster index by indexing the FAT with the current cluster index.
Writing a file consists of finding an empty cluster (FAT will tell you which ones are empty) setting it to used, then write the data. If you need more than one cluster, allocate another one, and point the previous cluster's FAT entry to the new cluster.
If you paid attention, you'll see file size is stored twice: one accurate to the byte and one accurate to the cluster size.
So let's take the root directory. Initially (let's assume all directories fit within one cluster so no need for a chain). I can create/add directories contiguously until I hit a used cluster. When that does happen, I add another cluster to the chain. Let's assume that I have the cluster value C. Should I then set C to the directory entry of root (the directory entry whose attribute has the Volume bit set)?
As for allocating a cluster, FAT should tell me everything. Is the offset in which I find an empty chain the cluster number?
Thank you for the very detailed explanation.
Re: FAT 32 troubles (creating directories)
the [FAT] table
- each [CLUSTER] on disk has got a representative in the FAT table;
- so each FAT table entry [a 12bit/16bit/32bit value] tells you if that cluster is :
a) free (= 0)
b) last cluster in the chain ({for 12bit 0x7ff}/{for 16bit 0xfff0}/{for 32bit 0xfffffff0})
c) one of the chain : a value from 1 up to (TOTAL_NUMBER_OF_CLUSTERS-1) [note: the first cluster is 0 but that's the ROOT directory; for fat32 the root directory must start with at cluster 0 and 0)
there's a rule for converting from cluster to sector position :
sec =(cluster - 2)*bootsect.SectorsPerCluster + rootdir_starting_sector
and the FAT starts at absolute sector:
fat_start=partition_start+ boot_sector.ReservedSectors + boot_sector.HiddenSectors
fat2_start=fat_start+boot_sector.BigSectorsPerFat
and the ROOTDIR starts at absolute sector : [for FAT32 partitions only]
rootdir_starting_sector = partition_start + boot_sector.NumberOfFATs * boot_sector.BigSectorsPerFAT
----
Be aware that a FAT32/FAT16 partition can have different SectorsPerCluster sizes (other than the standard values: 8sectors for fat32 and 16sectors for fat16) For instance I have a digital camera that uses FAT16 and 32KB per cluster [ 64sectors per cluster]
----
each sub-directory of a directory has this format:
-the directory_entry in the [parent directory]'s will have the STARTING_CLUSTER point to FIRST CLUSTER in the chain ;
-the [child directory]'s first cluster will have as :
a) first item the "." which will point to himself [the first cluster in the link]
b) 2nd item the ".." which will point to the parent dir
NOTE: the 2nd/3rd/.../up_to_the_last_one cluster in the directory linked list will NOT contain the this 2 items.
You will need to allocate clusters for your directory [writeing the same values in all the FATs]
Try:
Alex Vestak's FAT docx: http://averstak.tripod.com/fatdox/00dindex.htm
[here's how I'm doing MAKEDIR for my own project - written in freebasic... ]
[ DH is the drive's handle an OOP object with vital information about the filesystem etc]
[ parw - is the partition number - 0..3]
[ fname - contains the new directory's name]
[ fdir - is not used, ... it's 0]
[and here's how I create a file:]
my project is hosted at :http://sourceforge.net/projects/filesystemd/files/
- each [CLUSTER] on disk has got a representative in the FAT table;
- so each FAT table entry [a 12bit/16bit/32bit value] tells you if that cluster is :
a) free (= 0)
b) last cluster in the chain ({for 12bit 0x7ff}/{for 16bit 0xfff0}/{for 32bit 0xfffffff0})
c) one of the chain : a value from 1 up to (TOTAL_NUMBER_OF_CLUSTERS-1) [note: the first cluster is 0 but that's the ROOT directory; for fat32 the root directory must start with at cluster 0 and 0)
there's a rule for converting from cluster to sector position :
sec =(cluster - 2)*bootsect.SectorsPerCluster + rootdir_starting_sector
and the FAT starts at absolute sector:
fat_start=partition_start+ boot_sector.ReservedSectors + boot_sector.HiddenSectors
fat2_start=fat_start+boot_sector.BigSectorsPerFat
and the ROOTDIR starts at absolute sector : [for FAT32 partitions only]
rootdir_starting_sector = partition_start + boot_sector.NumberOfFATs * boot_sector.BigSectorsPerFAT
----
Be aware that a FAT32/FAT16 partition can have different SectorsPerCluster sizes (other than the standard values: 8sectors for fat32 and 16sectors for fat16) For instance I have a digital camera that uses FAT16 and 32KB per cluster [ 64sectors per cluster]
----
each sub-directory of a directory has this format:
-the directory_entry in the [parent directory]'s will have the STARTING_CLUSTER point to FIRST CLUSTER in the chain ;
-the [child directory]'s first cluster will have as :
a) first item the "." which will point to himself [the first cluster in the link]
b) 2nd item the ".." which will point to the parent dir
NOTE: the 2nd/3rd/.../up_to_the_last_one cluster in the directory linked list will NOT contain the this 2 items.
You will need to allocate clusters for your directory [writeing the same values in all the FATs]
Try:
Alex Vestak's FAT docx: http://averstak.tripod.com/fatdox/00dindex.htm
[here's how I'm doing MAKEDIR for my own project - written in freebasic... ]
[ DH is the drive's handle an OOP object with vital information about the filesystem etc]
[ parw - is the partition number - 0..3]
[ fname - contains the new directory's name]
[ fdir - is not used, ... it's 0]
Code: Select all
Sub make_dir(dh as drive_handle ptr ,parw As Integer,fname As Any Ptr, fdir as dir_entry ptr)
if dh=0 or parw <0 or fname=0 then exit sub
if len(*cptr(zstring ptr,fname))=0 then exit sub
dim as ubyte ptr clusterb
dim as Dir_entry ptr dent,sent
Dim As Dir_entry ment
Dim As LFN_entry Ptr lfne,lfns
Dim As Integer lfn_size
Dim as integer i,k,j,lastlev
dim as uinteger cu,du,lu,xu
dim as uinteger max_clusty,clusty,cluster_len
dim as string din=*cptr(zstring ptr, fname)
Dim As UInteger Ptr dd
Dim As Integer dcnt
Dim As Integer needed,founded,ii,sum
i=1:k=0
'Print "mkdir :";din
while instr(i,din,"\")>0 or instr(i,din,"/")>0
if instr(i,din,"\")>0 then
k+=1
i=instr(i,din,"\")+1
elseif instr(i,din,"/")>0 then
k+=1
i=instr(i,din,"/")+1
end if
wend
if i<=len(din) then k+=1
'Print "there are # entries";k
lastlev=k
dim as string d(1 to lastlev)
i=1:j=0
while instr(i,din,"\")>0 or instr(i,din,"/")>0
if instr(i,din,"\")>0 then
j+=1
d(j)=mid(din,i,instr(i,din,"\")-i)
i=instr(i,din,"\")+1
elseif instr(i,din,"/")>0 then
j+=1
d(j)=mid(din,i,instr(i,din,"/")-i)
i=instr(i,din,"/")+1
end if
wend
if i<=len(din) then
j+=1
d(j)=mid(din,i,len(din)-i+1)
end if
if j=0 then exit Sub
needed=1
If (InStrRev(d(lastlev),".")>9) Or _
((InStr(d(lastlev),".")<1) And (Len(d(lastlev))>8)) Or _
(((Len(d(lastlev))-InStrRev(d(lastlev),"."))>3) And (InStrrev(d(lastlev),".")>0)) Then
d(k)+=Chr(0)
ii=IIf(InStr(d(k),".")>0,InStr(d(lastlev),".")-1-1,Len(d(lastlev))-1)
If ii>7 Then ii=7
For k=0 To ii
ment.Filename(k)=Asc(ucase(d(lastlev)),k+1)
Next k
ment.Filename(6)=Asc("~")
ment.Filename(7)=Asc("1")
ii=IIf(InStr(d(lastlev),".")>0,Len(d(lastlev))-InStr(d(lastlev),".")-1,-1)
If ii>2 Then ii=2
For k=0 To ii
ment.Extension(k)=Asc(ucase(d(lastlev)),InStr(d(lastlev),".")+1+k)
Next k
create_lfn_entries(StrPtr(d(lastlev)),@ment,@lfne,@lfn_size)
d(lastlev)=getfatdrec_name(@ment)
needed+=lfn_size
'pause1 "size="+Str(lfn_size)
lfns=lfne
'Else
'pause1 "not lfn !"
EndIf
'Print "j=";j
'For i=1 To j
' Print i,d(i)
'Next i
cluster_len=dh->ide_info_dat->bootsect(parw).SectorsPerCluster*512
clusterb=callocate(cluster_len+512)
max_clusty=get_max_cluster(dh,parw)
j=1
cu=iif(dh->ide_info_dat->where(parw).fat16is=0,2,0)
dd=Callocate(1000 shl 2)
redo_from_start_search_mkdir:
dcnt=0
'pause1 "make dir :"+d(lastlev)
if dh->alloctable_cached=0 or (dh->alloctable=0) then
While (cu<>0 or (dcnt=0 and dh->ide_info_dat->where(parw).fat16is=1)) And cu<max_clusty And cu<dh->ide_info_dat->where(parw).dataclusters
dd[dcnt]=cu: cu=getfatentry(dh,parw,cu):dcnt+=1
Wend
dd[dcnt]=cu
elseif (dh->alloctable_cached=0) and (dh->alloctable<>0) then
While (cu<>0 or (dcnt=0 and dh->ide_info_dat->where(parw).fat16is=1)) And cu<max_clusty And cu<dh->ide_info_dat->where(parw).dataclusters
dd[dcnt]=cu: cu=getfatentryvirtual(dh,parw,dh->alloctable,cu):dcnt+=1
Wend
dd[dcnt]=cu
end if
stosb1 &h20,@ment,11
For k=0 To IIf(InStr(d(j),".")>0,InStr(d(j),".")-1-1,Len(d(j))-1)
ment.Filename(k)=Asc(ucase(d(j)),k+1)
Next k
For k=0 To IIf(InStr(d(j),".")>0,Len(d(j))-InStr(d(j),".")-1,-1)
ment.Extension(k)=Asc(ucase(d(j)),InStr(d(j),".")+1+k)
Next k
ment.attribute=attrDirectory
i=0
While (dd[i]<>0 or (i=0 and dh->ide_info_dat->where(parw).fat16is=1)) and dd[i]<max_clusty
readcluster(dh,parw,dd[i],clusterb)
restart_dasda:
sent=clusterb
founded=0
while sent<clusterb+cluster_len
If j<lastlev Then
If (cmpsb1 (sent,@ment,11)=1) And (sent->Attribute And ment.Attribute = ment.Attribute) Then
cu = (sent->Starting_cluster_high Shl 16) + sent->Starting_cluster
'print "we are @ ";d(j);" and going to :";
j+=1
'Print d(j)
GoTo redo_from_start_search_mkdir
EndIf
Else
If (cmpsb1 (sent,@ment,11)=1) And (sent->Attribute And ment.Attribute = ment.Attribute) And (needed>1) Then
If ment.Filename(7)=Asc("9") Then
If ment.filename(6)=Asc("~") Then
ment.filename(5)=Asc("~")
ment.Filename(6)=Asc("1")
Else
ment.Filename(6)+=1
EndIf
Else
ment.Filename(7)+=1
EndIf
GoTo restart_dasda
EndIf
If (sent->Filename(0)=Dir_entry_deleted) Or (sent->Filename(0)=0) Then
'pause1 "creating dir !"
founded+=1
If needed<=founded Then
ment.Size=0
ment.Case_=0
ment.attribute=attrDirectory
if dh->alloctable_cached=0 or dh->alloctable=0 then
cu=getfreefatentry(dh,parw)
else
cu=getfreefatvirtual_smart(dh,parw,dh->alloctable,0,0)
end if
ment.Starting_cluster=cu
ment.Starting_cluster_high=cu Shr 16
setfatdrec_datetime(@ment)
'Print "first free cluster=";Hex(cu)
'Print "setting new entry ! and writeing cluster=";Hex(dd[i])
'Print "setting fat1/2 entry for new cluster"
'Print "creating '.' and '..' entries"
'Print "cluster[0] of parent dir:";Hex(dd[0])
'Print "writing new cluster"
'Print "done"
'Input "continue to do all this ?(1=yes,<>1 = no)",k
'If k<>1 Then GoTo make_dir_dealloc
If lfn_size>0 Then
sent=sent-needed+1
For ii=0 to 10
If (Asc(d(j),ii+1)<>Asc(" ")) And (Asc(d(j),ii+1)=0) Then
sum=(((sum and 1)shl 7) or ((sum and &HFE) shr 1))+Asc(d(j),ii+1)
End If
Next ii
ii=0
While ii<lfn_size
lfne->Alias_checksum=sum
movsb1 lfne,sent,Len(LFN_entry)
sent+=1
lfne+=1
ii+=1
Wend
EndIf
movsb1 @ment,sent,Len(Dir_entry)
writecluster(dh,parw,dd[i],clusterb)
if dh->alloctable_cached=0 or dh->alloctable=0 then
setfatentry(dh,parw,cu,max_clusty or &hf)
setfat2entry(dh,parw,cu,max_clusty or &hf)
else
setfatentryvirtual(dh,parw,dh->alloctable,cu,max_clusty or &hf)
end if
stosb1 0,clusterb,cluster_len
stosb1 &h20,@ment, 11
ment.Filename(0)=Asc(".")
sent=clusterb
movsb1 @ment,sent,Len(Dir_entry)
if (dd[0]>2 and dh->ide_info_dat->where(parw).fat16is=0) or (dd[0]>0 and dh->ide_info_dat->where(parw).fat16is=1) then
ment.starting_cluster=dd[0] and &hffff
ment.starting_cluster_high=dd[0] shr 16
else
ment.starting_cluster=0
ment.starting_cluster_high=0
end if
ment.Filename(1)=Asc(".")
sent+=1
movsb1 @ment,sent,Len(Dir_entry)
writecluster(dh,parw,cu,clusterb)
GoTo make_dir_dealloc
End If
Else
founded=0
EndIf
End If
sent+=1
Wend
i+=1
Wend
if j>=lastlev and dcnt>0 then
'if we arrive here and it means there are no free entries ! So link one more cluster !
if dh->alloctable_cached=0 or dh->alloctable=0 then
cu=getfreefatentry(dh,parw)
setfatentry(dh, parw,dd[dcnt-1],cu)
setfatentry(dh, parw,cu,max_clusty or &hf)
setfat2entry(dh, parw,dd[dcnt-1],cu)
setfat2entry(dh, parw,cu,max_clusty or &hf)
dd[dcnt]=cu: i=dcnt
dcnt+=1: dd[dcnt]=max_clusty or &hf
else
cu=getfreefatvirtual_smart(dh,parw,dh->alloctable,0,0)
setfatentryvirtual(dh, parw,dh->alloctable, dd[dcnt-1],cu)
setfatentryvirtual(dh, parw,cu,dh->alloctable,max_clusty or &hf)
dd[dcnt]=cu: i=dcnt
dcnt+=1: dd[dcnt]=max_clusty or &hf
end if
ment.Size=0
ment.Case_=0
if dh->alloctable_cached=0 or dh->alloctable=0 then
cu=getfreefatentry(dh,parw)
else
cu=getfreefatvirtual_smart(dh,parw,dh->alloctable,0,0)
end if
ment.Starting_cluster=cu
ment.Starting_cluster_high=cu Shr 16
setfatdrec_datetime(@ment)
'Print "first free cluster=";Hex(cu)
'Print "setting new entry ! and writeing cluster=";Hex(dd[i])
'Print "setting fat1/2 entry for new cluster"
'Print "creating '.' and '..' entries"
'Print "cluster[0] of parent dir:";Hex(dd[0])
'Print "writing new cluster"
'Print "done"
'Input "continue to do all this ?(1=yes,<>1 = no)",k
'If k<>1 Then GoTo make_dir_dealloc
stosb1 0,clusterb,cluster_len
sent=clusterb
If lfn_size>0 Then
For ii=0 to 10
If (Asc(d(j),ii+1)<>Asc(" ")) And (Asc(d(j),ii+1)=0) Then
sum=(((sum and 1)shl 7) or ((sum and &HFE) shr 1))+Asc(d(j),ii+1)
End If
Next ii
ii=0
While ii<lfn_size
lfne->Alias_checksum=sum
movsb1 lfne,sent,Len(LFN_entry)
sent+=1
lfne+=1
ii+=1
Wend
End If
movsb1 @ment,clusterb,Len(Dir_entry)
writecluster(dh,parw,dd[i],clusterb)
if dh->alloctable_cached=0 or dh->alloctable=0 then
setfatentry(dh,parw,cu,max_clusty or &hf)
setfat2entry(dh,parw,cu,max_clusty or &hf)
else
setfatentryvirtual(dh,parw,dh->alloctable,cu,max_clusty or &hf)
end if
stosb1 0,clusterb,cluster_len
stosb1 &h20,@ment, 11
ment.Filename(0)=Asc(".")
sent=clusterb
movsb1 @ment,sent,Len(Dir_entry)
if (dd[0]>2 and dh->ide_info_dat->where(parw).fat16is=0) or (dd[0]>0 and dh->ide_info_dat->where(parw).fat16is=1) then
ment.starting_cluster=dd[0] and &hffff
ment.starting_cluster_high=dd[0] shr 16
else
ment.starting_cluster=0
ment.starting_cluster_high=0
end if
ment.Filename(1)=Asc(".")
sent+=1
movsb1 @ment,sent,Len(Dir_entry)
writecluster(dh,parw,cu,clusterb)
GoTo make_dir_dealloc
end if
make_dir_dealloc:
dealloc2 @clusterb
dealloc2 @dd
dealloc2 @lfns
'Print "returning": Sleep
End Sub
Code: Select all
Sub make_file(dh as drive_handle ptr ,parw As Integer,fname As Any Ptr, fdir as dir_entry ptr, parentcl as uinteger ptr)
if dh=0 or parw <0 or fname=0 then exit sub
if len(*cptr(zstring ptr,fname))=0 then exit sub
dim as ubyte ptr clusterb
dim as Dir_entry ptr dent,sent
Dim As Dir_entry ment
Dim As LFN_entry Ptr lfne,lfns
Dim As Integer lfn_size
Dim as integer i,k,j,lastlev
dim as uinteger cu,du,lu,xu
dim as uinteger max_clusty,clusty,cluster_len
dim as string din=*cptr(zstring ptr, fname)
Dim As UInteger Ptr dd
Dim As Integer dcnt
Dim As Integer needed,founded,ii,sum
i=1:k=0
'Print "mkdir :";din
while instr(i,din,"\")>0 or instr(i,din,"/")>0
if instr(i,din,"\")>0 then
k+=1
i=instr(i,din,"\")+1
elseif instr(i,din,"/")>0 then
k+=1
i=instr(i,din,"/")+1
end if
wend
if i<=len(din) then k+=1
'Print "there are # entries";k
lastlev=k
dim as string d(1 to lastlev)
i=1:j=0
while instr(i,din,"\")>0 or instr(i,din,"/")>0
if instr(i,din,"\")>0 then
j+=1
d(j)=mid(din,i,instr(i,din,"\")-i)
i=instr(i,din,"\")+1
elseif instr(i,din,"/")>0 then
j+=1
d(j)=mid(din,i,instr(i,din,"/")-i)
i=instr(i,din,"/")+1
end if
wend
if i<=len(din) then
j+=1
d(j)=mid(din,i,len(din)-i+1)
end if
if j=0 then exit Sub
needed=1
If (InStrRev(d(lastlev),".")>9) Or _
((InStr(d(lastlev),".")<1) And (Len(d(lastlev))>8)) Or _
(((Len(d(lastlev))-InStrRev(d(lastlev),"."))>3) And (InStrrev(d(lastlev),".")>0)) Then
d(k)+=Chr(0)
ii=IIf(InStr(d(k),".")>0,InStr(d(lastlev),".")-1-1,Len(d(lastlev))-1)
If ii>7 Then ii=7
For k=0 To ii
ment.Filename(k)=Asc(ucase(d(lastlev)),k+1)
Next k
ment.Filename(6)=Asc("~")
ment.Filename(7)=Asc("1")
ii=IIf(InStr(d(lastlev),".")>0,Len(d(lastlev))-InStr(d(lastlev),".")-1,-1)
If ii>2 Then ii=2
For k=0 To ii
ment.Extension(k)=Asc(ucase(d(lastlev)),InStr(d(lastlev),".")+1+k)
Next k
create_lfn_entries(StrPtr(d(lastlev)),@ment,@lfne,@lfn_size)
d(lastlev)=getfatdrec_name(@ment)
needed+=lfn_size
'pause1 "size="+Str(lfn_size)
lfns=lfne
'Else
'pause1 "not lfn !"
EndIf
'Print "j=";j
'For i=1 To j
' Print i,d(i)
'Next i
cluster_len=dh->ide_info_dat->bootsect(parw).SectorsPerCluster shl 9
clusterb=callocate(cluster_len+512)
max_clusty=get_max_cluster(dh,parw)
j=1
cu=iif(dh->ide_info_dat->where(parw).fat16is=0,2,0)
dd=Callocate(1000 shl 2)
redo_from_start_search_mkfile:
dcnt=0
if dh->alloctable_cached=0 or (dh->alloctable=0) then
While (cu<>0 or (dcnt=0 and dh->ide_info_dat->where(parw).fat16is=1)) And cu<max_clusty And cu<dh->ide_info_dat->where(parw).dataclusters
dd[dcnt]=cu: cu=getfatentry(dh,parw,cu):dcnt+=1
Wend
dd[dcnt]=cu
elseif (dh->alloctable_cached=0) and (dh->alloctable<>0) then
While (cu<>0 or (dcnt=0 and dh->ide_info_dat->where(parw).fat16is=1)) And cu<max_clusty And cu<dh->ide_info_dat->where(parw).dataclusters
dd[dcnt]=cu: cu=getfatentryvirtual(dh,parw,dh->alloctable,cu):dcnt+=1
Wend
dd[dcnt]=cu
end if
ment.attribute=attrDirectory
stosb1 &h20,@ment,11
For k=0 To IIf(InStr(d(j),".")>0,InStr(d(j),".")-1-1,Len(d(j))-1)
ment.Filename(k)=Asc(ucase(d(j)),k+1)
Next k
For k=0 To IIf(InStr(d(j),".")>0,Len(d(j))-InStr(d(j),".")-1,-1)
ment.Extension(k)=Asc(ucase(d(j)),InStr(d(j),".")+1+k)
Next k
if j=lastlev then
While (dd[i]<>0 or (i=0 and dh->ide_info_dat->where(parw).fat16is=1)) and dd[i]<max_clusty and i<dcnt
readcluster(dh,parw,dd[i],clusterb)
sent=clusterb
while sent<clusterb+cluster_len
If (cmpsb1 (sent,@ment,11)=1) And (sent->Attribute And ment.Attribute = ment.Attribute) Then
goto make_file_dealloc
end if
sent+=1
wend
i+=1
wend
end if
i=0
While (dd[i]<>0 or (i=0 and dh->ide_info_dat->where(parw).fat16is=1))and dd[i]<max_clusty and i<dcnt
readcluster(dh,parw,dd[i],clusterb)
restart_dasda2:
sent=clusterb
founded=0
while sent<clusterb+cluster_len
If j<lastlev Then
If (cmpsb1 (sent,@ment,11)=1) And (sent->Attribute And ment.Attribute = ment.Attribute) Then
cu = (sent->Starting_cluster_high Shl 16) + sent->Starting_cluster
'print "we are @ ";d(j);" and going to :";
j+=1
'Print d(j)
GoTo redo_from_start_search_mkfile
EndIf
Else
If (cmpsb1 (sent,@ment,11)=1) And (sent->Attribute And ment.Attribute = ment.Attribute) And (needed>1) Then
If ment.Filename(7)=Asc("9") Then
If ment.filename(6)=Asc("~") Then
ment.filename(5)=Asc("~")
ment.Filename(6)=Asc("1")
Else
ment.Filename(6)+=1
EndIf
Else
ment.Filename(7)+=1
EndIf
GoTo restart_dasda2
EndIf
If (sent->Filename(0)=Dir_entry_deleted) Or (sent->Filename(0)=0) Then
'pause1 "creating dir !"+getfatdrec_name(@ment)
founded+=1
If needed<=founded Then
ment.attribute=attrArchive
ment.Case_=0
ment.Size=0
'cu=getfreefatentry(dh,parw)
ment.Starting_cluster=0
ment.Starting_cluster_high=0
setfatdrec_datetime(@ment)
'Print "first free cluster=";Hex(cu)
'Print "setting new entry ! and writeing cluster=";Hex(dd[i])
'Print "setting fat1/2 entry for new cluster"
'Print "creating '.' and '..' entries"
'Print "cluster[0] of parent dir:";Hex(dd[0])
'Print "writing new cluster"
'Print "done"
'Input "continue to do all this ?(1=yes,<>1 = no)",k
'If k<>1 Then GoTo make_dir_dealloc
If lfn_size>0 Then
sent=sent-needed+1
For ii=0 to 10
If (Asc(d(j),ii+1)<>Asc(" ")) And (Asc(d(j),ii+1)=0) Then
sum=(((sum and 1)shl 7) or ((sum and &HFE) shr 1))+Asc(d(j),ii+1)
End If
Next ii
ii=0
While ii<lfn_size
lfne->Alias_checksum=sum
movsb1 lfne,sent,Len(LFN_entry)
sent+=1
lfne+=1
ii+=1
Wend
EndIf
movsb1 @ment,sent,Len(Dir_entry)
writecluster(dh,parw,dd[i],clusterb)
if fdir<>0 then movsb1 @ment,fdir,len(dir_entry)
'print "stored :";getfatdrec_name(fdir):sleep
if parentcl<>0 then *parentcl=dd[i]
'pause1 "finshed"
GoTo make_file_dealloc
End If
Else
founded=0
EndIf
End If
sent+=1
Wend
i+=1
Wend
'pause1 "no more free !"+str(j)+"%"+str(lastlev)+":"+str(dcnt)
if j>=lastlev and dcnt>0 then
'if we arrive here and it means there are no free entries ! So link one more cluster !
if dh->alloctable_cached=0 or dh->alloctable=0 then
cu=getfreefatentry(dh,parw)
setfatentry(dh, parw,dd[dcnt-1],cu)
setfatentry(dh, parw,cu,max_clusty or &hf)
setfat2entry(dh, parw,dd[dcnt-1],cu)
setfat2entry(dh, parw,cu,max_clusty or &hf)
dd[dcnt]=cu: i=dcnt
dcnt+=1: dd[dcnt]=max_clusty or &hf
else
cu=getfreefatvirtual_smart(dh,parw,dh->alloctable,0,0)
setfatentryvirtual(dh, parw,dh->alloctable, dd[dcnt-1],cu)
setfatentryvirtual(dh, parw,cu,dh->alloctable,max_clusty or &hf)
dd[dcnt]=cu: i=dcnt
dcnt+=1: dd[dcnt]=max_clusty or &hf
end if
'Print "creating dir !"
ment.Case_=0
ment.Size=0
ment.attribute=attrArchive
'cu=getfreefatentry(dh,parw)
ment.Starting_cluster=0
ment.Starting_cluster_high=0
setfatdrec_datetime(@ment)
stosb1 0,clusterb,cluster_len
sent=clusterb
If lfn_size>0 Then
sent=sent-needed+1
For ii=0 to 10
If (Asc(d(j),ii+1)<>Asc(" ")) And (Asc(d(j),ii+1)=0) Then
sum=(((sum and 1)shl 7) or ((sum and &HFE) shr 1))+Asc(d(j),ii+1)
End If
Next ii
ii=0
While ii<lfn_size
lfne->Alias_checksum=sum
movsb1 lfne,sent,Len(LFN_entry)
sent+=1
lfne+=1
ii+=1
Wend
EndIf
movsb1 @ment,sent,Len(Dir_entry)
writecluster(dh,parw,dd[i],clusterb)
if fdir<>0 then
movsb1 @ment,fdir,len(dir_entry)
'print "stored :";getfatdrec_name(fdir):sleep
end if
if parentcl<>0 Then *parentcl=dd[i]
GoTo make_file_dealloc
end if
make_file_dealloc:
dealloc2 @clusterb
dealloc2 @dd
dealloc2 @lfns
'Print "returning": Sleep
End Sub