17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*087719fdSdp * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * This module contains functions used for reading and writing the index file. 317c478bd9Sstevel@tonic-gate * setzoneent() opens the file. getzoneent() parses the file, doing the usual 327c478bd9Sstevel@tonic-gate * skipping of comment lines, etc., and using gettok() to deal with the ":" 337c478bd9Sstevel@tonic-gate * delimiters. endzoneent() closes the file. putzoneent() updates the file, 347c478bd9Sstevel@tonic-gate * adding, deleting or modifying lines, locking and unlocking appropriately. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <ctype.h> 397c478bd9Sstevel@tonic-gate #include <string.h> 407c478bd9Sstevel@tonic-gate #include <errno.h> 417c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 437c478bd9Sstevel@tonic-gate #include <fcntl.h> 447c478bd9Sstevel@tonic-gate #include <sys/stat.h> 457c478bd9Sstevel@tonic-gate #include <assert.h> 467c478bd9Sstevel@tonic-gate #include "zonecfg_impl.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define _PATH_TMPFILE ZONE_CONFIG_ROOT "/zonecfg.XXXXXX" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * gettok() is a helper function for parsing the index file, used to split 537c478bd9Sstevel@tonic-gate * the lines by their ":" delimiters. Note that an entry may contain a ":" 547c478bd9Sstevel@tonic-gate * inside double quotes; this should only affect the zonepath, as zone names 557c478bd9Sstevel@tonic-gate * do not allow such characters, and zone states do not have them either. 567c478bd9Sstevel@tonic-gate * Same with double-quotes themselves: they are not allowed in zone names, 577c478bd9Sstevel@tonic-gate * and do not occur in zone states, and in theory should never occur in a 587c478bd9Sstevel@tonic-gate * zonepath since zonecfg does not support a method for escaping them. 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate static char * 627c478bd9Sstevel@tonic-gate gettok(char **cpp) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate char *cp = *cpp, *retv; 657c478bd9Sstevel@tonic-gate boolean_t quoted = B_FALSE; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate if (cp == NULL) 687c478bd9Sstevel@tonic-gate return (""); 697c478bd9Sstevel@tonic-gate if (*cp == '"') { 707c478bd9Sstevel@tonic-gate quoted = B_TRUE; 717c478bd9Sstevel@tonic-gate cp++; 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate retv = cp; 747c478bd9Sstevel@tonic-gate if (quoted) { 757c478bd9Sstevel@tonic-gate while (*cp != '\0' && *cp != '"') 767c478bd9Sstevel@tonic-gate cp++; 777c478bd9Sstevel@tonic-gate if (*cp == '"') 787c478bd9Sstevel@tonic-gate *cp++ = '\0'; 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate while (*cp != '\0' && *cp != ':') 817c478bd9Sstevel@tonic-gate cp++; 827c478bd9Sstevel@tonic-gate if (*cp == '\0') { 837c478bd9Sstevel@tonic-gate *cpp = NULL; 847c478bd9Sstevel@tonic-gate } else { 857c478bd9Sstevel@tonic-gate *cp++ = '\0'; 867c478bd9Sstevel@tonic-gate *cpp = cp; 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate return (retv); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate char * 927c478bd9Sstevel@tonic-gate getzoneent(FILE *cookie) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate struct zoneent *ze; 957c478bd9Sstevel@tonic-gate char *name; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if ((ze = getzoneent_private(cookie)) == NULL) 987c478bd9Sstevel@tonic-gate return (NULL); 997c478bd9Sstevel@tonic-gate name = strdup(ze->zone_name); 1007c478bd9Sstevel@tonic-gate free(ze); 1017c478bd9Sstevel@tonic-gate return (name); 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate struct zoneent * 1057c478bd9Sstevel@tonic-gate getzoneent_private(FILE *cookie) 1067c478bd9Sstevel@tonic-gate { 1077c478bd9Sstevel@tonic-gate char *cp, buf[MAX_INDEX_LEN], *p; 1087c478bd9Sstevel@tonic-gate struct zoneent *ze; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate if (cookie == NULL) 1117c478bd9Sstevel@tonic-gate return (NULL); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if ((ze = malloc(sizeof (struct zoneent))) == NULL) 1147c478bd9Sstevel@tonic-gate return (NULL); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate for (;;) { 1177c478bd9Sstevel@tonic-gate if (fgets(buf, sizeof (buf), cookie) == NULL) { 1187c478bd9Sstevel@tonic-gate free(ze); 1197c478bd9Sstevel@tonic-gate return (NULL); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate if ((cp = strpbrk(buf, "\r\n")) == NULL) { 1227c478bd9Sstevel@tonic-gate /* this represents a line that's too long */ 1237c478bd9Sstevel@tonic-gate continue; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate *cp = '\0'; 1267c478bd9Sstevel@tonic-gate cp = buf; 1277c478bd9Sstevel@tonic-gate if (*cp == '#') { 1287c478bd9Sstevel@tonic-gate /* skip comment lines */ 1297c478bd9Sstevel@tonic-gate continue; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate p = gettok(&cp); 1327c478bd9Sstevel@tonic-gate if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) { 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * empty or very long zone names are not allowed 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate continue; 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate (void) strlcpy(ze->zone_name, p, ZONENAME_MAX); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate p = gettok(&cp); 1417c478bd9Sstevel@tonic-gate if (p == NULL || *p == '\0') { 1427c478bd9Sstevel@tonic-gate /* state field should not be empty */ 1437c478bd9Sstevel@tonic-gate continue; 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate errno = 0; 1467c478bd9Sstevel@tonic-gate if (strcmp(p, ZONE_STATE_STR_CONFIGURED) == 0) { 1477c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_CONFIGURED; 1487c478bd9Sstevel@tonic-gate } else if (strcmp(p, ZONE_STATE_STR_INCOMPLETE) == 0) { 1497c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_INCOMPLETE; 1507c478bd9Sstevel@tonic-gate } else if (strcmp(p, ZONE_STATE_STR_INSTALLED) == 0) { 1517c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_INSTALLED; 1527c478bd9Sstevel@tonic-gate } else 1537c478bd9Sstevel@tonic-gate continue; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate p = gettok(&cp); 1567c478bd9Sstevel@tonic-gate if (strlen(p) > MAXPATHLEN) { 1577c478bd9Sstevel@tonic-gate /* very long paths are not allowed */ 1587c478bd9Sstevel@tonic-gate continue; 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate if (p == NULL) { 1617c478bd9Sstevel@tonic-gate /* empty paths accepted for backwards compatibility */ 1627c478bd9Sstevel@tonic-gate p = ""; 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate (void) strlcpy(ze->zone_path, p, MAXPATHLEN); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate break; 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate return (ze); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate FILE * 1737c478bd9Sstevel@tonic-gate setzoneent(void) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate return (fopen(ZONE_INDEX_FILE, "r")); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate void 1797c478bd9Sstevel@tonic-gate endzoneent(FILE *cookie) 1807c478bd9Sstevel@tonic-gate { 1817c478bd9Sstevel@tonic-gate if (cookie != NULL) 1827c478bd9Sstevel@tonic-gate (void) fclose(cookie); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate static int 1867c478bd9Sstevel@tonic-gate lock_index_file(int *lock_fd) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate struct flock lock; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && errno != EEXIST) 1917c478bd9Sstevel@tonic-gate return (Z_LOCKING_FILE); 1927c478bd9Sstevel@tonic-gate *lock_fd = open(ZONE_INDEX_LOCK_FILE, O_CREAT|O_RDWR, 0644); 1937c478bd9Sstevel@tonic-gate if (*lock_fd < 0) 1947c478bd9Sstevel@tonic-gate return (Z_LOCKING_FILE); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 1977c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 1987c478bd9Sstevel@tonic-gate lock.l_start = 0; 1997c478bd9Sstevel@tonic-gate lock.l_len = 0; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate if (fcntl(*lock_fd, F_SETLKW, &lock) == -1) 2027c478bd9Sstevel@tonic-gate return (Z_LOCKING_FILE); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate return (Z_OK); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate static int 2087c478bd9Sstevel@tonic-gate unlock_index_file(int lock_fd) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate struct flock lock; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate lock.l_type = F_UNLCK; 2137c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2147c478bd9Sstevel@tonic-gate lock.l_start = 0; 2157c478bd9Sstevel@tonic-gate lock.l_len = 0; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLK, &lock) == -1) 2187c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (close(lock_fd) == -1) 2217c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate return (Z_OK); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * This function adds or removes a zone name et al. to the index file. 2287c478bd9Sstevel@tonic-gate * 2297c478bd9Sstevel@tonic-gate * If ze->zone_state is < 0, it means leave the 2307c478bd9Sstevel@tonic-gate * existing value unchanged; this is only meaningful when operation == 231*087719fdSdp * PZE_MODIFY (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE). 2327c478bd9Sstevel@tonic-gate * 233*087719fdSdp * A zero-length ze->zone_path means leave the existing value 2347c478bd9Sstevel@tonic-gate * unchanged; this is only meaningful when operation == PZE_MODIFY 235*087719fdSdp * (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE). 236*087719fdSdp * 237*087719fdSdp * A zero-length ze->zone_newname means leave the existing name 238*087719fdSdp * unchanged; otherwise the zone is renamed to zone_newname. This is 239*087719fdSdp * only meaningful when operation == PZE_MODIFY. 2407c478bd9Sstevel@tonic-gate * 2417c478bd9Sstevel@tonic-gate * Locking and unlocking is done via the functions above. 2427c478bd9Sstevel@tonic-gate * The file itself is not modified in place; rather, a copy is made which 2437c478bd9Sstevel@tonic-gate * is modified, then the copy is atomically renamed back to the main file. 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate int 2467c478bd9Sstevel@tonic-gate putzoneent(struct zoneent *ze, zoneent_op_t operation) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate FILE *index_file, *tmp_file; 2497c478bd9Sstevel@tonic-gate char *tmp_file_name, buf[MAX_INDEX_LEN], orig_buf[MAX_INDEX_LEN]; 2507c478bd9Sstevel@tonic-gate char zone[ZONENAME_MAX + 1]; /* name plus newline */ 2517c478bd9Sstevel@tonic-gate char line[MAX_INDEX_LEN]; 2527c478bd9Sstevel@tonic-gate int tmp_file_desc, lock_fd, err; 2537c478bd9Sstevel@tonic-gate boolean_t exists = B_FALSE, need_quotes; 2547c478bd9Sstevel@tonic-gate char *cp, *p; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate assert(ze != NULL); 2577c478bd9Sstevel@tonic-gate if (operation == PZE_ADD && 2587c478bd9Sstevel@tonic-gate (ze->zone_state < 0 || strlen(ze->zone_path) == 0)) 2597c478bd9Sstevel@tonic-gate return (Z_INVAL); 260*087719fdSdp 261*087719fdSdp if (operation != PZE_MODIFY && strlen(ze->zone_newname) != 0) 262*087719fdSdp return (Z_INVAL); 263*087719fdSdp 2647c478bd9Sstevel@tonic-gate if ((err = lock_index_file(&lock_fd)) != Z_OK) 2657c478bd9Sstevel@tonic-gate return (err); 2667c478bd9Sstevel@tonic-gate tmp_file_name = strdup(_PATH_TMPFILE); 2677c478bd9Sstevel@tonic-gate if (tmp_file_name == NULL) { 2687c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 2697c478bd9Sstevel@tonic-gate return (Z_NOMEM); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate tmp_file_desc = mkstemp(tmp_file_name); 2727c478bd9Sstevel@tonic-gate if (tmp_file_desc == -1) { 2737c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 2747c478bd9Sstevel@tonic-gate free(tmp_file_name); 2757c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 2767c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate if ((tmp_file = fdopen(tmp_file_desc, "w")) == NULL) { 2797c478bd9Sstevel@tonic-gate (void) close(tmp_file_desc); 2807c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 2817c478bd9Sstevel@tonic-gate free(tmp_file_name); 2827c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 2837c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate if ((index_file = fopen(ZONE_INDEX_FILE, "r")) == NULL) { 2867c478bd9Sstevel@tonic-gate (void) fclose(tmp_file); 2877c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 2887c478bd9Sstevel@tonic-gate free(tmp_file_name); 2897c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 2907c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * We need to quote a path which contains a ":"; this should only 2957c478bd9Sstevel@tonic-gate * affect the zonepath, as zone names do not allow such characters, 2967c478bd9Sstevel@tonic-gate * and zone states do not have them either. Same with double-quotes 2977c478bd9Sstevel@tonic-gate * themselves: they are not allowed in zone names, and do not occur 2987c478bd9Sstevel@tonic-gate * in zone states, and in theory should never occur in a zonepath 2997c478bd9Sstevel@tonic-gate * since zonecfg does not support a method for escaping them. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate need_quotes = (strchr(ze->zone_path, ':') != NULL); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s\n", ze->zone_name, 3047c478bd9Sstevel@tonic-gate zone_state_str(ze->zone_state), need_quotes ? "\"" : "", 3057c478bd9Sstevel@tonic-gate ze->zone_path, need_quotes ? "\"" : ""); 3067c478bd9Sstevel@tonic-gate for (;;) { 3077c478bd9Sstevel@tonic-gate if (fgets(buf, sizeof (buf), index_file) == NULL) { 3087c478bd9Sstevel@tonic-gate if (operation == PZE_ADD && !exists) 3097c478bd9Sstevel@tonic-gate (void) fputs(line, tmp_file); 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate (void) strlcpy(orig_buf, buf, sizeof (orig_buf)); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if ((cp = strpbrk(buf, "\r\n")) == NULL) { 3157c478bd9Sstevel@tonic-gate /* this represents a line that's too long */ 3167c478bd9Sstevel@tonic-gate continue; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate *cp = '\0'; 3197c478bd9Sstevel@tonic-gate cp = buf; 3207c478bd9Sstevel@tonic-gate if (*cp == '#') { 3217c478bd9Sstevel@tonic-gate /* skip comment lines */ 3227c478bd9Sstevel@tonic-gate (void) fputs(orig_buf, tmp_file); 3237c478bd9Sstevel@tonic-gate continue; 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate p = gettok(&cp); 3267c478bd9Sstevel@tonic-gate if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) { 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * empty or very long zone names are not allowed 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate continue; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate (void) strlcpy(zone, p, ZONENAME_MAX); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (strcmp(zone, ze->zone_name) == 0) { 3357c478bd9Sstevel@tonic-gate exists = B_TRUE; /* already there */ 3367c478bd9Sstevel@tonic-gate if (operation == PZE_ADD) { 3377c478bd9Sstevel@tonic-gate /* can't add same zone */ 3387c478bd9Sstevel@tonic-gate goto error; 3397c478bd9Sstevel@tonic-gate } else if (operation == PZE_MODIFY) { 3407c478bd9Sstevel@tonic-gate char tmp_state[ZONE_STATE_MAXSTRLEN + 1]; 341*087719fdSdp char *tmp_name; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (ze->zone_state >= 0 && 3447c478bd9Sstevel@tonic-gate strlen(ze->zone_path) > 0) { 3457c478bd9Sstevel@tonic-gate /* use specified values */ 3467c478bd9Sstevel@tonic-gate (void) fputs(line, tmp_file); 3477c478bd9Sstevel@tonic-gate continue; 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate /* use existing value for state */ 3507c478bd9Sstevel@tonic-gate p = gettok(&cp); 3517c478bd9Sstevel@tonic-gate if (p == NULL || *p == '\0') { 3527c478bd9Sstevel@tonic-gate /* state field should not be empty */ 3537c478bd9Sstevel@tonic-gate goto error; 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_state, 3567c478bd9Sstevel@tonic-gate (ze->zone_state < 0) ? p : 3577c478bd9Sstevel@tonic-gate zone_state_str(ze->zone_state), 3587c478bd9Sstevel@tonic-gate sizeof (tmp_state)); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate p = gettok(&cp); 3617c478bd9Sstevel@tonic-gate 362*087719fdSdp /* 363*087719fdSdp * If a new name is supplied, use it. 364*087719fdSdp */ 365*087719fdSdp if (strlen(ze->zone_newname) != 0) 366*087719fdSdp tmp_name = ze->zone_newname; 367*087719fdSdp else 368*087719fdSdp tmp_name = ze->zone_name; 369*087719fdSdp 3707c478bd9Sstevel@tonic-gate (void) fprintf(tmp_file, "%s:%s:%s%s%s\n", 371*087719fdSdp tmp_name, tmp_state, 3727c478bd9Sstevel@tonic-gate need_quotes ? "\"" : "", 3737c478bd9Sstevel@tonic-gate (strlen(ze->zone_path) == 0) ? p : 3747c478bd9Sstevel@tonic-gate ze->zone_path, need_quotes ? "\"" : ""); 3757c478bd9Sstevel@tonic-gate } 376*087719fdSdp /* else if (operation == PZE_REMOVE) { no-op } */ 3777c478bd9Sstevel@tonic-gate } else { 3787c478bd9Sstevel@tonic-gate (void) fputs(orig_buf, tmp_file); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate (void) fclose(index_file); 3837c478bd9Sstevel@tonic-gate if (fclose(tmp_file) != 0) { 3847c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 3857c478bd9Sstevel@tonic-gate free(tmp_file_name); 3867c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 3877c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate (void) chmod(tmp_file_name, 0644); 3907c478bd9Sstevel@tonic-gate if (rename(tmp_file_name, ZONE_INDEX_FILE) == -1) { 3917c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 3927c478bd9Sstevel@tonic-gate free(tmp_file_name); 3937c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 3947c478bd9Sstevel@tonic-gate if (errno == EACCES) 3957c478bd9Sstevel@tonic-gate return (Z_ACCES); 3967c478bd9Sstevel@tonic-gate return (Z_MISC_FS); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate free(tmp_file_name); 3997c478bd9Sstevel@tonic-gate if (unlock_index_file(lock_fd) != Z_OK) 4007c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 4017c478bd9Sstevel@tonic-gate return (Z_OK); 4027c478bd9Sstevel@tonic-gate error: 4037c478bd9Sstevel@tonic-gate (void) fclose(index_file); 4047c478bd9Sstevel@tonic-gate (void) fclose(tmp_file); 4057c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 4067c478bd9Sstevel@tonic-gate free(tmp_file_name); 4077c478bd9Sstevel@tonic-gate if (unlock_index_file(lock_fd) != Z_OK) 4087c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 4097c478bd9Sstevel@tonic-gate return (Z_UPDATING_INDEX); 4107c478bd9Sstevel@tonic-gate } 411