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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This module contains functions used for reading and writing the scratch zone
31 * translation files. These files are used by Live Upgrade to keep track of
32 * mappings between actual kernel zone names and the zones in an alternate boot
35 * The functions are MT-safe.
37 * The file format looks like this:
39 * <zonename> <kernel-zonename> <alt-root>
41 * The expected usage model is:
43 * fp = zonecfg_open_scratch("", B_TRUE);
44 * zonecfg_lock_scratch(fp);
45 * if (zonecfg_find_scratch(fp, zonename, altroot, NULL, 0) == 0) {
46 * handle error; zone already mounted
49 * zonecfg_add_scratch(fp, zonename, kernname, altroot);
50 * zonecfg_close_scratch(fp);
51 * fp = zonecfg_open_scratch(zoneroot, B_TRUE);
52 * ftruncate(fileno(fp), 0);
53 * zonecfg_add_scratch(fp, zonename, kernname, "/");
54 * zonecfg_close_scratch(fp);
62 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <libzonecfg.h>
67 #define PATH_MAPFILE "tmp/.alt.lu-zone-map"
70 lock_op(int fd
, int type
)
75 lock
.l_whence
= SEEK_SET
;
79 return (fcntl(fd
, F_SETLKW
, &lock
));
83 zonecfg_open_scratch(const char *rootpath
, boolean_t createfile
)
85 mode_t oldmask
= umask(0);
86 struct stat lbuf
, fbuf
;
89 char mapfile
[MAXPATHLEN
];
91 (void) snprintf(mapfile
, sizeof (mapfile
), "%s/" PATH_MAPFILE
,
94 flags
= O_RDWR
| O_NOFOLLOW
| O_NOLINKS
;
96 flags
|= O_EXCL
| O_CREAT
;
97 if ((fd
= open(mapfile
, flags
, 0644)) == -1) {
102 if (lstat(mapfile
, &lbuf
) == -1)
104 if (!S_ISREG(lbuf
.st_mode
) || lbuf
.st_nlink
!= 1 ||
109 fd
= open(mapfile
, O_RDWR
);
112 if (fstat(fd
, &fbuf
) == -1)
114 if (lbuf
.st_ino
!= fbuf
.st_ino
|| lbuf
.st_dev
!= fbuf
.st_dev
) {
119 if (lock_op(fd
, F_RDLCK
) == -1)
121 (void) umask(oldmask
);
122 if ((fp
= fdopen(fd
, "r+")) == NULL
)
129 (void) umask(oldmask
);
134 zonecfg_lock_scratch(FILE *fp
)
138 return (lock_op(fileno(fp
), F_WRLCK
));
142 zonecfg_close_scratch(FILE *fp
)
148 zonecfg_get_scratch(FILE *fp
, char *zonename
, size_t namelen
, char *kernname
,
149 size_t kernlen
, char *altroot
, size_t altlen
)
151 char line
[2 * ZONENAME_MAX
+ MAXPATHLEN
+ 2];
154 /* We always hold at least a read lock on the file */
156 if (fgets(line
, sizeof (line
), fp
) == NULL
)
158 if ((cp
= strchr(line
, '\n')) == NULL
)
161 if ((cp
= strchr(line
, ' ')) == NULL
)
162 cp
= line
+ strlen(line
);
165 if (zonename
!= NULL
&&
166 strlcpy(zonename
, line
, namelen
) >= namelen
)
168 if ((cp2
= strchr(cp
, ' ')) == NULL
)
169 cp2
= cp
+ strlen(cp
);
172 if (kernname
!= NULL
&&
173 strlcpy(kernname
, cp
, kernlen
) >= kernlen
)
175 if (altroot
!= NULL
&& strlcpy(altroot
, cp2
, altlen
) >= altlen
)
183 zonecfg_find_scratch(FILE *fp
, const char *zonename
, const char *altroot
,
184 char *kernzone
, size_t kernlen
)
186 char zone
[ZONENAME_MAX
];
187 char aroot
[MAXPATHLEN
];
190 while (zonecfg_get_scratch(fp
, zone
, sizeof (zone
), kernzone
, kernlen
,
191 aroot
, sizeof (aroot
)) == 0) {
192 if (strcmp(zone
, zonename
) == 0 && strcmp(altroot
, aroot
) == 0)
199 zonecfg_reverse_scratch(FILE *fp
, const char *kernzone
, char *zonename
,
200 size_t namelen
, char *altroot
, size_t altlen
)
202 char kzone
[ZONENAME_MAX
];
205 while (zonecfg_get_scratch(fp
, zonename
, namelen
, kzone
,
206 sizeof (kzone
), altroot
, altlen
) == 0) {
207 if (strcmp(kzone
, kernzone
) == 0)
214 zonecfg_add_scratch(FILE *fp
, const char *zonename
, const char *kernzone
,
217 if (fseek(fp
, 0, SEEK_END
) == -1)
219 if (fprintf(fp
, "%s %s %s\n", zonename
, kernzone
, altroot
) == EOF
)
227 zonecfg_delete_scratch(FILE *fp
, const char *kernzone
)
229 char zone
[ZONENAME_MAX
];
230 char kzone
[ZONENAME_MAX
];
231 char aroot
[MAXPATHLEN
];
235 * The implementation here is intentionally quite simple. We could
236 * allocate a buffer that's big enough to hold the data up to
237 * stat.st_size and then write back out the part we need to, but there
238 * seems to be little point.
244 if (zonecfg_get_scratch(fp
, NULL
, 0, kzone
, sizeof (kzone
),
248 } while (strcmp(kzone
, kernzone
) != 0);
249 while (zonecfg_get_scratch(fp
, zone
, sizeof (zone
), kzone
,
250 sizeof (kzone
), aroot
, sizeof aroot
) == 0) {
252 if (fseek(fp
, woffs
, SEEK_SET
) == -1)
254 if (fprintf(fp
, "%s %s %s\n", zone
, kzone
, aroot
) == EOF
)
257 if (fseek(fp
, roffs
, SEEK_SET
) == -1)
260 (void) ftruncate(fileno(fp
), woffs
);
265 zonecfg_is_scratch(const char *kernzone
)
267 return (strncmp(kernzone
, "SUNWlu", 6) == 0);