/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* 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
*/
/*
*/
/*
* This module contains functions used for reading and writing the index file.
* setzoneent() opens the file. getzoneent() parses the file, doing the usual
* skipping of comment lines, etc., and using gettok() to deal with the ":"
* delimiters. endzoneent() closes the file. putzoneent() updates the file,
* adding, deleting or modifying lines, locking and unlocking appropriately.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libzonecfg.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include "zonecfg_impl.h"
/*
* gettok() is a helper function for parsing the index file, used to split
* the lines by their ":" delimiters. Note that an entry may contain a ":"
* inside double quotes; this should only affect the zonepath, as zone names
* do not allow such characters, and zone states do not have them either.
* Same with double-quotes themselves: they are not allowed in zone names,
* and do not occur in zone states, and in theory should never occur in a
* zonepath since zonecfg does not support a method for escaping them.
*
* It never returns NULL.
*/
static char *
{
return ("");
if (*cp == '"') {
cp++;
}
if (quoted) {
cp++;
if (*cp == '"')
*cp++ = '\0';
}
cp++;
if (*cp == '\0') {
} else {
*cp++ = '\0';
}
return (retv);
}
char *
{
char *name;
return (NULL);
return (name);
}
struct zoneent *
{
return (NULL);
return (NULL);
for (;;) {
return (NULL);
}
/* this represents a line that's too long */
continue;
}
*cp = '\0';
if (*cp == '#') {
/* skip comment lines */
continue;
}
/*
* empty or very long zone names are not allowed
*/
continue;
}
if (*p == '\0') {
/* state field should not be empty */
continue;
}
errno = 0;
if (strcmp(p, ZONE_STATE_STR_CONFIGURED) == 0) {
} else if (strcmp(p, ZONE_STATE_STR_INCOMPLETE) == 0) {
} else if (strcmp(p, ZONE_STATE_STR_INSTALLED) == 0) {
} else {
continue;
}
if (strlen(p) >= MAXPATHLEN) {
/* very long paths are not allowed */
continue;
}
break;
}
return (ze);
}
static boolean_t
{
}
FILE *
setzoneent(void)
{
if (!get_index_path(path)) {
return (NULL);
}
}
void
{
}
static int
lock_index_file(void)
{
int lock_fd;
ZONE_INDEX_LOCK_DIR) >= sizeof (path))
return (-1);
return (-1);
sizeof (path))
return (-1);
if (lock_fd == -1)
return (-1);
return (-1);
}
return (lock_fd);
}
static int
{
return (Z_UNLOCKING_FILE);
return (Z_UNLOCKING_FILE);
return (Z_OK);
}
/*
* This function adds or removes a zone name et al. to the index file.
*
* If ze->zone_state is < 0, it means leave the
* existing value unchanged; this is only meaningful when operation ==
* PZE_MODIFY (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE).
*
* A zero-length ze->zone_path means leave the existing value
* unchanged; this is only meaningful when operation == PZE_MODIFY
* (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE).
*
* A zero-length ze->zone_newname means leave the existing name
* unchanged; otherwise the zone is renamed to zone_newname. This is
* only meaningful when operation == PZE_MODIFY.
*
* Locking and unlocking is done via the functions above.
* The file itself is not modified in place; rather, a copy is made which
* is modified, then the copy is atomically renamed back to the main file.
*/
int
{
char *cp;
/*
* Don't allow modification of Global Zone entry
* in index file
*/
if ((operation == PZE_MODIFY) &&
return (Z_OK);
}
return (Z_INVAL);
return (Z_INVAL);
return (Z_LOCKING_FILE);
/* using sizeof gives us room for the terminating NUL byte as well */
if (tmp_file_name == NULL) {
(void) unlock_index_file(lock_fd);
return (Z_NOMEM);
}
if (tmp_file_desc == -1) {
(void) unlink(tmp_file_name);
(void) unlock_index_file(lock_fd);
return (Z_TEMP_FILE);
}
(void) close(tmp_file_desc);
goto error;
}
if (!get_index_path(path)) {
goto error;
}
goto error;
}
for (;;) {
zone_uuid = "";
goto add_entry;
}
/*
* It's not considered an error to delete something
* that doesn't exist, but we can't modify a missing
* record.
*/
goto error;
}
break;
}
if (buf[0] == '#') {
/* skip and preserve comment lines */
continue;
}
/* skip and preserve non-target lines */
continue;
}
/* this represents a line that's too long; delete */
continue;
}
*cp = '\0';
/*
* Skip over the zone name. Because we've already matched the
* target zone (above), we know for certain here that the zone
* name is present and correctly formed. No need to check.
*/
if (*zone_state == '\0') {
/* state field should not be empty */
goto error;
}
switch (operation) {
case PZE_ADD:
/* can't add same zone */
goto error;
case PZE_MODIFY:
/*
* If the caller specified a new state for the zone,
* then use that. Otherwise, use the current state.
*/
if (ze->zone_state >= 0) {
/*
* If the caller is uninstalling this zone,
* then wipe out the uuid. The zone's contents
* are no longer known.
*/
zone_uuid = "";
}
/* If a new name is supplied, use it. */
break;
case PZE_REMOVE:
default:
continue;
}
/*
* If the entry in the file is in greater than configured
* state, then we must have a UUID. Make sure that we do.
* (Note that the file entry is only tokenized, not fully
* parsed, so we need to do a string comparison here.)
*/
*zone_uuid == '\0') {
}
/*
* We need to quote a path that contains a ":"; this should
* only affect the zonepath, as zone names do not allow such
* characters, and zone states do not have them either. Same
* with double-quotes themselves: they are not allowed in zone
* names, and do not occur in zone states, and in theory should
* never occur in a zonepath since zonecfg does not support a
* method for escaping them.
*/
}
(void) fclose(index_file);
index_file = NULL;
goto error;
}
goto error;
}
return (Z_UNLOCKING_FILE);
return (Z_OK);
if (index_file != NULL)
(void) fclose(index_file);
(void) unlink(tmp_file_name);
(void) unlock_index_file(lock_fd);
return (err);
}