2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/fs/vfat/dirwr.c
5 * PURPOSE: VFAT Filesystem : write in directory
9 /* INCLUDES *****************************************************************/
11 #include <ddk/ntddk.h>
14 #include <internal/string.h>
17 #include <internal/debug.h>
21 NTSTATUS
updEntry(PDEVICE_EXTENSION DeviceExt
,PFILE_OBJECT pFileObject
)
23 update an existing FAT entry
26 WCHAR DirName
[MAX_PATH
],*FileName
,*PathFileName
;
28 ULONG Sector
=0,Entry
=0;
30 FATDirEntry
* pEntries
;
32 FILE_OBJECT FileObject
;
34 PVFATFCB pDirFcb
,pFcb
;
35 short i
,posCar
,NameLen
;
36 PathFileName
=pFileObject
->FileName
.Buffer
;
37 pFcb
=((PVFATCCB
)pFileObject
->FsContext2
)->pFcb
;
38 //find last \ in PathFileName
40 for(i
=0;PathFileName
[i
];i
++)
41 if(PathFileName
[i
]=='\\')posCar
=i
;
43 return STATUS_UNSUCCESSFUL
;
44 FileName
=&PathFileName
[posCar
+1];
45 for(NameLen
=0;FileName
[NameLen
];NameLen
++);
46 // extract directory name from pathname
47 memcpy(DirName
,PathFileName
,posCar
*sizeof(WCHAR
));
49 if(FileName
[0]==0 && DirName
[0]==0)
50 return STATUS_SUCCESS
;//root : nothing to do ?
51 memset(&FileObject
,0,sizeof(FILE_OBJECT
));
52 DPRINT("open directory %S for update of entry %S\n",DirName
,FileName
);
53 status
=FsdOpenFile(DeviceExt
,&FileObject
,DirName
);
54 pDirCcb
=(PVFATCCB
)FileObject
.FsContext2
;
56 pDirFcb
=pDirCcb
->pFcb
;
58 FileFcb
.ObjectName
=&FileFcb
.PathName
[0];
59 status
=FindFile(DeviceExt
,&FileFcb
,pDirFcb
,FileName
,&Sector
,&Entry
);
60 if(NT_SUCCESS(status
))
62 Buffer
=ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
63 DPRINT("update entry: sector %d, entry %d\n",Sector
,Entry
);
64 VFATReadSectors(DeviceExt
->StorageDevice
,Sector
,1,Buffer
);
65 pEntries
=(FATDirEntry
*)Buffer
;
66 memcpy(&pEntries
[Entry
],&pFcb
->entry
,sizeof(FATDirEntry
));
67 VFATWriteSectors(DeviceExt
->StorageDevice
,Sector
,1,Buffer
);
70 FsdCloseFile(DeviceExt
,&FileObject
);
74 NTSTATUS
addEntry(PDEVICE_EXTENSION DeviceExt
75 ,PFILE_OBJECT pFileObject
,ULONG RequestedOptions
,UCHAR ReqAttr
)
77 create a new FAT entry
80 WCHAR DirName
[MAX_PATH
],*FileName
,*PathFileName
;
81 VFATFCB DirFcb
,FileFcb
;
84 FILE_OBJECT FileObject
;
87 ULONG LengthRead
,Offset
;
88 short nbSlots
=0,nbFree
=0,i
,j
,posCar
,NameLen
;
89 PUCHAR Buffer
,Buffer2
;
90 BOOLEAN needTilde
=FALSE
,needLong
=FALSE
;
96 PathFileName
=pFileObject
->FileName
.Buffer
;
97 DPRINT("addEntry: Pathname=%S\n",PathFileName
);
98 //find last \ in PathFileName
100 for(i
=0;PathFileName
[i
];i
++)
101 if(PathFileName
[i
]=='\\')posCar
=i
;
103 return STATUS_UNSUCCESSFUL
;
104 FileName
=&PathFileName
[posCar
+1];
105 for(NameLen
=0;FileName
[NameLen
];NameLen
++);
106 // extract directory name from pathname
107 memcpy(DirName
,PathFileName
,posCar
*sizeof(WCHAR
));
109 // open parent directory
110 memset(&FileObject
,0,sizeof(FILE_OBJECT
));
111 status
=FsdOpenFile(DeviceExt
,&FileObject
,DirName
);
112 nbSlots
=(NameLen
+12)/13+1;//nb of entry needed for long name+normal entry
113 DPRINT("NameLen= %d, nbSlots =%d\n",NameLen
,nbSlots
);
114 Buffer
=ExAllocatePool(NonPagedPool
,(nbSlots
+1)*sizeof(FATDirEntry
));
115 memset(Buffer
,0,(nbSlots
+1)*sizeof(FATDirEntry
));
116 pEntry
=(FATDirEntry
*)(Buffer
+(nbSlots
-1)*sizeof(FATDirEntry
));
117 pSlots
=(slot
*)Buffer
;
120 // find last point in name
122 for(i
=0;FileName
[i
];i
++)
123 if(FileName
[i
]=='.')posCar
=i
;
124 if(!posCar
) posCar
=i
;
125 if(posCar
>8) needTilde
=TRUE
;
126 //copy 8 characters max
127 memset(pEntry
,' ',11);
128 for(i
=0,j
=0;j
<8 && i
<posCar
;i
++)
130 //FIXME : is there other characters to ignore ?
140 pEntry
->Filename
[j
++]=toupper((char) FileName
[i
]);
146 for(j
=0,i
=posCar
+1;FileName
[i
] && i
<posCar
+4;i
++)
148 pEntry
->Ext
[j
++]=toupper((char)( FileName
[i
] &0x7F));
152 //find good value for tilde
156 DPRINT("searching a good value for tilde\n");
158 DirName
[i
]=pEntry
->Filename
[i
];
160 DirName
[i
+8]=pEntry
->Ext
[i
];
161 //try first with xxxxxx~y.zzz
163 pEntry
->Filename
[6]='~';
169 pEntry
->Filename
[7]='0'+i
;
170 status
=FindFile(DeviceExt
,&FileFcb
171 ,&DirFcb
,DirName
,NULL
,NULL
);
172 if(status
!=STATUS_SUCCESS
)break;
174 //try second with xxxxx~yy.zzz
181 pEntry
->Filename
[7]='0'+i
;
182 status
=FindFile(DeviceExt
,&FileFcb
183 ,&DirFcb
,DirName
,NULL
,NULL
);
184 if(status
!=STATUS_SUCCESS
)break;
187 if(i
==100)//FIXME : what to do after 99 tilde ?
189 FsdCloseFile(DeviceExt
,&FileObject
);
191 return STATUS_UNSUCCESSFUL
;
196 DPRINT("check if long name entry needed, needlong=%d\n",needLong
);
197 for(i
=0;i
<posCar
;i
++)
198 if((USHORT
)pEntry
->Filename
[i
]!=FileName
[i
])
200 DPRINT("i=%d,%d,%d\n",i
,pEntry
->Filename
[i
],FileName
[i
]);
205 i
++;//jump on point char
206 for(j
=0,i
=posCar
+1;FileName
[i
] && i
<posCar
+4;i
++)
207 if((USHORT
)pEntry
->Ext
[j
++]!= FileName
[i
])
209 DPRINT("i=%d,j=%d,%d,%d\n",i
,j
,pEntry
->Filename
[i
],FileName
[i
]);
217 memcpy(Buffer
,pEntry
,sizeof(FATDirEntry
));
218 memset(pEntry
,0,sizeof(FATDirEntry
));
219 pEntry
=(FATDirEntry
*)Buffer
;
223 memset(DirName
,0xff,sizeof(DirName
));
224 memcpy(DirName
,FileName
,NameLen
*sizeof(WCHAR
));
227 DPRINT("dos name=%11.11s\n",pEntry
->Filename
);
228 //FIXME : set attributes, dates, times
229 pEntry
->Attrib
=ReqAttr
;
231 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
232 pEntry
->Attrib
|= FILE_ATTRIBUTE_DIRECTORY
;
233 pEntry
->CreationDate
=0x21;
234 pEntry
->UpdateDate
=0x21;
235 // calculate checksum for 8.3 name
236 for(pSlots
[0].alias_checksum
=i
=0;i
<11;i
++)
238 pSlots
[0].alias_checksum
=(((pSlots
[0].alias_checksum
&1)<<7
239 |((pSlots
[0].alias_checksum
&0xfe)>>1))
240 +pEntry
->Filename
[i
]);
242 //construct slots and entry
243 for(i
=nbSlots
-2;i
>=0;i
--)
245 DPRINT("construct slot %d\n",i
);
248 pSlots
[i
].id
=nbSlots
-i
-1;
250 pSlots
[i
].id
=nbSlots
-i
-1+0x40;
251 pSlots
[i
].alias_checksum
=pSlots
[0].alias_checksum
;
252 //FIXME pSlots[i].start=;
253 memcpy(pSlots
[i
].name0_4
,FileName
+(nbSlots
-i
-2)*13
255 memcpy(pSlots
[i
].name5_10
,FileName
+(nbSlots
-i
-2)*13+5
257 memcpy(pSlots
[i
].name11_12
,FileName
+(nbSlots
-i
-2)*13+11
260 //try to find nbSlots contiguous entries frees in directory
261 for(i
=0,status
=STATUS_SUCCESS
;status
==STATUS_SUCCESS
;i
++)
263 status
=FsdReadFile(DeviceExt
,&FileObject
,&FatEntry
264 ,sizeof(FATDirEntry
),i
*sizeof(FATDirEntry
),&LengthRead
);
265 if(IsLastEntry(&FatEntry
,0))
267 if(IsDeletedEntry(&FatEntry
,0)) nbFree
++;
269 if (nbFree
==nbSlots
) break;
271 DPRINT("NbFree %d, entry number %d\n",nbFree
,i
);
272 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
274 CurrentCluster
=GetNextWriteCluster(DeviceExt
,0);
276 Buffer2
=ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
277 memset(Buffer2
,0,DeviceExt
->BytesPerCluster
);
278 VFATWriteCluster(DeviceExt
,Buffer2
,CurrentCluster
);
280 if (DeviceExt
->FatType
== FAT32
)
282 pEntry
->FirstClusterHigh
=CurrentCluster
>>16;
283 pEntry
->FirstCluster
=CurrentCluster
;
286 pEntry
->FirstCluster
=CurrentCluster
;
290 Offset
=(i
-nbSlots
+1)*sizeof(FATDirEntry
);
291 status
=FsdWriteFile(DeviceExt
,&FileObject
,Buffer
292 ,sizeof(FATDirEntry
)*nbSlots
,Offset
);
295 {//write at end of directory
296 Offset
=(i
-nbFree
)*sizeof(FATDirEntry
);
297 status
=FsdWriteFile(DeviceExt
,&FileObject
,Buffer
298 ,sizeof(FATDirEntry
)*(nbSlots
+1),Offset
);
300 DPRINT("write entry offset %d status=%x\n",Offset
,status
);
301 newCCB
= ExAllocatePool(NonPagedPool
,sizeof(VFATCCB
));
302 newFCB
= ExAllocatePool(NonPagedPool
,sizeof(VFATFCB
));
303 memset(newCCB
,0,sizeof(VFATCCB
));
304 memset(newFCB
,0,sizeof(VFATFCB
));
306 newCCB
->PtrFileObject
=pFileObject
;
310 * FIXME : initialize all fields in FCB and CCB
312 KeAcquireSpinLock(&DeviceExt
->FcbListLock
, &oldIrql
);
313 InsertTailList(&DeviceExt
->FcbListHead
, &newFCB
->FcbListEntry
);
314 KeReleaseSpinLock(&DeviceExt
->FcbListLock
, oldIrql
);
317 memcpy(&newFCB
->entry
,pEntry
,sizeof(FATDirEntry
));
318 DPRINT("new : entry=%11.11s\n",newFCB
->entry
.Filename
);
319 DPRINT("new : entry=%11.11s\n",pEntry
->Filename
);
320 vfat_wcsncpy(newFCB
->PathName
,PathFileName
,MAX_PATH
);
321 newFCB
->ObjectName
=newFCB
->PathName
+(PathFileName
-FileName
);
322 newFCB
->pDevExt
=DeviceExt
;
323 pFileObject
->FsContext
=(PVOID
) &newFCB
->NTRequiredFCB
;
324 pFileObject
->FsContext2
= newCCB
;
325 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
328 memcpy(pEntry
->Filename
,". ",11);
329 status
=FsdWriteFile(DeviceExt
,pFileObject
,pEntry
330 ,sizeof(FATDirEntry
),0L);
332 =((VFATCCB
*)(FileObject
.FsContext2
))->pFcb
->entry
.FirstCluster
;
333 pEntry
->FirstClusterHigh
334 =((VFATCCB
*)(FileObject
.FsContext2
))->pFcb
->entry
.FirstClusterHigh
;
335 memcpy(pEntry
->Filename
,".. ",11);
336 if(pEntry
->FirstCluster
==1 && DeviceExt
->FatType
!=FAT32
)
337 pEntry
->FirstCluster
=0;
338 status
=FsdWriteFile(DeviceExt
,pFileObject
,pEntry
339 ,sizeof(FATDirEntry
),sizeof(FATDirEntry
));
341 FsdCloseFile(DeviceExt
,&FileObject
);
343 DPRINT("addentry ok\n");
344 return STATUS_SUCCESS
;