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 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Just in case we're not in a build environment, make sure that
30 * TEXT_DOMAIN gets set to something.
32 #if !defined(TEXT_DOMAIN)
33 #define TEXT_DOMAIN "SYS_TEST"
37 * patch /kernel/drv/md.conf file
39 #include <sys/types.h>
42 #include <sys/lvm/md_mddb.h>
45 * magic strings in system
47 #define BEGROOTSTR "* Begin MDD root info (do not edit)\n"
48 #define ENDROOTSTR "* End MDD root info (do not edit)\n"
49 #define BEGMDDBSTR "# Begin MDD database info (do not edit)\n"
50 #define ENDMDDBSTR "# End MDD database info (do not edit)\n"
53 * copy system file, yank root and database lines
57 char *sname
, /* system file name */
58 int doroot
, /* remove mdd root stuff */
59 int domddb
, /* remove mdd database stuff */
60 int doit
, /* really copy file */
61 int verbose
, /* show what we're doing */
62 char **tname
, /* returned temp file name */
63 FILE **tfp
, /* returned open FILE */
64 md_error_t
*ep
/* returned error */
69 char buf
[MDDB_BOOTLIST_MAX_LEN
];
74 assert(sname
!= NULL
);
75 assert(tname
!= NULL
);
80 *tname
= Malloc(strlen(sname
) + strlen(".tmp") + 1);
81 (void) strcpy(*tname
, sname
);
82 (void) strcat(*tname
, ".tmp");
84 /* copy system file, yank stuff */
85 if (((fp
= fopen(sname
, "r")) == NULL
) ||
86 (fstat(fileno(fp
), &sbuf
) != 0)) {
87 if (errno
!= ENOENT
) {
88 (void) mdsyserror(ep
, errno
, sname
);
93 if ((*tfp
= fopen(*tname
, "w")) == NULL
) {
95 * If we are on the miniroot we need to create
96 * files in /var/tmp. Opening a writable file
97 * in the miniroot result is EROFS error.
100 (void) mdsyserror(ep
, errno
, *tname
);
104 *tname
= tempnam("/var/tmp", "svm_");
105 if (*tname
== NULL
) {
106 (void) mdsyserror(ep
, errno
, NULL
);
109 if ((*tfp
= fopen(*tname
, "w")) == NULL
) {
110 (void) mdsyserror(ep
, errno
, *tname
);
115 if ((fchmod(fileno(*tfp
), (sbuf
.st_mode
& 0777))
117 (fchown(fileno(*tfp
), sbuf
.st_uid
, sbuf
.st_gid
)
119 (void) mdsyserror(ep
, errno
, *tname
);
125 (void) printf(dgettext(TEXT_DOMAIN
,
126 "Delete the following lines from %s:\n\n"), sname
);
128 while ((fp
!= NULL
) && (fgets(buf
, sizeof (buf
), fp
) != NULL
)) {
129 if ((doroot
) && (strcmp(buf
, BEGROOTSTR
) == 0)) {
132 (void) printf("%s", buf
);
136 if (strcmp(buf
, ENDROOTSTR
) == 0)
139 (void) printf("%s", buf
);
142 if ((domddb
) && (strcmp(buf
, BEGMDDBSTR
) == 0)) {
145 (void) printf("%s", buf
);
149 if (strcmp(buf
, ENDMDDBSTR
) == 0)
152 (void) printf("%s", buf
);
156 if (fputs(buf
, *tfp
) == EOF
) {
157 (void) mdsyserror(ep
, errno
, *tname
);
165 (void) mdsyserror(ep
, errno
, sname
);
173 /* make sure we didn't stop mid-delete */
174 if ((delroot
) || (delmddb
)) {
175 (void) mderror(ep
, MDE_SYSTEM_FILE
, sname
);
181 if ((fflush(*tfp
) != 0) ||
182 (fsync(fileno(*tfp
)) != 0)) {
183 (void) mdsyserror(ep
, errno
, *tname
);
191 /* cleanup, return error */
195 if (*tname
!= NULL
) {
196 (void) unlink(*tname
);
205 * append root on MD lines to system
208 meta_systemfile_append_mdroot(
209 mdname_t
*rootnp
, /* root device name */
210 char *sname
, /* system file name */
211 char *tname
, /* temp file name */
212 FILE *tfp
, /* temp FILE */
213 int ismeta
, /* is a metadevice */
214 int doit
, /* really patch file */
215 int verbose
, /* show what we're doing */
222 assert(sname
!= NULL
);
223 assert(tname
!= NULL
);
224 assert(!doit
|| tfp
!= NULL
);
226 /* get root /devices name */
227 if ((longblkname
= metagetdevicesname(rootnp
, ep
)) == NULL
)
232 (void) printf(dgettext(TEXT_DOMAIN
,
233 "Add the following lines to %s:\n\n"), sname
);
234 (void) printf("%s", BEGROOTSTR
);
237 if (fprintf(tfp
, "%s", BEGROOTSTR
) == EOF
) {
238 return (mdsyserror(ep
, errno
, tname
));
245 (void) printf("rootdev:%s\n", longblkname
);
247 if (fprintf(tfp
, "rootdev:%s\n", longblkname
) == EOF
) {
248 return (mdsyserror(ep
, errno
, tname
));
255 (void) printf("%s\n", ENDROOTSTR
);
258 if (fprintf(tfp
, "%s", ENDROOTSTR
) == EOF
) {
259 return (mdsyserror(ep
, errno
, tname
));
265 if ((fflush(tfp
) != 0) ||
266 (fsync(fileno(tfp
)) != 0)) {
267 return (mdsyserror(ep
, errno
, tname
));
278 * Caller of this routine needs to free the device id string that
279 * is passed back during a successful return.
283 char *line
, /* line in file */
284 char **driver
, /* returned driver name */
285 minor_t
*mnump
, /* returned minor number */
286 daddr_t
*block
, /* returned block offset */
287 char **devid_char_pp
/* returned device id string */
299 while ((*p
!= ' ') && (*p
!= '\t'))
305 *mnump
= strtoul(p
, &p
, 10);
307 *block
= strtol(p
, &p
, 10);
310 /* parse out devid */
311 while ((*p
== ' ') || (*p
== '\t')) {
314 i
= strcspn(p
, " \t");
315 *devid_char_pp
= Malloc(i
+1);
316 (void) strncpy(*devid_char_pp
, p
, i
);
317 (*devid_char_pp
)[i
] = '\0';
320 for (i
= 0; i
< devid_size
; i
++) {
321 chksum
+= (*devid_char_pp
)[i
];
324 chksum
+= strtol(p
, &p
, 10);
326 Free (*devid_char_pp
);
327 devid_char_pp
= NULL
;
334 * append MDDB lines to system
337 meta_systemfile_append_mddb(
338 char *cname
, /* mddb.cf file name */
339 char *sname
, /* system file name */
340 char *tname
, /* temp file name */
341 FILE *tfp
, /* temp FILE */
342 int doit
, /* really patch file */
343 int verbose
, /* show what we're doing */
344 int check
, /* if set check that mddb.cf is not */
345 /* empty before updating md.conf */
346 md_error_t
*ep
/* returned error */
356 char line
[MDDB_BOOTLIST_MAX_LEN
];
357 char entry
[MDDB_BOOTLIST_MAX_LEN
];
358 char *devid_char_p
= NULL
;
362 assert(cname
!= NULL
);
363 assert(sname
!= NULL
);
364 assert(tname
!= NULL
);
365 assert(!doit
|| tfp
!= NULL
);
367 /* open database conf file */
368 if ((cfp
= fopen(cname
, "r")) == NULL
) {
369 (void) mdsyserror(ep
, errno
, cname
);
372 /* Check that it is an ordinary file */
373 if (stat(cname
, &statbuf
) != 0) {
374 (void) mdsyserror(ep
, errno
, cname
);
377 if ((statbuf
.st_mode
& S_IFMT
) != S_IFREG
) {
378 (void) mderror(ep
, MDE_MDDB_FILE
, cname
);
384 (void) printf(dgettext(TEXT_DOMAIN
,
385 "Add the following lines to %s:\n\n"), sname
);
386 (void) printf("%s", BEGMDDBSTR
);
389 if (fprintf(tfp
, "%s", BEGMDDBSTR
) == EOF
) {
390 (void) mdsyserror(ep
, errno
, tname
);
395 /* append database lines */
396 while (((p
= fgets(buf
, sizeof (buf
), cfp
)) != NULL
) &&
397 (confline(buf
, &driver
, &mnum
, &block
, &devid_char_p
) != 0))
400 * It is possible to be in a state where the md_devid_destroy flag
401 * has been set and the mdmonitor service not be enabled on reboot
402 * such that metadevadm doesn't get run and the entries in mddb.cf
403 * recreated. The following checks for this condition and will not
404 * allow an empty mddb.cf to overwrite md.conf and lose the users
407 if (check
&& p
== NULL
) {
408 (void) mderror(ep
, MDE_MDDB_FILE
, cname
);
412 for (i
= 1; ((p
!= NULL
) && (i
<= MDDB_MAX_PATCH
)); ++i
) {
413 (void) snprintf(line
, sizeof (line
),
414 "mddb_bootlist%d=\"%s:%lu:%ld:%s",
415 i
, driver
, mnum
, block
, devid_char_p
);
416 if (devid_char_p
!= NULL
) {
421 while ((p
= fgets(buf
, sizeof (buf
), cfp
)) != NULL
) {
422 if (confline(buf
, &driver
, &mnum
, &block
,
423 &devid_char_p
) != 0) {
426 (void) snprintf(entry
, sizeof (entry
), " %s:%lu:%ld:%s",
427 driver
, mnum
, block
, devid_char_p
);
429 if ((strlen(line
) + strlen(entry
) + 4) > sizeof (line
))
431 (void) strcat(line
, entry
);
432 if (devid_char_p
!= NULL
) {
439 (void) printf("%s\";\n", line
);
442 if (fprintf(tfp
, "%s\";\n", line
) <= 0) {
443 (void) mdsyserror(ep
, errno
, tname
);
449 if (devid_char_p
!= NULL
) {
456 (void) printf("%s\n", ENDMDDBSTR
);
458 if (fprintf(tfp
, "%s", ENDMDDBSTR
) == EOF
) {
459 (void) mdsyserror(ep
, errno
, tname
);
464 /* close database conf file */
465 if (fclose(cfp
) != 0) {
467 (void) mdsyserror(ep
, errno
, cname
);
474 if ((fflush(tfp
) != 0) ||
475 (fsync(fileno(tfp
)) != 0)) {
476 (void) mdsyserror(ep
, errno
, tname
);
484 /* cleanup, return error */