/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "file_system_struct.h" #include "bin.h" #include "ro_fs.h" #include "pfs.h" #include "pfs_structs.h" #include #include #include #include #include #include #include #include #include #include #include struct rootfs_file_struct; struct rootfs_file_operations_struct { int (*find)(const struct rootfs_file_struct *, const char *, unsigned long *, int *); int (*get_name)(const struct rootfs_file_struct *, char []); int (*get_size)(const struct rootfs_file_struct *, unsigned long *); int (*read_dir)(const struct rootfs_file_struct *, unsigned long, char *, unsigned int); int (*read)(const struct rootfs_file_struct *, unsigned long, char *, unsigned int); }; struct rootfs_file_struct { struct pfs_dir_entry_struct dir_entry; /* entree de repertoire */ union { struct pfs_dir_struct dir; /* repertoire */ const void *bin_addr; /* addresse de fichier bin */ }; const struct rootfs_file_operations_struct *operations; }; static int mount_count; /* nombre de montages */ static long mount_time; /* heure du premier montage */ /* Operations sur les fichiers */ static int stat(const struct rootfs_file_struct *file, struct stat_struct *fs_buf) { struct stat_struct statbuf; int rv; if (!verify_area(fs_buf, sizeof (struct stat_struct), PF_WRITE)) return -EFAULT; statbuf.dev = DEV_NONE; statbuf.id = file->dir_entry.info.id; statbuf.type = file->dir_entry.info.type; statbuf.rdev = DEV_NONE; if (file->dir_entry.info.type == FT_REG) { if ((rv = file->operations->get_size(file, &statbuf.size)) < 0) return rv; } else statbuf.size = 0; statbuf.mtime = mount_time; memcpy_tofs(fs_buf, &statbuf, sizeof (struct stat_struct)); return 0; } static int root_find(const struct rootfs_file_struct *file, const char *fs_basename, unsigned long *id, int *type) { return pfs_find(&file->dir, fs_basename, id, type); } static int root_get_name(const struct rootfs_file_struct *file, char name[]) { strcpy(name, file->dir_entry.info.name); return 0; } static int root_read_dir(const struct rootfs_file_struct *file, unsigned long pos, char *fs_buf, unsigned int count) { return pfs_read_dir(&file->dir, pos, fs_buf, count); } static int rootfs_bin_find(const struct rootfs_file_struct *file, const char *fs_basename, unsigned long *id, int *type) { return bin_find(file->bin_addr, fs_basename, id, type); } static int rootfs_bin_get_name(const struct rootfs_file_struct *file, char name[]) { return bin_get_name(file->bin_addr, name); } static int rootfs_bin_read_dir(const struct rootfs_file_struct *file, unsigned long pos, char *fs_buf, unsigned int count) { return bin_read_dir(file->bin_addr, pos, fs_buf, count); } static int rootfs_bin_get_size(const struct rootfs_file_struct *file, unsigned long *size) { return bin_get_size(file->bin_addr, size); } static int rootfs_bin_read(const struct rootfs_file_struct *file, unsigned long pos, char *fs_buf, unsigned int count) { return bin_read(file->bin_addr, pos, fs_buf, count); } static const struct rootfs_file_operations_struct root_dir_operations = { .find = root_find, .get_name = root_get_name, .read_dir = root_read_dir }; static const struct rootfs_file_operations_struct bin_dir_operations = { .find = rootfs_bin_find, .get_name = root_get_name, .read_dir = rootfs_bin_read_dir }; static const struct rootfs_file_operations_struct bin_file_operations = { .get_size = rootfs_bin_get_size, .get_name = rootfs_bin_get_name, .read = rootfs_bin_read }; /* Fichiers */ /* racine */ static struct rootfs_file_struct root_dir = { .dir_entry = { .info = { .type = FT_DIR } }, .operations = &root_dir_operations }; /* dev */ static struct rootfs_file_struct dev_dir = { .dir_entry = { .info = { .name = "dev", .type = FT_DIR } }, .operations = &root_dir_operations }; /* proc */ static struct rootfs_file_struct proc_dir = { .dir_entry = { .info = { .name = "proc", .type = FT_DIR } }, .operations = &root_dir_operations }; /* bin */ static struct rootfs_file_struct bin_dir = { .dir_entry = { .info = { .name = "bin", .type = FT_DIR } }, .operations = &bin_dir_operations }; /* lib */ static struct rootfs_file_struct lib_dir = { .dir_entry = { .info = { .name = "lib", .type = FT_DIR } }, .operations = &bin_dir_operations }; /* floppy */ static struct rootfs_file_struct floppy_dir = { .dir_entry = { .info = { .name = "floppy", .type = FT_DIR } }, .operations = &root_dir_operations }; /* home */ static struct rootfs_file_struct home_dir = { .dir_entry = { .info = { .name = "home", .type = FT_DIR } }, .operations = &root_dir_operations }; static struct rootfs_file_struct *const root_file_index[] = { &root_dir, &dev_dir, &proc_dir, &bin_dir, &lib_dir, &floppy_dir, &home_dir }; static const unsigned int root_file_index_size = sizeof root_file_index / sizeof root_file_index[0]; static void build_bin_file(struct rootfs_file_struct *file, const void *bin_addr) { file->dir_entry.info.id = (unsigned long)bin_addr; file->dir_entry.info.type = FT_REG; file->bin_addr = bin_addr; file->operations = &bin_file_operations; } static int init() { unsigned int i; for (i = 0; i < root_file_index_size; i++) root_file_index[i]->dir_entry.info.id = i; pfs_init_dir(&root_dir.dir); pfs_init_dir(&dev_dir.dir); pfs_init_dir(&proc_dir.dir); bin_dir.bin_addr = usr_start + ((const usr_hdr_t *)usr_start)->bin_offset; if (!bin_check(bin_dir.bin_addr)) return -EINVAL; lib_dir.bin_addr = usr_start + ((const usr_hdr_t *)usr_start)->lib_offset; if (!bin_check(lib_dir.bin_addr)) return -EINVAL; pfs_init_dir(&floppy_dir.dir); pfs_init_dir(&home_dir.dir); for (i = 1; i < root_file_index_size; i++) pfs_insert_dir_entry(&root_file_index[i]->dir_entry, &root_dir.dir); return 0; } /* resolution des fichiers */ static struct rootfs_file_struct *get_file(unsigned long id, struct rootfs_file_struct *filebuf) { if (id < root_file_index_size) return root_file_index[id]; else { build_bin_file(filebuf, (void *)id); return filebuf; } } /* Methodes du systeme de fichiers */ static int rootfs_mount(const struct device_struct *device, void **data) { int rv; if (!mount_count) { mount_time = get_time(); if ((rv = init()) < 0) return rv; } mount_count++; *data = NULL; return 0; } static void rootfs_umount(void *data) { mount_count--; } static int rootfs_find(void *data, unsigned long dir_id, const char *fs_basename, unsigned long *id, int *type) { struct rootfs_file_struct filebuf; const struct rootfs_file_struct *file; file = get_file(dir_id, &filebuf); return file->operations->find(file, fs_basename, id, type); } static int rootfs_get_name(void *data, unsigned long id, char name[]) { struct rootfs_file_struct filebuf; const struct rootfs_file_struct *file; file = get_file(id, &filebuf); return file->operations->get_name(file, name); } static int rootfs_get_size(void *data, unsigned long reg_id, unsigned long *size) { struct rootfs_file_struct filebuf; const struct rootfs_file_struct *file; file = get_file(reg_id, &filebuf); return file->operations->get_size(file, size); } static int rootfs_stat(void *data, unsigned long id, struct stat_struct *fs_buf) { struct rootfs_file_struct filebuf; return stat(get_file(id, &filebuf), fs_buf); } static int rootfs_read_dir(void *data, unsigned long dir_id, unsigned long pos, char *fs_buf, unsigned int count) { struct rootfs_file_struct filebuf; const struct rootfs_file_struct *file; file = get_file(dir_id, &filebuf); return file->operations->read_dir(file, pos, fs_buf, count); } static int rootfs_read(void *data, unsigned long leaf_id, unsigned long pos, char *fs_buf, unsigned int count) { struct rootfs_file_struct filebuf; const struct rootfs_file_struct *file; file = get_file(leaf_id, &filebuf); return file->operations->read(file, pos, fs_buf, count); } const struct file_system_struct rootfs = { .name = "rootfs", .type = FT_NONE, .mount = rootfs_mount, .umount = rootfs_umount, .find = rootfs_find, .get_name = rootfs_get_name, .get_device = NULL, .get_size = rootfs_get_size, .stat = rootfs_stat, .read_dir = rootfs_read_dir, .read = rootfs_read, .write = no_write, .ioctl = NULL, .create = no_create, .mkdir = no_mkdir, .can_remove = no_can_remove, .remove = no_remove, .rmdir = no_rmdir, .rename = no_rename };