Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37403908
en ru br
Репозитории 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
www.altlinux.org/Changes

Группа :: Система/Ядро и оборудование
Пакет: 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);
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin