Репозитории ALT
S: | 2.5.5-alt68 |
5.1: | 2.5.5-alt13 |
4.1: | 2.5.5-alt9 |
4.0: | 2.5.5-alt5.M40.4 |
3.0: | 2.5.2-alt3 |
Группа :: Система/Ядро и оборудование
Пакет: evms
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: evms-2.5.0-alt-fat.patch
Скачать
Скачать
--- evms-2.5.0.orig/aclocal.m4 2004-10-20 23:50:31 +0400
+++ evms-2.5.0/aclocal.m4 2004-11-19 15:00:21 +0300
@@ -116,6 +116,11 @@
[Disable the ReiserFS FSIM]),
[build_reiser="$enableval"],
[build_reiser="yes"])
+AC_ARG_ENABLE([fat],
+ AC_HELP_STRING([--disable-fat],
+ [Disable the FAT FSIM]),
+ [build_fat="$enableval"],
+ [build_fat="yes"])
AC_ARG_ENABLE([xfs],
AC_HELP_STRING([--disable-xfs],
[Disable the XFS FSIM]),
@@ -145,7 +150,7 @@
# Create the list of plugin directories to build. This is where each plugin
# can specify its dependencies.
plugin_dirs=""
-plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink error ext2 gpt ha jfs lvm lvm2 mac md multipath ntfs ogfs reiser replace rsct s390 snapshot swap xfs"
+plugin_distdirs="bbr bbr_seg bsd csm disk dos drivelink error ext2 gpt ha jfs lvm lvm2 mac md multipath ntfs ogfs reiser fat replace rsct s390 snapshot swap xfs"
# BBR
if test "$build_bbr" = "no"; then
@@ -323,6 +328,14 @@
AC_MSG_NOTICE([ building reiser])
fi
+# FAT
+if test "$build_fat" = "no"; then
+ AC_MSG_NOTICE([ not building fat ... disabled by user])
+else
+ plugin_dirs="$plugin_dirs fat"
+ AC_MSG_NOTICE([ building fat])
+fi
+
# Replace
if test "$build_replace" = "no"; then
AC_MSG_NOTICE([ not building replace ... disabled by user])
--- evms-2.5.0.orig/configure.ac 2004-10-20 23:46:50 +0400
+++ evms-2.5.0/configure.ac 2004-11-19 15:00:36 +0300
@@ -177,6 +177,7 @@
[plugins/ntfs/Makefile] \
[plugins/ogfs/Makefile] \
[plugins/reiser/Makefile] \
+ [plugins/fat/Makefile] \
[plugins/replace/Makefile] \
[plugins/rsct/Makefile] \
[plugins/s390/Makefile] \
--- evms-2.5.0/plugins/dos/segoptions.c.orig 2004-09-13 19:15:46 +0400
+++ evms-2.5.0/plugins/dos/segoptions.c 2005-01-18 21:23:29 +0300
@@ -49,6 +49,7 @@
static const struct seg_partition_type_info_s partition_types[] =
{
+ {"FAT32", 0x0b},
{"FAT16", 6},
{"HPFS", 7},
{"NTFS", 7},
diff -Naur evms-2.5.2/plugins/fat.orig/fatfsim.c evms-2.5.2/plugins/fat/fatfsim.c
--- evms-2.5.2/plugins/fat.orig/fatfsim.c 1970-01-01 03:00:00 +0300
+++ evms-2.5.2/plugins/fat/fatfsim.c 2005-09-12 17:24:51 +0400
@@ -0,0 +1,1323 @@
+/*
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: fatfsim.c
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include <plugin.h>
+
+#include "fatfsim.h"
+#include "utils.h"
+
+/* FIXME: correct min FAT size */
+#define MIN_FAT_SIZE (8 * 1024)
+
+static plugin_record_t fat_plugrec;
+static plugin_record_t fat16_plugrec;
+plugin_record_t * my_plugin_record;
+engine_functions_t * EngFncs;
+boolean have_mkdosfs = FALSE;
+boolean have_dosfsck = FALSE;
+boolean have_fatresize = FALSE;
+
+static int fat_setup(engine_functions_t *engine_function_table) {
+
+ int rc = 0;
+
+ EngFncs = engine_function_table;
+
+ LOG_ENTRY();
+
+ if (try_run("mkdosfs") == 0) {
+ have_mkdosfs = TRUE;
+ }
+
+ if (try_run("dosfsck") == 0) {
+ have_dosfsck = TRUE;
+ }
+
+ if (try_run("fatresize") == 0) {
+ have_fatresize = TRUE;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Free all of the private data we have left on volumes.
+ */
+static void _fat_cleanup(int isfat16) {
+ int rc = 0;
+ list_anchor_t global_volumes;
+ list_element_t iter;
+ logical_volume_t * vol;
+ LOG_ENTRY();
+
+ rc = EngFncs->get_volume_list(my_plugin_record, NULL, 0, &global_volumes);
+ if (!rc) {
+ LIST_FOR_EACH(global_volumes, iter, vol) {
+ free_private_data(vol);
+ }
+
+ EngFncs->destroy_list(global_volumes);
+ global_volumes = NULL;
+ }
+
+ have_mkdosfs = FALSE;
+ have_dosfsck = FALSE;
+ have_fatresize = FALSE;
+
+ LOG_EXIT_VOID();
+}
+
+static void fat_cleanup() {
+ my_plugin_record = &fat_plugrec;
+ _fat_cleanup(0);
+}
+
+static void fat16_cleanup() {
+ my_plugin_record = &fat16_plugrec;
+ _fat_cleanup(1);
+}
+
+/*
+ * Does this FSIM manage the file system on this volume?
+ * Return 0 for "yes", else a reason code.
+ */
+static int _fat_probe(int isfat16, logical_volume_t * volume) {
+
+ int rc = 0;
+ fat_boot *boot;
+
+ LOG_ENTRY();
+
+ boot = EngFncs->engine_alloc(sizeof(fat_boot));
+ if (boot == NULL) {
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ rc = get_fat_boot(isfat16, volume, boot);
+
+ if (rc == 0) {
+ volume->private_data = EngFncs->engine_alloc(sizeof(private_data_t));
+
+ if (volume->private_data != NULL) {
+ rc = fill_private_data(isfat16, volume, boot);
+
+ } else {
+ rc = ENOMEM;
+ }
+ }
+ EngFncs->engine_free(boot);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static int fat_probe(logical_volume_t * volume) {
+ my_plugin_record = &fat_plugrec;
+ return _fat_probe(0, volume);
+}
+
+static int fat16_probe(logical_volume_t * volume) {
+ my_plugin_record = &fat16_plugrec;
+ return _fat_probe(1, volume);
+}
+
+
+/*
+ * Get the size limits for this volume.
+ */
+static int fat_get_fs_limits(logical_volume_t * volume,
+ sector_count_t * min_size,
+ sector_count_t * max_volume_size,
+ sector_count_t * max_object_size) {
+
+ int rc = 0;
+ private_data_t * pd = volume->private_data;
+
+ LOG_ENTRY();
+
+ rc = get_fs_limits(volume, min_size, max_volume_size, max_object_size);
+ *max_object_size = pd->max_vol_size;
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Can mkfs this volume?
+ */
+static int fat_can_mkfs(logical_volume_t * volume) {
+
+ LOG_ENTRY();
+
+ if (!have_mkdosfs) {
+ LOG_DEBUG("The mkdosfs utility is not installed.\n");
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ if (volume->vol_size < MIN_FAT_SIZE) {
+ LOG_DETAILS("Volume %s is too small. FAT volumes must be at least 128k in size.\n",
+ volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EBUSY;
+ }
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * Can unmkfs this volume?
+ */
+static int _fat_can_unmkfs(logical_volume_t * volume) {
+
+ LOG_ENTRY();
+
+ if (volume->file_system_manager != my_plugin_record) {
+ /* It's not my volume. */
+ LOG_DEBUG("Volume %s does not have FAT on it.\n", volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ /* If mounted, can't unmkfs. */
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ LOG_DEBUG("Volume %s is mounted.\n", volume->name);
+ LOG_EXIT_INT(EBUSY);
+ return EBUSY;
+ }
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+static int fat_can_unmkfs(logical_volume_t * volume) {
+ my_plugin_record = &fat_plugrec;
+ return _fat_can_unmkfs(volume);
+}
+
+static int fat16_can_unmkfs(logical_volume_t * volume) {
+ my_plugin_record = &fat16_plugrec;
+ return _fat_can_unmkfs(volume);
+}
+
+
+/*
+ * Can fsck this volume?
+ */
+static int fat_can_fsck(logical_volume_t * volume) {
+
+ LOG_ENTRY();
+
+ if (!have_dosfsck) {
+ LOG_DEBUG("The dosfsck utility is not installed.\n");
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * Can this volume be expanded?
+ */
+static int fat_can_expand_by(logical_volume_t * volume,
+ sector_count_t * delta_size) {
+
+ int rc = 0;
+
+ LOG_ENTRY();
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ rc = EBUSY; /* If mounted, can't expand */
+ goto errout;
+ }
+ rc = fat_get_fs_limits(volume, /* reset limits */
+ &volume->min_fs_size,
+ &volume->max_fs_size,
+ &volume->max_vol_size);
+
+ if (*delta_size > volume->max_fs_size - volume->fs_size) {
+ *delta_size = volume->max_fs_size - volume->fs_size;
+ }
+errout:
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Can this volume be shrunk?
+ */
+static int fat_can_shrink_by(logical_volume_t * volume,
+ sector_count_t * delta_size) {
+
+ int rc = 0;
+
+ LOG_ENTRY();
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ rc = EBUSY; /* If mounted, can't shrink */
+ goto errout;
+ }
+ rc = fat_get_fs_limits(volume, /* reset limits */
+ &volume->min_fs_size,
+ &volume->max_fs_size,
+ &volume->max_vol_size);
+ if (*delta_size > volume->fs_size - volume->min_fs_size) {
+ *delta_size = volume->fs_size - volume->min_fs_size;
+ }
+ if (volume->min_fs_size >= volume->fs_size) {
+ rc = ENOSPC;
+ }
+errout:
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Get the current size of this volume
+ */
+static int fat_get_fs_size(logical_volume_t * volume,
+ sector_count_t * size) {
+
+ private_data_t * pd = volume->private_data;
+
+ LOG_ENTRY();
+
+ *size = pd->fs_size;
+ LOG_DEBUG("Size of file system on volume %s is %"PRIu64"\n", volume->name, pd->fs_size);
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * mkfs has been scheduled. Do any setup work such as claiming another
+ * volume for an external log.
+ */
+static int fat_mkfs_setup(logical_volume_t * volume,
+ option_array_t * options) {
+
+ int rc = 0;
+
+ LOG_ENTRY();
+
+ volume->private_data = EngFncs->engine_alloc(sizeof(private_data_t));
+
+ if (volume->private_data == NULL) {
+ LOG_CRITICAL("Unable to get memory for private data.\n");
+ rc = ENOMEM;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * NAME: set_fat_mkfs_options
+ *
+ * FUNCTION: Build options array (argv) for mkdosfs
+ *
+ * PARAMETERS:
+ * options - options array passed from EVMS engine
+ * argv - mkfs options array
+ * vol_name - volume on which program will be executed
+ *
+ */
+static void set_fat_mkfs_options(int isfat16,
+ option_array_t * options,
+ char * * argv,
+ logical_volume_t * volume) {
+
+ int i;
+ int bufsize;
+ int opt_count = 0;
+ char *buf;
+
+ LOG_ENTRY();
+
+ argv[opt_count++] = "mkdosfs";
+ argv[opt_count++] = isfat16 ? "-F16" : "-F32";
+
+ for (i = 0; i < options->count; i++) {
+
+ if (!options->option[i].is_number_based) {
+
+ if (!strcmp(options->option[i].name, MKFS_LABEL_NAME)) {
+ options->option[i].number = MKFS_LABEL_INDEX;
+ } else {
+ /* Unknown. Ignore. */
+ continue;
+ }
+ }
+
+ switch (options->option[i].number) {
+
+ case MKFS_LABEL_INDEX:
+ if (options->option[i].value.s != NULL) {
+ argv[opt_count++] = "-n";
+ argv[opt_count++] = options->option[i].value.s;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ argv[opt_count++] = volume->dev_node;
+ argv[opt_count] = NULL;
+
+ bufsize = 0;
+ for (i = 0; argv[i]; i++) {
+ bufsize += strlen(argv[i]) + 1;
+ }
+ buf = EngFncs->engine_alloc(bufsize + 1);
+ if (buf != NULL) {
+ buf[0] = 0;
+ for (i=0; argv[i]; i++) {
+ strcat(buf, argv[i]);
+ strcat(buf, " ");
+ }
+
+ LOG_DEBUG("mkdosfs command: %s\n", buf);
+ EngFncs->engine_free(buf);
+ }
+
+ LOG_EXIT_VOID();
+ return;
+}
+
+
+/*
+ * Put the file system on the volume.
+ */
+static int _fat_mkfs(int isfat16,
+ logical_volume_t * volume,
+ option_array_t * options) {
+
+ int rc = 0;
+ char * argv[MKFS_OPTIONS_COUNT + 10];
+ pid_t pidm;
+ int status;
+ int fds[2];
+
+ LOG_ENTRY();
+
+ if (!have_mkdosfs) {
+ MESSAGE(_("The mkdosfs utility is not installed on this machine.\n"));
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ set_fat_mkfs_options(isfat16, options, argv, volume);
+
+ fds[0] = 0;
+ fds[1] = open("/dev/null", O_WRONLY);
+
+ pidm = EngFncs->fork_and_execvp(volume, argv, NULL, fds, fds);
+ if (pidm != -1) {
+ waitpid( pidm, &status, 0 );
+ if (WIFEXITED(status)) {
+ /* get mkdosfs exit code */
+ rc = WEXITSTATUS(status);
+ } else {
+ rc = EINTR;
+ }
+ } else {
+ rc = errno;
+ }
+
+ close(fds[1]);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static int fat_mkfs(logical_volume_t * volume, option_array_t * options) {
+ my_plugin_record = &fat_plugrec;
+ return _fat_mkfs(0, volume, options);
+}
+
+static int fat16_mkfs(logical_volume_t * volume, option_array_t * options) {
+ my_plugin_record = &fat16_plugrec;
+ return _fat_mkfs(1, volume, options);
+}
+
+
+/*
+ * Expand the volume to new_size. If the volume is not expanded exactly to
+ * new_size, set new_size to the new_size of the volume.
+ */
+static int _fat_expand(int isfat16,
+ logical_volume_t * volume,
+ sector_count_t * new_size) {
+
+ int rc;
+
+ LOG_ENTRY();
+
+ /* Expand must be done offline. */
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ LOG_DETAILS("Volume %s is mounted.\n", volume->name);
+ LOG_EXIT_INT(EBUSY);
+ return EBUSY;
+ }
+
+ rc = resize_fat(isfat16, volume, new_size);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static int fat_expand(logical_volume_t * volume,
+ sector_count_t * new_size) {
+ return _fat_expand(0, volume, new_size);
+}
+
+static int fat16_expand(logical_volume_t * volume,
+ sector_count_t * new_size) {
+ return _fat_expand(1, volume, new_size);
+}
+
+/*
+ * Shrink the volume to new_size. If the volume is not shrunk exactly to
+ * new_size, set new_size to the new_size of the volume.
+ */
+static int _fat_shrink(int isfat16,
+ logical_volume_t * volume,
+ sector_count_t requested_size,
+ sector_count_t * new_size) {
+
+ int rc;
+
+ LOG_ENTRY();
+
+ /* Shrink must be done offline. */
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ LOG_DETAILS("Volume %s is mounted.\n", volume->name);
+ LOG_EXIT_INT(EBUSY);
+ return EBUSY;
+ }
+
+ *new_size = requested_size;
+ rc = resize_fat(isfat16, volume, new_size);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static int fat_shrink(logical_volume_t * volume,
+ sector_count_t requested_size,
+ sector_count_t * new_size) {
+ return _fat_shrink(0, volume, requested_size, new_size);
+}
+
+static int fat16_shrink(logical_volume_t * volume,
+ sector_count_t requested_size,
+ sector_count_t * new_size) {
+ return _fat_shrink(1, volume, requested_size, new_size);
+}
+
+/*
+ * Forget about this volume. Don't remove the file system. Just clean up any
+ * data structures you may have associated with it.
+ */
+static int fat_discard(logical_volume_t * volume) {
+
+ LOG_ENTRY();
+
+ if (volume->private_data) {
+ free_private_data(volume);
+ }
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * unmkfs has been scheduled. Do any setup work such as releasing another
+ * volume that was used for an external log.
+ */
+static int fat_unmkfs_setup(logical_volume_t * volume) {
+
+ LOG_ENTRY();
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * Remove the file system from the volume.
+ */
+static int fat_unmkfs(logical_volume_t * volume) {
+
+ int rc = 0;
+
+ LOG_ENTRY();
+
+ if (EngFncs->is_mounted(volume->dev_node, NULL)) {
+ rc = EBUSY;
+ } else {
+ rc = clear_fat_boot_sectors(volume);
+ if (rc == 0) {
+ free_private_data(volume);
+ }
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Do any operations you wanted to do at commit time, based on the phase of the
+ * commit.
+ */
+int fat_commit_changes(logical_volume_t * volume, commit_phase_t phase) {
+
+ LOG_ENTRY();
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * Return the total number of supported options for the specified task.
+ */
+static int fat_get_option_count(task_context_t * context) {
+
+ int count = 0;
+
+ LOG_ENTRY();
+
+ switch (context->action) {
+ case EVMS_Task_mkfs:
+ count = MKFS_OPTIONS_COUNT;
+ break;
+ default:
+ count = -1;
+ break;
+ }
+
+ LOG_EXIT_INT(count);
+ return count;
+}
+
+/*
+ * Initialize mkfs task acceptable objects by enumerating volumes, finding
+ * those that have no FSIM claiming them and are of the proper size and
+ * adding them to the acceptable objects list.
+ */
+static int init_mkfs_acceptable_objects(task_context_t * context) {
+
+ int rc;
+ list_anchor_t global_volumes;
+ list_element_t vol_list_iter;
+ logical_volume_t * volume;
+
+ LOG_ENTRY();
+
+ rc = EngFncs->get_volume_list(NULL, NULL, 0, &global_volumes);
+ if (!rc) {
+ LIST_FOR_EACH(global_volumes, vol_list_iter, volume) {
+ if ((volume->file_system_manager == NULL) &&
+ (!EngFncs->is_mounted(volume->name, NULL)) &&
+ (volume->vol_size >= MIN_FAT_SIZE)) {
+ EngFncs->insert_thing(context->acceptable_objects,
+ volume,
+ INSERT_BEFORE,
+ NULL);
+ }
+ }
+ EngFncs->destroy_list(global_volumes);
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Fill in the initial list of acceptable objects. Fill in the minimum and
+ * maximum number of objects that must/can be selected. Set up all initial
+ * values in the option_descriptors in the context record for the given
+ * task. Some fields in the option_descriptor may be dependent on a
+ * selected object. Leave such fields blank for now, and fill in during the
+ * set_objects call.
+ */
+static int fat_init_task(task_context_t * context) {
+
+ int rc = 0;
+ option_descriptor_t * opt;
+
+ LOG_ENTRY();
+
+ /* Parameter check */
+ if (!context) {
+ LOG_EXIT_INT(EFAULT);
+ return EFAULT;
+ }
+
+ switch (context->action) {
+
+ case EVMS_Task_mkfs:
+ rc = init_mkfs_acceptable_objects(context);
+ if (rc) {
+ LOG_EXIT_INT(rc);
+ return rc;
+ }
+ context->option_descriptors->count = MKFS_OPTIONS_COUNT;
+
+ /* Volume label option */
+ opt = &context->option_descriptors->option[MKFS_LABEL_INDEX];
+ opt->name = EngFncs->engine_strdup(MKFS_LABEL_NAME);
+ opt->title = EngFncs->engine_strdup(_("Volume label"));
+ opt->tip = EngFncs->engine_strdup(_("Set the label for the volume."));
+ opt->help = NULL;
+ opt->type = EVMS_Type_String;
+ opt->unit = EVMS_Unit_None;
+ opt->min_len = 1;
+ opt->max_len = MAX_LABEL_LEN;
+ opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+ opt->constraint_type = EVMS_Collection_None;
+ opt->value.s = EngFncs->engine_alloc(MAX_LABEL_LEN + 1);
+
+ context->min_selected_objects = 0;
+ context->max_selected_objects = 0;
+ break;
+
+ default:
+ rc = EINVAL;
+ break;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+
+}
+
+
+/*
+ * Examine the specified value, and determine if it is valid for the task
+ * and option_descriptor index. If it is acceptable, set that value in the
+ * appropriate entry in the option_descriptor. The value may be adjusted
+ * if necessary/allowed. If so, set the effect return value accordingly.
+ */
+static int fat_set_option(task_context_t * context,
+ u_int32_t index,
+ value_t * value,
+ task_effect_t * effect) {
+ int rc= 0;
+
+ LOG_ENTRY();
+
+ /* Parameter check */
+ if (!context || !value || !effect) {
+ LOG_EXIT_INT(EFAULT);
+ return EFAULT;
+ }
+
+ switch (context->action) {
+
+ case EVMS_Task_mkfs:
+ switch (index) {
+ case MKFS_LABEL_INDEX:
+ strncpy(context->option_descriptors->option[index].value.s, value->s, MAX_LABEL_LEN);
+ if (strlen(value->s) > MAX_LABEL_LEN) {
+ MESSAGE(_("Volume label is truncated to \"%s\".\n"),
+ context->option_descriptors->option[index].value.s);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ LOG_ERROR("I don't know how to set an option for action code %d (%#x).\n",
+ context->action, context->action);
+ rc = EINVAL;
+ break;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Validate the volumes in the selected_objects list in the task context.
+ * Remove from the selected objects lists any volumes which are not
+ * acceptable. For unacceptable volumes, create a declined_handle_t
+ * structure with the reason why it is not acceptable, and add it to the
+ * declined_volumes list. Modify the acceptable_objects list in the task
+ * context as necessary based on the selected objects and the current
+ * settings of the options. Modify any option settings as necessary based
+ * on the selected objects. Return the appropriate task_effect_t settings
+ * if the object list(s), minimum or maximum objects selected, or option
+ * settings have changed.
+ */
+static int fat_set_volumes(task_context_t * context,
+ list_anchor_t declined_volumes, /* of type declined_handle_t */
+ task_effect_t * effect) {
+ int rc;
+ list_element_t iter1;
+ list_element_t iter2;
+ logical_volume_t * vol;
+
+ LOG_ENTRY();
+
+ switch (context->action) {
+ case EVMS_Task_mkfs:
+
+ /* get the selected volume */
+ LIST_FOR_EACH_SAFE(context->selected_objects, iter1, iter2, vol){
+ if (EngFncs->is_mounted(vol->dev_node, NULL)) {
+ /* If mounted, can't mkdosfs. */
+ LOG_ERROR("Volume %s is mounted on %s.\n",
+ vol->name, vol->mount_point);
+ rc = EBUSY;
+ } else {
+ if (vol->vol_size < MIN_FAT_SIZE) {
+ LOG_ERROR("Volume %s is too small. "
+ "FAT volumes must be at least 1MB in size.\n",
+ vol->name);
+ rc = EINVAL;
+
+ } else {
+ /* This one looks fine. */
+ rc = 0;
+ }
+ }
+
+ if (rc != 0) {
+ declined_object_t * dec_vol;
+
+ EngFncs->delete_element(iter1);
+
+ dec_vol = EngFncs->engine_alloc(sizeof(declined_object_t));
+ if (dec_vol != NULL) {
+ dec_vol->object = vol;
+ dec_vol->reason = rc;
+
+ EngFncs->insert_thing(declined_volumes,
+ dec_vol,
+ INSERT_AFTER,
+ NULL);
+ } else {
+ LOG_CRITICAL("Unable to get memory for a declined_object_t.\n");
+
+ /*
+ * Put any already declined objects
+ * back on the selected_objects list.
+ */
+
+ /*
+ * Yeah, I know I'm using the iterators
+ * from the loop we're in. We're bailing
+ * out here, so it doesn't matter.
+ */
+ LIST_FOR_EACH_SAFE(declined_volumes, iter1, iter2, dec_vol) {
+ EngFncs->delete_element(iter1);
+ EngFncs->insert_thing(context->selected_objects,
+ dec_vol->object,
+ INSERT_AFTER,NULL);
+ EngFncs->engine_free(dec_vol);
+ }
+
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+ }
+ }
+ break;
+
+ default:
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+
+/*
+ * Return any additional information that you wish to provide about the
+ * volume. The Engine provides an external API to get the information
+ * stored in the logical_volume_t. This call is to get any other
+ * information about the volume that is not specified in the
+ * logical_volume_t. Any piece of information you wish to provide must be
+ * in an extended_info_t structure. Use the Engine's engine_alloc() to
+ * allocate the memory for the extended_info_t. Also use engine_alloc() to
+ * allocate any strings that may go into the extended_info_t. Then use
+ * engine_alloc() to allocate an extended_info_array_t with enough entries
+ * for the number of extended_info_t structures you are returning. Fill
+ * in the array and return it in *info.
+ * If you have extended_info_t descriptors that themselves may have more
+ * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+ * in the extended_info_t flags field. If the caller wants more information
+ * about a particular extended_info_t item, this API will be called with a
+ * pointer to the storage_object_t and with a pointer to the name of the
+ * extended_info_t item. In that case, return an extended_info_array_t with
+ * further information about the item. Each of those items may have the
+ * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire. It is your
+ * responsibility to give the items unique names so that you know which item
+ * the caller is asking additional information for. If info_name is NULL,
+ * the caller just wants top level information about the object.
+ */
+static int fat_get_volume_info(logical_volume_t * volume,
+ char * info_name,
+ extended_info_array_t * * info) {
+ int rc = 0;
+ private_data_t * pd = volume->private_data;
+ extended_info_array_t * Info;
+ int i;
+
+ LOG_ENTRY();
+
+ if (pd == NULL) {
+ LOG_SERIOUS("Oops! Volume %s does not have private data.\n", volume->name);
+ LOG_EXIT_INT(ENOENT);
+ return ENOENT;
+ }
+
+ if (info_name != NULL) {
+ LOG_ERROR("Volume %s has no extra information named \"%s\".\n",
+ volume->name, info_name);
+ rc = EINVAL;
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + (3 * sizeof(extended_info_t)));
+
+ if (Info == NULL) {
+ LOG_CRITICAL("Unable to allocate memory for the extended_info_array_t buffer.\n");
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ i = 0;
+
+ if (pd->vol_name != NULL) {
+ Info->info[i].name = EngFncs->engine_strdup("FAT Volume Name");
+ Info->info[i].title = EngFncs->engine_strdup(_("FAT Volume Name"));
+ Info->info[i].desc = EngFncs->engine_strdup(_("The FAT name of the volume"));
+ Info->info[i].type = EVMS_Type_String;
+ Info->info[i].unit = EVMS_Unit_None;
+ Info->info[i].value.s = EngFncs->engine_strdup(pd->vol_name);
+ Info->info[i].collection_type = EVMS_Collection_None;
+ i++;
+ }
+
+ if (pd->vol_id != 0) {
+ Info->info[i].name = EngFncs->engine_strdup("FAT Volume ID");
+ Info->info[i].title = EngFncs->engine_strdup(_("FAT Volume ID"));
+ Info->info[i].desc = EngFncs->engine_strdup(_("The FAT ID of the volume"));
+ Info->info[i].type = EVMS_Type_Int32;
+ Info->info[i].unit = EVMS_Unit_None;
+ Info->info[i].format = EVMS_Format_Hex;
+ Info->info[i].value.i32 = pd->vol_id;
+ Info->info[i].collection_type = EVMS_Collection_None;
+ i++;
+ }
+
+ if (pd->cluster_size != 0) {
+ Info->info[i].name = EngFncs->engine_strdup("Cluster Size");
+ Info->info[i].title = EngFncs->engine_strdup(_("Cluster Size"));
+ Info->info[i].desc = EngFncs->engine_strdup(_("Size of a cluster."));
+ Info->info[i].type = EVMS_Type_Unsigned_Int32;
+ Info->info[i].unit = EVMS_Unit_None;
+ Info->info[i].value.ui32 = pd->cluster_size;
+ Info->info[i].collection_type = EVMS_Collection_None;
+ i++;
+ }
+
+ Info->count = i;
+ *info = Info;
+
+ rc = 0;
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ * Return Plug-in specific information.
+ */
+static int _fat_get_plugin_info(int isfat16,
+ char * descriptor_name,
+ extended_info_array_t * * info) {
+
+ int rc = EINVAL;
+ extended_info_array_t * Info;
+ char version_string[64];
+ char required_engine_api_version_string[64];
+ char required_fsim_api_version_string[64];
+
+ LOG_ENTRY();
+
+ if (info) {
+
+ if (descriptor_name == NULL) {
+ *info = NULL; // init to no info returned
+
+ Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + (6 * sizeof(extended_info_t)));
+ if (Info) {
+
+ Info->count = 6;
+
+ sprintf(version_string, "%d.%d.%d",
+ MAJOR_VERSION,
+ MINOR_VERSION,
+ PATCH_LEVEL);
+
+ sprintf(required_engine_api_version_string, "%d.%d.%d",
+ my_plugin_record->required_engine_api_version.major,
+ my_plugin_record->required_engine_api_version.minor,
+ my_plugin_record->required_engine_api_version.patchlevel);
+
+ sprintf(required_fsim_api_version_string, "%d.%d.%d",
+ my_plugin_record->required_plugin_api_version.fsim.major,
+ my_plugin_record->required_plugin_api_version.fsim.minor,
+ my_plugin_record->required_plugin_api_version.fsim.patchlevel);
+
+ Info->info[0].name = EngFncs->engine_strdup("Short Name");
+ Info->info[0].title = EngFncs->engine_strdup(_("Short Name"));
+ Info->info[0].desc = EngFncs->engine_strdup(_("A short name given to this plug-in"));
+ Info->info[0].type = EVMS_Type_String;
+ Info->info[0].unit = EVMS_Unit_None;
+ Info->info[0].value.s = EngFncs->engine_strdup(my_plugin_record->short_name);
+ Info->info[0].collection_type = EVMS_Collection_None;
+ memset(&Info->info[0].group, 0, sizeof(group_info_t));
+
+ Info->info[1].name = EngFncs->engine_strdup("Long Name");
+ Info->info[1].title = EngFncs->engine_strdup(_("Long Name"));
+ Info->info[1].desc = EngFncs->engine_strdup(_("A longer, more descriptive name for this plug-in"));
+ Info->info[1].type = EVMS_Type_String;
+ Info->info[1].unit = EVMS_Unit_None;
+ Info->info[1].value.s = EngFncs->engine_strdup(my_plugin_record->long_name);
+ Info->info[1].collection_type = EVMS_Collection_None;
+ memset(&Info->info[1].group, 0, sizeof(group_info_t));
+
+ Info->info[2].name = EngFncs->engine_strdup("Type");
+ Info->info[2].title = EngFncs->engine_strdup(_("Plug-in Type"));
+ Info->info[2].desc = EngFncs->engine_strdup(_("There are various types of plug-ins, each responsible for some kind of storage object or logical volume."));
+ Info->info[2].type = EVMS_Type_String;
+ Info->info[2].unit = EVMS_Unit_None;
+ Info->info[2].value.s = EngFncs->engine_strdup(_("File System Interface Module"));
+ Info->info[2].collection_type = EVMS_Collection_None;
+ memset(&Info->info[2].group, 0, sizeof(group_info_t));
+
+ Info->info[3].name = EngFncs->engine_strdup("Version");
+ Info->info[3].title = EngFncs->engine_strdup(_("Plug-in Version"));
+ Info->info[3].desc = EngFncs->engine_strdup(_("This is the version number of the plug-in."));
+ Info->info[3].type = EVMS_Type_String;
+ Info->info[3].unit = EVMS_Unit_None;
+ Info->info[3].value.s = EngFncs->engine_strdup(version_string);
+ Info->info[3].collection_type = EVMS_Collection_None;
+ memset(&Info->info[3].group, 0, sizeof(group_info_t));
+
+ Info->info[4].name = EngFncs->engine_strdup("Required Engine Services Version");
+ Info->info[4].title = EngFncs->engine_strdup(_("Required Engine Services Version"));
+ Info->info[4].desc = EngFncs->engine_strdup(_("This is the version of the Engine services that this plug-in requires. "
+ "It will not run on older versions of the Engine services."));
+ Info->info[4].type = EVMS_Type_String;
+ Info->info[4].unit = EVMS_Unit_None;
+ Info->info[4].value.s = EngFncs->engine_strdup(required_engine_api_version_string);
+ Info->info[4].collection_type = EVMS_Collection_None;
+ memset(&Info->info[4].group, 0, sizeof(group_info_t));
+
+ Info->info[5].name = EngFncs->engine_strdup("Required Engine FSIM API Version");
+ Info->info[5].title = EngFncs->engine_strdup(_("Required Engine FSIM API Version"));
+ Info->info[5].desc = EngFncs->engine_strdup(_("This is the version of the Engine FSIM API that this plug-in requires. "
+ "It will not run on older versions of the Engine FSIM API."));
+ Info->info[5].type = EVMS_Type_String;
+ Info->info[5].unit = EVMS_Unit_None;
+ Info->info[5].value.s = EngFncs->engine_strdup(required_fsim_api_version_string);
+ Info->info[5].collection_type = EVMS_Collection_None;
+ memset(&Info->info[5].group, 0, sizeof(group_info_t));
+
+ *info = Info;
+
+ rc = 0;
+ } else {
+ rc = ENOMEM;
+ }
+
+ } else {
+ /* There is no more information on any of the descriptors. */
+ rc = EINVAL;
+ }
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+static inline int fat_get_plugin_info(char * descriptor_name, extended_info_array_t * * info) {
+ my_plugin_record = &fat_plugrec;
+ return _fat_get_plugin_info(0, descriptor_name, info);
+}
+
+static inline int fat16_get_plugin_info(char * descriptor_name, extended_info_array_t * * info) {
+ my_plugin_record = &fat16_plugrec;
+ return _fat_get_plugin_info(1, descriptor_name, info);
+}
+
+/*
+ * Return an array of plug-in functions that you support for this volume.
+ */
+static int _fat_get_plugin_functions(int isfat16,
+ logical_volume_t * volume,
+ function_info_array_t * * actions) {
+
+ private_data_t * pd;
+ function_info_array_t * fia;
+ int i;
+
+ LOG_ENTRY();
+
+ /* "volume" is NULL when the Engine is asking for functions that
+ * apply to the plug-in rather than to a particular volume.
+ */
+ if (volume == NULL) {
+ LOG_DEBUG("There are no functions targeted at this plug-in.\n");
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ if (volume->file_system_manager != my_plugin_record) {
+ /* It's not my volume. */
+ LOG_DEBUG("Volume %s does not have FAT16/FAT32 on it.\n", volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ if (!(volume->flags & (VOLFLAG_ACTIVE | VOLFLAG_NEEDS_ACTIVATE))) {
+ LOG_DEBUG("Volume %s is not active.\n",
+ volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ if (volume->flags & VOLFLAG_NEEDS_DEACTIVATE) {
+ LOG_DEBUG("Volume %s will be deactivated.\n", volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ if (volume->flags & (VOLFLAG_NEW | VOLFLAG_MKFS)) {
+ /* mkdosfs has yet to be run on this volume. */
+ LOG_DEBUG("Volume %s does not yet have FAT16/FAT32 on it. mkfs is scheduled to be run.\n",
+ volume->name);
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ pd = (private_data_t *) volume->private_data;
+
+ fia = EngFncs->engine_alloc(sizeof(function_info_array_t) + sizeof(function_info_t));
+ if (fia == NULL) {
+ LOG_CRITICAL("Unable to get memory for a function_info_array_t.\n");
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ i = 0;
+
+ fia->count = i;
+ *actions = fia;
+
+ LOG_EXIT_INT(0);
+ return 0;
+}
+
+int fat_get_plugin_functions(logical_volume_t * volume,
+ function_info_array_t * * actions) {
+ my_plugin_record = &fat_plugrec;
+ return _fat_get_plugin_functions(0, volume, actions);
+}
+
+static int fat16_get_plugin_functions(logical_volume_t * volume,
+ function_info_array_t * * actions) {
+ my_plugin_record = &fat16_plugrec;
+ return _fat_get_plugin_functions(1, volume, actions);
+}
+
+/*
+ * Execute the plug-in function on the volume.
+ */
+static int fat_plugin_function(logical_volume_t * volume,
+ task_action_t action,
+ list_anchor_t objects,
+ option_array_t * options) {
+
+ int rc = 0;
+
+ LOG_ENTRY();
+
+ if (volume == NULL) {
+ LOG_ERROR("No volume specified.\n");
+ LOG_EXIT_INT(EINVAL);
+ return EINVAL;
+ }
+
+ switch (action) {
+ default:
+ LOG_ERROR("Plug-in function %d (%#x) is not supported.\n",
+ action, action);
+ rc = EINVAL;
+ break;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/*-------------------------------------------------------------------------------------+
++ +
++ PLUG-IN FUNCTION TABLE +
++ +
++--------------------------------------------------------------------------------------*/
+static fsim_functions_t fsim_ops = {
+
+ setup_evms_plugin: fat_setup,
+ cleanup_evms_plugin: fat_cleanup,
+ probe: fat_probe,
+ get_fs_size: fat_get_fs_size,
+ get_fs_limits: fat_get_fs_limits,
+ mkfs_setup: fat_mkfs_setup,
+ mkfs: fat_mkfs,
+ can_mkfs: fat_can_mkfs,
+ can_unmkfs: fat_can_unmkfs,
+ can_fsck: fat_can_fsck,
+ can_expand_by: fat_can_expand_by,
+ can_shrink_by: fat_can_shrink_by,
+ discard: fat_discard,
+ unmkfs_setup: fat_unmkfs_setup,
+ unmkfs: fat_unmkfs,
+ expand: fat_expand,
+ shrink: fat_shrink,
+ commit_changes: fat_commit_changes,
+ get_option_count: fat_get_option_count,
+ init_task: fat_init_task,
+ set_option: fat_set_option,
+ set_volumes: fat_set_volumes,
+ get_volume_info: fat_get_volume_info,
+ get_plugin_info: fat_get_plugin_info,
+ get_plugin_functions: fat_get_plugin_functions,
+ plugin_function: fat_plugin_function
+};
+
+static fsim_functions_t fsim16_ops = {
+
+ setup_evms_plugin: fat_setup,
+ cleanup_evms_plugin: fat16_cleanup,
+ probe: fat16_probe,
+ get_fs_size: fat_get_fs_size,
+ get_fs_limits: fat_get_fs_limits,
+ mkfs_setup: fat_mkfs_setup,
+ mkfs: fat16_mkfs,
+ can_mkfs: fat_can_mkfs,
+ can_unmkfs: fat16_can_unmkfs,
+ can_fsck: fat_can_fsck,
+ can_expand_by: fat_can_expand_by,
+ can_shrink_by: fat_can_shrink_by,
+ discard: fat_discard,
+ unmkfs_setup: fat_unmkfs_setup,
+ unmkfs: fat_unmkfs,
+ expand: fat16_expand,
+ shrink: fat16_shrink,
+ commit_changes: fat_commit_changes,
+ get_option_count: fat_get_option_count,
+ init_task: fat_init_task,
+ set_option: fat_set_option,
+ set_volumes: fat_set_volumes,
+ get_volume_info: fat_get_volume_info,
+ get_plugin_info: fat16_get_plugin_info,
+ get_plugin_functions: fat16_get_plugin_functions,
+ plugin_function: fat_plugin_function
+};
+
+
+/*-------------------------------------------------------------------------------------+
++ +
++ PLUG-IN RECORD +
++ +
++-------------------------------------------------------------------------------------*/
+
+static plugin_record_t fat_plugrec = {
+ id: SetPluginID(795, EVMS_FILESYSTEM_INTERFACE_MODULE, FS_TYPE_FAT),
+ version: {MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL},
+ required_engine_api_version: {15, 0, 0},
+ required_plugin_api_version: {fsim: {11, 0, 0}},
+ short_name: "FAT32",
+ long_name: "FAT32 File System Interface Module",
+ oem_name: "ALT Linux",
+ functions: {fsim: &fsim_ops},
+ container_functions: NULL
+
+};
+
+static plugin_record_t fat16_plugrec = {
+ id: SetPluginID(795, EVMS_FILESYSTEM_INTERFACE_MODULE, FS_TYPE_FAT16),
+ version: {MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL},
+ required_engine_api_version: {15, 0, 0},
+ required_plugin_api_version: {fsim: {11, 0, 0}},
+ short_name: "FAT16",
+ long_name: "FAT16 File System Interface Module",
+ oem_name: "ALT Linux",
+ functions: {fsim: &fsim16_ops},
+ container_functions: NULL
+
+};
+
+// Vector of plug-in record pointers that we export for the EVMS Engine.
+plugin_record_t *evms_plugin_records[] = {
+ &fat_plugrec,
+ &fat16_plugrec,
+ NULL
+};
+
diff -Naur evms-2.5.2/plugins/fat.orig/fatfsim.h evms-2.5.2/plugins/fat/fatfsim.h
--- evms-2.5.2/plugins/fat.orig/fatfsim.h 1970-01-01 03:00:00 +0300
+++ evms-2.5.2/plugins/fat/fatfsim.h 2005-09-12 17:14:34 +0400
@@ -0,0 +1,47 @@
+/*
+ *
+ * (C) Copyright ALT Linux Ltd. 2005
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: fatfsim.h
+ */
+
+extern plugin_record_t * my_plugin_record;
+extern engine_functions_t * EngFncs;
+extern boolean have_fatresize;
+
+#define FS_TYPE_FAT 19
+#define FS_TYPE_FAT16 20
+
+typedef struct private_data_s {
+ sector_count_t fs_size;
+ sector_count_t max_fs_size;
+ sector_count_t max_vol_size;
+ u_int32_t cluster_size;
+ u_int16_t logical_sector_size;
+ char * vol_name;
+ u_int32_t vol_id;
+ logical_volume_t * clone_source;
+ logical_volume_t * clone_target;
+ u_int32_t flags;
+} private_data_t;
+
+/* mkntfs option array indices */
+#define MKFS_LABEL_INDEX 0
+#define MKFS_LABEL_NAME "label"
+#define MKFS_OPTIONS_COUNT 1
+
+#define MAX_LABEL_LEN 11
diff -Naur evms-2.5.2/plugins/fat.orig/Makefile.in evms-2.5.2/plugins/fat/Makefile.in
--- evms-2.5.2/plugins/fat.orig/Makefile.in 1970-01-01 03:00:00 +0300
+++ evms-2.5.2/plugins/fat/Makefile.in 2005-09-12 17:14:34 +0400
@@ -0,0 +1,50 @@
+# Enterprise Volume Management System
+#
+# (C) Copyright ALT Linux Ltd. 2005
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+include @top_srcdir@/make.rules
+
+NAME = fat
+TARGET = $(PLUGIN_TARGET)
+
+MAJOR_VERSION = 1
+MINOR_VERSION = 1
+PATCH_LEVEL = 12
+
+all: $(TARGET)
+
+$(TARGET): .depend .export $(OBJECTS)
+ $(BUILD_PLUGIN)
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(evmspluginsdir)
+ $(INSTALL) -m 755 $(TARGET) $(DESTDIR)$(evmspluginsdir)
+
+uninstall:
+ rm -f $(DESTDIR)$(evmspluginsdir)/$(TARGET)
+
+clean:
+ rm -f .depend .export $(OBJECTS) $(TARGET)
+
+distclean: clean
+ rm -f Makefile
+
+ifeq (.depend, $(wildcard .depend))
+include .depend
+endif
diff -Naur evms-2.5.2/plugins/fat.orig/utils.c evms-2.5.2/plugins/fat/utils.c
--- evms-2.5.2/plugins/fat.orig/utils.c 1970-01-01 03:00:00 +0300
+++ evms-2.5.2/plugins/fat/utils.c 2005-09-12 17:29:32 +0400
@@ -0,0 +1,500 @@
+/*
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: utils.c
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <plugin.h>
+
+#include "utils.h"
+#include "fatfsim.h"
+
+#define LLONG_MAX 0x8fffffffffffffffLL
+#define FAT_BLOCK_SIZE 512
+
+/*
+ * FIXME: correct values
+ */
+#define MAXVOL_FAT16 1024*1024*4
+#define MAXVOL_FAT32 INT32_MAX
+
+/*
+ * is_boot_sector_fat() checks whether the buffer at boot_sector is a valid
+ * FAT boot sector. Returns TRUE if it is valid and FALSE if not.
+ */
+static boolean is_boot_sector_fat(const fat_boot * boot) {
+
+ LOG_ENTRY();
+
+ if (!strncmp(boot->b.system_id, "MSDOS", 5) ||
+ !strncmp(boot->b.system_id, "MSWIN", 5) ||
+ !strncmp(boot->b.system_id, "MTOOL", 5) ||
+ !strncmp(boot->b.system_id, "mkdosfs", 7) ||
+ !strncmp(boot->b.system_id, "kmkdosfs", 8) ||
+ /* Michal Svec: created by fdformat, old msdos utility for
+ * formatting large (1.7) floppy disks.
+ */
+ !strncmp(boot->b.system_id, "CH-FOR18", 8)
+ || !strncmp(boot->b.fat.vi.fs, "FAT12 ", 8) ||
+ !strncmp(boot->b.fat.vi.fs, "FAT16 ", 8) ||
+ !strncmp(boot->b.fat32.vi.fs, "FAT32 ", 8)) {
+
+ LOG_EXIT_BOOL(TRUE);
+ return TRUE;
+ }
+
+ LOG_EXIT_BOOL(FALSE);
+ return FALSE;
+}
+
+int fill_private_data(int isfat16,
+ logical_volume_t * vol,
+ const fat_boot * boot) {
+
+ int rc = 0;
+ private_data_t * pd = (private_data_t *) vol->private_data;
+ u_int16_t sectors;
+
+ LOG_ENTRY();
+
+ pd->logical_sector_size = DISK_TO_CPU16(boot->b.sector_size);
+ if (!pd->logical_sector_size) {
+ LOG_DETAILS("Logical sector size is zero.");
+ //LOG_EXIT_BOOL(FALSE);
+ //return FALSE;
+ }
+ pd->cluster_size = boot->b.cluster_size*pd->logical_sector_size;
+ if (!pd->cluster_size) {
+ LOG_DETAILS("Cluster size is zero.");
+ //LOG_EXIT_BOOL(FALSE);
+ //return FALSE;
+ }
+ if (boot->b.fats != 2 && boot->b.fats != 1) {
+ LOG_DETAILS("Currently, only 1 or 2 FATs are supported, not %d.\n", boot->b.fats);
+ //LOG_EXIT_BOOL(FALSE);
+ //return FALSE;
+ }
+ sectors = DISK_TO_CPU16(boot->b.sectors);
+ pd->fs_size = sectors ? sectors : DISK_TO_CPU32(boot->b.total_sect);
+
+ /*
+ * FIXME: make correct MAX VOLUME size
+ */
+ pd->max_vol_size = isfat16 ? MAXVOL_FAT16 : MAXVOL_FAT32;
+ pd->max_fs_size = pd->fs_size;
+
+ pd->vol_id = isfat16 ? DISK_TO_CPU32(boot->b.fat.vi.volume_id)
+ : DISK_TO_CPU32(boot->b.fat32.vi.volume_id);
+
+ pd->vol_name = isfat16 ? EngFncs->engine_strdup(boot->b.fat.vi.volume_label)
+ : EngFncs->engine_strdup(boot->b.fat32.vi.volume_label);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+/*
+ * Read the boot sector from the volume and validate it.
+ */
+int get_fat_boot(int isfat16, logical_volume_t * ev, fat_boot *boot)
+{
+ int rc = 0;
+ int fd;
+
+ if (boot == NULL) {
+ LOG_CRITICAL("Failed to allocate memory for a boot info.\n");
+
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ fd = EngFncs->open_volume(ev, O_RDONLY);
+ if (fd < 0) {
+ LOG_SERIOUS("Failed to open volume %s. Error code is %d: %s\n",
+ ev->name, -fd, EngFncs->strerror(-fd));
+ LOG_EXIT_INT(-fd);
+ return -fd;
+ }
+
+ /* Try to read primary boot sector. */
+ if (EngFncs->read_volume(ev, fd, &boot->b, FAT_BLOCK_SIZE, 0) == FAT_BLOCK_SIZE) {
+ if (is_boot_sector_fat(boot)) {
+ if (isfat16 || (!boot->b.fat_length && boot->b.fat32.length)) {
+ goto finished;
+ }
+ } else {
+ LOG_DETAILS("Primary boot sector is not valid.");
+ }
+ } else
+ LOG_WARNING("Unable to read primary boot sector.");
+
+ rc = EINVAL;
+finished:
+ EngFncs->close_volume(ev, fd);
+ // FIXME: trim space chars
+ if (isfat16) {
+ boot->b.fat.vi.volume_label[11] = '\0';
+ } else {
+ boot->b.fat32.vi.volume_label[11] = '\0';
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+int clear_fat_boot_sectors(logical_volume_t * ev)
+{
+ int rc = 0;
+ int fd;
+ void * block;
+ int32_t bytes_written;
+
+ LOG_ENTRY();
+
+ block = EngFncs->engine_alloc(FAT_BLOCK_SIZE);
+ if (block == NULL) {
+ LOG_CRITICAL("Can't get a buffer for writing.\n");
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ fd = EngFncs->open_volume(ev, O_WRONLY);
+ if (fd < 0) {
+ LOG_SERIOUS("Failed to open volume %s. Error code is %d: %s\n",
+ ev->name, -fd, EngFncs->strerror(-fd));
+ EngFncs->engine_free(block);
+ LOG_EXIT_INT(-fd);
+ return -fd;
+ }
+
+ /* Wipe out the primary boot sector. */
+ bytes_written = EngFncs->write_volume(ev, fd, block, FAT_BLOCK_SIZE, 0);
+ if (bytes_written != FAT_BLOCK_SIZE) {
+ LOG_WARNING("Failed to clear the primary boot sector on volume %s. "
+ "Only %d bytes were written.\n",
+ ev->name, bytes_written);
+ rc = -bytes_written;
+ }
+
+ EngFncs->close_volume(ev, fd);
+
+ EngFncs->engine_free(block);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+int try_run(char * prog_name) {
+
+ int rc = 0;
+ char * argv[3];
+ pid_t pidm;
+ int status;
+ int fds[2];
+
+ /* Open a pipe to catch the program output that we don't care about. */
+ rc = pipe(fds);
+ if (rc) {
+ LOG_SERIOUS("Could not opening a pipe. Error code is %d: %s\n",
+ errno, strerror(errno));
+
+ LOG_EXIT_INT(errno);
+ return(errno);
+ }
+
+ argv[0] = prog_name;
+ argv[1] = NULL;
+
+ pidm = EngFncs->fork_and_execvp(NULL, argv, NULL, NULL, NULL);
+
+ if (pidm != -1) {
+
+ waitpid(pidm, &status, 0);
+
+ if (WIFEXITED(status)) {
+
+ LOG_DEFAULT("%s completed with exit code %d.\n",
+ prog_name, WEXITSTATUS(status));
+
+ } else {
+ LOG_WARNING("%s did not exit normally.\n", prog_name);
+ rc = EINTR;
+ }
+
+ } else {
+ rc = errno;
+ LOG_DEFAULT("Unable to run %s. Error code is %d: %s\n",
+ prog_name, rc, EngFncs->strerror(rc));
+ }
+
+ close(fds[0]);
+ close(fds[1]);
+
+ LOG_EXIT_INT(rc);
+ return(rc);
+}
+
+
+int get_fs_limits(logical_volume_t * vol, sector_count_t * min_fs_size,
+ sector_count_t * max_fs_size,
+ sector_count_t * max_vol_size) {
+
+ int rc = 0;
+ char * argv[5];
+ pid_t pidm;
+ int status;
+ int fds[2];
+ char * buffer = NULL;
+ char * p = NULL;
+ u_int64_t min_fs_size_bytes = 0;
+ u_int64_t max_fs_size_bytes = 0;
+
+ LOG_ENTRY();
+
+ if (!have_fatresize) {
+ LOG_DETAILS("The fatresize utility is not installed.\n");
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ *min_fs_size = vol->fs_size;
+ *max_fs_size = vol->fs_size;
+ *max_vol_size = vol->fs_size;
+
+ buffer = EngFncs->engine_alloc(MAX_USER_MESSAGE_LEN);
+ if (buffer == NULL) {
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ status = pipe(fds);
+ if (status < 0) {
+ EngFncs->engine_free(buffer);
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ /* Run fatresize -i to get the smallest volume size. */
+ argv[0] = "fatresize";
+ argv[1] = "-i";
+ argv[2] = vol->dev_node;
+ argv[3] = NULL;
+
+ fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL, 0) | O_NONBLOCK);
+ fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL, 0) | O_NONBLOCK);
+
+ pidm = EngFncs->fork_and_execvp(vol, argv, NULL, fds, fds);
+ if (pidm != -1) {
+
+ waitpid( pidm, &status, 0);
+
+ if (WIFEXITED(status)) {
+ read(fds[0], buffer, MAX_USER_MESSAGE_LEN);
+
+ rc = WEXITSTATUS(status);
+ LOG_DETAILS("%s completed with exit code %d \n", argv[0], rc);
+ } else {
+ /*
+ * The process didn't exit. It must have been
+ * interrupted by a signal.
+ */
+ rc = EINTR;
+ }
+
+ } else {
+ LOG_SERIOUS("Failed to fork and exec %s. Error code is %d: %s\n",
+ argv[0], rc, EngFncs->strerror(rc));
+ rc = errno;
+ }
+
+ if (rc == 0) {
+
+ if ((p = strstr(buffer, "Min size:"))) {
+ p += 10;
+ min_fs_size_bytes = atoll(p);
+ }
+
+ if ((p = strstr(buffer, "Max size:"))) {
+ p += 10;
+ max_fs_size_bytes = atoll(p);
+ }
+
+ if (min_fs_size_bytes != 0) {
+ /* fatresize reports the size in bytes. */
+ *min_fs_size = min_fs_size_bytes >> EVMS_VSECTOR_SIZE_SHIFT;
+ }
+
+ if (max_fs_size_bytes != 0) {
+ /* fatresize reports the size in bytes. */
+ *max_fs_size = max_fs_size_bytes >> EVMS_VSECTOR_SIZE_SHIFT;
+ *max_vol_size = *max_fs_size;
+ }
+ }
+
+ EngFncs->engine_free(buffer);
+
+ close(fds[0]);
+ close(fds[1]);
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
+
+
+/*
+ if (pd->ntfs_cluster_size == EVMS_VSECTOR_SIZE) {
+ pd->fs_size = pd->ntfs_nr_clusters;
+ pd->max_fs_size = LLONG_MAX;
+
+ } else if (pd->ntfs_cluster_size > EVMS_VSECTOR_SIZE) {
+ pd->fs_size = pd->ntfs_nr_clusters * (pd->ntfs_cluster_size / EVMS_VSECTOR_SIZE);
+ pd->max_fs_size = LLONG_MAX * (pd->ntfs_cluster_size / EVMS_VSECTOR_SIZE);
+
+ } else {
+ pd->fs_size = pd->ntfs_nr_clusters / (EVMS_VSECTOR_SIZE - pd->ntfs_cluster_size);
+ pd->max_fs_size = LLONG_MAX / (EVMS_VSECTOR_SIZE - pd->ntfs_cluster_size);
+ }
+
+*/
+
+void free_private_data(logical_volume_t * vol) {
+
+ LOG_ENTRY();
+
+ if (vol->private_data != NULL) {
+ private_data_t * pd = (private_data_t *) vol->private_data;
+
+ if (pd->vol_name != NULL) {
+ EngFncs->engine_free(pd->vol_name);
+ }
+
+ EngFncs->engine_free(vol->private_data);
+ vol->private_data = NULL;
+ }
+
+ LOG_EXIT_VOID();
+}
+
+int resize_fat(int isfat16, logical_volume_t * volume, sector_count_t * new_size) {
+
+ int rc = 0;
+ char * argv[6];
+ char ascii_new_size[16];
+ pid_t pidm;
+ int status;
+ int fds[2];
+ char * buffer = NULL;
+ fat_boot *boot = NULL;
+ private_data_t * pd = volume->private_data;
+
+ LOG_ENTRY();
+
+ if (!have_fatresize) {
+ MESSAGE("The fatresize utility is not installed on this machine. "
+ "The FAT16/FAT32 FSIM uses fatresize to expand the FAT16/FAT32 file system on the volume. "
+ "Get the latest version of the FAT utilities from http://sourceforge.net/projects/fatresize/\n");
+ LOG_EXIT_INT(ENOSYS);
+ return ENOSYS;
+ }
+
+ buffer = EngFncs->engine_alloc(MAX_USER_MESSAGE_LEN);
+ if (buffer == NULL) {
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ status = pipe(fds);
+ if (status < 0) {
+ EngFncs->engine_free(buffer);
+ LOG_EXIT_INT(errno);
+ return errno;
+ }
+
+ argv[0] = "fatresize";
+ argv[1] = "-vvv";
+ argv[2] = "-s";
+
+ /* Get the ASCII version of the new size in KB. */
+ sprintf(ascii_new_size, "%"PRIu64, (*new_size) >> 1);
+ strcat(ascii_new_size, "k");
+ argv[3] = ascii_new_size;
+
+ argv[4] = volume->dev_node;
+ argv[5] = NULL;
+
+ fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL, 0) | O_NONBLOCK);
+ fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL, 0) | O_NONBLOCK);
+
+ pidm = EngFncs->fork_and_execvp(volume, argv, NULL, fds, fds);
+ if (pidm != -1) {
+
+ waitpid(pidm, &status, 0);
+ if (WIFEXITED(status)) {
+ rc = WEXITSTATUS(status);
+ if (rc == 0) {
+ LOG_DETAILS("%s completed with exit code %d \n", argv[0], rc);
+ } else {
+ LOG_WARNING("%s completed with exit code %d \n", argv[0], rc);
+ }
+ } else {
+ /*
+ * The process didn't exit. It must have been
+ * interrupted by a signal.
+ */
+ rc = EINTR;
+ }
+
+ } else {
+ LOG_SERIOUS("Failed to fork and exec %s. Error code is %d: %s\n",
+ argv[0], rc, EngFncs->strerror(rc));
+ rc = errno;
+ }
+
+ close(fds[0]);
+ close(fds[1]);
+
+ EngFncs->engine_free(buffer);
+
+ if (rc == 0) {
+ /* Get the new sizes into the private data. */
+ memset(pd, 0, sizeof(private_data_t));
+
+ boot = EngFncs->engine_alloc(sizeof(fat_boot));
+ if (boot == NULL) {
+ LOG_EXIT_INT(ENOMEM);
+ return ENOMEM;
+ }
+
+ rc = get_fat_boot(isfat16, volume, boot);
+ if (rc == 0) {
+ rc = fill_private_data(isfat16, volume, boot);
+ }
+ /*
+ * FIXME: shall I get new size after resize?
+ */
+ pd->fs_size = *new_size;
+ }
+
+ LOG_EXIT_INT(rc);
+ return rc;
+}
diff -Naur evms-2.5.2/plugins/fat.orig/utils.h evms-2.5.2/plugins/fat/utils.h
--- evms-2.5.2/plugins/fat.orig/utils.h 1970-01-01 03:00:00 +0300
+++ evms-2.5.2/plugins/fat/utils.h 2005-09-12 17:14:34 +0400
@@ -0,0 +1,98 @@
+/*
+ * (C) ALT Linux Ltd. 2005
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: utils.h
+ *
+ */
+
+/*
+ * FAT boot sector structure.
+ */
+struct msdos_volume_info {
+ u_int8_t drive_number; /* BIOS drive number */
+ u_int8_t RESERVED; /* Unused */
+ u_int8_t ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
+ u_int32_t volume_id; /* Volume ID number */
+ u_int8_t volume_label[11];/* Volume label */
+ u_int8_t fs[8]; /* Typically FAT12 or FAT16 */
+} __attribute__ ((packed));
+
+typedef struct {
+ u_int8_t ignored[3]; /* Boot strap short or near jump */
+ u_int8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ u_int16_t sector_size; /* bytes per logical sector */
+ u_int8_t cluster_size; /* sectors/cluster */
+ u_int16_t reserved; /* reserved sectors */
+ u_int8_t fats; /* number of FATs */
+ u_int8_t dir_entries[2]; /* root directory entries */
+ u_int16_t sectors; /* number of sectors */
+ u_int8_t media; /* media code (unused) */
+ u_int16_t fat_length; /* sectors/FAT */
+ u_int16_t secs_track; /* sectors per track */
+ u_int16_t heads; /* number of heads */
+ u_int32_t hidden; /* hidden sectors (unused) */
+ u_int32_t total_sect; /* number of sectors (if sectors == 0) */
+
+ union {
+ struct {
+ struct msdos_volume_info vi;
+ //u_int8_t fs[8]; /* FS name */
+ u_int16_t reserved2[14];
+ } __attribute__ ((packed)) fat;
+ struct {
+ /* The following fields are only used by FAT32 */
+ u_int32_t length; /* sectors/FAT */
+ u_int16_t flags; /* bit 8: fat mirroring, low 4: active fat */
+ u_int8_t version[2]; /* major, minor filesystem version */
+ u_int32_t root_cluster; /* first cluster in root directory */
+ u_int16_t info_sector; /* filesystem info sector */
+ u_int16_t backup_boot; /* backup boot sector */
+ u_int16_t reserved2[6]; /* Unused */
+ struct msdos_volume_info vi;
+ //u_int8_t fs[8]; /* FS name: FAT 32 */
+ } __attribute__ ((packed)) fat32;
+ };
+
+ /* fill up to 512 bytes */
+ u_int8_t junk[422];
+} __attribute__ ((packed)) fat_boot_sector;
+
+typedef struct {
+ fat_boot_sector b;
+} fat_boot;
+
+extern int get_fat_boot(int isfat16, logical_volume_t * ev, fat_boot *boot);
+
+extern int clear_fat_boot_sectors(logical_volume_t * ev);
+
+extern int try_run(char * prog_name);
+
+extern int get_fs_limits(logical_volume_t * vol,
+ sector_count_t * min_fs_size,
+ sector_count_t * max_fs_size,
+ sector_count_t * max_vol_size);
+
+void free_private_data(logical_volume_t * vol);
+
+extern int fill_private_data(int isfat16,
+ logical_volume_t * vol,
+ const fat_boot * boot);
+
+extern int resize_fat(int isfat16,
+ logical_volume_t * volume,
+ sector_count_t * new_size);