OpenSolaris_b135/lib/libfsmgt/common/fs_dfstab.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <thread.h>
#include <synch.h>
#include "libfsmgt.h"

/*
 * Private datastructures.
 */
typedef struct dfstab_entry {
	struct dfstab_entry *next;
	char    *path;
	char    *resource;
	char    *fstype;
	char    *options;
	char    *description;
} dfstab_entry_t;

static const char *whitespace = " \t";
static mutex_t dfstab_lock = DEFAULTMUTEX;

/*
 * Private functions
 */
static dfstab_entry_t *get_dfstab_ents(int *);
static void free_dfstab_list(dfstab_entry_t *);
static dfstab_entry_t *dfstab_line_to_dfstab_entry(char *, int *);
static char *create_share_cmd(dfstab_entry_t *, char *, int *);
static dfstab_entry_t *change_dfstab_ent(dfstab_entry_t *,
	dfstab_entry_t *, int *);
static void add_entry_to_dfstab(dfstab_entry_t *, int *);


static dfstab_entry_t *
get_dfstab_ents(int *err)
{
	dfstab_entry_t *dfstablist, *headptr, *tailptr = NULL;
	FILE *dfp;		/* fp for dfs list */
	static char cmd[BUFSIZE];
	*err = 0;

	if ((dfp = fopen(DFSTAB, "r")) != NULL) {
		char *share_cmd;
		(void) mutex_lock(&dfstab_lock);
		while ((share_cmd =
		    fileutil_getline(dfp, cmd, BUFSIZE)) != NULL) {
			if ((dfstablist =
			    dfstab_line_to_dfstab_entry(share_cmd, err)) !=
			    NULL) {
				if (tailptr == NULL) {
					headptr = dfstablist;
					tailptr = dfstablist;
				} else {
					tailptr->next = dfstablist;
					tailptr = dfstablist;
				}
				dfstablist = dfstablist->next;
			} else {
				free(share_cmd);
				break;
			}
			free(share_cmd);
		}
		if (tailptr == NULL) {
			headptr = tailptr;
		}
		(void) mutex_unlock(&dfstab_lock);
		fclose(dfp);
	} else {
		*err = errno;
		(void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTAB);
		headptr = NULL;
	}
	return (headptr);
} /* get_dfstab_ents */

static void
add_entry_to_dfstab(dfstab_entry_t *list, int *err)
{
	FILE *dfp;		/* fp for dfs list */

	if ((dfp = fopen(DFSTAB, "a")) != NULL) {
		char *share_cmd;
		if ((share_cmd = create_share_cmd(list, NULL, err)) != NULL) {
			(void) mutex_lock(&dfstab_lock);
			fprintf(dfp, "%s", share_cmd);
			fclose(dfp);
			(void) mutex_unlock(&dfstab_lock);
			free(share_cmd);
		} else {
			*err = errno;
		}
	} else {
		*err = errno;
	}

} /* add_entry_to_dfstab */

static void
free_dfstab_list(dfstab_entry_t *headp)
{
	dfstab_entry_t *tmp = headp;

	while (headp != NULL) {
		tmp = headp->next;
		if (headp->path != NULL) {
			free(headp->path);
		}
		if (headp->resource != NULL) {
			free(headp->resource);
		}
		if (headp->fstype != NULL) {
			free(headp->fstype);
		}
		if (headp->options != NULL) {
			free(headp->options);
		}
		if (headp->description != NULL) {
			free(headp->description);
		}
		headp->next = NULL;
		free(headp);
		headp = tmp;
	}
} /* free_dfstab_list */

static char *
create_share_cmd(dfstab_entry_t *new_entry, char *temp_line, int *err)
{
	char tempstr[BUFSIZE];
	char *cmd, *ret_val;

	cmd = (char *)calloc((size_t)1, BUFSIZE);
	if (cmd == NULL) {
		*err = errno;
		return (NULL);
	}
	sprintf(cmd, "share ");
	if (new_entry->fstype) {
		sprintf(tempstr, "-F %s ", new_entry->fstype);
		strlcat(cmd, tempstr, BUFSIZE);
	}
	if (new_entry->options) {
		sprintf(tempstr, "-o %s ", new_entry->options);
		strlcat(cmd, tempstr, BUFSIZE);
	}
	if (new_entry->description) {
		sprintf(tempstr, "-d %s ",
		    new_entry->description);
		strlcat(cmd, tempstr, BUFSIZE);
	}
	sprintf(tempstr, "%s\n", new_entry->path);
	strlcat(cmd, tempstr, BUFSIZE);
	if (temp_line != NULL && strchr(temp_line, '#')) {
		sprintf(tempstr, " %s", strchr(temp_line, '#'));
		strlcat(cmd, tempstr, BUFSIZE);
	}
	ret_val = strdup(cmd);
	free(cmd);
	return (ret_val);
} /* create_share_cmd */

/*
 * dfstab_line_to_dfstab_entry - parses a line from dfstab and fills in
 * the fields of a dfstab_entry_t structure
 * Parameters:
 * char *cmd - the share command or dfstab line to be parsed
 * int *err - a pointer for returning any error codes encountered
 */
static dfstab_entry_t *
dfstab_line_to_dfstab_entry(char *cmd, int *err)
{

	dfstab_entry_t *dfstablist;
	extern char *optarg;
	extern int optind;
	int c, argcount = 0;
	char *temp_str;
	char *arglist[LINESZ];

	c = 0;
	optind = 1;

	temp_str = strdup(cmd);
	if (temp_str == NULL) {
		*err = ENOMEM;
		return (NULL);
	}

	for (arglist[argcount] = strtok(temp_str, whitespace);
	    arglist[argcount] != NULL; /* CSTYLED */) {
		arglist[++argcount] = strtok(NULL, whitespace);
	}
	argcount--;
	dfstablist =
	    (dfstab_entry_t *)calloc((size_t)1,
	    sizeof (dfstab_entry_t));
	if (dfstablist == NULL) {
		*err = ENOMEM;
		free(temp_str);
		return (NULL);
	}
	while ((c = getopt(argcount, arglist, "F:d:o:")) != -1) {
		switch (c) {
		case 'F':
					/* file system type */
					/* at most one -F */
			*err |= (dfstablist->fstype != NULL);
			dfstablist->fstype = strdup(optarg);
			if (dfstablist->fstype == NULL) {
				*err = ENOMEM;
				free_dfstab_list(dfstablist);
				free(temp_str);
				return (NULL);
			}
			break;
		case 'd':		/* description */
					/* at most one -d */
			*err |= (dfstablist->description != NULL);
			dfstablist->description = strdup(optarg);
			if (dfstablist->description == NULL) {
				*err = ENOMEM;
				free_dfstab_list(dfstablist);
				free(temp_str);
				return (NULL);
			}
			break;
		case 'o':		/* fs specific options */
					/* at most one - o */
			*err |= (dfstablist->options != NULL);
			dfstablist->options = strdup(optarg);
			if (dfstablist->options == NULL) {
				*err = ENOMEM;
				free_dfstab_list(dfstablist);
				free(temp_str);
				return (NULL);
			}
			break;
		case '?':
			*err = 1;
			break;
		}
	}
	if (dfstablist->fstype == NULL) {
		FILE *fp;

		if ((fp = fopen(DFSTYPES, "r")) == NULL) {
			(void) fprintf(stderr, "%s: cannot open %s\n",
			    cmd, DFSTYPES);
			free_dfstab_list(dfstablist);
			free(temp_str);
			return (NULL);
		}
		(void) mutex_lock(&dfstab_lock);
		dfstablist->fstype = strdup(fileutil_getfs(fp));
		(void) mutex_unlock(&dfstab_lock);
		fclose(fp);
	}
	dfstablist->path = strdup(arglist[argcount]);
	if (dfstablist->path == NULL) {
		*err = ENOMEM;
		free_dfstab_list(dfstablist);
		free(temp_str);
		return (NULL);
	}
	free(temp_str);
	return (dfstablist);
} /* dfstab_line_to_dfstab_entry */

static dfstab_entry_t *
change_dfstab_ent(
	dfstab_entry_t *old_entry,
	dfstab_entry_t *new_entry,
	int *err)
{

	FILE *fp;
	dfstab_entry_t *temp_list, *ret_val;
	char cmd[BUFSIZE];
	char **temp_dfstab = NULL;
	int line_found = 0;

	if ((fp = fopen(DFSTAB, "r")) != NULL) {
		char *share_cmd;
		int count = 0;
		(void) mutex_lock(&dfstab_lock);
		while (fgets(cmd, BUFSIZE, fp) != NULL) {
			if ((share_cmd =
			    fileutil_get_cmd_from_string(cmd)) == NULL) {
				if (!fileutil_add_string_to_array(
				    &temp_dfstab, cmd, &count, err)) {
					ret_val = NULL;
					line_found = 0;
					break;
				}
				continue;
			}
			if ((temp_list =
			    dfstab_line_to_dfstab_entry(share_cmd, err)) ==
			    NULL) {
				free(share_cmd);
				ret_val = NULL;
				break;
			}
			if (strcmp(old_entry->path,
			    temp_list->path) == 0) {
				char *new_cmd = NULL;
				line_found = 1;
				if (new_entry != NULL && (new_cmd =
				    create_share_cmd(new_entry, cmd,
				    err)) != NULL) {
					if (!fileutil_add_string_to_array(
					    &temp_dfstab, new_cmd, &count,
					    err)) {
						ret_val = NULL;
						line_found = 0;
						free(share_cmd);
						free(new_cmd);
						break;
					}
					free(new_cmd);
				}
			} else {
				if (!fileutil_add_string_to_array(
				    &temp_dfstab, cmd, &count, err)) {
					free(share_cmd);
					ret_val = NULL;
					line_found = 0;
					break;
				}
			}
			free_dfstab_list(temp_list);
			free(share_cmd);
		}
		fclose(fp);

		if (line_found && temp_dfstab != NULL) {
			if ((fp = fopen(DFSTAB, "w")) != NULL) {
				int i;
				for (i = 0; i < count; i++) {
					fprintf(fp, "%s", temp_dfstab[i]);
				}
				fclose(fp);
				(void) mutex_unlock(&dfstab_lock);
				ret_val = get_dfstab_ents(err);
				fileutil_free_string_array(temp_dfstab, count);
			} else {
				*err = errno;
				(void) mutex_unlock(&dfstab_lock);
				fileutil_free_string_array(temp_dfstab, count);
				ret_val = NULL;
			}
		} else {
			(void) mutex_unlock(&dfstab_lock);
			if (temp_dfstab != NULL) {
				fileutil_free_string_array(temp_dfstab, count);
			}
			ret_val = NULL;
		}
	} else {
		*err = errno;
		ret_val = NULL;
	}
	return (ret_val);
} /* change_dfstab_ent */

/*
 * Public accessor functions.
 */

/*
 * fs_add_DFStab_ent - adds an entry to dfstab and to the list of dfstab
 * entries. Returns a pointer to the head of the dfstab entry list.
 * Parameters:
 * char *cmd - the same command to be added to dstab
 * int *err - an error pointer for retruning any errors
 */
fs_dfstab_entry_t
fs_add_DFStab_ent(char *cmd, int *err)
{
	dfstab_entry_t *dfstab_ent;

	dfstab_ent = dfstab_line_to_dfstab_entry(cmd, err);
	if (dfstab_ent == NULL) {
		*err = errno;
		return (NULL);
	}
	add_entry_to_dfstab(dfstab_ent, err);
	if (*err != 0) {
		free_dfstab_list(dfstab_ent);
		return (NULL);
	}
	free_dfstab_list(dfstab_ent);
	return (get_dfstab_ents(err));
}

/*
 * set_DFStab_ent - adds an entry to dfstab and to the list of dfstab entries.
 * returns a pointer to the head of the dfstab entry list.
 */
fs_dfstab_entry_t
fs_set_DFStab_ent(
	char *path,
	char *fstype,
	char *options,
	char *description,
	int *err)
{

	dfstab_entry_t *new_entry;
	new_entry = (dfstab_entry_t *)calloc((size_t)1,
	    sizeof (dfstab_entry_t));
	if (new_entry == NULL) {
		*err = ENOMEM;
		return (NULL);
	}
	if (path != NULL) {
		new_entry->path = strdup(path);
	} else {
		*err = EINVAL;
		free_dfstab_list(new_entry);
		return (NULL);
	}
	if (fstype != NULL) {
		new_entry->fstype = strdup(fstype);
	} else {
		FILE *fp;

		if ((fp = fopen(DFSTYPES, "r")) == NULL) {
			/* change this to error handler */
			(void) fprintf(stderr, "cannot open %s\n",
			    DFSTYPES);
			free_dfstab_list(new_entry);
			return (NULL);
		}
		(void) mutex_lock(&dfstab_lock);
		new_entry->fstype = strdup(fileutil_getfs(fp));
		(void) mutex_unlock(&dfstab_lock);
		fclose(fp);
	}
	if (options != NULL) {
		new_entry->options = strdup(options);
	}
	if (description != NULL) {
		new_entry->description = strdup(description);
	}
	add_entry_to_dfstab(new_entry, err);
	if (*err != 0) {
		free_dfstab_list(new_entry);
		return (NULL);
	}
	free_dfstab_list(new_entry);
	return (get_dfstab_ents(err));
} /* set_DFStab_ent */

/*
 * Accessor function for path element of dfstab entry.
 */
char *
fs_get_DFStab_ent_Path(void *entry)
{
	dfstab_entry_t *entryptr = (dfstab_entry_t *)entry;
	if (entryptr == NULL) {
		return (NULL);
	}
	return (entryptr->path);
} /* get_DFStab_ent_Path */

/*
 * Accessor function for fstype element of dfstab entry.
 */
char *
fs_get_DFStab_ent_Fstype(void *entry)
{
	dfstab_entry_t *entryptr = (dfstab_entry_t *)entry;
	if (entryptr == NULL) {
		return (NULL);
	}
	return (entryptr->fstype);
}

/*
 * Accessor function for options element of dfstab entry.
 */
char *
fs_get_DFStab_ent_Options(void *entry)
{
	dfstab_entry_t *entryptr = (dfstab_entry_t *)entry;
	if (entryptr == NULL) {
		return (NULL);
	}
	return (entryptr->options);
}

/*
 * Accessor function for description element of dfstab entry.
 */
char *
fs_get_DFStab_ent_Desc(void *entry)
{
	dfstab_entry_t *entryptr = (dfstab_entry_t *)entry;
	if (entryptr == NULL) {
		return (NULL);
	}
	return (entryptr->description);
}

/*
 * Accessor function for resource element of dfstab entry.
 */
char *
fs_get_DFStab_ent_Res(void *entry)
{
	dfstab_entry_t *entryptr = (dfstab_entry_t *)entry;
	if (entryptr == NULL) {
		return (NULL);
	}
	return (entryptr->resource);
}


/*
 * Calls get_dfstab_ents to create the list of dfstab
 * entries and returns that list.
 */
fs_dfstab_entry_t
fs_get_DFStab_ents(int *err)
{
	dfstab_entry_t *list;
	list = get_dfstab_ents(err);
	return (list);
}

/*
 * Retrives and returns the next entry in the list.
 */
fs_dfstab_entry_t
fs_get_DFStab_ent_Next(void *list)
{
	dfstab_entry_t *listptr = (dfstab_entry_t *)list;
	if (listptr == NULL) {
		return (NULL);
	}
	return (listptr->next);
}

/*
 * Retrives and returns a share command based on the dfstab entry passed in.
 */
char *
fs_get_Dfstab_share_cmd(fs_dfstab_entry_t dfstab_ent, int *err)
{
	char *share_cmd;
	if (dfstab_ent == NULL) {
		return (NULL);
	}
	share_cmd = create_share_cmd((dfstab_entry_t *)dfstab_ent, NULL, err);
	return (share_cmd);
} /* fs_get_Dfstab_share_cmd */

/*
 * edit_DFStab_ent - changes an entry in dfstab.
 */
fs_dfstab_entry_t
fs_edit_DFStab_ent(char *old_cmd, char *new_cmd, int *err)
{
	dfstab_entry_t *old_dfstabent, *new_dfstabent, *ret_val;

	if ((old_dfstabent =
	    dfstab_line_to_dfstab_entry(old_cmd, err)) == NULL) {
		return (NULL);
	}
	if ((new_dfstabent =
	    dfstab_line_to_dfstab_entry(new_cmd, err)) == NULL) {
		return (NULL);
	}
	if ((ret_val =
	    change_dfstab_ent(old_dfstabent, new_dfstabent, err)) == NULL) {
		return (NULL);
	}
	free_dfstab_list(old_dfstabent);
	free_dfstab_list(new_dfstabent);
	return (ret_val);
}

/*
 * del_DFStab_ent - deletes an entry in dfstab.
 */
fs_dfstab_entry_t
fs_del_DFStab_ent(char *del_cmd, int *err)
{
	dfstab_entry_t *del_dfstabent, *ret_val;

	if ((del_dfstabent =
	    dfstab_line_to_dfstab_entry(del_cmd, err)) == NULL) {
		return (NULL);
	}
	if ((ret_val =
	    change_dfstab_ent(del_dfstabent, NULL, err)) == NULL) {
		return (NULL);
	}
	free_dfstab_list(del_dfstabent);
	return (ret_val);
}

/*
 * del_All_DFStab_ents_with_Path - deletes all duplicate entries with
 * the specified path.
 */
fs_dfstab_entry_t
fs_del_All_DFStab_ents_with_Path(char *path, int *err)
{
	dfstab_entry_t del_dfstabent, *ret_val;

	if (path != NULL) {
		if ((del_dfstabent.path = strdup(path)) != NULL) {
			if ((ret_val = change_dfstab_ent(&del_dfstabent,
			    NULL, err)) == NULL) {
				ret_val = NULL;
			}
			free(del_dfstabent.path);
		} else {
			*err = ENOMEM;
			ret_val = NULL;
		}
	} else {
		*err = EINVAL;
		ret_val = NULL;
	}
	return (ret_val);
}


int
fs_check_for_duplicate_DFStab_paths(char *path, int *err)
{
	dfstab_entry_t *dfstablist;
	int count = 0;

	*err = 0;
	if (path == NULL) {
		count = -1;
	}
	dfstablist = get_dfstab_ents(err);
	if (dfstablist != NULL) {
		while (dfstablist != NULL) {
			if (strcmp(dfstablist->path, path) == 0) {
				count++;
			}
			dfstablist = dfstablist->next;
		}

		free_dfstab_list(dfstablist);
	} else {
		if (err != 0)
			count = *err;
		else
			count = 0;
	}
	return (count);
}

void
fs_free_DFStab_ents(void *list)
{
	dfstab_entry_t *headp = (dfstab_entry_t *)list;
	free_dfstab_list(headp);
}

/*
 * used for debugging only
 */
void
fs_print_dfstab_entries(void *list)
{
	while (list != NULL) {

		if (fs_get_DFStab_ent_Fstype(list) != NULL)
			printf("fstype: %s", fs_get_DFStab_ent_Fstype(list));
		if (fs_get_DFStab_ent_Desc(list) != NULL)
			printf(" description: %s",
			    fs_get_DFStab_ent_Desc(list));
		if (fs_get_DFStab_ent_Options(list) != NULL)
			printf(" options: %s",
			    fs_get_DFStab_ent_Options(list));
		if (fs_get_DFStab_ent_Path(list) != NULL)
			printf(" shared path is: %s\n",
			    fs_get_DFStab_ent_Path(list));
		list = (void *)fs_get_DFStab_ent_Next(list);
	}

}