diff --git a/freeldr/freeldr/CHANGELOG b/freeldr/freeldr/CHANGELOG index 795fb19de2d..2378f384df0 100644 --- a/freeldr/freeldr/CHANGELOG +++ b/freeldr/freeldr/CHANGELOG @@ -1,3 +1,7 @@ +Changes in v1.7.1 (8/7/2002) (brianp) + +- Symbolic links on EXT2/3 are now supported + Changes in v1.7 (8/6/2002) (brianp) - EXT2/EXT3 file system support. diff --git a/freeldr/freeldr/fs/ext2.c b/freeldr/freeldr/fs/ext2.c index 22c52a16bc0..437736d485d 100644 --- a/freeldr/freeldr/fs/ext2.c +++ b/freeldr/freeldr/fs/ext2.c @@ -90,24 +90,96 @@ FILE* Ext2OpenFile(PUCHAR FileName) { EXT2_FILE_INFO TempExt2FileInfo; PEXT2_FILE_INFO FileHandle; + UCHAR SymLinkPath[EXT3_NAME_LEN]; + UCHAR FullPath[EXT3_NAME_LEN * 2]; + U32 Index; DbgPrint((DPRINT_FILESYSTEM, "Ext2OpenFile() FileName = %s\n", FileName)); + RtlZeroMemory(SymLinkPath, EXT3_NAME_LEN); + + // Lookup the file in the file system if (!Ext2LookupFile(FileName, &TempExt2FileInfo)) { return NULL; } - FileHandle = MmAllocateMemory(sizeof(EXT2_FILE_INFO)); - - if (FileHandle == NULL) + // If we got a symbolic link then fix up the path + // and re-call this function + if ((TempExt2FileInfo.Inode.i_mode & EXT2_S_IFMT) == EXT2_S_IFLNK) { - return NULL; + DbgPrint((DPRINT_FILESYSTEM, "File is a symbolic link\n")); + + // Now read in the symbolic link path + if (!Ext2ReadFile(&TempExt2FileInfo, TempExt2FileInfo.FileSize, NULL, SymLinkPath)) + { + if (TempExt2FileInfo.FileBlockList != NULL) + { + MmFreeMemory(TempExt2FileInfo.FileBlockList); + } + + return NULL; + } + + DbgPrint((DPRINT_FILESYSTEM, "Symbolic link path = %s\n", SymLinkPath)); + + // Get the full path + if (SymLinkPath[0] == '/' || SymLinkPath[0] == '\\') + { + // Symbolic link is an absolute path + // So copy it to FullPath, but skip over + // the '/' char at the beginning + strcpy(FullPath, &SymLinkPath[1]); + } + else + { + // Symbolic link is a relative path + // Copy the first part of the path + strcpy(FullPath, FileName); + + // Remove the last part of the path + for (Index=strlen(FullPath); Index>0; ) + { + Index--; + if (FullPath[Index] == '/' || FullPath[Index] == '\\') + { + break; + } + } + FullPath[Index] = '\0'; + + // Concatenate the symbolic link + strcat(FullPath, "/"); + strcat(FullPath, SymLinkPath); + } + + DbgPrint((DPRINT_FILESYSTEM, "Full file path = %s\n", FullPath)); + + if (TempExt2FileInfo.FileBlockList != NULL) + { + MmFreeMemory(TempExt2FileInfo.FileBlockList); + } + + return Ext2OpenFile(FullPath); } + else + { + FileHandle = MmAllocateMemory(sizeof(EXT2_FILE_INFO)); - RtlCopyMemory(FileHandle, &TempExt2FileInfo, sizeof(EXT2_FILE_INFO)); + if (FileHandle == NULL) + { + if (TempExt2FileInfo.FileBlockList != NULL) + { + MmFreeMemory(TempExt2FileInfo.FileBlockList); + } - return (FILE*)FileHandle; + return NULL; + } + + RtlCopyMemory(FileHandle, &TempExt2FileInfo, sizeof(EXT2_FILE_INFO)); + + return (FILE*)FileHandle; + } } /* @@ -181,21 +253,37 @@ BOOL Ext2LookupFile(PUCHAR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer) return FALSE; } - if ((InodeData.i_mode & EXT2_S_IFMT) != EXT2_S_IFREG) + if (((InodeData.i_mode & EXT2_S_IFMT) != EXT2_S_IFREG) && + ((InodeData.i_mode & EXT2_S_IFMT) != EXT2_S_IFLNK)) { - FileSystemError("Inode is not a regular file."); + FileSystemError("Inode is not a regular file or symbolic link."); return FALSE; } + // Set the drive number Ext2FileInfoPointer->DriveNumber = Ext2DriveNumber; - Ext2FileInfoPointer->FileBlockList = Ext2ReadBlockPointerList(&InodeData); + + // If it's a regular file or a regular symbolic link + // then get the block pointer list otherwise it must + // be a fast symbolic link which doesn't have a block list + if (((InodeData.i_mode & EXT2_S_IFMT) == EXT2_S_IFREG) || + ((InodeData.i_mode & EXT2_S_IFMT) == EXT2_S_IFLNK && InodeData.i_size > 60)) + { + Ext2FileInfoPointer->FileBlockList = Ext2ReadBlockPointerList(&InodeData); + + if (Ext2FileInfoPointer->FileBlockList == NULL) + { + return FALSE; + } + } + else + { + Ext2FileInfoPointer->FileBlockList = NULL; + } + Ext2FileInfoPointer->FilePointer = 0; Ext2FileInfoPointer->FileSize = Ext2GetInodeFileSize(&InodeData); - - if (Ext2FileInfoPointer->FileBlockList == NULL) - { - return FALSE; - } + RtlCopyMemory(&Ext2FileInfoPointer->Inode, &InodeData, sizeof(EXT2_INODE)); return TRUE; } @@ -272,6 +360,19 @@ BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffe *BytesRead = 0; } + // Make sure we have the block pointer list if we need it + if (Ext2FileInfo->FileBlockList == NULL) + { + // Block pointer list is NULL + // so this better be a fast symbolic link or else + if (((Ext2FileInfo->Inode.i_mode & EXT2_S_IFMT) != EXT2_S_IFLNK) || + (Ext2FileInfo->FileSize > 60)) + { + FileSystemError("Block pointer list is NULL and file is not a fast symbolic link."); + return FALSE; + } + } + // // If they are trying to read past the // end of the file then return success @@ -291,6 +392,24 @@ BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffe BytesToRead = (Ext2FileInfo->FileSize - Ext2FileInfo->FilePointer); } + // Check if this is a fast symbolic link + // if so then the read is easy + if (((Ext2FileInfo->Inode.i_mode & EXT2_S_IFMT) == EXT2_S_IFLNK) && + (Ext2FileInfo->FileSize <= 60)) + { + DbgPrint((DPRINT_FILESYSTEM, "Reading fast symbolic link data\n")); + + // Copy the data from the link + RtlCopyMemory(Buffer, (PVOID)(Ext2FileInfo->Inode.i_block) + Ext2FileInfo->FilePointer, BytesToRead); + + if (BytesRead != NULL) + { + *BytesRead = BytesToRead; + } + + return TRUE; + } + // // Ok, now we have to perform at most 3 calculations // I'll draw you a picture (using nifty ASCII art): diff --git a/freeldr/freeldr/fs/ext2.h b/freeldr/freeldr/fs/ext2.h index 921d0b109bc..c4064159ce9 100644 --- a/freeldr/freeldr/fs/ext2.h +++ b/freeldr/freeldr/fs/ext2.h @@ -650,15 +650,16 @@ typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY; #define EXT2_S_IFDIR 0x4000 // Directory #define EXT2_S_IFBLK 0x6000 // Block device #define EXT2_S_IFREG 0x8000 // Regular file -#define EXT2_S_IFSOCK 0xA000 // Socket -#define EXT2_S_IFLNK 0xC000 // Symbolic link +#define EXT2_S_IFLNK 0xA000 // Symbolic link +#define EXT2_S_IFSOCK 0xC000 // Socket typedef struct { - U64 FileSize; // File size - U64 FilePointer; // File pointer - U32* FileBlockList; // File block list - U8 DriveNumber; // Drive number of open file + U64 FileSize; // File size + U64 FilePointer; // File pointer + U32* FileBlockList; // File block list + U8 DriveNumber; // Drive number of open file + EXT2_INODE Inode; // File's inode } EXT2_FILE_INFO, * PEXT2_FILE_INFO; diff --git a/freeldr/freeldr/include/version.h b/freeldr/freeldr/include/version.h index 80428296bf0..72ce8297b13 100644 --- a/freeldr/freeldr/include/version.h +++ b/freeldr/freeldr/include/version.h @@ -22,7 +22,7 @@ /* just some stuff */ -#define VERSION "FreeLoader v1.7" +#define VERSION "FreeLoader v1.7.1" #define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer " #define AUTHOR_EMAIL "" #define BY_AUTHOR "by Brian Palmer" @@ -36,7 +36,7 @@ // #define FREELOADER_MAJOR_VERSION 1 #define FREELOADER_MINOR_VERSION 7 -#define FREELOADER_PATCH_VERSION 0 +#define FREELOADER_PATCH_VERSION 1 PUCHAR GetFreeLoaderVersionString(VOID);