diff options
author | Marcus Brinkmann <marcus@gnu.org> | 2002-12-03 20:52:59 +0000 |
---|---|---|
committer | Marcus Brinkmann <marcus@gnu.org> | 2002-12-03 20:52:59 +0000 |
commit | 8f48e6fa4324fc242af66ab0d49e467f98656f15 (patch) | |
tree | cc222f7c92b8aa3d267833a401e69b897aad92a2 /fatfs/main.c | |
parent | f56926743a89f4aa10302b5837aebaf5817a4e01 (diff) | |
download | hurd-8f48e6fa4324fc242af66ab0d49e467f98656f15.tar.gz hurd-8f48e6fa4324fc242af66ab0d49e467f98656f15.tar.bz2 hurd-8f48e6fa4324fc242af66ab0d49e467f98656f15.zip |
Initial check-in.
Diffstat (limited to 'fatfs/main.c')
-rw-r--r-- | fatfs/main.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/fatfs/main.c b/fatfs/main.c new file mode 100644 index 00000000..800e58b4 --- /dev/null +++ b/fatfs/main.c @@ -0,0 +1,265 @@ +/* main.c - FAT filesystem. + Copyright (C) 1997, 1998, 1999, 2002 Free Software Foundation, Inc. + Written by Thomas Bushnell, n/BSG and Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd 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 2, or (at your option) + any later version. + + The GNU Hurd 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <string.h> +#include <error.h> +#include <argp.h> +#include <argz.h> +#include <limits.h> + +#include <version.h> +#include "fatfs.h" + +struct node *diskfs_root_node; + +struct store *store = 0; +struct store_parsed *store_parsed = 0; +char *diskfs_disk_name = 0; + +char *diskfs_server_name = "fatfs"; +char *diskfs_server_version = HURD_VERSION; +char *diskfs_extra_version = "GNU Hurd"; +int diskfs_synchronous = 0; + +int diskfs_link_max = 1; +int diskfs_name_max = FAT_NAME_MAX; +int diskfs_maxsymlinks = 8; /* XXX */ + +/* This filesystem is not capable of writing yet. */ +int diskfs_readonly = 1, diskfs_hard_readonly = 1; + +/* Handy source of zeroes. */ +vm_address_t zerocluster; + +struct dirrect dr_root_node; + +/* The UID and GID for all files in the filesystem. */ +uid_t default_fs_uid; +gid_t default_fs_gid; +uid_t fs_uid; +gid_t fs_gid; + +/* fatfs specific options. */ +static const struct argp_option options[] = + { + { "uid", 'U', "uid", 0, "Default uid for files" }, + { "gid", 'G', "gid", 0, "Default gid for files" }, + { 0 } + }; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case 'U': + if (arg) + fs_uid = atoi (arg); + refresh_node_stats (); + break; + case 'G': + if (arg) + fs_gid = atoi (arg); + refresh_node_stats (); + break; + case ARGP_KEY_INIT: + state->child_inputs[0] = state->input; + break; + case ARGP_KEY_SUCCESS: + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +/* Add our startup arguments to the standard diskfs set. */ +static const struct argp_child startup_children[] = + { { &diskfs_store_startup_argp }, { 0 } }; +static struct argp startup_argp = + { options, parse_opt, 0, 0, startup_children }; + +/* Similarly at runtime. */ +static const struct argp_child runtime_children[] = + { { &diskfs_std_runtime_argp }, { 0 } }; +static struct argp runtime_argp = + { options, parse_opt, 0, 0, runtime_children }; + +struct argp *diskfs_runtime_argp = (struct argp *) &runtime_argp; + + +/* Override the standard diskfs routine so we can add our own + output. */ +error_t +diskfs_append_args (char **argz, unsigned *argz_len) +{ + error_t err; + char buf[100]; + + /* Get the standard things. */ + err = diskfs_append_std_options (argz, argz_len); + + if (!err && fs_uid != default_fs_uid) + { + snprintf (buf, sizeof buf, "--uid=%d", fs_uid); + err = argz_add (argz, argz_len, buf); + } + + if (!err && fs_gid != default_fs_gid) + { + snprintf (buf, sizeof buf, "--gid=%d", fs_gid); + err = argz_add (argz, argz_len, buf); + } + + if (! err) + err = store_parsed_append_args (store_parsed, argz, argz_len); + + return err; +} + + +/* Fetch the root node. */ +static void +fetch_root () +{ + error_t err; + ino_t inum; + inode_t inode; + + memset (&dr_root_node, 0, sizeof(struct dirrect)); + + /* Fill root directory entry. XXX Should partially be in fat.c */ + dr_root_node.attribute = FAT_DIR_ATTR_DIR; + if (fat_type == FAT32) + { + /* FAT12/16: There is no such thing as a start cluster, because + the whole root dir is in a special region after the FAT. The + start cluster of the root node is undefined. */ + dr_root_node.first_cluster_high[1] + = sblock->compat.fat32.root_cluster[3]; + dr_root_node.first_cluster_high[0] + = sblock->compat.fat32.root_cluster[2]; + dr_root_node.first_cluster_low[1] = sblock->compat.fat32.root_cluster[1]; + dr_root_node.first_cluster_low[0] = sblock->compat.fat32.root_cluster[0]; + } + + /* Determine size of the directory (different for fat12/16 vs 32). */ + switch (fat_type) + { + case FAT12: + case FAT16: + write_dword(dr_root_node.file_size, nr_of_root_dir_sectors + << log2_bytes_per_sector); + break; + + case FAT32: + { + /* Extend the cluster chain of the root directory and calculate + file_size based on that. */ + cluster_t rootdir; + int cs = 0; + + rootdir = (cluster_t) *sblock->compat.fat32.root_cluster; + while (rootdir != FAT_EOC) + { + fat_get_next_cluster (rootdir, &rootdir); + cs++; + } + write_dword (dr_root_node.file_size, cs << log2_bytes_per_cluster); + } + break; + + default: + assert(!"don't know how to set size of root dir"); + }; + + /* The magic vi_key {0, 1} for the root directory is distinguished + from the vi_zero_key (in the dir_offset value) as well as all + normal virtual inode keys (in the dir_inode value). Enter the + disknode into the inode table. */ + err = vi_new ((struct vi_key) {0, 1}, &inum, &inode); + assert_perror (err); + + /* Allocate a node for the root directory disknode in + diskfs_root_node. */ + if (!err) + err = diskfs_cached_lookup (inum, &diskfs_root_node); + + assert_perror (err); + + mutex_unlock (&diskfs_root_node->lock); +} + + +int +main (int argc, char **argv) +{ + mach_port_t bootstrap; + + default_fs_uid = getuid (); + default_fs_gid = getgid (); + fs_uid = default_fs_uid; + fs_gid = default_fs_gid; + + /* Initialize the diskfs library, parse arguments, and open the + store. This starts the first diskfs thread for us. */ + store = diskfs_init_main (&startup_argp, argc, argv, &store_parsed, + &bootstrap); + + fat_read_sblock (); + + create_fat_pager (); + + zerocluster = (vm_address_t) mmap (0, bytes_per_cluster, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + fetch_root (); + + diskfs_startup_diskfs (bootstrap, 0); + + cthread_exit (0); + + return 0; +} + + +/* Nothing to do for read-only medium. */ +error_t +diskfs_reload_global_state () +{ + return 0; +} + + +error_t +diskfs_set_hypermetadata (int wait, int clean) +{ + return 0; +} + + +void +diskfs_readonly_changed (int readonly) +{ + /* We should never get here because we set diskfs_hard_readonly above. */ + abort (); +} + |