Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / sbin / svhlabel / svhlabel.c
bloba9d497db76f08c31be60f112167730f8de7ed88e
1 /* $NetBSD: svhlabel.c,v 1.4 2007/06/30 02:05:27 rumble Exp $ */
3 /*
4 * Copyright (C) 2007 Stephen M. Rumble.
5 * Copyright (C) 1998 Wolfgang Solfrank.
6 * Copyright (C) 1998 TooLs GmbH.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __RCSID("$NetBSD: svhlabel.c,v 1.4 2007/06/30 02:05:27 rumble Exp $");
38 #endif /* not lint */
40 #include <stdio.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <limits.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <util.h>
50 #include <sys/param.h>
51 #define FSTYPENAMES
52 #include <sys/disklabel.h>
53 #include <sys/bootblock.h>
54 #include <sys/ioctl.h>
56 #include <fs/efs/efs.h>
57 #include <fs/efs/efs_sb.h>
59 #include "dkcksum.h"
60 #include "extern.h"
62 int main(int, char **);
63 static void usage(void);
64 static void getlabel(int);
65 static void setlabel(int, int);
66 static int getparts(int, int);
67 static int is_efs(int, uint32_t);
68 static struct sgi_boot_block *convert_sgi_boot_block(unsigned char *);
70 struct disklabel label;
72 static void
73 getlabel(int sd)
76 if (ioctl(sd, DIOCGDINFO, &label) < 0) {
77 perror("get label");
78 exit(1);
81 * Some ports seem to not set the number of partitions
82 * correctly, albeit they seem to set the raw partition ok!
84 if (label.d_npartitions <= getrawpartition())
85 label.d_npartitions = getrawpartition() + 1;
88 static void
89 setlabel(int sd, int doraw)
91 int one = 1;
93 label.d_checksum = 0;
94 label.d_checksum = dkcksum(&label);
95 if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) {
96 perror("set label");
97 exit(1);
99 if (!doraw)
100 /* If we haven't written to the disk, don't discard on close */
101 ioctl(sd, DIOCKLABEL, &one);
105 static int
106 getparts(int sd, int verbose)
108 unsigned char buf[DEV_BSIZE];
109 struct sgi_boot_block *vh;
110 struct partition npe;
111 int i, j, changed;
113 changed = 0;
115 if (lseek(sd, 0, SEEK_SET) == -1) {
116 perror("seek vh");
117 exit(1);
119 if ((i = read(sd, buf, sizeof(buf))) != DEV_BSIZE) {
120 perror("read vh");
121 exit(1);
123 vh = convert_sgi_boot_block(buf);
125 if (vh->magic != SGI_BOOT_BLOCK_MAGIC)
126 return (changed);
128 if (label.d_secsize != SGI_BOOT_BLOCK_BLOCKSIZE)
129 changed++;
130 label.d_secsize = SGI_BOOT_BLOCK_BLOCKSIZE;
132 for (i = j = 0; i < SGI_BOOT_BLOCK_MAXPARTITIONS; i++) {
133 if (vh->partitions[i].blocks == 0)
134 continue;
136 if (j == MAXPARTITIONS)
137 break;
139 switch (vh->partitions[i].type) {
140 case SGI_PTYPE_EFS:
142 * For some reason, my IRIX CDs list EFS partitions as SYSV!?
144 case SGI_PTYPE_SYSV:
145 if (is_efs(sd, vh->partitions[i].first)) {
146 npe.p_fstype = FS_EFS;
147 npe.p_size = vh->partitions[i].blocks;
148 npe.p_offset = vh->partitions[i].first;
149 npe.p_fsize = 0;
150 npe.p_frag = 0;
151 npe.p_cpg = 0;
153 break;
155 case SGI_PTYPE_VOLUME:
156 if (label.d_secperunit != (uint32_t)vh->partitions[i].blocks)
157 changed++;
158 label.d_secperunit = vh->partitions[i].blocks;
159 continue;
161 default:
162 continue;
165 if (j >= label.d_npartitions)
166 break;
168 if (j == getrawpartition()) {
169 if (++j >= label.d_npartitions)
170 break;
173 if (memcmp(&label.d_partitions[j], &npe, sizeof(npe)) != 0) {
174 label.d_partitions[j] = npe;
175 changed++;
178 j++;
181 /* XXX - fudge */
182 if (label.d_nsectors != 1 || label.d_ntracks != 1 ||
183 label.d_secpercyl != 1 || label.d_ncylinders != label.d_secperunit)
184 changed++;
185 label.d_nsectors = 1;
186 label.d_ntracks = 1;
187 label.d_secpercyl = 1;
188 label.d_ncylinders = label.d_secperunit;
190 i = getrawpartition();
191 if (label.d_partitions[i].p_fstype != FS_UNUSED ||
192 label.d_partitions[i].p_offset != 0 ||
193 label.d_partitions[i].p_size != label.d_secperunit) {
194 label.d_partitions[i].p_fstype = FS_UNUSED;
195 label.d_partitions[i].p_offset = 0;
196 label.d_partitions[i].p_size = label.d_secperunit;
197 changed++;
200 return (changed);
203 static int
204 is_efs(int sd, uint32_t blkoff)
206 struct efs_sb sb;
207 off_t oldoff;
209 if ((oldoff = lseek(sd, 0, SEEK_CUR)) == -1) {
210 perror("is_efs lseek 0");
211 exit(1);
214 blkoff *= SGI_BOOT_BLOCK_BLOCKSIZE;
215 if (lseek(sd, blkoff + (EFS_BB_SB * EFS_BB_SIZE), SEEK_SET) == -1) {
216 perror("is_efs lseek 1");
217 exit(1);
220 if (read(sd, &sb, sizeof(sb)) != sizeof(sb)) {
221 perror("is_efs read");
222 exit(1);
225 if (lseek(sd, oldoff, SEEK_SET) == -1) {
226 perror("is_efs lseek 2");
227 exit(1);
230 BE32TOH(sb.sb_magic);
232 return (sb.sb_magic == EFS_SB_MAGIC || sb.sb_magic == EFS_SB_NEWMAGIC);
235 static struct sgi_boot_block *
236 convert_sgi_boot_block(unsigned char *buf)
238 struct sgi_boot_block *vh;
239 int i;
241 vh = (struct sgi_boot_block *)buf;
243 BE32TOH(vh->magic);
244 BE16TOH(vh->root);
245 BE16TOH(vh->swap);
247 BE16TOH(vh->dp.dp_cyls);
248 BE16TOH(vh->dp.dp_shd0);
249 BE16TOH(vh->dp.dp_trks0);
250 BE16TOH(vh->dp.dp_secs);
251 BE16TOH(vh->dp.dp_secbytes);
252 BE16TOH(vh->dp.dp_interleave);
253 BE32TOH(vh->dp.dp_flags);
254 BE32TOH(vh->dp.dp_datarate);
255 BE32TOH(vh->dp.dp_nretries);
256 BE32TOH(vh->dp.dp_mspw);
257 BE16TOH(vh->dp.dp_xgap1);
258 BE16TOH(vh->dp.dp_xsync);
259 BE16TOH(vh->dp.dp_xrdly);
260 BE16TOH(vh->dp.dp_xgap2);
261 BE16TOH(vh->dp.dp_xrgate);
262 BE16TOH(vh->dp.dp_xwcont);
264 for (i = 0; i < SGI_BOOT_BLOCK_MAXVOLDIRS; i++) {
265 BE32TOH(vh->voldir[i].block);
266 BE32TOH(vh->voldir[i].bytes);
269 for (i = 0; i < SGI_BOOT_BLOCK_MAXPARTITIONS; i++) {
270 BE32TOH(vh->partitions[i].blocks);
271 BE32TOH(vh->partitions[i].first);
272 BE32TOH(vh->partitions[i].type);
275 BE32TOH(vh->checksum);
277 return (vh);
280 static void
281 usage(void)
283 fprintf(stderr, "usage: %s [-fqrw] rawdisk\n",
284 getprogname());
285 exit(1);
290 main(int argc, char **argv)
292 int sd, ch, changed;
293 char name[MAXPATHLEN];
294 int force; /* force label update */
295 int raw; /* update on-disk label as well */
296 int verbose; /* verbose output */
297 int write_it; /* update in-core label if changed */
299 force = 0;
300 raw = 0;
301 verbose = 1;
302 write_it = 0;
303 while ((ch = getopt(argc, argv, "fqrw")) != -1) {
304 switch (ch) {
305 case 'f':
306 force = 1;
307 break;
308 case 'q':
309 verbose = 0;
310 break;
311 case 'r':
312 raw = 1;
313 break;
314 case 'w':
315 write_it = 1;
316 break;
317 default:
318 usage();
321 argc -= optind;
322 argv += optind;
323 if (argc != 1)
324 usage();
326 if ((sd = opendisk(argv[0], write_it ? O_RDWR : O_RDONLY, name,
327 (size_t)MAXPATHLEN, 1)) < 0) {
328 perror(argv[0]);
329 exit(1);
331 getlabel(sd);
332 changed = getparts(sd, verbose);
334 if (verbose) {
335 putchar('\n');
336 showpartitions(stdout, &label, 0);
337 putchar('\n');
339 if (write_it) {
340 if (! changed && ! force)
341 printf("No change; not updating disk label.\n");
342 else {
343 if (verbose)
344 printf("Updating in-core %sdisk label.\n",
345 raw ? "and on-disk " : "");
346 raw = 0; /* XXX */
347 setlabel(sd, raw);
349 } else {
350 printf("Not updating disk label.\n");
352 close(sd);
353 return (0);