/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: services/fs/ext2/dir.c * PURPOSE: ext2 filesystem * PROGRAMMER: David Welch (welch@cwcom.net) * UPDATE HISTORY: */ /* INCLUDES *****************************************************************/ #include #include #include //#define NDEBUG #include #include "ext2fs.h" /* FUNCTIONS *****************************************************************/ static VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len) { ULONG i; for (i=0; iinode, &inode); switch (IoStack->Parameters.QueryDirectory.FileInformationClass) { case FileNamesInformation: FNI = (PFILE_NAMES_INFORMATION)Buffer; FNI->NextEntryOffset = sizeof(FileDirectoryInformation) + dir_entry->name_len + 1; FNI->FileNameLength = dir_entry->name_len; Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len); Buffer = Buffer + FNI->NextEntryOffset; break; case FileDirectoryInformation: FDI = (PFILE_DIRECTORY_INFORMATION)Buffer; FDI->NextEntryOffset = sizeof(FileDirectoryInformation) + dir_entry->name_len + 1; FDI->FileIndex = FileIndex; // FDI->CreationTime = 0; // FDI->LastAccessTime = 0; // FDI->LastWriteTime = 0; // FDI->ChangeTime = 0; FDI->AllocationSize.QuadPart = FDI->EndOfFile.QuadPart = inode.i_size; FDI->FileAttributes = 0; FDI->FileNameLength = dir_entry->name_len; Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len); Buffer = Buffer + FDI->NextEntryOffset; break; case FileBothDirectoryInformation: FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer; FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) + dir_entry->name_len + 1; FBI->FileIndex = FileIndex; FBI->AllocationSize.QuadPart = FBI->EndOfFile.QuadPart = inode.i_size; FBI->FileAttributes = 0; FBI->FileNameLength = dir_entry->name_len; Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len); memset(FBI->ShortName, 0, sizeof(FBI->ShortName)); Buffer = Buffer + FBI->NextEntryOffset; break; default: UNIMPLEMENTED; } return(Buffer); } NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt, PEXT2_FCB Fcb, PIRP Irp, PIO_STACK_LOCATION IoStack) { ULONG Max; ULONG i; ULONG StartIndex; PVOID Buffer = NULL; struct ext2_dir_entry dir_entry; Buffer = Irp->UserBuffer; DPRINT("Buffer %x\n",Buffer); DPRINT("IoStack->Flags %x\n",IoStack->Flags); if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY) { Max = 1; } else { UNIMPLEMENTED; } DPRINT("Buffer->FileIndex %d\n", ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex); if (IoStack->Flags & SL_INDEX_SPECIFIED) { StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex; } else { StartIndex = 0; } if (IoStack->Flags & SL_RESTART_SCAN) { StartIndex = 0; } DPRINT("StartIndex %d\n",StartIndex); for (i=0; iinode,"*",&dir_entry,&StartIndex)) { ((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0; return(STATUS_NO_MORE_FILES); } Buffer = Ext2ProcessDirEntry(DeviceExt, &dir_entry, IoStack, Buffer, StartIndex); } return(STATUS_SUCCESS); } NTSTATUS STDCALL Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = Stack->FileObject; PEXT2_FCB Fcb = (PVOID)FileObject->FsContext; NTSTATUS Status; PDEVICE_EXTENSION DeviceExt; DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); DeviceExt = DeviceObject->DeviceExtension; switch (Stack->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack); break; default: Status = STATUS_UNSUCCESSFUL; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); } BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt, struct ext2_inode* dir, PCH filename, struct ext2_dir_entry* ret, PULONG StartIndex) { ULONG i; char* buffer; ULONG offset; char name[255]; struct ext2_dir_entry* current; ULONG block; BOOL b; DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret); buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); for (i=0; i<((*StartIndex)/BLOCKSIZE); i++); for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++) { DPRINT("block %d\n",block); b = Ext2ReadSectors(DeviceExt->StorageDevice, block, 1, buffer); if (!b) { DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__); return(FALSE); } offset = (*StartIndex)%BLOCKSIZE; while (offset < BLOCKSIZE) { current = &buffer[offset]; strncpy(name,current->name,current->name_len); name[current->name_len]=0; DPRINT("Scanning offset %d inode %d name %s\n", offset,current->inode,name); DPRINT("Comparing %s %s\n",name,filename); if (strcmp(name,filename)==0 || strcmp(filename,"*")==0) { DPRINT("Match found\n"); *StartIndex = (i*BLOCKSIZE) + offset + current->rec_len; memcpy(ret,current,sizeof(struct ext2_dir_entry)); ExFreePool(buffer); return(TRUE); } offset = offset + current->rec_len; assert(current->rec_len != 0); DPRINT("offset %d\n",offset); } DPRINT("Onto next block\n"); } DPRINT("No match\n"); ExFreePool(buffer); return(FALSE); } void unicode_to_ansi(PCH StringA, PWSTR StringW) { while((*StringW)!=0) { *StringA = *StringW; StringA++; StringW++; } *StringA = 0; } NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName) /* * FUNCTION: Opens a file */ { EXT2_INODE parent_inode; struct ext2_dir_entry entry; char name[255]; ULONG current_inode = 2; char* current_segment; PEXT2_FCB Fcb; ULONG StartIndex = 0; DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %S)\n", DeviceExt,FileObject,FileName); Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB)); unicode_to_ansi(name,FileName); DPRINT("name %s\n",name); DPRINT("strtok %x\n",strtok); current_segment = strtok(name,"\\"); DPRINT("current_segment %x\n", current_segment); while (current_segment!=NULL) { Ext2LoadInode(DeviceExt, current_inode, &parent_inode); if (!Ext2ScanDir(DeviceExt, parent_inode.inode, current_segment, &entry, &StartIndex)) { Ext2ReleaseInode(DeviceExt, &parent_inode); ExFreePool(Fcb); return(STATUS_UNSUCCESSFUL); } current_inode = entry.inode; current_segment = strtok(NULL,"\\"); StartIndex = 0; Ext2ReleaseInode(DeviceExt, &parent_inode); } DPRINT("Found file\n"); Fcb->inode = current_inode; CcRosInitializeFileCache(FileObject, &Fcb->Bcb, PAGE_SIZE*3); FileObject->FsContext = Fcb; return(STATUS_SUCCESS); } NTSTATUS STDCALL Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = Stack->FileObject; NTSTATUS Status; PDEVICE_EXTENSION DeviceExt; DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); DeviceExt = DeviceObject->DeviceExtension; Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); }