dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libadm / common / rdwr_vtoc.c
blob0e3d36ca018b87b37d641fcd7ae786fb341a565e
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /*LINTLIBRARY*/
30 #include <stdio.h>
31 #include <errno.h>
32 #include <memory.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/dkio.h>
37 #include <sys/vtoc.h>
38 #include <strings.h>
39 #include <limits.h>
42 * To copy each field of vtoc individually for copying extvtoc
43 * to 32 bit vtoc and vs.
44 * Currently bootinfo and timestamp are not really supported.
47 #define libadm_vtoc_copy(vs, vd) \
48 { \
49 int i; \
50 vd->v_bootinfo[0] = (unsigned)vs->v_bootinfo[0]; \
51 vd->v_bootinfo[1] = (unsigned)vs->v_bootinfo[1]; \
52 vd->v_bootinfo[2] = (unsigned)vs->v_bootinfo[2]; \
53 vd->v_sanity = (unsigned)vs->v_sanity; \
54 vd->v_version = (unsigned)vs->v_version; \
55 bcopy(vs->v_volume, vd->v_volume, LEN_DKL_VVOL); \
56 vd->v_sectorsz = vs->v_sectorsz; \
57 vd->v_nparts = vs->v_nparts; \
58 vd->v_version = (unsigned)vs->v_version; \
59 for (i = 0; i < 10; i++) \
60 vd->v_reserved[i] = (unsigned)vs->v_reserved[i];\
61 for (i = 0; i < V_NUMPAR; i++) { \
62 vd->v_part[i].p_tag = vs->v_part[i].p_tag; \
63 vd->v_part[i].p_flag = vs->v_part[i].p_flag; \
64 vd->v_part[i].p_start = (unsigned)vs->v_part[i].p_start;\
65 vd->v_part[i].p_size = (unsigned)vs->v_part[i].p_size; \
66 } \
67 for (i = 0; i < V_NUMPAR; i++) \
68 if ((sizeof (vd->timestamp[i]) != sizeof (vs->timestamp[i])) &&\
69 (vs->timestamp[i] > INT32_MAX)) \
70 vd->timestamp[i] = INT32_MAX; \
71 else \
72 vd->timestamp[i] = (unsigned)vs->timestamp[i]; \
73 bcopy(vs->v_asciilabel, vd->v_asciilabel, LEN_DKL_ASCII); \
78 * Read VTOC - return partition number.
80 int
81 read_vtoc(int fd, struct vtoc *vtoc)
83 struct dk_cinfo dki_info;
86 * Read the vtoc.
88 if (ioctl(fd, DKIOCGVTOC, (caddr_t)vtoc) == -1) {
89 switch (errno) {
90 case EIO:
91 return (VT_EIO);
92 case EINVAL:
93 return (VT_EINVAL);
94 case ENOTSUP:
95 /* GPT labeled or disk > 1TB with no extvtoc support */
96 return (VT_ENOTSUP);
97 case EOVERFLOW:
98 return (VT_EOVERFLOW);
99 default:
100 return (VT_ERROR);
105 * Sanity-check the vtoc.
107 if (vtoc->v_sanity != VTOC_SANE) {
108 return (VT_EINVAL);
112 * Convert older-style vtoc's.
114 switch (vtoc->v_version) {
115 case 0:
117 * No vtoc information. Install default
118 * nparts/sectorsz and version. We are
119 * assuming that the driver returns the
120 * current partition information correctly.
123 vtoc->v_version = V_VERSION;
124 if (vtoc->v_nparts == 0)
125 vtoc->v_nparts = V_NUMPAR;
126 if (vtoc->v_sectorsz == 0)
127 vtoc->v_sectorsz = DEV_BSIZE;
129 break;
131 case V_VERSION:
132 break;
134 default:
135 return (VT_EINVAL);
139 * Return partition number for this file descriptor.
141 if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
142 switch (errno) {
143 case EIO:
144 return (VT_EIO);
145 case EINVAL:
146 return (VT_EINVAL);
147 default:
148 return (VT_ERROR);
151 if (dki_info.dki_partition > V_NUMPAR) {
152 return (VT_EINVAL);
154 return ((int)dki_info.dki_partition);
158 * Write VTOC
161 write_vtoc(int fd, struct vtoc *vtoc)
163 int i;
165 * Sanity-check the vtoc
167 if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts > V_NUMPAR) {
168 return (-1);
172 * since many drivers won't allow opening a device make sure
173 * all partitions aren't being set to zero. If all are zero then
174 * we have no way to set them to something else
177 for (i = 0; i < (int)vtoc->v_nparts; i++)
178 if (vtoc->v_part[i].p_size > 0)
179 break;
180 if (i == (int)vtoc->v_nparts)
181 return (-1);
184 * Write the vtoc
186 if (ioctl(fd, DKIOCSVTOC, (caddr_t)vtoc) == -1) {
187 switch (errno) {
188 case EIO:
189 return (VT_EIO);
190 case EINVAL:
191 return (VT_EINVAL);
192 case ENOTSUP:
193 /* GPT labeled or disk > 1TB with no extvtoc support */
194 return (VT_ENOTSUP);
195 case EOVERFLOW:
196 return (VT_EOVERFLOW);
197 default:
198 return (VT_ERROR);
201 return (0);
205 read_extvtoc(int fd, struct extvtoc *extvtoc)
207 struct dk_cinfo dki_info;
208 struct vtoc oldvtoc;
209 struct vtoc *oldvtocp = &oldvtoc;
210 int ret;
213 * Read the vtoc.
215 if (ioctl(fd, DKIOCGEXTVTOC, (caddr_t)extvtoc) == -1) {
216 switch (errno) {
217 case EIO:
218 return (VT_EIO);
219 case EINVAL:
220 return (VT_EINVAL);
221 /* for disks > 1TB */
222 case ENOTSUP:
223 return (VT_ENOTSUP);
224 case EOVERFLOW:
225 return (VT_EOVERFLOW);
226 case ENOTTY:
228 if ((ret = read_vtoc(fd, oldvtocp)) < 0)
229 return (ret);
231 #ifdef _LP64
233 * 64-bit vtoc and extvtoc have the same field sizes
234 * and offsets.
236 bcopy(oldvtocp, extvtoc, sizeof (struct extvtoc));
237 #else
238 bzero(extvtoc, sizeof (struct extvtoc));
239 libadm_vtoc_copy(oldvtocp, extvtoc);
240 #endif
241 return (ret);
244 default:
245 return (VT_ERROR);
250 * Sanity-check the vtoc.
252 if (extvtoc->v_sanity != VTOC_SANE) {
253 return (VT_EINVAL);
256 switch (extvtoc->v_version) {
257 case 0:
259 * For pre-version 1 vtoc keep same functionality
260 * as read_vtoc.
263 extvtoc->v_version = V_VERSION;
264 if (extvtoc->v_nparts == 0)
265 extvtoc->v_nparts = V_NUMPAR;
266 if (extvtoc->v_sectorsz == 0)
267 extvtoc->v_sectorsz = DEV_BSIZE;
269 break;
271 case V_VERSION:
272 break;
274 default:
275 return (VT_EINVAL);
279 * Return partition number for this file descriptor.
281 if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
282 switch (errno) {
283 case EIO:
284 return (VT_EIO);
285 case EINVAL:
286 return (VT_EINVAL);
287 default:
288 return (VT_ERROR);
291 if (dki_info.dki_partition > V_NUMPAR) {
292 return (VT_EINVAL);
294 return ((int)dki_info.dki_partition);
298 * Write ext VTOC.
301 write_extvtoc(int fd, struct extvtoc *extvtoc)
303 int i;
304 struct vtoc oldvtoc;
305 struct vtoc *oldvtocp = &oldvtoc;
307 * Sanity-check the vtoc
309 if (extvtoc->v_sanity != VTOC_SANE || extvtoc->v_nparts > V_NUMPAR) {
310 return (-1);
314 * since many drivers won't allow opening a device make sure
315 * all partitions aren't being set to zero. If all are zero then
316 * we have no way to set them to something else
319 for (i = 0; i < (int)extvtoc->v_nparts; i++)
320 if (extvtoc->v_part[i].p_size > 0)
321 break;
322 if (i == (int)extvtoc->v_nparts)
323 return (-1);
326 * Write the extvtoc
328 if (ioctl(fd, DKIOCSEXTVTOC, (caddr_t)extvtoc) == -1) {
329 switch (errno) {
330 case EIO:
331 return (VT_EIO);
332 case EINVAL:
333 return (VT_EINVAL);
334 /* for disks > 1TB */
335 case ENOTSUP:
336 return (VT_ENOTSUP);
337 case EOVERFLOW:
338 return (VT_EOVERFLOW);
339 case ENOTTY:
340 #ifdef _LP64
342 * 64-bit vtoc and extvtoc have the same field sizes
343 * and offsets.
345 bcopy(extvtoc, oldvtocp, sizeof (struct vtoc));
346 #else
347 bzero(oldvtocp, sizeof (struct vtoc));
348 libadm_vtoc_copy(extvtoc, oldvtocp);
350 #endif
351 return (write_vtoc(fd, &oldvtoc));
353 default:
354 return (VT_ERROR);
358 return (0);