1*70cbfe41SPhilippe Jung /* 2*70cbfe41SPhilippe Jung * CDDL HEADER START 3*70cbfe41SPhilippe Jung * 4*70cbfe41SPhilippe Jung * The contents of this file are subject to the terms of the 5*70cbfe41SPhilippe Jung * Common Development and Distribution License (the "License"). 6*70cbfe41SPhilippe Jung * You may not use this file except in compliance with the License. 7*70cbfe41SPhilippe Jung * 8*70cbfe41SPhilippe Jung * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*70cbfe41SPhilippe Jung * or http://www.opensolaris.org/os/licensing. 10*70cbfe41SPhilippe Jung * See the License for the specific language governing permissions 11*70cbfe41SPhilippe Jung * and limitations under the License. 12*70cbfe41SPhilippe Jung * 13*70cbfe41SPhilippe Jung * When distributing Covered Code, include this CDDL HEADER in each 14*70cbfe41SPhilippe Jung * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*70cbfe41SPhilippe Jung * If applicable, add the following below this CDDL HEADER, with the 16*70cbfe41SPhilippe Jung * fields enclosed by brackets "[]" replaced with your own identifying 17*70cbfe41SPhilippe Jung * information: Portions Copyright [yyyy] [name of copyright owner] 18*70cbfe41SPhilippe Jung * 19*70cbfe41SPhilippe Jung * CDDL HEADER END 20*70cbfe41SPhilippe Jung */ 21*70cbfe41SPhilippe Jung /* 22*70cbfe41SPhilippe Jung * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*70cbfe41SPhilippe Jung * Use is subject to license terms. 24*70cbfe41SPhilippe Jung */ 25*70cbfe41SPhilippe Jung 26*70cbfe41SPhilippe Jung 27*70cbfe41SPhilippe Jung #include <assert.h> 28*70cbfe41SPhilippe Jung #include <stdlib.h> 29*70cbfe41SPhilippe Jung #include <string.h> 30*70cbfe41SPhilippe Jung #include <unistd.h> 31*70cbfe41SPhilippe Jung #include <errno.h> 32*70cbfe41SPhilippe Jung #include <sys/param.h> 33*70cbfe41SPhilippe Jung #include "startd.h" 34*70cbfe41SPhilippe Jung 35*70cbfe41SPhilippe Jung /* 36*70cbfe41SPhilippe Jung * The service deathrow mechanism addresses the problem of removing services 37*70cbfe41SPhilippe Jung * from a non accessible SMF repository. In this case, we can't simply use the 38*70cbfe41SPhilippe Jung * "SVCCFG_REPOSITORY=$ROOT/etc/svc/repository.db svccfg delete service_fmri" 39*70cbfe41SPhilippe Jung * command as the alternate repository format is not committed and could be 40*70cbfe41SPhilippe Jung * incompatible with the local SMF commands version. 41*70cbfe41SPhilippe Jung * 42*70cbfe41SPhilippe Jung * The idea is to manage a file (/etc/svc/deathrow) on the alternate root 43*70cbfe41SPhilippe Jung * directory that lists the FMRIs that need to disappear from the repository 44*70cbfe41SPhilippe Jung * when the system that uses this root directory boots up. 45*70cbfe41SPhilippe Jung * r.manifest and i.manifest update the file /etc/svc/deathrow in the alternate 46*70cbfe41SPhilippe Jung * root case. 47*70cbfe41SPhilippe Jung * 48*70cbfe41SPhilippe Jung * When svc.startd daemon launches, it first reads the /etc/svc/deathrow file 49*70cbfe41SPhilippe Jung * and for all FMRIs listed in this file, the service is not configured and 50*70cbfe41SPhilippe Jung * dependencies on it are forced satisfied (during svc.startd init time only). 51*70cbfe41SPhilippe Jung * 52*70cbfe41SPhilippe Jung * Than manifest-import service will actually, as first task, delete the 53*70cbfe41SPhilippe Jung * unconfigured services found in the /etc/svc/deathrow file and the 54*70cbfe41SPhilippe Jung * manifest hash entry from the repository. 55*70cbfe41SPhilippe Jung * 56*70cbfe41SPhilippe Jung */ 57*70cbfe41SPhilippe Jung 58*70cbfe41SPhilippe Jung #define SVC_DEATHROW_FILE "/etc/svc/deathrow" 59*70cbfe41SPhilippe Jung 60*70cbfe41SPhilippe Jung /* 61*70cbfe41SPhilippe Jung * These data structures are unprotected because they 62*70cbfe41SPhilippe Jung * are modified by a single thread, at startup time. 63*70cbfe41SPhilippe Jung * After initialization, these data structures are 64*70cbfe41SPhilippe Jung * used only in read mode, thus requiring no protection. 65*70cbfe41SPhilippe Jung */ 66*70cbfe41SPhilippe Jung 67*70cbfe41SPhilippe Jung /* list of deathrow fmris, created from the file SVC_DEATHROW_FILE */ 68*70cbfe41SPhilippe Jung typedef struct deathrow { 69*70cbfe41SPhilippe Jung char *fmri; 70*70cbfe41SPhilippe Jung uu_list_node_t deathrow_link; 71*70cbfe41SPhilippe Jung } deathrow_t; 72*70cbfe41SPhilippe Jung 73*70cbfe41SPhilippe Jung static uu_list_pool_t *deathrow_pool; 74*70cbfe41SPhilippe Jung static uu_list_t *deathrow_list; 75*70cbfe41SPhilippe Jung 76*70cbfe41SPhilippe Jung static boolean_t deathrow_handling_status = B_FALSE; 77*70cbfe41SPhilippe Jung 78*70cbfe41SPhilippe Jung static deathrow_t *fmri_in_deathrow_internal(const char *); 79*70cbfe41SPhilippe Jung static void deathrow_add(const char *); 80*70cbfe41SPhilippe Jung 81*70cbfe41SPhilippe Jung static void 82*70cbfe41SPhilippe Jung deathrow_handling_start() 83*70cbfe41SPhilippe Jung { 84*70cbfe41SPhilippe Jung assert(deathrow_handling_status == B_FALSE); 85*70cbfe41SPhilippe Jung deathrow_handling_status = B_TRUE; 86*70cbfe41SPhilippe Jung } 87*70cbfe41SPhilippe Jung 88*70cbfe41SPhilippe Jung static void 89*70cbfe41SPhilippe Jung deathrow_handling_stop() 90*70cbfe41SPhilippe Jung { 91*70cbfe41SPhilippe Jung assert(deathrow_handling_status == B_TRUE); 92*70cbfe41SPhilippe Jung deathrow_handling_status = B_FALSE; 93*70cbfe41SPhilippe Jung } 94*70cbfe41SPhilippe Jung 95*70cbfe41SPhilippe Jung void 96*70cbfe41SPhilippe Jung deathrow_init() 97*70cbfe41SPhilippe Jung { 98*70cbfe41SPhilippe Jung FILE *file; 99*70cbfe41SPhilippe Jung char *line; 100*70cbfe41SPhilippe Jung char *fmri; 101*70cbfe41SPhilippe Jung char *manifest; 102*70cbfe41SPhilippe Jung char *pkgname; 103*70cbfe41SPhilippe Jung size_t line_size, sz; 104*70cbfe41SPhilippe Jung unsigned int line_parsed = 0; 105*70cbfe41SPhilippe Jung 106*70cbfe41SPhilippe Jung log_framework(LOG_DEBUG, "Deathrow init\n"); 107*70cbfe41SPhilippe Jung 108*70cbfe41SPhilippe Jung while ((file = fopen(SVC_DEATHROW_FILE, "r")) == NULL) { 109*70cbfe41SPhilippe Jung if (errno == EINTR) { 110*70cbfe41SPhilippe Jung continue; 111*70cbfe41SPhilippe Jung } 112*70cbfe41SPhilippe Jung if (errno != ENOENT) { 113*70cbfe41SPhilippe Jung log_framework(LOG_ERR, 114*70cbfe41SPhilippe Jung "Deathrow not processed. " 115*70cbfe41SPhilippe Jung "Error opening file (%s): %s\n", 116*70cbfe41SPhilippe Jung SVC_DEATHROW_FILE, strerror(errno)); 117*70cbfe41SPhilippe Jung } 118*70cbfe41SPhilippe Jung return; 119*70cbfe41SPhilippe Jung } 120*70cbfe41SPhilippe Jung 121*70cbfe41SPhilippe Jung deathrow_pool = uu_list_pool_create("deathrow", 122*70cbfe41SPhilippe Jung sizeof (deathrow_t), offsetof(deathrow_t, deathrow_link), 123*70cbfe41SPhilippe Jung NULL, UU_LIST_POOL_DEBUG); 124*70cbfe41SPhilippe Jung if (deathrow_pool == NULL) { 125*70cbfe41SPhilippe Jung uu_die("deathrow_init couldn't create deathrow_pool"); 126*70cbfe41SPhilippe Jung } 127*70cbfe41SPhilippe Jung 128*70cbfe41SPhilippe Jung deathrow_list = uu_list_create(deathrow_pool, deathrow_list, 0); 129*70cbfe41SPhilippe Jung if (deathrow_list == NULL) { 130*70cbfe41SPhilippe Jung uu_die("deathrow_init couldn't create deathrow_list"); 131*70cbfe41SPhilippe Jung } 132*70cbfe41SPhilippe Jung 133*70cbfe41SPhilippe Jung /* 134*70cbfe41SPhilippe Jung * A deathrow file line looks like: 135*70cbfe41SPhilippe Jung * <fmri>< ><manifest path>< ><package name><\n> 136*70cbfe41SPhilippe Jung * (field separator is a space character) 137*70cbfe41SPhilippe Jung */ 138*70cbfe41SPhilippe Jung line_size = max_scf_fmri_size + 3 + MAXPATHLEN + MAXNAMELEN; 139*70cbfe41SPhilippe Jung line = (char *)startd_alloc(line_size); 140*70cbfe41SPhilippe Jung *line = '\0'; 141*70cbfe41SPhilippe Jung 142*70cbfe41SPhilippe Jung while (fgets(line, line_size, file) != NULL) { 143*70cbfe41SPhilippe Jung line_parsed++; 144*70cbfe41SPhilippe Jung fmri = NULL; 145*70cbfe41SPhilippe Jung manifest = NULL; 146*70cbfe41SPhilippe Jung pkgname = NULL; 147*70cbfe41SPhilippe Jung sz = strlen(line); 148*70cbfe41SPhilippe Jung if (sz > 0) { 149*70cbfe41SPhilippe Jung /* remove linefeed */ 150*70cbfe41SPhilippe Jung if (line[sz - 1] == '\n') { 151*70cbfe41SPhilippe Jung line[sz - 1] = '\0'; 152*70cbfe41SPhilippe Jung } 153*70cbfe41SPhilippe Jung manifest = strchr(line, ' '); 154*70cbfe41SPhilippe Jung if (manifest != NULL) { 155*70cbfe41SPhilippe Jung fmri = line; 156*70cbfe41SPhilippe Jung *manifest = '\0'; 157*70cbfe41SPhilippe Jung manifest++; 158*70cbfe41SPhilippe Jung pkgname = strchr(manifest, ' '); 159*70cbfe41SPhilippe Jung if (pkgname != NULL) { 160*70cbfe41SPhilippe Jung *pkgname = '\0'; 161*70cbfe41SPhilippe Jung pkgname++; 162*70cbfe41SPhilippe Jung } 163*70cbfe41SPhilippe Jung } 164*70cbfe41SPhilippe Jung } 165*70cbfe41SPhilippe Jung if (fmri != NULL && strlen(fmri) > 0 && 166*70cbfe41SPhilippe Jung strlen(fmri) < max_scf_fmri_size && 167*70cbfe41SPhilippe Jung manifest != NULL && strlen(manifest) > 0 && 168*70cbfe41SPhilippe Jung pkgname != NULL && strlen(pkgname) > 0) { 169*70cbfe41SPhilippe Jung log_framework(LOG_DEBUG, 170*70cbfe41SPhilippe Jung "Deathrow parser <%s><%s><%s>\n", 171*70cbfe41SPhilippe Jung fmri, manifest, pkgname); 172*70cbfe41SPhilippe Jung if (fmri_in_deathrow_internal(fmri) == NULL) { 173*70cbfe41SPhilippe Jung /* fmri is not in list, add fmri */ 174*70cbfe41SPhilippe Jung deathrow_add(fmri); 175*70cbfe41SPhilippe Jung } 176*70cbfe41SPhilippe Jung } else { 177*70cbfe41SPhilippe Jung log_framework(LOG_ERR, 178*70cbfe41SPhilippe Jung "Deathrow error processing file (%s). " 179*70cbfe41SPhilippe Jung "Skipping line %u.\n", 180*70cbfe41SPhilippe Jung SVC_DEATHROW_FILE, line_parsed); 181*70cbfe41SPhilippe Jung } 182*70cbfe41SPhilippe Jung *line = '\0'; 183*70cbfe41SPhilippe Jung } 184*70cbfe41SPhilippe Jung startd_free(line, line_size); 185*70cbfe41SPhilippe Jung (void) fclose(file); 186*70cbfe41SPhilippe Jung 187*70cbfe41SPhilippe Jung if (uu_list_first(deathrow_list) != NULL) { 188*70cbfe41SPhilippe Jung deathrow_handling_start(); 189*70cbfe41SPhilippe Jung } 190*70cbfe41SPhilippe Jung } 191*70cbfe41SPhilippe Jung 192*70cbfe41SPhilippe Jung void 193*70cbfe41SPhilippe Jung deathrow_fini() 194*70cbfe41SPhilippe Jung { 195*70cbfe41SPhilippe Jung deathrow_t *d; 196*70cbfe41SPhilippe Jung void *cookie = NULL; 197*70cbfe41SPhilippe Jung 198*70cbfe41SPhilippe Jung if (deathrow_handling_status == B_FALSE) { 199*70cbfe41SPhilippe Jung log_framework(LOG_DEBUG, "Deathrow fini\n"); 200*70cbfe41SPhilippe Jung return; 201*70cbfe41SPhilippe Jung } 202*70cbfe41SPhilippe Jung deathrow_handling_stop(); 203*70cbfe41SPhilippe Jung 204*70cbfe41SPhilippe Jung while ((d = uu_list_teardown(deathrow_list, &cookie)) != NULL) { 205*70cbfe41SPhilippe Jung startd_free(d->fmri, strlen(d->fmri) + 1); 206*70cbfe41SPhilippe Jung startd_free(d, sizeof (deathrow_t)); 207*70cbfe41SPhilippe Jung } 208*70cbfe41SPhilippe Jung 209*70cbfe41SPhilippe Jung uu_list_destroy(deathrow_list); 210*70cbfe41SPhilippe Jung uu_list_pool_destroy(deathrow_pool); 211*70cbfe41SPhilippe Jung deathrow_pool = NULL; 212*70cbfe41SPhilippe Jung deathrow_list = NULL; 213*70cbfe41SPhilippe Jung log_framework(LOG_DEBUG, "Deathrow fini\n"); 214*70cbfe41SPhilippe Jung } 215*70cbfe41SPhilippe Jung 216*70cbfe41SPhilippe Jung static void 217*70cbfe41SPhilippe Jung deathrow_add(const char *fmri) 218*70cbfe41SPhilippe Jung { 219*70cbfe41SPhilippe Jung deathrow_t *d; 220*70cbfe41SPhilippe Jung 221*70cbfe41SPhilippe Jung assert(fmri != NULL); 222*70cbfe41SPhilippe Jung 223*70cbfe41SPhilippe Jung d = startd_alloc(sizeof (deathrow_t)); 224*70cbfe41SPhilippe Jung d->fmri = startd_alloc(strlen(fmri) + 1); 225*70cbfe41SPhilippe Jung (void) strcpy(d->fmri, fmri); 226*70cbfe41SPhilippe Jung uu_list_node_init(d, &d->deathrow_link, deathrow_pool); 227*70cbfe41SPhilippe Jung (void) uu_list_insert_after(deathrow_list, NULL, d); 228*70cbfe41SPhilippe Jung 229*70cbfe41SPhilippe Jung log_framework(LOG_DEBUG, "Deathrow added <%s>\n", d->fmri); 230*70cbfe41SPhilippe Jung } 231*70cbfe41SPhilippe Jung 232*70cbfe41SPhilippe Jung static deathrow_t * 233*70cbfe41SPhilippe Jung fmri_in_deathrow_internal(const char *fmri) 234*70cbfe41SPhilippe Jung { 235*70cbfe41SPhilippe Jung deathrow_t *d; 236*70cbfe41SPhilippe Jung 237*70cbfe41SPhilippe Jung assert(fmri != NULL); 238*70cbfe41SPhilippe Jung assert(deathrow_pool != NULL); 239*70cbfe41SPhilippe Jung assert(deathrow_list != NULL); 240*70cbfe41SPhilippe Jung 241*70cbfe41SPhilippe Jung for ((d = uu_list_first(deathrow_list)); d != NULL; 242*70cbfe41SPhilippe Jung d = uu_list_next(deathrow_list, d)) { 243*70cbfe41SPhilippe Jung if (strcmp(fmri, d->fmri) == 0) { 244*70cbfe41SPhilippe Jung return (d); 245*70cbfe41SPhilippe Jung } 246*70cbfe41SPhilippe Jung } 247*70cbfe41SPhilippe Jung return (NULL); 248*70cbfe41SPhilippe Jung } 249*70cbfe41SPhilippe Jung 250*70cbfe41SPhilippe Jung boolean_t 251*70cbfe41SPhilippe Jung is_fmri_in_deathrow(const char *fmri) 252*70cbfe41SPhilippe Jung { 253*70cbfe41SPhilippe Jung if (deathrow_handling_status == B_FALSE) { 254*70cbfe41SPhilippe Jung return (B_FALSE); 255*70cbfe41SPhilippe Jung } 256*70cbfe41SPhilippe Jung return ((fmri_in_deathrow_internal(fmri) != NULL) ? B_TRUE : B_FALSE); 257*70cbfe41SPhilippe Jung } 258