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