4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <sys/param.h>
36 * The service deathrow mechanism addresses the problem of removing services
37 * from a non accessible SMF repository. In this case, we can't simply use the
38 * "SVCCFG_REPOSITORY=$ROOT/etc/svc/repository.db svccfg delete service_fmri"
39 * command as the alternate repository format is not committed and could be
40 * incompatible with the local SMF commands version.
42 * The idea is to manage a file (/etc/svc/deathrow) on the alternate root
43 * directory that lists the FMRIs that need to disappear from the repository
44 * when the system that uses this root directory boots up.
45 * r.manifest and i.manifest update the file /etc/svc/deathrow in the alternate
48 * When svc.startd daemon launches, it first reads the /etc/svc/deathrow file
49 * and for all FMRIs listed in this file, the service is not configured and
50 * dependencies on it are forced satisfied (during svc.startd init time only).
52 * Than manifest-import service will actually, as first task, delete the
53 * unconfigured services found in the /etc/svc/deathrow file and the
54 * manifest hash entry from the repository.
58 #define SVC_DEATHROW_FILE "/etc/svc/deathrow"
61 * These data structures are unprotected because they
62 * are modified by a single thread, at startup time.
63 * After initialization, these data structures are
64 * used only in read mode, thus requiring no protection.
67 /* list of deathrow fmris, created from the file SVC_DEATHROW_FILE */
68 typedef struct deathrow
{
70 uu_list_node_t deathrow_link
;
73 static uu_list_pool_t
*deathrow_pool
;
74 static uu_list_t
*deathrow_list
;
76 static boolean_t deathrow_handling_status
= B_FALSE
;
78 static deathrow_t
*fmri_in_deathrow_internal(const char *);
79 static void deathrow_add(const char *);
82 deathrow_handling_start()
84 assert(deathrow_handling_status
== B_FALSE
);
85 deathrow_handling_status
= B_TRUE
;
89 deathrow_handling_stop()
91 assert(deathrow_handling_status
== B_TRUE
);
92 deathrow_handling_status
= B_FALSE
;
103 size_t line_size
, sz
;
104 unsigned int line_parsed
= 0;
106 log_framework(LOG_DEBUG
, "Deathrow init\n");
108 while ((file
= fopen(SVC_DEATHROW_FILE
, "r")) == NULL
) {
109 if (errno
== EINTR
) {
112 if (errno
!= ENOENT
) {
113 log_framework(LOG_ERR
,
114 "Deathrow not processed. "
115 "Error opening file (%s): %s\n",
116 SVC_DEATHROW_FILE
, strerror(errno
));
121 deathrow_pool
= uu_list_pool_create("deathrow",
122 sizeof (deathrow_t
), offsetof(deathrow_t
, deathrow_link
),
123 NULL
, UU_LIST_POOL_DEBUG
);
124 if (deathrow_pool
== NULL
) {
125 uu_die("deathrow_init couldn't create deathrow_pool");
128 deathrow_list
= uu_list_create(deathrow_pool
, deathrow_list
, 0);
129 if (deathrow_list
== NULL
) {
130 uu_die("deathrow_init couldn't create deathrow_list");
134 * A deathrow file line looks like:
135 * <fmri>< ><manifest path>< ><package name><\n>
136 * (field separator is a space character)
138 line_size
= max_scf_fmri_size
+ 3 + MAXPATHLEN
+ MAXNAMELEN
;
139 line
= (char *)startd_alloc(line_size
);
142 while (fgets(line
, line_size
, file
) != NULL
) {
149 /* remove linefeed */
150 if (line
[sz
- 1] == '\n') {
153 manifest
= strchr(line
, ' ');
154 if (manifest
!= NULL
) {
158 pkgname
= strchr(manifest
, ' ');
159 if (pkgname
!= NULL
) {
165 if (fmri
!= NULL
&& strlen(fmri
) > 0 &&
166 strlen(fmri
) < max_scf_fmri_size
&&
167 manifest
!= NULL
&& strlen(manifest
) > 0 &&
168 pkgname
!= NULL
&& strlen(pkgname
) > 0) {
169 log_framework(LOG_DEBUG
,
170 "Deathrow parser <%s><%s><%s>\n",
171 fmri
, manifest
, pkgname
);
172 if (fmri_in_deathrow_internal(fmri
) == NULL
) {
173 /* fmri is not in list, add fmri */
177 log_framework(LOG_ERR
,
178 "Deathrow error processing file (%s). "
179 "Skipping line %u.\n",
180 SVC_DEATHROW_FILE
, line_parsed
);
184 startd_free(line
, line_size
);
187 if (uu_list_first(deathrow_list
) != NULL
) {
188 deathrow_handling_start();
198 if (deathrow_handling_status
== B_FALSE
) {
199 log_framework(LOG_DEBUG
, "Deathrow fini\n");
202 deathrow_handling_stop();
204 while ((d
= uu_list_teardown(deathrow_list
, &cookie
)) != NULL
) {
205 startd_free(d
->fmri
, strlen(d
->fmri
) + 1);
206 startd_free(d
, sizeof (deathrow_t
));
209 uu_list_destroy(deathrow_list
);
210 uu_list_pool_destroy(deathrow_pool
);
211 deathrow_pool
= NULL
;
212 deathrow_list
= NULL
;
213 log_framework(LOG_DEBUG
, "Deathrow fini\n");
217 deathrow_add(const char *fmri
)
221 assert(fmri
!= NULL
);
223 d
= startd_alloc(sizeof (deathrow_t
));
224 d
->fmri
= startd_alloc(strlen(fmri
) + 1);
225 (void) strcpy(d
->fmri
, fmri
);
226 uu_list_node_init(d
, &d
->deathrow_link
, deathrow_pool
);
227 (void) uu_list_insert_after(deathrow_list
, NULL
, d
);
229 log_framework(LOG_DEBUG
, "Deathrow added <%s>\n", d
->fmri
);
233 fmri_in_deathrow_internal(const char *fmri
)
237 assert(fmri
!= NULL
);
238 assert(deathrow_pool
!= NULL
);
239 assert(deathrow_list
!= NULL
);
241 for ((d
= uu_list_first(deathrow_list
)); d
!= NULL
;
242 d
= uu_list_next(deathrow_list
, d
)) {
243 if (strcmp(fmri
, d
->fmri
) == 0) {
251 is_fmri_in_deathrow(const char *fmri
)
253 if (deathrow_handling_status
== B_FALSE
) {
256 return ((fmri_in_deathrow_internal(fmri
) != NULL
) ? B_TRUE
: B_FALSE
);