2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/fs/ext2/dir.c
5 * PURPOSE: ext2 filesystem
6 * PROGRAMMER: David Welch (welch@cwcom.net)
10 /* INCLUDES *****************************************************************/
12 #include <ddk/ntddk.h>
21 /* FUNCTIONS *****************************************************************/
24 static VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len)
37 PVOID Ext2ProcessDirEntry(PDEVICE_EXTENSION DeviceExt,
38 struct ext2_dir_entry* dir_entry,
39 PIO_STACK_LOCATION IoStack,
43 PFILE_DIRECTORY_INFORMATION FDI;
44 PFILE_NAMES_INFORMATION FNI;
45 PFILE_BOTH_DIRECTORY_INFORMATION FBI;
46 struct ext2_inode inode;
48 DPRINT("FileIndex %d\n",FileIndex);
49 DPRINT("Buffer %x\n",Buffer);
51 Ext2ReadInode(DeviceExt,
55 switch (IoStack->Parameters.QueryDirectory.FileInformationClass)
57 case FileNamesInformation:
58 FNI = (PFILE_NAMES_INFORMATION)Buffer;
59 FNI->NextEntryOffset = sizeof(FileDirectoryInformation) +
60 dir_entry->name_len + 1;
61 FNI->FileNameLength = dir_entry->name_len;
62 Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len);
63 Buffer = Buffer + FNI->NextEntryOffset;
66 case FileDirectoryInformation:
67 FDI = (PFILE_DIRECTORY_INFORMATION)Buffer;
68 FDI->NextEntryOffset = sizeof(FileDirectoryInformation) +
69 dir_entry->name_len + 1;
70 FDI->FileIndex = FileIndex;
71 // FDI->CreationTime = 0;
72 // FDI->LastAccessTime = 0;
73 // FDI->LastWriteTime = 0;
74 // FDI->ChangeTime = 0;
75 FDI->AllocationSize.QuadPart = FDI->EndOfFile.QuadPart = inode.i_size;
76 FDI->FileAttributes = 0;
77 FDI->FileNameLength = dir_entry->name_len;
78 Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len);
79 Buffer = Buffer + FDI->NextEntryOffset;
82 case FileBothDirectoryInformation:
83 FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer;
84 FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) +
85 dir_entry->name_len + 1;
86 FBI->FileIndex = FileIndex;
87 FBI->AllocationSize.QuadPart = FBI->EndOfFile.QuadPart = inode.i_size;
88 FBI->FileAttributes = 0;
89 FBI->FileNameLength = dir_entry->name_len;
90 Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len);
91 memset(FBI->ShortName, 0, sizeof(FBI->ShortName));
92 Buffer = Buffer + FBI->NextEntryOffset;
102 NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt,
105 PIO_STACK_LOCATION IoStack)
111 struct ext2_dir_entry dir_entry;
113 Buffer = Irp->UserBuffer;
114 DPRINT("Buffer %x\n",Buffer);
115 DPRINT("IoStack->Flags %x\n",IoStack->Flags);
117 if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY)
126 DPRINT("Buffer->FileIndex %d\n",
127 ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex);
128 if (IoStack->Flags & SL_INDEX_SPECIFIED)
130 StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex;
137 if (IoStack->Flags & SL_RESTART_SCAN)
142 DPRINT("StartIndex %d\n",StartIndex);
144 for (i=0; i<Max ;i++)
146 if (!Ext2ScanDir(DeviceExt,&Fcb->inode,"*",&dir_entry,&StartIndex))
148 ((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0;
149 return(STATUS_NO_MORE_FILES);
151 Buffer = Ext2ProcessDirEntry(DeviceExt,
157 return(STATUS_SUCCESS);
161 Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
163 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
164 PFILE_OBJECT FileObject = Stack->FileObject;
165 PEXT2_FCB Fcb = (PVOID)FileObject->FsContext;
167 PDEVICE_EXTENSION DeviceExt;
169 DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
171 DeviceExt = DeviceObject->DeviceExtension;
173 switch (Stack->MinorFunction)
175 case IRP_MN_QUERY_DIRECTORY:
176 Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack);
180 Status = STATUS_UNSUCCESSFUL;
183 Irp->IoStatus.Status = Status;
184 Irp->IoStatus.Information = 0;
186 IoCompleteRequest(Irp, IO_NO_INCREMENT);
190 BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt,
191 struct ext2_inode* dir,
193 struct ext2_dir_entry* ret,
200 struct ext2_dir_entry* current;
204 DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret);
206 buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
208 for (i=0; i<((*StartIndex)/BLOCKSIZE); i++);
209 for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++)
211 DPRINT("block %d\n",block);
212 b = Ext2ReadSectors(DeviceExt->StorageDevice,
218 DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__);
222 offset = (*StartIndex)%BLOCKSIZE;
223 while (offset < BLOCKSIZE)
225 current = &buffer[offset];
227 strncpy(name,current->name,current->name_len);
228 name[current->name_len]=0;
230 DPRINT("Scanning offset %d inode %d name %s\n",
231 offset,current->inode,name);
233 DPRINT("Comparing %s %s\n",name,filename);
234 if (strcmp(name,filename)==0 || strcmp(filename,"*")==0)
236 DPRINT("Match found\n");
237 *StartIndex = (i*BLOCKSIZE) + offset + current->rec_len;
238 memcpy(ret,current,sizeof(struct ext2_dir_entry));
243 offset = offset + current->rec_len;
244 assert(current->rec_len != 0);
245 DPRINT("offset %d\n",offset);
247 DPRINT("Onto next block\n");
249 DPRINT("No match\n");
254 void unicode_to_ansi(PCH StringA, PWSTR StringW)
265 NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
268 * FUNCTION: Opens a file
271 EXT2_INODE parent_inode;
272 struct ext2_dir_entry entry;
274 ULONG current_inode = 2;
275 char* current_segment;
277 ULONG StartIndex = 0;
279 DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %S)\n",
280 DeviceExt,FileObject,FileName);
282 Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
284 unicode_to_ansi(name,FileName);
285 DPRINT("name %s\n",name);
286 DPRINT("strtok %x\n",strtok);
287 current_segment = strtok(name,"\\");
288 DPRINT("current_segment %x\n", current_segment);
289 while (current_segment!=NULL)
291 Ext2LoadInode(DeviceExt,
294 if (!Ext2ScanDir(DeviceExt,
300 Ext2ReleaseInode(DeviceExt,
303 return(STATUS_UNSUCCESSFUL);
305 current_inode = entry.inode;
306 current_segment = strtok(NULL,"\\");
308 Ext2ReleaseInode(DeviceExt,
311 DPRINT("Found file\n");
313 Fcb->inode = current_inode;
314 CcRosInitializeFileCache(FileObject, &Fcb->Bcb, PAGE_SIZE*3);
315 FileObject->FsContext = Fcb;
317 return(STATUS_SUCCESS);
321 Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
323 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
324 PFILE_OBJECT FileObject = Stack->FileObject;
326 PDEVICE_EXTENSION DeviceExt;
328 DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
330 DeviceExt = DeviceObject->DeviceExtension;
331 Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
333 Irp->IoStatus.Status = Status;
334 Irp->IoStatus.Information = 0;
336 IoCompleteRequest(Irp, IO_NO_INCREMENT);