"Fossies" - the Fresh Open Source Software archive 
Member "evms-2.5.5/plugins/fat/fatfsim.c" of archive evms-2.5.5.tar.gz:
/*
* (C) Copyright IBM Corp. 2006
* (C) Copyright ALT Linux Ltd. 2006
*
* 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: FAT FSIM
* File: evms2/engine/plugins/fat/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: is this the 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(void)
{
list_anchor_t global_volumes = NULL;
list_element_t iter;
logical_volume_t *vol;
LOG_ENTRY();
EngFncs->get_volume_list(my_plugin_record, NULL,
0, &global_volumes);
LIST_FOR_EACH(global_volumes, iter, vol) {
free_private_data(vol);
}
EngFncs->destroy_list(global_volumes);
have_mkdosfs = FALSE;
have_dosfsck = FALSE;
have_fatresize = FALSE;
LOG_EXIT_VOID();
}
static void fat_cleanup(void)
{
my_plugin_record = &fat_plugrec;
_fat_cleanup();
}
static void fat16_cleanup(void)
{
my_plugin_record = &fat16_plugrec;
_fat_cleanup();
}
/*
* 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)
{
fat_boot_sector *boot;
int rc;
LOG_ENTRY();
boot = EngFncs->engine_alloc(sizeof(fat_boot_sector));
if (!boot) {
rc = ENOMEM;
goto out;
}
rc = get_fat_boot(isfat16, volume, boot);
if (rc) {
goto out;
}
volume->private_data = EngFncs->engine_alloc(sizeof(private_data_t));
if (!volume->private_data) {
rc = ENOMEM;
goto out;
}
rc = fill_private_data(isfat16, volume, boot);
out:
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;
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 %u sectors in size.\n",
volume->name, MIN_FAT_SIZE);
LOG_EXIT_INT(ENOSPC);
return ENOSPC;
}
LOG_EXIT_INT(0);
return 0;
}
/*
* Can unmkfs this volume?
*/
static int _fat_can_unmkfs(logical_volume_t *volume)
{
int rc = 0;
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);
rc = EINVAL;
} else if (EngFncs->is_mounted(volume->dev_node, NULL)) {
/* If mounted, can't unmkfs. */
LOG_DEBUG("Volume %s is mounted.\n", volume->name);
rc = EBUSY;
}
LOG_EXIT_INT(rc);
return rc;
}
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();
/* FIXME: Can we fsck if volume is mounted? */
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;
LOG_ENTRY();
if (EngFncs->is_mounted(volume->dev_node, NULL)) {
/* If mounted, can't expand */
rc = EBUSY;
goto errout;
}
/* reset limits */
rc = fat_get_fs_limits(volume, &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)) {
/* If mounted, can't shrink */
rc = EBUSY;
goto errout;
}
/* reset limits */
rc = fat_get_fs_limits(volume, &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" sectors\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) {
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) {
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();
free_private_data(volume);
LOG_EXIT_INT(0);
return 0;
}
/*
* Remove the file system from the volume.
*/
static int fat_unmkfs(logical_volume_t *volume)
{
int rc;
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;
}
/*
* Return the total number of supported options for the specified task.
*/
static int fat_get_option_count(task_context_t *context)
{
int count;
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)
{
list_anchor_t global_volumes = NULL;
list_element_t vol_list_iter;
logical_volume_t *volume;
LOG_ENTRY();
EngFncs->get_volume_list(NULL, NULL, 0, &global_volumes);
LIST_FOR_EACH(global_volumes, vol_list_iter, volume) {
if ((volume->file_system_manager == NULL) &&
(volume->vol_size >= MIN_FAT_SIZE) &&
(!EngFncs->is_mounted(volume->name, NULL))) {
EngFncs->insert_thing(context->acceptable_objects,
volume, INSERT_AFTER, NULL);
}
}
EngFncs->destroy_list(global_volumes);
LOG_EXIT_INT(0);
return 0;
}
/*
* 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();
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->type = EVMS_Type_String;
opt->min_len = 1;
opt->max_len = MAX_LABEL_LEN;
opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
opt->value.s = EngFncs->engine_alloc(MAX_LABEL_LEN + 1);
context->min_selected_objects = 1;
context->max_selected_objects = 1;
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 = 0;
logical_volume_t *vol;
LOG_ENTRY();
switch (context->action) {
case EVMS_Task_mkfs:
/* Only one selected volume allowed, so grab
* the first thing from the list.
*/
vol = EngFncs->first_thing(context->selected_objects, NULL);
if (!vol) {
rc = EINVAL;
break;
}
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;
break;
}
if (vol->vol_size < MIN_FAT_SIZE) {
LOG_ERROR("Volume %s is too small. FAT volumes must "
"be at least %u sectors in size.\n",
vol->name, MIN_FAT_SIZE);
rc = EINVAL;
break;
}
break;
default:
rc = EINVAL;
break;
}
LOG_EXIT_INT(rc);
return rc;
}
/*
* 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)
{
private_data_t *pd = volume->private_data;
extended_info_array_t *Info;
int i;
LOG_ENTRY();
if (info_name != NULL) {
LOG_ERROR("Volume %s has no extra information named \"%s\".\n",
volume->name, info_name);
LOG_EXIT_INT(EINVAL);
return EINVAL;
}
Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) +
3 * sizeof(extended_info_t));
if (!Info) {
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].value.s = EngFncs->engine_strdup(pd->vol_name);
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].format = EVMS_Format_Hex;
Info->info[i].value.i32 = pd->vol_id;
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_Bytes;
Info->info[i].value.ui32 = pd->cluster_size;
i++;
}
Info->count = i;
*info = Info;
LOG_EXIT_INT(0);
return 0;
}
/*
* Return Plug-in specific information.
*/
static int _fat_get_plugin_info(char *descriptor_name,
extended_info_array_t **info)
{
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 || descriptor_name) {
LOG_EXIT_INT(EINVAL);
return EINVAL;
}
/* Initializie to no info returned. */
*info = NULL;
Info = EngFncs->engine_alloc(sizeof(extended_info_array_t) +
6 * sizeof(extended_info_t));
if (!Info) {
LOG_EXIT_INT(ENOMEM);
return ENOMEM;
}
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].value.s = EngFncs->engine_strdup(my_plugin_record->short_name);
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].value.s = EngFncs->engine_strdup(my_plugin_record->long_name);
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].value.s = EngFncs->engine_strdup(_("File System Interface Module"));
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].value.s = EngFncs->engine_strdup(version_string);
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].value.s = EngFncs->engine_strdup(required_engine_api_version_string);
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].value.s = EngFncs->engine_strdup(required_fsim_api_version_string);
*info = Info;
LOG_EXIT_INT(0);
return 0;
}
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(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(descriptor_name, info);
}
/**
* Tables of standard FSIM APIs for the FAT plugins.
**/
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 = fat_unmkfs,
.expand = fat_expand,
.shrink = fat_shrink,
.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,
};
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 = fat_unmkfs,
.expand = fat16_expand,
.shrink = fat16_shrink,
.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,
};
/**
* Plugin records for the FAT plugins.
**/
static plugin_record_t fat_plugrec = {
.id = EVMS_FAT_PLUGIN_ID,
.version = {
.major = MAJOR_VERSION,
.minor = MINOR_VERSION,
.patchlevel = PATCH_LEVEL
},
.required_engine_api_version = {
.major = 15,
.minor = 0,
.patchlevel = 0
},
.required_plugin_api_version = {
.fsim = {
.major = 11,
.minor = 0,
.patchlevel = 0
}
},
.short_name = EVMS_FAT_PLUGIN_SHORT_NAME,
.long_name = EVMS_FAT_PLUGIN_LONG_NAME,
.oem_name = EVMS_ALT_LINUX_OEM_NAME,
.functions = {
.fsim = &fsim_ops
},
.container_functions = NULL
};
static plugin_record_t fat16_plugrec = {
.id = EVMS_FAT16_PLUGIN_ID,
.version = {
.major = MAJOR_VERSION,
.minor = MINOR_VERSION,
.patchlevel = PATCH_LEVEL
},
.required_engine_api_version = {
.major = 15,
.minor = 0,
.patchlevel = 0
},
.required_plugin_api_version = {
.fsim = {
.major = 11,
.minor = 0,
.patchlevel = 0
}
},
.short_name = EVMS_FAT16_PLUGIN_SHORT_NAME,
.long_name = EVMS_FAT16_PLUGIN_LONG_NAME,
.oem_name = EVMS_ALT_LINUX_OEM_NAME,
.functions = {
.fsim = &fsim16_ops
},
.container_functions = NULL
};
plugin_record_t *evms_plugin_records[] = {
&fat_plugrec,
&fat16_plugrec,
NULL
};