]> git.saurik.com Git - apple/bootx.git/blobdiff - bootx.tproj/fs.subproj/ext2fs.c
BootX-59.1.1.tar.gz
[apple/bootx.git] / bootx.tproj / fs.subproj / ext2fs.c
index ca3172ef3c76397eca7fecc57a37cd038b36ec28..1d16ab39e15ca476f031f6a1d363c98c0f1ee674 100644 (file)
@@ -3,34 +3,34 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*
  *  ext2.c - File System Module for Ext2.
  *
- *  Copyright (c) 1999-2000 Apple Computer, Inc.
+ *  Copyright (c) 1999-2002 Apple Computer, Inc.
  *
  *  DRI: Josh de Cesare
  */
 
 #include <sl.h>
-#include <fs.h>
-
-#include <bsd/sys/types.h>
 
 #include "ext2fs.h"
 #include "ext2fs_dinode.h"
@@ -43,11 +43,11 @@ typedef struct ext2fs_dinode Inode, *InodePtr;
 static long HowMany(long bufferSize, long unitSize);
 static char *ReadBlock(long blockNum, long blockOffset, long length,
                       char *buffer, long cache);
-static long ReadInode(long inodeNum, InodePtr inode);
+static long ReadInode(long inodeNum, InodePtr inode, long *flags, long *time);
 static long ResolvePathToInode(char *filePath, long *flags,
                                InodePtr fileInode, InodePtr dirInode);
 static long ReadDirEntry(InodePtr dirInode, long *fileInodeNum,
-                        long *dirIndex, char **name, long *flags, long *time);
+                        long *dirIndex, char **name);
 static long FindFileInDir(char *fileName, long *flags,
                           InodePtr fileInode, InodePtr dirInode);
 static char *ReadFileBlock(InodePtr fileInode, long blockNum, long blockOffset,
@@ -59,6 +59,7 @@ static CICell          gCurrentIH;
 static char            gFSBuf[SBSIZE * 2];
 static struct m_ext2fs *gFS;
 static long            gBlockSize;
+static long            gBlockSizeOld;
 static char            *gTempBlock;
 static char            gTempName[EXT2FS_MAXNAMLEN + 1];
 static char            gTempName2[EXT2FS_MAXNAMLEN + 1];
@@ -87,10 +88,13 @@ long Ext2InitPartition(CICell ih)
   
   // Calculate the block size and set up the block cache.
   gBlockSize = 1024 << gFS->e2fs.e2fs_log_bsize;
-  if (gTempBlock != 0) free(gTempBlock);
-  gTempBlock = malloc(gBlockSize);
+  if (gBlockSizeOld <= gBlockSize) {
+    gTempBlock = AllocateBootXMemory(gBlockSize);
+  }
   CacheInit(ih, gBlockSize);
   
+  gBlockSizeOld = gBlockSize;
+  
   gCurrentIH = ih;
   
   gdPerBlock = gBlockSize / sizeof(struct ext2_gd);
@@ -106,7 +110,7 @@ long Ext2InitPartition(CICell ih)
   gFS->e2fs_ngdb = HowMany(gFS->e2fs_ncg, gdPerBlock);
   gFS->e2fs_ipb = gFS->e2fs_bsize / EXT2_DINODE_SIZE;
   gFS->e2fs_itpg = gFS->e2fs.e2fs_ipg / gFS->e2fs_ipb;
-  gFS->e2fs_gd = malloc(gFS->e2fs_ngdb * gFS->e2fs_bsize);
+  gFS->e2fs_gd = AllocateBootXMemory(gFS->e2fs_ngdb * gFS->e2fs_bsize);
   
   // Read the summary information from disk.
   for (cnt = 0; cnt < gFS->e2fs_ngdb; cnt++) {
@@ -117,7 +121,7 @@ long Ext2InitPartition(CICell ih)
   }
   
   // Read the Root Inode
-  ReadInode(EXT2_ROOTINO, &gRootInode);
+  ReadInode(EXT2_ROOTINO, &gRootInode, 0, 0);
   
   return 0;
 }
@@ -135,7 +139,9 @@ long Ext2LoadFile(CICell ih, char *filePath)
   if (*filePath == '\\') filePath++;
   if (*filePath == '\\') filePath++;
   ret = ResolvePathToInode(filePath, &flags, &gFileInode, &gRootInode);
-  if ((ret == -1) || (flags != kFlatFileType)) return -1;
+  if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1;
+  
+  if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
   
   ret = ReadFile(&gFileInode, &length);
   if (ret != 0) return -1;
@@ -147,20 +153,23 @@ long Ext2LoadFile(CICell ih, char *filePath)
 long Ext2GetDirEntry(CICell ih, char *dirPath, long *dirIndex,
                     char **name, long *flags, long *time)
 {
-  long ret, fileInodeNum, dirFlags;
+  long  ret, fileInodeNum, dirFlags;
+  Inode tmpInode;
   
   if (Ext2InitPartition(ih) == -1) return -1;
   
   // Skip a leading '\' if present
   if (dirPath[0] == '\\') dirPath++;
   ret = ResolvePathToInode(dirPath, &dirFlags, &gFileInode, &gRootInode);
-  if ((ret == -1) || (dirFlags != kDirectoryFileType)) return -1;
+  if ((ret == -1) || ((dirFlags & kFileTypeMask) != kFileTypeDirectory))
+    return -1;
   
-  do {
-    ret = ReadDirEntry(&gFileInode, &fileInodeNum, dirIndex, name, flags,time);
-  } while ((ret != -1) && (*flags == kUnknownFileType));
+  ret = ReadDirEntry(&gFileInode, &fileInodeNum, dirIndex, name);
+  if (ret != 0) return ret;
   
-  return ret;
+  ReadInode(fileInodeNum, &tmpInode, flags, time);
+  
+  return 0;
 }
 
 // Private functions
@@ -191,7 +200,7 @@ static char *ReadBlock(long blockNum, long blockOffset, long length,
 }
 
 
-static long ReadInode(long inodeNum, InodePtr inode)
+static long ReadInode(long inodeNum, InodePtr inode, long *flags, long *time)
 {
   long blockNum = ino_to_fsba(gFS, inodeNum);
   long blockOffset = ino_to_fsbo(gFS, inodeNum) * sizeof(Inode);
@@ -199,6 +208,21 @@ static long ReadInode(long inodeNum, InodePtr inode)
   ReadBlock(blockNum, blockOffset, sizeof(Inode), (char *)inode, 1);
   e2fs_i_bswap(inode, inode);
   
+  if (time != 0) *time = inode->e2di_mtime;
+  
+  if (flags != 0) {
+    switch (inode->e2di_mode & EXT2_IFMT) {
+    case EXT2_IFREG: *flags = kFileTypeFlat; break;
+    case EXT2_IFDIR: *flags = kFileTypeDirectory; break;
+    case EXT2_IFLNK: *flags = kFileTypeLink; break;
+    default :        *flags = kFileTypeUnknown; break;
+    }
+    
+    *flags |= inode->e2di_mode & kPermMask;
+    
+    if (inode->e2di_uid != 0) *flags |= kOwnerNotRoot;
+  }
+  
   return 0;
 }
 
@@ -230,7 +254,7 @@ static long ResolvePathToInode(char *filePath, long *flags,
   ret = FindFileInDir(gTempName, flags, fileInode, dirInode);
   if (ret == -1) return -1;
 
-  if ((*restPath != '\0') && (*flags == kDirectoryFileType))
+  if ((*restPath != '\0') && ((*flags & kFileTypeMask) == kFileTypeDirectory))
     ret = ResolvePathToInode(restPath, flags, fileInode, fileInode);
   
   return ret;
@@ -238,39 +262,34 @@ static long ResolvePathToInode(char *filePath, long *flags,
 
 
 static long ReadDirEntry(InodePtr dirInode, long *fileInodeNum,
-                        long *dirIndex, char **name, long *flags, long *time)
+                        long *dirIndex, char **name)
 {
   struct ext2fs_direct *dir;
   char                 *buffer;
-  long                 offset, index = *dirIndex;
+  long                 offset, index;
   long                 blockNum, inodeNum;
-  Inode                tmpInode;
   
-  offset = index % gBlockSize;
-  blockNum = index / gBlockSize;
-  
-  buffer = ReadFileBlock(dirInode, blockNum, 0, gBlockSize, 0, 1);
-  if (buffer == 0) return -1;
-  
-  dir = (struct ext2fs_direct *)(buffer + offset);
-  inodeNum = bswap32(dir->e2d_ino);
-  if (inodeNum == 0) return -1;
+  while (1) {
+    index = *dirIndex;
+    
+    offset = index % gBlockSize;
+    blockNum = index / gBlockSize;
+    
+    buffer = ReadFileBlock(dirInode, blockNum, 0, gBlockSize, 0, 1);
+    if (buffer == 0) return -1;
+    
+    dir = (struct ext2fs_direct *)(buffer + offset);
+    *dirIndex += bswap16(dir->e2d_reclen);
+    
+    inodeNum = bswap32(dir->e2d_ino);
+    if (inodeNum != 0) break;
+    
+    if (offset != 0) return -1;
+  }
   
-  *dirIndex += bswap16(dir->e2d_reclen);
   *fileInodeNum = inodeNum;
   *name = strncpy(gTempName2, dir->e2d_name, dir->e2d_namlen);
   
-  ReadInode(inodeNum, &tmpInode);
-  
-  *time = tmpInode.e2di_mtime;
-  
-  switch (tmpInode.e2di_mode & EXT2_IFMT) {
-  case EXT2_IFREG: *flags = kFlatFileType; break;
-  case EXT2_IFDIR: *flags = kDirectoryFileType; break;
-  case EXT2_IFLNK: *flags = kLinkFileType; break;
-  default :        *flags = kUnknownFileType; break;
-  }
-  
   return 0;
 }
 
@@ -278,19 +297,17 @@ static long ReadDirEntry(InodePtr dirInode, long *fileInodeNum,
 static long FindFileInDir(char *fileName, long *flags,
                           InodePtr fileInode, InodePtr dirInode)
 {
-  long ret, inodeNum, time, index = 0;
+  long ret, inodeNum, index = 0;
   char *name;
   
   while (1) {
-    ret = ReadDirEntry(dirInode, &inodeNum, &index, &name, flags, &time);
+    ret = ReadDirEntry(dirInode, &inodeNum, &index, &name);
     if (ret == -1) return -1;
     
-    if (*flags == kUnknownFileType) continue;
-    
     if (strcmp(fileName, name) == 0) break;
   }
   
-  ReadInode(inodeNum, fileInode);
+  ReadInode(inodeNum, fileInode, flags, 0);
   
   return 0;
 }