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*6be356c5Sgz161490 * Copyright 2006 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 <string.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <fcntl.h> 437c478bd9Sstevel@tonic-gate #include <sys/stat.h> 447c478bd9Sstevel@tonic-gate #include <assert.h> 45108322fbScarlsonj #include <uuid/uuid.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. 59108322fbScarlsonj * 60108322fbScarlsonj * It never returns NULL. 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static char * 647c478bd9Sstevel@tonic-gate gettok(char **cpp) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate char *cp = *cpp, *retv; 677c478bd9Sstevel@tonic-gate boolean_t quoted = B_FALSE; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (cp == NULL) 707c478bd9Sstevel@tonic-gate return (""); 717c478bd9Sstevel@tonic-gate if (*cp == '"') { 727c478bd9Sstevel@tonic-gate quoted = B_TRUE; 737c478bd9Sstevel@tonic-gate cp++; 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate retv = cp; 767c478bd9Sstevel@tonic-gate if (quoted) { 777c478bd9Sstevel@tonic-gate while (*cp != '\0' && *cp != '"') 787c478bd9Sstevel@tonic-gate cp++; 797c478bd9Sstevel@tonic-gate if (*cp == '"') 807c478bd9Sstevel@tonic-gate *cp++ = '\0'; 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate while (*cp != '\0' && *cp != ':') 837c478bd9Sstevel@tonic-gate cp++; 847c478bd9Sstevel@tonic-gate if (*cp == '\0') { 857c478bd9Sstevel@tonic-gate *cpp = NULL; 867c478bd9Sstevel@tonic-gate } else { 877c478bd9Sstevel@tonic-gate *cp++ = '\0'; 887c478bd9Sstevel@tonic-gate *cpp = cp; 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate return (retv); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate char * 947c478bd9Sstevel@tonic-gate getzoneent(FILE *cookie) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate struct zoneent *ze; 977c478bd9Sstevel@tonic-gate char *name; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if ((ze = getzoneent_private(cookie)) == NULL) 1007c478bd9Sstevel@tonic-gate return (NULL); 1017c478bd9Sstevel@tonic-gate name = strdup(ze->zone_name); 1027c478bd9Sstevel@tonic-gate free(ze); 1037c478bd9Sstevel@tonic-gate return (name); 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate struct zoneent * 1077c478bd9Sstevel@tonic-gate getzoneent_private(FILE *cookie) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate char *cp, buf[MAX_INDEX_LEN], *p; 1107c478bd9Sstevel@tonic-gate struct zoneent *ze; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (cookie == NULL) 1137c478bd9Sstevel@tonic-gate return (NULL); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate if ((ze = malloc(sizeof (struct zoneent))) == NULL) 1167c478bd9Sstevel@tonic-gate return (NULL); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate for (;;) { 1197c478bd9Sstevel@tonic-gate if (fgets(buf, sizeof (buf), cookie) == NULL) { 1207c478bd9Sstevel@tonic-gate free(ze); 1217c478bd9Sstevel@tonic-gate return (NULL); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate if ((cp = strpbrk(buf, "\r\n")) == NULL) { 1247c478bd9Sstevel@tonic-gate /* this represents a line that's too long */ 1257c478bd9Sstevel@tonic-gate continue; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate *cp = '\0'; 1287c478bd9Sstevel@tonic-gate cp = buf; 1297c478bd9Sstevel@tonic-gate if (*cp == '#') { 1307c478bd9Sstevel@tonic-gate /* skip comment lines */ 1317c478bd9Sstevel@tonic-gate continue; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate p = gettok(&cp); 134108322fbScarlsonj if (*p == '\0' || strlen(p) >= ZONENAME_MAX) { 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * empty or very long zone names are not allowed 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate continue; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate (void) strlcpy(ze->zone_name, p, ZONENAME_MAX); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate p = gettok(&cp); 143108322fbScarlsonj if (*p == '\0') { 1447c478bd9Sstevel@tonic-gate /* state field should not be empty */ 1457c478bd9Sstevel@tonic-gate continue; 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate errno = 0; 1487c478bd9Sstevel@tonic-gate if (strcmp(p, ZONE_STATE_STR_CONFIGURED) == 0) { 1497c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_CONFIGURED; 1507c478bd9Sstevel@tonic-gate } else if (strcmp(p, ZONE_STATE_STR_INCOMPLETE) == 0) { 1517c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_INCOMPLETE; 1527c478bd9Sstevel@tonic-gate } else if (strcmp(p, ZONE_STATE_STR_INSTALLED) == 0) { 1537c478bd9Sstevel@tonic-gate ze->zone_state = ZONE_STATE_INSTALLED; 154108322fbScarlsonj } else { 1557c478bd9Sstevel@tonic-gate continue; 156108322fbScarlsonj } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate p = gettok(&cp); 159108322fbScarlsonj if (strlen(p) >= MAXPATHLEN) { 1607c478bd9Sstevel@tonic-gate /* very long paths are not allowed */ 1617c478bd9Sstevel@tonic-gate continue; 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate (void) strlcpy(ze->zone_path, p, MAXPATHLEN); 1647c478bd9Sstevel@tonic-gate 165108322fbScarlsonj p = gettok(&cp); 166108322fbScarlsonj if (uuid_parse(p, ze->zone_uuid) == -1) 167108322fbScarlsonj uuid_clear(ze->zone_uuid); 168108322fbScarlsonj 1697c478bd9Sstevel@tonic-gate break; 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate return (ze); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 175108322fbScarlsonj static boolean_t 176108322fbScarlsonj get_index_path(char *path) 177108322fbScarlsonj { 178108322fbScarlsonj return (snprintf(path, MAXPATHLEN, "%s%s", zonecfg_root, 179108322fbScarlsonj ZONE_INDEX_FILE) < MAXPATHLEN); 180108322fbScarlsonj } 181108322fbScarlsonj 1827c478bd9Sstevel@tonic-gate FILE * 1837c478bd9Sstevel@tonic-gate setzoneent(void) 1847c478bd9Sstevel@tonic-gate { 185108322fbScarlsonj char path[MAXPATHLEN]; 186108322fbScarlsonj 187108322fbScarlsonj if (!get_index_path(path)) { 188108322fbScarlsonj errno = EINVAL; 189108322fbScarlsonj return (NULL); 190108322fbScarlsonj } 191108322fbScarlsonj return (fopen(path, "r")); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate void 1957c478bd9Sstevel@tonic-gate endzoneent(FILE *cookie) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate if (cookie != NULL) 1987c478bd9Sstevel@tonic-gate (void) fclose(cookie); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate static int 202108322fbScarlsonj lock_index_file(void) 2037c478bd9Sstevel@tonic-gate { 204108322fbScarlsonj int lock_fd; 2057c478bd9Sstevel@tonic-gate struct flock lock; 206108322fbScarlsonj char path[MAXPATHLEN]; 2077c478bd9Sstevel@tonic-gate 208108322fbScarlsonj if (snprintf(path, sizeof (path), "%s%s", zonecfg_root, 209108322fbScarlsonj ZONE_INDEX_LOCK_DIR) >= sizeof (path)) 210108322fbScarlsonj return (-1); 211108322fbScarlsonj if ((mkdir(path, S_IRWXU) == -1) && errno != EEXIST) 212108322fbScarlsonj return (-1); 213108322fbScarlsonj if (strlcat(path, ZONE_INDEX_LOCK_FILE, sizeof (path)) >= 214108322fbScarlsonj sizeof (path)) 215108322fbScarlsonj return (-1); 216108322fbScarlsonj lock_fd = open(path, O_CREAT|O_RDWR, 0644); 217108322fbScarlsonj if (lock_fd == -1) 218108322fbScarlsonj return (-1); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 2217c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2227c478bd9Sstevel@tonic-gate lock.l_start = 0; 2237c478bd9Sstevel@tonic-gate lock.l_len = 0; 2247c478bd9Sstevel@tonic-gate 225108322fbScarlsonj if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { 226108322fbScarlsonj (void) close(lock_fd); 227108322fbScarlsonj return (-1); 228108322fbScarlsonj } 2297c478bd9Sstevel@tonic-gate 230108322fbScarlsonj return (lock_fd); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate static int 2347c478bd9Sstevel@tonic-gate unlock_index_file(int lock_fd) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate struct flock lock; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate lock.l_type = F_UNLCK; 2397c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2407c478bd9Sstevel@tonic-gate lock.l_start = 0; 2417c478bd9Sstevel@tonic-gate lock.l_len = 0; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLK, &lock) == -1) 2447c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (close(lock_fd) == -1) 2477c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate return (Z_OK); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * This function adds or removes a zone name et al. to the index file. 2547c478bd9Sstevel@tonic-gate * 2557c478bd9Sstevel@tonic-gate * If ze->zone_state is < 0, it means leave the 2567c478bd9Sstevel@tonic-gate * existing value unchanged; this is only meaningful when operation == 257087719fdSdp * PZE_MODIFY (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE). 2587c478bd9Sstevel@tonic-gate * 259087719fdSdp * A zero-length ze->zone_path means leave the existing value 2607c478bd9Sstevel@tonic-gate * unchanged; this is only meaningful when operation == PZE_MODIFY 261087719fdSdp * (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE). 262087719fdSdp * 263087719fdSdp * A zero-length ze->zone_newname means leave the existing name 264087719fdSdp * unchanged; otherwise the zone is renamed to zone_newname. This is 265087719fdSdp * only meaningful when operation == PZE_MODIFY. 2667c478bd9Sstevel@tonic-gate * 2677c478bd9Sstevel@tonic-gate * Locking and unlocking is done via the functions above. 2687c478bd9Sstevel@tonic-gate * The file itself is not modified in place; rather, a copy is made which 2697c478bd9Sstevel@tonic-gate * is modified, then the copy is atomically renamed back to the main file. 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate int 2727c478bd9Sstevel@tonic-gate putzoneent(struct zoneent *ze, zoneent_op_t operation) 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate FILE *index_file, *tmp_file; 2757c478bd9Sstevel@tonic-gate char *tmp_file_name, buf[MAX_INDEX_LEN], orig_buf[MAX_INDEX_LEN]; 276108322fbScarlsonj char zone[ZONENAME_MAX]; 2777c478bd9Sstevel@tonic-gate char line[MAX_INDEX_LEN]; 2787c478bd9Sstevel@tonic-gate int tmp_file_desc, lock_fd, err; 2797c478bd9Sstevel@tonic-gate boolean_t exists = B_FALSE, need_quotes; 2807c478bd9Sstevel@tonic-gate char *cp, *p; 281108322fbScarlsonj char path[MAXPATHLEN]; 282*6be356c5Sgz161490 char uuidstr[UUID_PRINTABLE_STRING_LENGTH]; 283108322fbScarlsonj size_t tlen; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate assert(ze != NULL); 2867c478bd9Sstevel@tonic-gate if (operation == PZE_ADD && 2877c478bd9Sstevel@tonic-gate (ze->zone_state < 0 || strlen(ze->zone_path) == 0)) 2887c478bd9Sstevel@tonic-gate return (Z_INVAL); 289087719fdSdp 290087719fdSdp if (operation != PZE_MODIFY && strlen(ze->zone_newname) != 0) 291087719fdSdp return (Z_INVAL); 292087719fdSdp 293108322fbScarlsonj if ((lock_fd = lock_index_file()) == -1) 294108322fbScarlsonj return (Z_LOCKING_FILE); 295108322fbScarlsonj 296108322fbScarlsonj /* using sizeof gives us room for the terminating NUL byte as well */ 297108322fbScarlsonj tlen = sizeof (_PATH_TMPFILE) + strlen(zonecfg_root); 298108322fbScarlsonj tmp_file_name = malloc(tlen); 2997c478bd9Sstevel@tonic-gate if (tmp_file_name == NULL) { 3007c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 3017c478bd9Sstevel@tonic-gate return (Z_NOMEM); 3027c478bd9Sstevel@tonic-gate } 303108322fbScarlsonj (void) snprintf(tmp_file_name, tlen, "%s%s", zonecfg_root, 304108322fbScarlsonj _PATH_TMPFILE); 305108322fbScarlsonj 3067c478bd9Sstevel@tonic-gate tmp_file_desc = mkstemp(tmp_file_name); 3077c478bd9Sstevel@tonic-gate if (tmp_file_desc == -1) { 3087c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 3097c478bd9Sstevel@tonic-gate free(tmp_file_name); 3107c478bd9Sstevel@tonic-gate (void) unlock_index_file(lock_fd); 3117c478bd9Sstevel@tonic-gate return (Z_TEMP_FILE); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate if ((tmp_file = fdopen(tmp_file_desc, "w")) == NULL) { 3147c478bd9Sstevel@tonic-gate (void) close(tmp_file_desc); 315108322fbScarlsonj err = Z_MISC_FS; 316108322fbScarlsonj goto error; 3177c478bd9Sstevel@tonic-gate } 318108322fbScarlsonj if (!get_index_path(path)) { 319108322fbScarlsonj err = Z_MISC_FS; 320108322fbScarlsonj goto error; 321108322fbScarlsonj } 322108322fbScarlsonj if ((index_file = fopen(path, "r")) == NULL) { 323108322fbScarlsonj err = Z_MISC_FS; 324108322fbScarlsonj goto error; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * We need to quote a path which contains a ":"; this should only 3297c478bd9Sstevel@tonic-gate * affect the zonepath, as zone names do not allow such characters, 3307c478bd9Sstevel@tonic-gate * and zone states do not have them either. Same with double-quotes 3317c478bd9Sstevel@tonic-gate * themselves: they are not allowed in zone names, and do not occur 3327c478bd9Sstevel@tonic-gate * in zone states, and in theory should never occur in a zonepath 3337c478bd9Sstevel@tonic-gate * since zonecfg does not support a method for escaping them. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate need_quotes = (strchr(ze->zone_path, ':') != NULL); 3367c478bd9Sstevel@tonic-gate 337108322fbScarlsonj /* 338108322fbScarlsonj * If this zone doesn't yet have a unique identifier, then give it one. 339108322fbScarlsonj */ 340108322fbScarlsonj if (uuid_is_null(ze->zone_uuid)) 341108322fbScarlsonj uuid_generate(ze->zone_uuid); 342108322fbScarlsonj uuid_unparse(ze->zone_uuid, uuidstr); 343108322fbScarlsonj 344108322fbScarlsonj (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s:%s\n", 345108322fbScarlsonj ze->zone_name, zone_state_str(ze->zone_state), 346108322fbScarlsonj need_quotes ? "\"" : "", ze->zone_path, need_quotes ? "\"" : "", 347108322fbScarlsonj uuidstr); 3487c478bd9Sstevel@tonic-gate for (;;) { 3497c478bd9Sstevel@tonic-gate if (fgets(buf, sizeof (buf), index_file) == NULL) { 3507c478bd9Sstevel@tonic-gate if (operation == PZE_ADD && !exists) 3517c478bd9Sstevel@tonic-gate (void) fputs(line, tmp_file); 3527c478bd9Sstevel@tonic-gate break; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate (void) strlcpy(orig_buf, buf, sizeof (orig_buf)); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if ((cp = strpbrk(buf, "\r\n")) == NULL) { 3577c478bd9Sstevel@tonic-gate /* this represents a line that's too long */ 3587c478bd9Sstevel@tonic-gate continue; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate *cp = '\0'; 3617c478bd9Sstevel@tonic-gate cp = buf; 3627c478bd9Sstevel@tonic-gate if (*cp == '#') { 3637c478bd9Sstevel@tonic-gate /* skip comment lines */ 3647c478bd9Sstevel@tonic-gate (void) fputs(orig_buf, tmp_file); 3657c478bd9Sstevel@tonic-gate continue; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate p = gettok(&cp); 368108322fbScarlsonj if (*p == '\0' || strlen(p) >= ZONENAME_MAX) { 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * empty or very long zone names are not allowed 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate continue; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate (void) strlcpy(zone, p, ZONENAME_MAX); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if (strcmp(zone, ze->zone_name) == 0) { 3777c478bd9Sstevel@tonic-gate exists = B_TRUE; /* already there */ 3787c478bd9Sstevel@tonic-gate if (operation == PZE_ADD) { 3797c478bd9Sstevel@tonic-gate /* can't add same zone */ 380108322fbScarlsonj err = Z_UPDATING_INDEX; 3817c478bd9Sstevel@tonic-gate goto error; 3827c478bd9Sstevel@tonic-gate } else if (operation == PZE_MODIFY) { 3837c478bd9Sstevel@tonic-gate char tmp_state[ZONE_STATE_MAXSTRLEN + 1]; 384087719fdSdp char *tmp_name; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (ze->zone_state >= 0 && 3877c478bd9Sstevel@tonic-gate strlen(ze->zone_path) > 0) { 3887c478bd9Sstevel@tonic-gate /* use specified values */ 3897c478bd9Sstevel@tonic-gate (void) fputs(line, tmp_file); 3907c478bd9Sstevel@tonic-gate continue; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate /* use existing value for state */ 3937c478bd9Sstevel@tonic-gate p = gettok(&cp); 394108322fbScarlsonj if (*p == '\0') { 3957c478bd9Sstevel@tonic-gate /* state field should not be empty */ 396108322fbScarlsonj err = Z_UPDATING_INDEX; 3977c478bd9Sstevel@tonic-gate goto error; 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_state, 4007c478bd9Sstevel@tonic-gate (ze->zone_state < 0) ? p : 4017c478bd9Sstevel@tonic-gate zone_state_str(ze->zone_state), 4027c478bd9Sstevel@tonic-gate sizeof (tmp_state)); 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate p = gettok(&cp); 4057c478bd9Sstevel@tonic-gate 406087719fdSdp /* 407087719fdSdp * If a new name is supplied, use it. 408087719fdSdp */ 409087719fdSdp if (strlen(ze->zone_newname) != 0) 410087719fdSdp tmp_name = ze->zone_newname; 411087719fdSdp else 412087719fdSdp tmp_name = ze->zone_name; 413087719fdSdp 414108322fbScarlsonj (void) fprintf(tmp_file, "%s:%s:%s%s%s:%s\n", 415087719fdSdp tmp_name, tmp_state, 4167c478bd9Sstevel@tonic-gate need_quotes ? "\"" : "", 4177c478bd9Sstevel@tonic-gate (strlen(ze->zone_path) == 0) ? p : 418108322fbScarlsonj ze->zone_path, need_quotes ? "\"" : "", 419108322fbScarlsonj uuidstr); 4207c478bd9Sstevel@tonic-gate } 421087719fdSdp /* else if (operation == PZE_REMOVE) { no-op } */ 4227c478bd9Sstevel@tonic-gate } else { 4237c478bd9Sstevel@tonic-gate (void) fputs(orig_buf, tmp_file); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate (void) fclose(index_file); 428108322fbScarlsonj index_file = NULL; 4297c478bd9Sstevel@tonic-gate if (fclose(tmp_file) != 0) { 430108322fbScarlsonj tmp_file = NULL; 431108322fbScarlsonj err = Z_MISC_FS; 432108322fbScarlsonj goto error; 4337c478bd9Sstevel@tonic-gate } 434108322fbScarlsonj tmp_file = NULL; 4357c478bd9Sstevel@tonic-gate (void) chmod(tmp_file_name, 0644); 436108322fbScarlsonj if (rename(tmp_file_name, path) == -1) { 437108322fbScarlsonj err = errno == EACCES ? Z_ACCES : Z_MISC_FS; 438108322fbScarlsonj goto error; 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate free(tmp_file_name); 4417c478bd9Sstevel@tonic-gate if (unlock_index_file(lock_fd) != Z_OK) 4427c478bd9Sstevel@tonic-gate return (Z_UNLOCKING_FILE); 4437c478bd9Sstevel@tonic-gate return (Z_OK); 444108322fbScarlsonj 4457c478bd9Sstevel@tonic-gate error: 446108322fbScarlsonj if (index_file != NULL) 4477c478bd9Sstevel@tonic-gate (void) fclose(index_file); 448108322fbScarlsonj if (tmp_file != NULL) 4497c478bd9Sstevel@tonic-gate (void) fclose(tmp_file); 4507c478bd9Sstevel@tonic-gate (void) unlink(tmp_file_name); 4517c478bd9Sstevel@tonic-gate free(tmp_file_name); 452108322fbScarlsonj (void) unlock_index_file(lock_fd); 453108322fbScarlsonj return (err); 4547c478bd9Sstevel@tonic-gate } 455