1 /* $Id: dirwr.c,v 1.9 2000/03/01 23:41:35 ea Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/dirwr.c
6 * PURPOSE: VFAT Filesystem : write in directory
10 /* INCLUDES *****************************************************************/
12 #include <ddk/ntddk.h>
15 #include <internal/string.h>
18 #include <internal/debug.h>
22 NTSTATUS
updEntry(PDEVICE_EXTENSION DeviceExt
,PFILE_OBJECT pFileObject
)
24 update an existing FAT entry
27 WCHAR DirName
[MAX_PATH
],*FileName
,*PathFileName
;
29 ULONG Sector
=0,Entry
=0;
31 FATDirEntry
* pEntries
;
33 FILE_OBJECT FileObject
;
35 PVFATFCB pDirFcb
,pFcb
;
36 short i
,posCar
,NameLen
;
37 PathFileName
=pFileObject
->FileName
.Buffer
;
38 pFcb
=((PVFATCCB
)pFileObject
->FsContext2
)->pFcb
;
39 //find last \ in PathFileName
41 for(i
=0;PathFileName
[i
];i
++)
42 if(PathFileName
[i
]=='\\')posCar
=i
;
44 return STATUS_UNSUCCESSFUL
;
45 FileName
=&PathFileName
[posCar
+1];
46 for(NameLen
=0;FileName
[NameLen
];NameLen
++);
47 // extract directory name from pathname
48 memcpy(DirName
,PathFileName
,posCar
*sizeof(WCHAR
));
50 if(FileName
[0]==0 && DirName
[0]==0)
51 return STATUS_SUCCESS
;//root : nothing to do ?
52 memset(&FileObject
,0,sizeof(FILE_OBJECT
));
53 DPRINT("open directory %S for update of entry %S\n",DirName
,FileName
);
54 status
=FsdOpenFile(DeviceExt
,&FileObject
,DirName
);
55 pDirCcb
=(PVFATCCB
)FileObject
.FsContext2
;
57 pDirFcb
=pDirCcb
->pFcb
;
59 FileFcb
.ObjectName
=&FileFcb
.PathName
[0];
60 status
=FindFile(DeviceExt
,&FileFcb
,pDirFcb
,FileName
,&Sector
,&Entry
);
61 if(NT_SUCCESS(status
))
63 Buffer
=ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
64 DPRINT("update entry: sector %d, entry %d\n",Sector
,Entry
);
65 VFATReadSectors(DeviceExt
->StorageDevice
,Sector
,1,Buffer
);
66 pEntries
=(FATDirEntry
*)Buffer
;
67 memcpy(&pEntries
[Entry
],&pFcb
->entry
,sizeof(FATDirEntry
));
68 VFATWriteSectors(DeviceExt
->StorageDevice
,Sector
,1,Buffer
);
71 FsdCloseFile(DeviceExt
,&FileObject
);
75 NTSTATUS
addEntry(PDEVICE_EXTENSION DeviceExt
76 ,PFILE_OBJECT pFileObject
,ULONG RequestedOptions
,UCHAR ReqAttr
)
78 create a new FAT entry
81 WCHAR DirName
[MAX_PATH
],*FileName
,*PathFileName
;
82 VFATFCB DirFcb
,FileFcb
;
85 FILE_OBJECT FileObject
;
88 ULONG LengthRead
,Offset
;
89 short nbSlots
=0,nbFree
=0,i
,j
,posCar
,NameLen
;
90 PUCHAR Buffer
,Buffer2
;
91 BOOLEAN needTilde
=FALSE
,needLong
=FALSE
;
97 PathFileName
=pFileObject
->FileName
.Buffer
;
98 DPRINT("addEntry: Pathname=%S\n",PathFileName
);
99 //find last \ in PathFileName
101 for(i
=0;PathFileName
[i
];i
++)
102 if(PathFileName
[i
]=='\\')posCar
=i
;
104 return STATUS_UNSUCCESSFUL
;
105 FileName
=&PathFileName
[posCar
+1];
106 for(NameLen
=0;FileName
[NameLen
];NameLen
++);
107 // extract directory name from pathname
108 memcpy(DirName
,PathFileName
,posCar
*sizeof(WCHAR
));
110 // open parent directory
111 memset(&FileObject
,0,sizeof(FILE_OBJECT
));
112 status
=FsdOpenFile(DeviceExt
,&FileObject
,DirName
);
113 nbSlots
=(NameLen
+12)/13+1;//nb of entry needed for long name+normal entry
114 DPRINT("NameLen= %d, nbSlots =%d\n",NameLen
,nbSlots
);
115 Buffer
=ExAllocatePool(NonPagedPool
,(nbSlots
+1)*sizeof(FATDirEntry
));
116 memset(Buffer
,0,(nbSlots
+1)*sizeof(FATDirEntry
));
117 pEntry
=(FATDirEntry
*)(Buffer
+(nbSlots
-1)*sizeof(FATDirEntry
));
118 pSlots
=(slot
*)Buffer
;
121 // find last point in name
123 for(i
=0;FileName
[i
];i
++)
124 if(FileName
[i
]=='.')posCar
=i
;
125 if(!posCar
) posCar
=i
;
126 if(posCar
>8) needTilde
=TRUE
;
127 //copy 8 characters max
128 memset(pEntry
,' ',11);
129 for(i
=0,j
=0;j
<8 && i
<posCar
;i
++)
131 //FIXME : is there other characters to ignore ?
141 pEntry
->Filename
[j
++]=toupper((char) FileName
[i
]);
147 for(j
=0,i
=posCar
+1;FileName
[i
] && i
<posCar
+4;i
++)
149 pEntry
->Ext
[j
++]=toupper((char)( FileName
[i
] &0x7F));
153 //find good value for tilde
157 DPRINT("searching a good value for tilde\n");
159 DirName
[i
]=pEntry
->Filename
[i
];
161 DirName
[i
+8]=pEntry
->Ext
[i
];
162 //try first with xxxxxx~y.zzz
164 pEntry
->Filename
[6]='~';
170 pEntry
->Filename
[7]='0'+i
;
171 status
=FindFile(DeviceExt
,&FileFcb
172 ,&DirFcb
,DirName
,NULL
,NULL
);
173 if(status
!=STATUS_SUCCESS
)break;
175 //try second with xxxxx~yy.zzz
182 pEntry
->Filename
[7]='0'+i
;
183 status
=FindFile(DeviceExt
,&FileFcb
184 ,&DirFcb
,DirName
,NULL
,NULL
);
185 if(status
!=STATUS_SUCCESS
)break;
188 if(i
==100)//FIXME : what to do after 99 tilde ?
190 FsdCloseFile(DeviceExt
,&FileObject
);
192 return STATUS_UNSUCCESSFUL
;
197 DPRINT("check if long name entry needed, needlong=%d\n",needLong
);
198 for(i
=0;i
<posCar
;i
++)
199 if((USHORT
)pEntry
->Filename
[i
]!=FileName
[i
])
201 DPRINT("i=%d,%d,%d\n",i
,pEntry
->Filename
[i
],FileName
[i
]);
206 i
++;//jump on point char
207 for(j
=0,i
=posCar
+1;FileName
[i
] && i
<posCar
+4;i
++)
208 if((USHORT
)pEntry
->Ext
[j
++]!= FileName
[i
])
210 DPRINT("i=%d,j=%d,%d,%d\n",i
,j
,pEntry
->Filename
[i
],FileName
[i
]);
218 memcpy(Buffer
,pEntry
,sizeof(FATDirEntry
));
219 memset(pEntry
,0,sizeof(FATDirEntry
));
220 pEntry
=(FATDirEntry
*)Buffer
;
224 memset(DirName
,0xff,sizeof(DirName
));
225 memcpy(DirName
,FileName
,NameLen
*sizeof(WCHAR
));
228 DPRINT("dos name=%11.11s\n",pEntry
->Filename
);
229 //FIXME : set attributes, dates, times
230 pEntry
->Attrib
=ReqAttr
;
232 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
233 pEntry
->Attrib
|= FILE_ATTRIBUTE_DIRECTORY
;
234 pEntry
->CreationDate
=0x21;
235 pEntry
->UpdateDate
=0x21;
236 // calculate checksum for 8.3 name
237 for(pSlots
[0].alias_checksum
=i
=0;i
<11;i
++)
239 pSlots
[0].alias_checksum
=(((pSlots
[0].alias_checksum
&1)<<7
240 |((pSlots
[0].alias_checksum
&0xfe)>>1))
241 +pEntry
->Filename
[i
]);
243 //construct slots and entry
244 for(i
=nbSlots
-2;i
>=0;i
--)
246 DPRINT("construct slot %d\n",i
);
249 pSlots
[i
].id
=nbSlots
-i
-1;
251 pSlots
[i
].id
=nbSlots
-i
-1+0x40;
252 pSlots
[i
].alias_checksum
=pSlots
[0].alias_checksum
;
253 //FIXME pSlots[i].start=;
254 memcpy(pSlots
[i
].name0_4
,FileName
+(nbSlots
-i
-2)*13
256 memcpy(pSlots
[i
].name5_10
,FileName
+(nbSlots
-i
-2)*13+5
258 memcpy(pSlots
[i
].name11_12
,FileName
+(nbSlots
-i
-2)*13+11
261 //try to find nbSlots contiguous entries frees in directory
262 for(i
=0,status
=STATUS_SUCCESS
;status
==STATUS_SUCCESS
;i
++)
264 status
=FsdReadFile(DeviceExt
,&FileObject
,&FatEntry
265 ,sizeof(FATDirEntry
),i
*sizeof(FATDirEntry
),&LengthRead
);
266 if(IsLastEntry(&FatEntry
,0))
268 if(IsDeletedEntry(&FatEntry
,0)) nbFree
++;
270 if (nbFree
==nbSlots
) break;
272 DPRINT("NbFree %d, entry number %d\n",nbFree
,i
);
273 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
275 CurrentCluster
=GetNextWriteCluster(DeviceExt
,0);
277 Buffer2
=ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
278 memset(Buffer2
,0,DeviceExt
->BytesPerCluster
);
279 VFATWriteCluster(DeviceExt
,Buffer2
,CurrentCluster
);
281 if (DeviceExt
->FatType
== FAT32
)
283 pEntry
->FirstClusterHigh
=CurrentCluster
>>16;
284 pEntry
->FirstCluster
=CurrentCluster
;
287 pEntry
->FirstCluster
=CurrentCluster
;
291 Offset
=(i
-nbSlots
+1)*sizeof(FATDirEntry
);
292 status
=FsdWriteFile(DeviceExt
,&FileObject
,Buffer
293 ,sizeof(FATDirEntry
)*nbSlots
,Offset
);
296 {//write at end of directory
297 Offset
=(i
-nbFree
)*sizeof(FATDirEntry
);
298 status
=FsdWriteFile(DeviceExt
,&FileObject
,Buffer
299 ,sizeof(FATDirEntry
)*(nbSlots
+1),Offset
);
301 DPRINT("write entry offset %d status=%x\n",Offset
,status
);
302 newCCB
= ExAllocatePool(NonPagedPool
,sizeof(VFATCCB
));
303 newFCB
= ExAllocatePool(NonPagedPool
,sizeof(VFATFCB
));
304 memset(newCCB
,0,sizeof(VFATCCB
));
305 memset(newFCB
,0,sizeof(VFATFCB
));
307 newCCB
->PtrFileObject
=pFileObject
;
311 * FIXME : initialize all fields in FCB and CCB
313 KeAcquireSpinLock(&DeviceExt
->FcbListLock
, &oldIrql
);
314 InsertTailList(&DeviceExt
->FcbListHead
, &newFCB
->FcbListEntry
);
315 KeReleaseSpinLock(&DeviceExt
->FcbListLock
, oldIrql
);
318 memcpy(&newFCB
->entry
,pEntry
,sizeof(FATDirEntry
));
319 DPRINT("new : entry=%11.11s\n",newFCB
->entry
.Filename
);
320 DPRINT("new : entry=%11.11s\n",pEntry
->Filename
);
321 vfat_wcsncpy(newFCB
->PathName
,PathFileName
,MAX_PATH
);
322 newFCB
->ObjectName
=newFCB
->PathName
+(PathFileName
-FileName
);
323 newFCB
->pDevExt
=DeviceExt
;
324 pFileObject
->FsContext
=(PVOID
) &newFCB
->NTRequiredFCB
;
325 pFileObject
->FsContext2
= newCCB
;
326 if(RequestedOptions
&FILE_DIRECTORY_FILE
)
329 memcpy(pEntry
->Filename
,". ",11);
330 status
=FsdWriteFile(DeviceExt
,pFileObject
,pEntry
331 ,sizeof(FATDirEntry
),0L);
333 =((VFATCCB
*)(FileObject
.FsContext2
))->pFcb
->entry
.FirstCluster
;
334 pEntry
->FirstClusterHigh
335 =((VFATCCB
*)(FileObject
.FsContext2
))->pFcb
->entry
.FirstClusterHigh
;
336 memcpy(pEntry
->Filename
,".. ",11);
337 if(pEntry
->FirstCluster
==1 && DeviceExt
->FatType
!=FAT32
)
338 pEntry
->FirstCluster
=0;
339 status
=FsdWriteFile(DeviceExt
,pFileObject
,pEntry
340 ,sizeof(FATDirEntry
),sizeof(FATDirEntry
));
342 FsdCloseFile(DeviceExt
,&FileObject
);
344 DPRINT("addentry ok\n");
345 return STATUS_SUCCESS
;