#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__SOLARIS__)
# include <sys/mnttab.h>
# include <sys/vfstab.h>
#else
# include <mntent.h>
#endif
#include <sys/stat.h>
#include <gtk/gtk.h>

#include "../include/string.h"
#include "../include/fio.h"
#include "../include/disk.h"

#include "edvtypes.h"
#include "edvdevices.h"
#include "edvdevicesfio.h"
#include "config.h"


void EDVDevicesListLoadFromSystem(
	edv_device_struct ***list, gint *total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
);

void EDVDevicesListUpdateMountStatesFromSystem(
	edv_device_struct **list, gint total
);

void EDVDevicesListLoadFromFile(
	const gchar *filename,
	edv_device_struct ***list, gint *total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
);
void EDVDeviceListSaveToFile(
	const gchar *filename,
	edv_device_struct **list, gint total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *	Loads devices found in the system (/etc/fstab) list of devices
 *	and appends them to the Devices list.
 */
void EDVDevicesListLoadFromSystem(
	edv_device_struct ***list, gint *total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
)
{
	FILE *fp;
	gulong file_size;
	gint dev_num = -1;
	edv_device_struct *dev_ptr = NULL;
#if defined(__SOLARIS__)
	struct vfstab *vfs_ptr = NULL;
	int mtback;
#else
	struct mntent *mt_ptr;
#endif
	struct stat stat_buf;


	if((list == NULL) || (total == NULL))
	    return;


	/* Open the system's devices list file */
#if defined(__SOLARIS__)
	fp = FOpen("/etc/vfstab", "rb");
#else
	fp = setmntent("/etc/fstab", "rb");
#endif
	if(fp == NULL)
	    return;

	/* Get file statistics */
	if(fstat(fileno(fp), &stat_buf))
	    file_size = 0l;
	else
	    file_size = (gulong)stat_buf.st_size;

	/* Report initial progress */
	if(progress_cb != NULL)
	    progress_cb(client_data, 0l, file_size);

	/* Begin reading the system's devices list file */
#if defined(__SOLARIS__)
	vfs_ptr = (struct vfstab *)g_malloc(sizeof(struct vfstab));
	mtback = getvfsent(fp, vfs_ptr);
	while(mtback != 0)
#else
	mt_ptr = getmntent(fp);
	while(mt_ptr != NULL)
#endif
	{
	    /* Report progress */
	    if(progress_cb != NULL)
	    {
		if(progress_cb(
		    client_data, (gulong)ftell(fp), file_size
		))
		    break;
	    }

	    /* Check if an existing device already exists in
	     * the list that matches the device_path
	     */
	    dev_ptr = EDVDeviceListMatchDevicePath(
		*list, *total,
		&dev_num, mt_ptr->mnt_fsname
	    );
	    if(dev_ptr == NULL)
	    {
		/* No existing device structure exists that matches the
		 * device path, so create a new one
		 */
		dev_num = *total;
		*total = dev_num + 1;
		*list = (edv_device_struct **)g_realloc(
		    *list, (*total) * sizeof(edv_device_struct *)
		);
		if(*list == NULL)
		{
		    *total = 0;
		    dev_num = -1;
		    dev_ptr = NULL;
		    break;
		}
		else
		{
		    (*list)[dev_num] = dev_ptr = EDVDeviceNew(
#if defined(__SOLARIS__)
			EDVDeviceGetFSFromString(vfs_ptr->vfs_fstype),
			NULL, vfs_ptr->vfs_special, vfs_ptr->vfs_mountp
#else
			EDVDeviceGetFSFromString(mt_ptr->mnt_type),
			NULL, mt_ptr->mnt_fsname, mt_ptr->mnt_dir
#endif
		    );
		    if(dev_ptr == NULL)
		    {
			dev_num = -1;
			break;
		    }

		    /* Set other default values for this new device */

		    /* Default icons */
		    if(EDV_DEVICE_TOTAL_ICON_STATES >= 1)
		    {
			/* Small icon? */
			if(dev_ptr->small_icon_file[0] == NULL)
			{
			    dev_ptr->small_icon_file[0] = STRDUP(
				EDV_DEF_DEVICE_ICON_SMALL_FILE
			    );
			}
			/* Medium icon? */
			if(dev_ptr->medium_icon_file[0] == NULL)
			{
			    dev_ptr->medium_icon_file[0] = STRDUP(
				EDV_DEF_DEVICE_ICON_MEDIUM_FILE
			    );
			}
			/* Large icon? */
			if(dev_ptr->large_icon_file[0] == NULL)
			{
			    dev_ptr->large_icon_file[0] = STRDUP(
				EDV_DEF_DEVICE_ICON_LARGE_FILE
			    );
			}
		    }

		    /* Default fsck program */
		    g_free(dev_ptr->command_check);
		    dev_ptr->command_check = g_strdup_printf(
			"%s %s",
			EDV_DEF_FSCK_FRONT_PROG,
#if defined(__SOLARIS__)
			vfs_ptr->vfs_special
#else
			mt_ptr->mnt_fsname
#endif
		    );

		    /* Default format program */
		    g_free(dev_ptr->command_format);
		    dev_ptr->command_format = g_strdup_printf(
			"%s %s",
			EDV_DEF_FORMAT_FRONT_PROG,
#if defined(__SOLARIS__)
			vfs_ptr->vfs_special
#else
			mt_ptr->mnt_fsname
#endif
		    );

		}
	    }
	    else
	    {
		/* Existing device structure exists that matches the 
		 * device path, so update its values
		 */

		/* File system type */
#if defined(__SOLARIS__)
		dev_ptr->fs_type = EDVDeviceGetFSFromString(vfs_ptr->vfs_fstype);
#else
		dev_ptr->fs_type = EDVDeviceGetFSFromString(mt_ptr->mnt_type);
#endif

		/* Mount path */
#if defined(__SOLARIS__)
		if(vfs_ptr->vfs_mountp != NULL)
#else
		if(mt_ptr->mnt_dir != NULL)
#endif
		{
		    g_free(dev_ptr->mount_path);
#if defined(__SOLARIS__)
		    dev_ptr->mount_path = STRDUP(vfs_ptr->vfs_mountp);
#else
		    dev_ptr->mount_path = STRDUP(mt_ptr->mnt_dir);
#endif
		}

	    }

	    /* Read next mount entry */
#if defined(__SOLARIS__)
	    mtback = getmntent(fp, vfs_ptr);
#else
	    mt_ptr = getmntent(fp);
#endif
	}


	/* Close the system's devices list file */
#if defined(__SOLARIS__)
	FClose(fp);
#else
	endmntent(fp);
#endif

	/* Report final progress */
	if(progress_cb != NULL)
	    progress_cb(
		client_data, file_size, file_size
	    );
}


/*
 *	Updates the mount states of all the Devices in the list with
 *	the system device's mount states.
 */
void EDVDevicesListUpdateMountStatesFromSystem(
	edv_device_struct **list, gint total
)
{
	FILE *fp;
	gint dev_num = -1;
	edv_device_struct *dev_ptr = NULL;
#if defined(__SOLARIS__)
	struct mnttab *mt_ptr = NULL;
	int mtback;
#else
	struct mntent *mt_ptr;
#endif

	if((list == NULL) || (total <= 0))
	    return;


	/* Reset mount states on all device structures */
	for(dev_num = 0; dev_num < total; dev_num++)
	{
	    dev_ptr = list[dev_num];
	    if(dev_ptr == NULL)
		continue;

	    dev_ptr->is_mounted = FALSE;
	}


	/* Open the system's mounted devices list file */
#if defined(__SOLARIS__)
	fp = FOpen("/etc/mnttab", "rb");
#else
/*	fp = setmntent("/etc/mtab", "rb"); */
	fp = setmntent("/proc/mounts", "rb");
#endif
	if(fp == NULL)
	    return;

	/* Begin reading the system's mounted devices list file */
#if defined(__SOLARIS__)
	mt_ptr = (struct mnttab *)g_malloc(sizeof(struct mnttab));
	mtback = getmntent(fp, mt_ptr);
	while(mtback != 0)
#else
	mt_ptr = getmntent(fp);
	while(mt_ptr != NULL)
#endif
	{
	    /* Check if the mounted device path matches a Device in
	     * the specified list
	     */
	    dev_ptr = EDVDeviceListMatchDevicePath(
		list, total,
#if defined(__SOLARIS__)
		&dev_num, mt_ptr->mnt_special
#else
		&dev_num, mt_ptr->mnt_fsname
#endif
	    );
	    if(dev_ptr != NULL)
	    {
		/* Entry from system's list of mounted devices matches
		 * one of the Devices in the list so mark that Device as
		 * mounted
		 */
		dev_ptr->is_mounted = TRUE;
	    }

	    /* Read next mount entry */
#if defined(__SOLARIS__)
	    mtback = getmntent(fp, mt_ptr);
#else
	    mt_ptr = getmntent(fp);
#endif
	}


	/* Close the system's mounted devices list file */
#if defined(__SOLARIS__)
	FClose(fp);
#else
	endmntent(fp);
#endif
}


/*
 *	Appends the devices in the specified file to the device list
 *	and updates any existing devices already in the list (if their
 *	device_path match).
 */
void EDVDevicesListLoadFromFile(
	const gchar *filename,
	edv_device_struct ***list, gint *total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
)
{
	gchar *parm;
	FILE *fp;
	gulong file_size;
	gint dev_num = -1;
	edv_device_struct *dev_ptr = NULL;
	struct stat stat_buf;


	if((list == NULL) || (total == NULL) || STRISEMPTY(filename))
	    return;

	/* Open devices file */
	fp = FOpen(filename, "rb");
	if(fp == NULL)
	    return;

	/* Get file statistics */
	if(fstat(fileno(fp), &stat_buf))
	    file_size = 0l;
	else
	    file_size = (gulong)stat_buf.st_size;

	/* Call progress callback */
	if(progress_cb != NULL)
	    progress_cb(
		client_data, 0l, file_size
	    );

	/* Begin file */
	parm = NULL;
	while(TRUE)
	{
	    /* Call progress callback */
	    if(progress_cb != NULL)
	    {
		if(progress_cb(
		    client_data, (gulong)ftell(fp), file_size
		))
		    break;
	    }

	    /* Read next parameter */
	    parm = FSeekNextParm(
		fp, parm,
		EDV_CFG_COMMENT_CHAR,
		EDV_CFG_DELIMINATOR_CHAR
	    );
	    if(parm == NULL)
		break;

	    /* Begin handling by parameter */

	    /* BeginDevice */
	    if(!g_strcasecmp(parm, "BeginDevice"))
	    {
		gchar *device_path = FGetString(fp);

		/* Check if an existing device already exists in
		 * the list that matches the device_path
		 */
		dev_ptr = EDVDeviceListMatchDevicePath(
		    *list, *total,
		    &dev_num, device_path
		);
		if(dev_ptr == NULL)
		{
		    /* No existing device structure exists that matches
		     * the given device_path, so create a new one
		     */
		    dev_num = *total;
		    *total = dev_num + 1;
		    *list = (edv_device_struct **)g_realloc(
			*list, (*total) * sizeof(edv_device_struct *)
		    );
		    if(*list == NULL)
		    {
			*total = 0;
			dev_num = -1;
			dev_ptr = NULL;
		    }
		    else
		    {
			(*list)[dev_num] = dev_ptr = EDVDeviceNew(
			    EDV_FS_TYPE_EMPTY, NULL, device_path, NULL
			);
			if(dev_ptr == NULL)
			{
			    dev_num = -1;
			}
		    }
		}
	    }

	    /* FSType */
	    else if(!g_strcasecmp(parm, "FSType") ||
		    !g_strcasecmp(parm, "FileSystemType")
	    )
	    {
		gint v[1];
		FGetValuesI(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->fs_type = v[0];
	    }
	    /* NoUnmount */
	    else if(!g_strcasecmp(parm, "NoUnmount"))
	    {
		gint v[1];
		FGetValuesI(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->no_unmount = (gboolean)v[0];
	    }
	    /* ReadOnly */
	    else if(!g_strcasecmp(parm, "ReadOnly"))
	    {
		gint v[1];
		FGetValuesI(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->read_only = (gboolean)v[0];
	    }
	    /* Unlisted */
	    else if(!g_strcasecmp(parm, "Unlisted"))
	    {
		gint v[1];
		FGetValuesI(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->unlisted = (gboolean)v[0];
	    }
	    /* Name */
	    else if(!g_strcasecmp(parm, "Name"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->name);
		    dev_ptr->name = STRDUP(v);
		}
		g_free(v);
	    }
	    /* MountPath */
	    else if(!g_strcasecmp(parm, "MountPath"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->mount_path);
		    dev_ptr->mount_path = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandMount */
	    else if(!g_strcasecmp(parm, "CommandMount"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_mount);
		    dev_ptr->command_mount = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandUnmount */
	    else if(!g_strcasecmp(parm, "CommandUnmount"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_unmount);
		    dev_ptr->command_unmount = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandEject */
	    else if(!g_strcasecmp(parm, "CommandEject"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_eject);
		    dev_ptr->command_eject = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandCheck */
	    else if(!g_strcasecmp(parm, "CommandCheck"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_check);
		    dev_ptr->command_check = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandTools */
	    else if(!g_strcasecmp(parm, "CommandTools"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_tools);
		    dev_ptr->command_tools = STRDUP(v);
		}
		g_free(v);
	    }
	    /* CommandFormat */
	    else if(!g_strcasecmp(parm, "CommandFormat"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    g_free(dev_ptr->command_format);
		    dev_ptr->command_format = STRDUP(v);
		}
		g_free(v);
	    }

	    /* IconSmallStandard */
	    else if(!g_strcasecmp(parm, "IconSmallStandard"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->small_icon_file[
			EDV_DEVICE_ICON_STATE_STANDARD
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconSmallSelected */
	    else if(!g_strcasecmp(parm, "IconSmallSelected"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->small_icon_file[
			EDV_DEVICE_ICON_STATE_SELECTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconSmallUnmounted */
	    else if(!g_strcasecmp(parm, "IconSmallUnmounted"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->small_icon_file[
			EDV_DEVICE_ICON_STATE_UNMOUNTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }

	    /* IconMediumStandard */
	    else if(!g_strcasecmp(parm, "IconMediumStandard"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->medium_icon_file[
			EDV_DEVICE_ICON_STATE_STANDARD
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconMediumSelected */
	    else if(!g_strcasecmp(parm, "IconMediumSelected"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->medium_icon_file[
		        EDV_DEVICE_ICON_STATE_SELECTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconMediumUnmounted */
	    else if(!g_strcasecmp(parm, "IconMediumUnmounted"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->medium_icon_file[
			EDV_DEVICE_ICON_STATE_UNMOUNTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }

	    /* IconLargeStandard */
	    else if(!g_strcasecmp(parm, "IconLargeStandard"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->large_icon_file[
		        EDV_DEVICE_ICON_STATE_STANDARD
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconLargeSelected */
	    else if(!g_strcasecmp(parm, "IconLargeSelected"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->large_icon_file[
			EDV_DEVICE_ICON_STATE_SELECTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }
	    /* IconLargeUnmounted */
	    else if(!g_strcasecmp(parm, "IconLargeUnmounted"))
	    {
		gchar *v = FGetString(fp);
		if(dev_ptr != NULL)
		{
		    gchar **t = &dev_ptr->large_icon_file[
			EDV_DEVICE_ICON_STATE_UNMOUNTED
		    ];
		    g_free(*t);
		    *t = STRDUP(v);
		}
		g_free(v);
	    }

	    /* LastMountTime */
	    else if(!g_strcasecmp(parm, "LastMountTime"))
	    {
		glong v[1];
		FGetValuesL(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->last_mount_time = (gulong)v[0];
	    }
	    /* LastCheckTime */
	    else if(!g_strcasecmp(parm, "LastCheckTime"))
	    {
		glong v[1];
		FGetValuesL(fp, v, 1);
		if(dev_ptr != NULL)
		    dev_ptr->last_check_time = (gulong)v[0];
	    }

	    /* End of a device block? */
	    else if(!g_strcasecmp(parm, "EndDevice"))
	    {
		FSeekNextLine(fp);

		/* Reset contexts */
		dev_num = -1;
		dev_ptr = NULL;
	    }
	    /* All else unsupported parameter or wrong context */
	    else
	    {
		FSeekNextLine(fp);
	    }
	}

	/* Delete parameter */
	g_free(parm);

	/* Close devices file */
	FClose(fp);
}

/*
 *	Saves the list of devices to the specified file.
 */
void EDVDeviceListSaveToFile(
	const gchar *filename,
	edv_device_struct **list, gint total,
	gint (*progress_cb)(gpointer, gulong, gulong),
	gpointer client_data
)
{
	gint dev_num;
	const edv_device_struct *dev_ptr;
	gchar *parent_path;
	FILE *fp;
	const gchar *path;


	if((list == NULL) || STRISEMPTY(filename))
	    return;

	/* Get parent directory and create it as needed */
	parent_path = g_dirname(filename);
	if(parent_path != NULL)
	{
	    rmkdir(parent_path, S_IRUSR | S_IWUSR | S_IXUSR);
	    g_free(parent_path);
	    parent_path = NULL;
	}

	/* Open devices file for writing */
	fp = FOpen(filename, "wb");
	if(fp == NULL)
	    return;

	/* Call progress callback */
	if(progress_cb != NULL)
	    progress_cb(
		client_data, 0l, (gulong)total
	    );

	/* Iterate through all device structures */
	for(dev_num = 0; dev_num < total; dev_num++)
	{
	    dev_ptr = list[dev_num];
	    if(dev_ptr == NULL)
		continue;

	    /* Skip devices that are marked internal, meaning they
	     * should not be saved to file
	     */
	    if(dev_ptr->internal)
		continue;

	    /* Call progress callback */
	    if(progress_cb != NULL)
	    {
		if(progress_cb(
		    client_data, (gulong)(dev_num + 1), (gulong)total
		))
		    break;
	    }


	    /* BeginDevice */
	    fprintf(
		fp,
		"BeginDevice = %s\n",
		dev_ptr->device_path
	    );

	    /* FSType */
	    fprintf(
		fp,
		"\tFSType = %i\n",
		dev_ptr->fs_type
	    );
	    /* NoUnmount */
	    fprintf(
		fp,
		"\tNoUnmount = %i\n",
		dev_ptr->no_unmount
	    );
	    /* ReadOnly */
	    fprintf(
		fp,
		"\tReadOnly = %i\n",
		dev_ptr->read_only
	    );
	    /* Unlisted */
	    fprintf(
		fp,
		"\tUnlisted = %i\n",
		dev_ptr->unlisted
	    );
	    /* Name */
	    if(!STRISEMPTY(dev_ptr->name))
		fprintf(
		    fp,
		    "\tName = %s\n",
		    dev_ptr->name
		);
	    /* MountPath */
	    if(!STRISEMPTY(dev_ptr->mount_path))
		fprintf(
		    fp,
		    "\tMountPath = %s\n",
		    dev_ptr->mount_path
		);

	    /* CommandMount */
	    if(!STRISEMPTY(dev_ptr->command_mount))
		fprintf(
		    fp,
		    "\tCommandMount = %s\n",
		    dev_ptr->command_mount
		);
	    /* CommandUnmount */
	    if(!STRISEMPTY(dev_ptr->command_unmount))
		fprintf(
		    fp,
		    "\tCommandUnmount = %s\n",
		    dev_ptr->command_unmount
		);
	    /* CommandEject */
	    if(!STRISEMPTY(dev_ptr->command_eject))
		fprintf(
		    fp,
		    "\tCommandEject = %s\n",
		    dev_ptr->command_eject
		);
	    /* CommandCheck */
	    if(!STRISEMPTY(dev_ptr->command_check))
		fprintf(
		    fp,
		    "\tCommandCheck = %s\n",
		    dev_ptr->command_check
		);
	    /* CommandTools */
	    if(!STRISEMPTY(dev_ptr->command_tools))
		fprintf(
		    fp,
		    "\tCommandTools = %s\n",
		    dev_ptr->command_tools
		);
	    /* CommandFormat */
	    if(!STRISEMPTY(dev_ptr->command_format))
		fprintf(
		    fp,
		    "\tCommandFormat = %s\n",
		    dev_ptr->command_format
		);

	    /* IconSmallStandard */
	    path = dev_ptr->small_icon_file[EDV_DEVICE_ICON_STATE_STANDARD];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconSmallStandard = %s\n",
		    path
		);
	    /* IconSmallSelected */
	    path = dev_ptr->small_icon_file[EDV_DEVICE_ICON_STATE_SELECTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconSmallSelected = %s\n",
		    path
		);
	    /* IconSmallUnmounted */
	    path = dev_ptr->small_icon_file[EDV_DEVICE_ICON_STATE_UNMOUNTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconSmallUnmounted = %s\n",
		    path
		);

	    /* IconMediumStandard */
	    path = dev_ptr->medium_icon_file[EDV_DEVICE_ICON_STATE_STANDARD];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconMediumStandard = %s\n",
		    path
		);
	    /* IconMediumSelected */
	    path = dev_ptr->medium_icon_file[EDV_DEVICE_ICON_STATE_SELECTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconMediumSelected = %s\n",
		    path
		);
	    /* IconMediumUnmounted */
	    path = dev_ptr->medium_icon_file[EDV_DEVICE_ICON_STATE_UNMOUNTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconMediumUnmounted = %s\n",
		    path
		);

	    /* IconLargeStandard */
	    path = dev_ptr->large_icon_file[EDV_DEVICE_ICON_STATE_STANDARD];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconLargeStandard = %s\n",
		    path
		);
	    /* IconLargeSelected */
	    path = dev_ptr->large_icon_file[EDV_DEVICE_ICON_STATE_SELECTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconLargeSelected = %s\n",
		    path
		);
	    /* IconLargeUnmounted */
	    path = dev_ptr->large_icon_file[EDV_DEVICE_ICON_STATE_UNMOUNTED];
	    if(!STRISEMPTY(path))
		fprintf(
		    fp,
		    "\tIconLargeUnmounted = %s\n",
		    path
		);

	    /* LastMountTime */
	    if(dev_ptr->last_mount_time > 0l)
		fprintf(
		    fp,
		    "\tLastMountTime = %ld\n",
		    dev_ptr->last_mount_time
		);
	    /* LastCheckTime */
	    if(dev_ptr->last_check_time > 0l)
		fprintf(
		    fp,
		    "\tLastCheckTime = %ld\n",
		    dev_ptr->last_check_time
		);

	    /* EndDevice */
	    fprintf(
		fp,
		"EndDevice\n"
	    );
	}

	/* Close devices file */
	FClose(fp);
}
