1 /* $NetBSD: edlabel.c,v 1.16 2006/10/23 03:56:38 mrg Exp $ */
4 * Copyright (c) 1995 Gordon W. Ross
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
33 #include <sys/disklabel.h>
45 * Machine dependent constants you want to retrieve only once...
47 int rawpartition
, maxpartitions
;
50 * This is a data-driven program
55 int f_type
; /* 1:char, 2:short, 4:int, >4:string */
58 /* Table describing fields in the head of a disklabel. */
59 #define dloff(f) (int)(&((struct disklabel *)0)->f)
60 struct field label_head
[] = {
61 { " type_num", dloff(d_type
), 2 },
62 { " sub_type", dloff(d_subtype
), 2 },
63 { " type_name", dloff(d_typename
), 16 },
64 { " pack_name", dloff(d_packname
), 16 },
65 { " bytes/sector", dloff(d_secsize
), 4 },
66 { " sectors/track", dloff(d_nsectors
), 4 },
67 { " tracks/cylinder", dloff(d_ntracks
), 4 },
68 { " cylinders", dloff(d_ncylinders
), 4 },
69 { "sectors/cylinder", dloff(d_secpercyl
), 4 },
70 /* Don't care about the others until later... */
75 void check_divisors(struct disklabel
*);
76 u_short
dkcksum(struct disklabel
*);
77 void edit_geo(struct disklabel
*);
78 void edit_head_all(struct disklabel
*, int);
79 void edit_head_field(void *, struct field
*, int);
80 void edit_partition(struct disklabel
*, int, int);
81 void get_fstype(char *, u_int8_t
*);
82 void get_val_cts(struct disklabel
*, char *, u_int32_t
*);
83 void label_modify(struct disklabel
*, char *);
84 void label_print(struct disklabel
*, char *);
85 void label_quit(struct disklabel
*, char *);
86 void label_read(struct disklabel
*, char *);
87 void label_write(struct disklabel
*, char *);
89 void print_val_cts(struct disklabel
*, u_long val
);
94 edit_head_field(void *v
, struct field
*f
, int modify
/* also modify */)
102 printf("%s: ", f
->f_name
);
104 /* Print current value... */
111 tmp
= *((u_int16_t
*)cp
);
115 tmp
= *((u_int32_t
*)cp
);
120 /* must be a string. */
121 strlcpy(tmpbuf
, (char*)cp
, sizeof(tmpbuf
));
122 printf("%s", tmpbuf
);
134 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
136 if ((tmpbuf
[0] == '\0') || (tmpbuf
[0] == '\n')) {
137 /* no new value supplied. */
141 /* store new value */
143 if (sscanf(tmpbuf
, "%d", &tmp
) != 1)
151 *((u_int16_t
*)cp
) = tmp
;
154 *((u_int32_t
*)cp
) = tmp
;
157 /* Get rid of the trailing newline. */
158 tmp
= strlen(tmpbuf
);
161 if (tmpbuf
[tmp
-1] == '\n')
162 tmpbuf
[tmp
-1] = '\0';
163 strncpy((char*)cp
, tmpbuf
, f
->f_type
);
169 edit_head_all(struct disklabel
*d
, int modify
)
173 /* Edit head stuff. */
174 for (f
= label_head
; f
->f_name
; f
++)
175 edit_head_field(d
, f
, modify
);
179 edit_geo(struct disklabel
*d
)
181 int nsect
, ntrack
, ncyl
, spc
;
183 nsect
= ntrack
= ncyl
= spc
= 0;
185 printf("Sectors/track: ");
187 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
189 if (sscanf(tmpbuf
, "%d", &nsect
) != 1)
190 nsect
= d
->d_nsectors
;
191 printf("Track/cyl: ");
193 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
195 if (sscanf(tmpbuf
, "%d", &ntrack
) != 1)
196 ntrack
= d
->d_ntracks
;
197 if (!nsect
|| !ntrack
)
199 spc
= nsect
* ntrack
;
200 if (!(ncyl
= d
->d_secperunit
/ spc
))
202 d
->d_nsectors
= nsect
;
203 d
->d_ntracks
= ntrack
;
204 d
->d_ncylinders
= ncyl
;
205 d
->d_secpercyl
= spc
;
209 print_val_cts(struct disklabel
*d
, u_long val
)
211 int sects
, trks
, cyls
;
215 marker
= (val
% d
->d_secpercyl
) ? '*' : ' ';
216 sects
= val
% d
->d_nsectors
;
217 cyls
= val
/ d
->d_nsectors
;
218 trks
= cyls
% d
->d_ntracks
;
219 cyls
/= d
->d_ntracks
;
220 snprintf(buf
, sizeof(buf
), "(%d/%02d/%02d)%c", cyls
, trks
, sects
,
222 printf(" %9ld %16s", val
, buf
);
226 get_val_cts(struct disklabel
*d
, char *buf
, u_int32_t
*result
)
229 int cyls
, trks
, sects
;
231 tmp
= sscanf(buf
, "%d/%d/%d", &cyls
, &trks
, §s
);
233 *result
= cyls
; /* really nblks! */
238 tmp
*= d
->d_nsectors
;
245 get_fstype(char *buf
, u_int8_t
*fstype
)
249 /* An empty response retains previous value */
252 for (i
= 0, len
= strlen(buf
) - 1; i
< FSMAXTYPES
; i
++) {
253 if (!strncasecmp(buf
, fstypenames
[i
], len
)) {
261 edit_partition(struct disklabel
*d
, int idx
, int modify
)
267 if ((idx
< 0) || (idx
>= maxpartitions
)) {
268 printf("bad partition index\n");
272 p
= &d
->d_partitions
[idx
];
275 /* Set hint about partition type */
276 if (idx
== rawpartition
)
290 /* Print current value... */
291 printf(" %c (%s) ", letter
, comment
);
292 print_val_cts(d
, p
->p_offset
);
293 print_val_cts(d
, p
->p_size
);
294 printf(" %s\n", fstypenames
[p
->p_fstype
]);
299 /* starting block, or cyls/trks/sects */
300 printf("start as <blkno> or <cyls/trks/sects> : ");
302 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
304 get_val_cts(d
, tmpbuf
, &p
->p_offset
);
306 /* number of blocks, or cyls/trks/sects */
307 printf("length as <nblks> or <cyls/trks/sects> : ");
309 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
311 get_val_cts(d
, tmpbuf
, &p
->p_size
);
315 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
317 get_fstype(tmpbuf
, &p
->p_fstype
);
320 /*****************************************************************/
323 check_divisors(struct disklabel
*d
)
325 if (d
->d_nsectors
== 0) {
327 printf("bad sect/trk, set to 1\n");
329 if (d
->d_ntracks
== 0) {
331 printf("bad trks/cyl, set to 1\n");
333 if (d
->d_ncylinders
== 0) {
335 printf("bad cyls, set to 1\n");
337 if (d
->d_secpercyl
== 0) {
338 d
->d_secpercyl
= (d
->d_nsectors
* d
->d_ntracks
);
339 printf("bad sect/cyl, set to %d\n", d
->d_secpercyl
);
345 dkcksum(struct disklabel
*d
)
347 u_short
*start
, *end
;
350 start
= (u_short
*)d
;
351 end
= (u_short
*)&d
->d_partitions
[d
->d_npartitions
];
358 label_write(struct disklabel
*d
, char *dn
)
362 d
->d_magic
= DISKMAGIC
;
363 d
->d_magic2
= DISKMAGIC
;
365 d
->d_checksum
= dkcksum(d
);
367 fd
= open(dn
, O_RDWR
, 0);
372 if (ioctl(fd
, DIOCWDINFO
, d
) < 0) {
373 perror("ioctl DIOCWDINFO");
379 label_read(struct disklabel
*dl
, char *dn
)
383 fd
= open(dn
, O_RDONLY
, 0);
388 if (ioctl(fd
, DIOCGDINFO
, dl
) < 0) {
390 fprintf(stderr
, "edlabel: No disk label on disk\n");
392 perror("ioctl DIOCGDINFO");
396 /* Make sure divisors are non-zero. */
402 /*****************************************************************/
405 label_print(struct disklabel
*dl
, char *dn
)
409 /* Print out head stuff. */
410 edit_head_all(dl
, 0);
412 /* And the partition header. */
413 printf("partition%6sstart%9s(c/t/s)%6snblks%9s(c/t/s) type\n\n"
415 for (i
= 0; i
< dl
->d_npartitions
; i
++)
416 edit_partition(dl
, i
, 0);
419 char modify_cmds
[] = "modify subcommands:\n\
420 @ : modify disk parameters\n\
421 a-%c : modify partition\n%s\
422 q : quit this subcommand\n";
425 label_modify(struct disklabel
*dl
, char *dn
)
430 if (!strcmp(dl
->d_typename
, "SCSI disk")
431 && !strcmp(dl
->d_packname
, "fictitious"))
434 printf(modify_cmds
, 'a' + maxpartitions
- 1,
435 scsi_fict
? " s : standardize geometry\n" : "");
437 printf("edlabel/modify> ");
439 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
442 if ((c
== '\0') || (c
== '\n'))
443 continue; /* blank line */
447 edit_head_all(dl
, 1);
451 if ((c
== 's') && scsi_fict
) {
455 if ((c
< 'a') || (c
> 'q')) {
456 printf("bad input. ");
457 printf(modify_cmds
, 'a' + maxpartitions
- 1,
458 scsi_fict
? " s : standardize geometry\n" : "");
461 edit_partition(dl
, c
- 'a', 1);
463 /* Set the d_npartitions field correctly */
464 for (i
= 0; i
< maxpartitions
; i
++) {
465 if (dl
->d_partitions
[i
].p_size
)
466 dl
->d_npartitions
= i
+ 1;
472 label_quit(struct disklabel
*dl
, char *dn
)
478 void (*cmd_func
)(struct disklabel
*, char *);
479 const char *cmd_name
;
480 const char *cmd_descr
;
482 { label_print
, "print", "display the current disk label" },
483 { label_modify
, "modify", "prompt for changes to the label" },
484 { label_write
, "write", "write the new label to disk" },
485 { label_quit
, "quit", "terminate program" },
494 printf("edlabel menu:\n");
495 for (cmd
= cmds
; cmd
->cmd_func
; cmd
++)
496 printf("%s\t- %s\n", cmd
->cmd_name
, cmd
->cmd_descr
);
500 main(int argc
, char **argv
)
507 fprintf(stderr
, "usage: edlabel RAWDISK\n");
512 rawpartition
= getrawpartition();
513 maxpartitions
= getmaxpartitions();
515 label_read(&dl
, dev_name
);
522 if (fgets(tmpbuf
, sizeof(tmpbuf
), stdin
) == NULL
)
524 for (cmd
= cmds
; cmd
->cmd_func
; cmd
++)
525 if (cmd
->cmd_name
[0] == tmpbuf
[0])
527 printf("Invalid command. ");
532 cmd
->cmd_func(&dl
, dev_name
);