Add preliminary ext2 support

This commit is contained in:
Laurent Vivier 2008-04-12 21:17:49 +00:00
parent 1272867d0c
commit 18d598d5fa
14 changed files with 620 additions and 8 deletions

View File

@ -18,10 +18,10 @@ include kernel.mk
first-clean second-clean docs-clean libiso9660-clean libgzip-clean \
libfloppy-clean libscsi-clean libstream-clean libblock-clean dist docs \
apple_driver apple_driver_clean libconfig libconfig-m68k libmap \
libmap-m68k
libmap-m68k libext2 libext2-m68k
all: tools.mk docs libemile libblock libiso9660 libiso9660-m68k libgzip-m68k \
tools first libstream libcontainer libmap \
tools first libstream libcontainer libmap libext2 libext2-m68k \
second/$(KARCH)-linux-floppy/second \
second/$(KARCH)-linux-scsi/second second/m68k-netbsd-floppy/second \
apple_driver libconfig libconfig-m68k \
@ -170,16 +170,16 @@ first::
apple_driver::
$(MAKE) -C apple_driver TARGET=m68k-linux
second/$(KARCH)-linux-floppy/second:: libmacos libunix libiso9660-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
second/$(KARCH)-linux-floppy/second:: libmacos libunix libiso9660-m68k libext2-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
$(MAKE) -C second MEDIA=floppy TARGET=$(KARCH)-linux
second/$(KARCH)-linux-scsi/second:: libmacos libunix libiso9660-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
second/$(KARCH)-linux-scsi/second:: libmacos libunix libiso9660-m68k libext2-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
$(MAKE) -C second MEDIA=scsi TARGET=$(KARCH)-linux
second/$(KARCH)-linux-all/second:: libmacos libunix libiso9660-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
second/$(KARCH)-linux-all/second:: libmacos libunix libiso9660-m68k libext2-m68k libgzip-m68k libfloppy libscsi libstream libblock libcontainer libui libconfig-m68k libmap-m68k
$(MAKE) -C second MEDIA=full TARGET=$(KARCH)-linux
second/m68k-netbsd-floppy/second:: libmacos libunix libiso9660-m68k libgzip-m68k libfloppy libstream libblock libcontainer libui libconfig-m68k libmap-m68k
second/m68k-netbsd-floppy/second:: libmacos libunix libiso9660-m68k libext2-m68k libgzip-m68k libfloppy libstream libblock libcontainer libui libconfig-m68k libmap-m68k
$(MAKE) -C second TARGET=m68k-netbsd MEDIA=floppy
first-install::
@ -206,6 +206,9 @@ libui::
libiso9660-m68k::
$(MAKE) -C libiso9660 all TARGET=m68k-linux
libext2-m68k::
$(MAKE) -C libext2 all TARGET=m68k-linux
libconfig-m68k::
$(MAKE) -C libconfig all TARGET=m68k-linux
@ -215,6 +218,9 @@ libconfig::
libiso9660::
$(MAKE) -C libiso9660 all TARGET=native CROSS_COMPILE=$(CROSS_COMPILE)
libext2::
$(MAKE) -C libext2 all TARGET=native CROSS_COMPILE=$(CROSS_COMPILE)
libcontainer::
$(MAKE) -C libcontainer all TARGET=m68k-linux
@ -245,7 +251,7 @@ libmap::
libmap-m68k::
$(MAKE) -C libmap all TARGET=m68k-linux
tools:: libemile libiso9660 libgzip libconfig libmap
tools:: libemile libiso9660 libext2 libgzip libconfig libmap
$(MAKE) -C tools all CROSS_COMPILE=$(CROSS_COMPILE)
tools-install:: tools
@ -298,6 +304,10 @@ libiso9660-clean::
$(MAKE) -C libiso9660 clean TARGET=native
$(MAKE) -C libiso9660 clean TARGET=$(KARCH)-linux
libext2-clean::
$(MAKE) -C libext2 clean TARGET=native
$(MAKE) -C libext2 clean TARGET=$(KARCH)-linux
libconfig-clean::
$(MAKE) -C libconfig clean TARGET=native
$(MAKE) -C libconfig clean TARGET=$(KARCH)-linux
@ -338,7 +348,8 @@ distclean:: clean
rm -f tools.mk
clean:: libemile-clean libmacos-clean libunix-clean tools-clean first-clean \
second-clean docs-clean libiso9660-clean libgzip-clean libfloppy-clean \
second-clean docs-clean libiso9660-clean libext2-clean libgzip-clean \
libfloppy-clean \
libscsi-clean libstream-clean libblock-clean libcontainer-clean \
apple_driver-clean libui-clean libconfig-clean libmap-clean
rm -f floppy.bin floppy.bin.X floppy_ramdisk.bin \
@ -368,6 +379,7 @@ dist:
@$(MAKE) -C libfloppy dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C libblock dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C libiso9660 dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C libext2 dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C libcontainer dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C libgzip dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)
@$(MAKE) -C tools dist DISTDIR=$(shell pwd)/$(PACKAGE)-$(VERSION)

34
libext2/Makefile Normal file
View File

@ -0,0 +1,34 @@
#
# (c) 2008 Laurent Vivier <Laurent@lvivier.info>
#
TOP = $(shell pwd)
VPATH=$(TOP)
TARGET = native
CFLAGS += -nostdlib -nodefaultlibs -Wall -Werror -Wno-multichar
ifeq ($(TARGET), m68k-linux)
68000FLAGS = -m68000 -Wa,-m68000
CFLAGS += -fpic -O2 -Os
else
CFLAGS += -g
endif
CPPFLAGS = -I$(TOP)/../libstream
LIBRARY = libext2.a
SOURCES = ext2_mount.c ext2_opendir.c \
ext2_closedir.c \
ext2_open.c \
ext2_read.c ext2_close.c \
ext2_lseek.c ext2_fstat.c \
ext2_utils.c ext2_readdir.c
HEADERS = libext2.h ext2_utils.h
all:
test -d $(TARGET) || mkdir $(TARGET)
$(MAKE) -C $(TARGET) -f $(TOP)/Makefile $(LIBRARY) TOP=$(TOP)
include $(TOP)/../tools.mk
include $(TOP)/../Rules.mk

16
libext2/ext2_close.c Normal file
View File

@ -0,0 +1,16 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <stdlib.h>
#include "libext2.h"
void ext2_close(ext2_FILE *file)
{
if (file == NULL)
return;
free(file->inode);
free(file);
}

16
libext2/ext2_closedir.c Normal file
View File

@ -0,0 +1,16 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <stdlib.h>
#include "libext2.h"
void ext2_closedir(ext2_DIR *dir)
{
if (dir == NULL)
return;
free(dir->inode);
free(dir);
}

13
libext2/ext2_fstat.c Normal file
View File

@ -0,0 +1,13 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include "libext2.h"
int ext2_fstat(ext2_FILE *file, struct stream_stat *buf)
{
buf->st_size = file->inode->i_size;
return 0;
}

35
libext2/ext2_lseek.c Normal file
View File

@ -0,0 +1,35 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include "libext2.h"
int ext2_lseek(ext2_FILE *file, long offset, int whence)
{
long new_offset;
switch(whence)
{
case SEEK_SET:
new_offset = offset;
break;
case SEEK_CUR:
new_offset = file->offset + offset;
break;
case SEEK_END:
new_offset = file->inode->i_size + offset;
break;
default:
return -1;
}
if ( (new_offset < 0) ||
(new_offset > file->inode->i_size) )
return -1;
file->offset = new_offset;
return new_offset;
}

60
libext2/ext2_mount.c Normal file
View File

@ -0,0 +1,60 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <stdlib.h>
#include "libext2.h"
#include "ext2_utils.h"
#define SB_OFFSET (2)
ext2_VOLUME* ext2_mount(device_io_t *device)
{
ext2_VOLUME *volume;
struct ext2_super_block *super;
char *buffer;
super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block));
if (super == NULL)
return NULL;
device->read_sector(device->data, 2, super, sizeof (*super));
if (super->s_magic != EXT2_SUPER_MAGIC) {
free(super);
return NULL;
}
buffer = (char*)malloc(EXT2_BLOCK_SIZE(super));
if (buffer == NULL) {
free(super);
return NULL;
}
volume = (ext2_VOLUME*)malloc(sizeof(ext2_VOLUME));
if (volume == NULL) {
free(super);
free(buffer);
return NULL;
}
volume->buffer = buffer;
volume->device = device;
volume->super = super;
volume->current = -1;
ext2_read_block(volume, 0);
return volume;
}
int ext2_umount(ext2_VOLUME* volume)
{
if (volume == NULL)
return -1;
free(volume->super);
free(volume->buffer);
free(volume);
return 0;
}

43
libext2/ext2_open.c Normal file
View File

@ -0,0 +1,43 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <stdlib.h>
#include "libext2.h"
#include "ext2_utils.h"
ext2_FILE* ext2_open(ext2_VOLUME *volume, char* pathname)
{
ext2_FILE *file;
struct ext2_inode *inode;
int ino;
int ret;
ino = ext2_seek_name(volume, pathname);
if (ino == 0)
return NULL;
inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode));
if (inode == NULL)
return NULL;
ret = ext2_get_inode(volume, ino, inode);
if (ret == -1) {
free(inode);
return NULL;
}
file = (ext2_FILE*)malloc(sizeof(ext2_FILE));
if (file == NULL) {
free(inode);
return NULL;
}
file->volume = volume;
file->inode = inode;
file->offset = 0;
return file;
}

49
libext2/ext2_opendir.c Normal file
View File

@ -0,0 +1,49 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <stdlib.h>
#include <sys/stat.h>
#include "libext2.h"
#include "ext2_utils.h"
ext2_DIR* ext2_opendir(ext2_VOLUME *volume, char *name)
{
ext2_DIR* dir;
int ino;
struct ext2_inode *inode;
int ret;
ino = ext2_seek_name(volume, name);
if (ino == 0)
return NULL;
inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode));
if (inode == NULL)
return NULL;
ret = ext2_get_inode(volume, ino, inode);
if (ret == -1) {
free(inode);
return NULL;
}
if (!S_ISDIR(inode->i_mode)) {
free(inode);
return NULL;
}
dir = (ext2_DIR*)malloc(sizeof(ext2_DIR));
if (dir == NULL) {
free(inode);
return NULL;
}
dir->volume = volume;
dir->inode = inode;
dir->index = 0;
return dir;
}

20
libext2/ext2_read.c Normal file
View File

@ -0,0 +1,20 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include "libext2.h"
#include "ext2_utils.h"
ssize_t ext2_read(ext2_FILE *file, void *buf, size_t count)
{
int ret;
ret = ext2_read_data(file->volume, file->inode, file->offset,
buf, count);
if (ret == -1)
return -1;
file->offset += ret;
return ret;
}

23
libext2/ext2_readdir.c Normal file
View File

@ -0,0 +1,23 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include "libext2.h"
#include "ext2_utils.h"
static struct ext2_dir_entry_2 entry;
struct ext2_dir_entry_2 *ext2_readdir(ext2_DIR *dir)
{
int ret;
ret = ext2_dir_entry(dir->volume, dir->inode, dir->index, &entry);
if (ret == -1)
return NULL;
dir->index = ret;
entry.name[entry.name_len] = 0;
return &entry;
}

223
libext2/ext2_utils.c Normal file
View File

@ -0,0 +1,223 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#include <string.h>
#include "libext2.h"
#include "ext2_utils.h"
void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock)
{
off_t block;
int blocksize;
if (fsblock == volume->current)
return;
volume->current = fsblock;
blocksize = volume->device->get_blocksize(volume->device->data);
block = fsblock * (EXT2_BLOCK_SIZE(volume->super) / blocksize);
volume->device->read_sector(volume->device->data, block,
volume->buffer,
EXT2_BLOCK_SIZE(volume->super));
}
void ext2_get_group_desc(ext2_VOLUME* volume,
int group_id, struct ext2_group_desc *gdp)
{
unsigned int block, offset;
block = 1 + volume->super->s_first_data_block;
block += group_id / EXT2_DESC_PER_BLOCK(volume->super);
ext2_read_block(volume, block);
offset = group_id % EXT2_DESC_PER_BLOCK(volume->super);
offset *= sizeof(*gdp);
memcpy(gdp, volume->buffer + offset, sizeof(*gdp));
}
int ext2_get_inode(ext2_VOLUME* volume,
unsigned int ino, struct ext2_inode *inode)
{
struct ext2_group_desc desc;
unsigned int block;
unsigned int group_id;
unsigned int offset;
ino--;
group_id = ino / EXT2_INODES_PER_GROUP(volume->super);
ext2_get_group_desc(volume, group_id, &desc);
ino %= EXT2_INODES_PER_GROUP(volume->super);
block = desc.bg_inode_table;
block += ino / (EXT2_BLOCK_SIZE(volume->super) /
EXT2_INODE_SIZE(volume->super));
ext2_read_block(volume, block);
offset = ino % (EXT2_BLOCK_SIZE(volume->super) /
EXT2_INODE_SIZE(volume->super));
offset *= EXT2_INODE_SIZE(volume->super);
memcpy(inode, volume->buffer + offset, sizeof(*inode));
return 0;
}
unsigned int ext2_get_block_addr(ext2_VOLUME* volume, struct ext2_inode *inode,
unsigned int logical)
{
unsigned int physical;
unsigned int addr_per_block;
/* direct */
if (logical < EXT2_NDIR_BLOCKS) {
physical = inode->i_block[logical];
return physical;
}
/* indirect */
logical -= EXT2_NDIR_BLOCKS;
addr_per_block = EXT2_ADDR_PER_BLOCK (volume->super);
if (logical < addr_per_block) {
ext2_read_block(volume, inode->i_block[EXT2_IND_BLOCK]);
physical = ((unsigned int *)volume->buffer)[logical];
return physical;
}
/* double indirect */
logical -= addr_per_block;
if (logical < addr_per_block * addr_per_block) {
ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
physical = ((unsigned int *)volume->buffer)
[logical / addr_per_block];
ext2_read_block(volume, physical);
physical = ((unsigned int *)volume->buffer)
[logical % addr_per_block];
return physical;
}
/* triple indirect */
logical -= addr_per_block * addr_per_block;
ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
physical = ((unsigned int *)volume->buffer)
[logical / (addr_per_block * addr_per_block)];
ext2_read_block(volume, physical);
logical = logical % (addr_per_block * addr_per_block);
physical = ((unsigned int *)volume->buffer)[logical / addr_per_block];
ext2_read_block(volume, physical);
physical = ((unsigned int *)volume->buffer)[logical % addr_per_block];
return physical;
}
int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode,
off_t offset, char *buffer, size_t length)
{
unsigned int logical, physical;
int blocksize = EXT2_BLOCK_SIZE(volume->super);
int shift;
size_t read;
if (offset >= inode->i_size)
return -1;
if (offset + length >= inode->i_size)
length = inode->i_size - offset;
read = 0;
logical = offset / blocksize;
shift = offset % blocksize;
if (shift) {
physical = ext2_get_block_addr(volume, inode, logical);
ext2_read_block(volume, physical);
if (length < blocksize - shift) {
memcpy(buffer, volume->buffer + shift, length);
return length;
}
read += blocksize - shift;
memcpy(buffer, volume->buffer + shift, read);
buffer += read;
length -= read;
logical++;
}
while (length) {
physical = ext2_get_block_addr(volume, inode, logical);
ext2_read_block(volume, physical);
if (length < blocksize) {
memcpy(buffer, volume->buffer, length);
read += length;
return read;
}
memcpy(buffer, volume->buffer, blocksize);
buffer += blocksize;
length -= blocksize;
read += blocksize;
logical++;
}
return read;
}
off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode,
off_t index, struct ext2_dir_entry_2 *entry)
{
int ret;
ret = ext2_read_data(volume, inode, index,
(char*)entry, sizeof(*entry));
if (ret == -1)
return -1;
return index + entry->rec_len;
}
unsigned int ext2_seek_name(ext2_VOLUME *volume, char *name)
{
struct ext2_inode inode;
int ret;
unsigned int ino;
off_t index;
struct ext2_dir_entry_2 entry;
ino = EXT2_ROOT_INO;
while(*name) {
if (*name == '/')
name++;
ret = ext2_get_inode(volume, ino, &inode);
if (ret == -1)
return 0;
index = 0;
while (1) {
index = ext2_dir_entry(volume, &inode, index, &entry);
if (index == -1)
return 0;
ret = strncmp(name, entry.name, entry.name_len);
if (ret == 0 &&
(name[entry.name_len] == 0 ||
name[entry.name_len] == '/')) {
ino = entry.inode;
break;
}
}
name += entry.name_len;
}
return ino;
}

23
libext2/ext2_utils.h Normal file
View File

@ -0,0 +1,23 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#ifndef __EXT2_UTILS_H__
#define __EXT2_UTILS_H__
extern void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock);
extern void ext2_get_group_desc(ext2_VOLUME* volume,
int group_id, struct ext2_group_desc *gdp);
extern int ext2_get_inode(ext2_VOLUME* volume,
unsigned int ino, struct ext2_inode *inode);
extern unsigned int ext2_get_block_addr(ext2_VOLUME* volume,
struct ext2_inode *inode,
unsigned int logical);
extern int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode,
off_t offset, char *buffer, size_t length);
extern off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode,
off_t offset, struct ext2_dir_entry_2 *entry);
extern unsigned int ext2_seek_name(ext2_VOLUME *volume, char *name);
#endif /* __EXT2_UTILS_H__ */

45
libext2/libext2.h Normal file
View File

@ -0,0 +1,45 @@
/*
*
* (c) 2008 Laurent Vivier <Laurent@lvivier.info>
*
*/
#ifndef __LIBEXT2_H__
#define __LIBEXT2_H__
#include <unistd.h>
#include <linux/ext2_fs.h>
#include <libstream.h>
typedef struct ext2_VOLUME {
device_io_t *device;
struct ext2_super_block *super;
unsigned int current;
char *buffer;
} ext2_VOLUME;
typedef struct ext2_DIR {
ext2_VOLUME *volume;
struct ext2_inode *inode;
off_t index;
} ext2_DIR;
typedef struct ext2_FILE {
ext2_VOLUME *volume;
struct ext2_inode *inode;
off_t offset;
} ext2_FILE;
extern ext2_VOLUME* ext2_mount(device_io_t *device);
extern int ext2_umount(ext2_VOLUME *volume);
extern ext2_DIR* ext2_opendir(ext2_VOLUME *, char *name);
extern struct ext2_dir_entry_2* ext2_readdir(ext2_DIR* dir);
extern void ext2_closedir(ext2_DIR *dir);
extern ext2_FILE* ext2_open(ext2_VOLUME *, char* pathname);
extern ssize_t ext2_read(ext2_FILE *file, void *buf, size_t count);
extern void ext2_close(ext2_FILE *file);
extern int ext2_lseek(ext2_FILE *file, long offset, int whence);
extern int ext2_fstat(ext2_FILE *file, struct stream_stat *buf);
#endif /* __LIBEXT2_H__ */