1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1991-1997,2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*LINTLIBRARY*/
30 
31 
32 #include <stdio.h>
33 #include <errno.h>
34 #include <memory.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/dkio.h>
39 #include <sys/vtoc.h>
40 
41 /*
42  * Read VTOC - return partition number.
43  */
44 int
45 read_vtoc(int fd, struct vtoc *vtoc)
46 {
47 	struct dk_cinfo		dki_info;
48 
49 	/*
50 	 * Read the vtoc.
51 	 */
52 	if (ioctl(fd, DKIOCGVTOC, (caddr_t)vtoc) == -1) {
53 		switch (errno) {
54 		case EIO:
55 			return (VT_EIO);
56 		case EINVAL:
57 			return (VT_EINVAL);
58 		/* for disks > 1TB */
59 		case ENOTSUP:
60 			return (VT_ENOTSUP);
61 		default:
62 			return (VT_ERROR);
63 		}
64 	}
65 
66 	/*
67 	 * Sanity-check the vtoc.
68 	 */
69 	if (vtoc->v_sanity != VTOC_SANE) {
70 		return (VT_EINVAL);
71 	}
72 
73 	/*
74 	 * Convert older-style vtoc's.
75 	 */
76 	switch (vtoc->v_version) {
77 	case 0:
78 		/*
79 		 * No vtoc information.  Install default
80 		 * nparts/sectorsz and version.  We are
81 		 * assuming that the driver returns the
82 		 * current partition information correctly.
83 		 */
84 
85 		vtoc->v_version = V_VERSION;
86 		if (vtoc->v_nparts == 0)
87 			vtoc->v_nparts = V_NUMPAR;
88 		if (vtoc->v_sectorsz == 0)
89 			vtoc->v_sectorsz = DEV_BSIZE;
90 
91 		break;
92 
93 	case V_VERSION:
94 		break;
95 
96 	default:
97 		return (VT_EINVAL);
98 	}
99 
100 	/*
101 	 * Return partition number for this file descriptor.
102 	 */
103 	if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
104 		switch (errno) {
105 		case EIO:
106 			return (VT_EIO);
107 		case EINVAL:
108 			return (VT_EINVAL);
109 		default:
110 			return (VT_ERROR);
111 		}
112 	}
113 	if (dki_info.dki_partition > V_NUMPAR) {
114 		return (VT_EINVAL);
115 	}
116 	return ((int)dki_info.dki_partition);
117 }
118 
119 /*
120  * Write VTOC
121  */
122 int
123 write_vtoc(int fd, struct vtoc *vtoc)
124 {
125 	int i;
126 	/*
127 	 * Sanity-check the vtoc
128 	 */
129 	if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts > V_NUMPAR) {
130 		return (-1);
131 	}
132 
133 	/*
134 	 * since many drivers won't allow opening a device make sure
135 	 * all partitions aren't being set to zero. If all are zero then
136 	 * we have no way to set them to something else
137 	 */
138 
139 	for (i = 0; i < (int)vtoc->v_nparts; i++)
140 		if (vtoc->v_part[i].p_size > 0)
141 			break;
142 	if (i == (int)vtoc->v_nparts)
143 		return (-1);
144 
145 	/*
146 	 * Write the vtoc
147 	 */
148 	if (ioctl(fd, DKIOCSVTOC, (caddr_t)vtoc) == -1) {
149 		switch (errno) {
150 		case EIO:
151 			return (VT_EIO);
152 		case EINVAL:
153 			return (VT_EINVAL);
154 		/* for disks > 1TB */
155 		case ENOTSUP:
156 			return (VT_ENOTSUP);
157 		default:
158 			return (VT_ERROR);
159 		}
160 	}
161 	return (0);
162 }
163