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 *****************************************************************/
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
);