1 /* @(#)makelabel.c 1.57 11/08/13 Copyright 1988-2011 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)makelabel.c 1.57 11/08/13 Copyright 1988-2011 J. Schilling";
6 #endif
7 /*
8 * Routines to create / modify a label
9 *
10 * Copyright (c) 1988-2011 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/stdio.h>
27 #include <schily/standard.h>
28 #include <schily/ioctl.h>
29 #include <schily/termios.h> /* For TIOCSTI (simulate terminal input) */
30 #include <schily/fcntl.h>
31 #ifdef HAVE_SYS_FILE_H
32 #include <sys/file.h>
33 #endif
34 #include "dsklabel.h"
35 #ifndef HAVE_DKIO
36 # undef SVR4
37 #endif
38 #ifdef SVR4
39 #include <sys/vtoc.h>
40 #endif
41 #include <schily/unistd.h>
42 #include <schily/stdlib.h>
43 #include <schily/string.h>
44 #include <schily/schily.h>
45
46 #include <scg/scsireg.h>
47 #include <scg/scsitransp.h>
48
49 #include "fmt.h"
50
51 LOCAL char labelbuf[80];
52 extern struct dk_label *d_label;
53
54 char labelname[] = "Label";
55 char labelproto[] = "Label.prototype";
56 char *Lname = labelname;
57 char *Lproto = labelproto;
58
59 EXPORT void set_default_vtmap __PR((struct dk_label *lp));
60 EXPORT unsigned short do_cksum __PR((struct dk_label *l));
61 EXPORT BOOL check_vtmap __PR((struct dk_label *lp, BOOL set));
62 EXPORT void setlabel_from_val __PR((SCSI *scgp, struct disk *dp, struct dk_label *lp));
63 EXPORT void makelabel __PR((SCSI *scgp, struct disk *dp, struct dk_label *lp));
64 LOCAL void chpart __PR((struct disk *dp, struct dk_label *lp, int idx));
65 #ifdef SVR4
66 LOCAL int prvttab __PR((FILE *f, struct dk_label *lp, int i, int n));
67 #endif
68 EXPORT void prpartab __PR((FILE *f, char *disk_type, struct dk_label *lp));
69 EXPORT void printlabel __PR((struct dk_label *lp));
70 LOCAL void printparthead __PR((void));
71 EXPORT void printpart __PR((struct dk_label *lp, int i));
72 LOCAL void _printpart __PR((struct dk_label *lp, int i));
73 EXPORT void printparts __PR((struct dk_label *lp));
74 EXPORT int readlabel __PR((char *name, struct dk_label *lp));
75 EXPORT void writelabel __PR((char *name, struct dk_label *lp));
76 LOCAL void writebackuplabel __PR((int f, struct dk_label *lp));
77 EXPORT int setlabel __PR((char *name, struct dk_label *lp));
78 LOCAL int setgeom __PR((int f, struct dk_label *lp));
79 EXPORT char *getasciilabel __PR((struct dk_label *lp));
80 EXPORT void setasciilabel __PR((struct dk_label *lp, char *lname));
81 EXPORT BOOL setval_from_label __PR((struct disk *dp, struct dk_label *lp));
82 EXPORT void label_null __PR((struct dk_label *lp));
83 EXPORT int label_cmp __PR((struct dk_label *lp1, struct dk_label *lp2));
84 EXPORT BOOL labelgeom_ok __PR((struct dk_label *lp, BOOL print));
85 LOCAL void lerror __PR((struct dk_label *lp, char *name));
86 LOCAL void tty_insert __PR((char *s));
87 LOCAL long getprevpart __PR((void));
88 LOCAL long getnextpart __PR((void));
89 EXPORT BOOL cvt_cyls __PR((char *linep, long *lp, long mini, long maxi, struct disk *dp));
90 EXPORT BOOL cvt_bcyls __PR((char *linep, long *lp, long mini, long maxi, struct disk *dp));
91
92 #ifdef SVR4
93 struct strval vtags[] = {
94 { V_UNASSIGNED, "unassigned", "" },
95 { V_BOOT, "boot", "" },
96 { V_ROOT, "root", "" },
97 { V_SWAP, "swap", "" },
98 { V_USR, "usr", "" },
99 { V_BACKUP, "backup", "" },
100 { V_STAND, "stand", "(used for opt)" },
101 { V_VAR, "var", "" },
102 { V_HOME, "home", "" },
103 { 0 }
104 };
105
106 struct strval vflags[] = {
107 { 0, "wm", "read-write, mountable" },
108 { V_UNMNT, "wu", "read-write, unmountable" },
109 { V_RONLY, "rm", "read-only, mountable" },
110 { V_RONLY|V_UNMNT, "ru", "read-only, unmountable" },
111 { 0 }
112 };
113
114 struct dk_map2 default_vtmap[NDKMAP] = {
115 { V_ROOT, 0 }, /* a == 0 */
116 { V_SWAP, V_UNMNT }, /* b == 1 */
117 { V_BACKUP, V_UNMNT }, /* c == 2 */
118 { V_UNASSIGNED, 0 }, /* d == 3 */
119 { V_UNASSIGNED, 0 }, /* e == 4 */
120 { V_UNASSIGNED, 0 }, /* f == 5 */
121 { V_USR, 0 }, /* g == 6 */
122 { V_UNASSIGNED, 0 }, /* h == 7 */
123 };
124
125 EXPORT void
set_default_vtmap(lp)126 set_default_vtmap(lp)
127 register struct dk_label *lp;
128 {
129 register int i;
130
131 lp->dkl_vtoc.v_version = V_VERSION;
132 lp->dkl_vtoc.v_nparts = NDKMAP;
133 lp->dkl_vtoc.v_sanity = VTOC_SANE;
134
135 for (i = 0; i < NDKMAP; i++) {
136 lp->dkl_vtoc.v_part[i].p_tag = default_vtmap[i].p_tag;
137 lp->dkl_vtoc.v_part[i].p_flag = default_vtmap[i].p_flag;
138
139 }
140 }
141 #else
142 /*
143 * dummies for SunOS 4.x
144 * to allow the interpratation of a unique database for
145 * SunOS 4.x and Solaris 2.x
146 */
147 struct strval vtags[] = {
148 { 0, "unassigned", "" },
149 { 0, "boot", "" },
150 { 0, "root", "" },
151 { 0, "swap", "" },
152 { 0, "usr", "" },
153 { 0, "backup", "" },
154 { 0, "stand", "" },
155 { 0, "var", "" },
156 { 0, "home", "" },
157 { 0 }
158 };
159
160 struct strval vflags[] = {
161 { 0, "wm", "" },
162 { 0, "wu", "" },
163 { 0, "rm", "" },
164 { 0, "ru", "" },
165 { 0 }
166 };
167
168 /* ARGSUSED */
169 EXPORT void
set_default_vtmap(lp)170 set_default_vtmap(lp)
171 register struct dk_label *lp;
172 {
173 }
174 #endif
175
176 EXPORT unsigned short
do_cksum(l)177 do_cksum(l)
178 register struct dk_label *l;
179 {
180 register short *sp;
181 register short sum = 0;
182 register short count = (sizeof (struct dk_label)/sizeof (short)) - 1;
183
184 sp = (short *)l;
185 while (count--) {
186 sum ^= *sp++;
187 }
188 return (sum);
189 }
190
191 EXPORT BOOL
check_vtmap(lp,set)192 check_vtmap(lp, set)
193 register struct dk_label *lp;
194 BOOL set;
195 {
196 int ret = TRUE;
197
198 #ifdef SVR4
199 if (lp->dkl_vtoc.v_version != V_VERSION) {
200 unsigned short sum = do_cksum(lp);
201
202 ret = FALSE;
203 if (set) {
204 printf("Assigning default vtoc map to label.\n");
205 set_default_vtmap(lp);
206 if (sum == lp->dkl_cksum)
207 lp->dkl_cksum = do_cksum(lp);
208 } else {
209 printf("WARNING: no vtoc map in label.\n");
210 }
211 }
212 #endif
213 return (ret);
214 }
215
216 EXPORT void
setlabel_from_val(scgp,dp,lp)217 setlabel_from_val(scgp, dp, lp)
218 SCSI *scgp;
219 struct disk *dp;
220 register struct dk_label *lp;
221 {
222 if (lp->dkl_magic != DKL_MAGIC)
223 fillbytes((caddr_t)lp, sizeof (*lp), '\0');
224
225 getasciilabel(lp);
226
227 lp->dkl_rpm = dp->rpm;
228
229 /*
230 * XXX
231 * Alternates pro Zylinder sind von SUN noch nicht vollst�ndig
232 * implementiert. Es ist noch nicht klar, wie
233 */
234 /* lp->dkl_apc = dp->nhead * dp->aspz / dp->tpz;*/
235 lp->dkl_apc = 0;
236 if (dp->gap1 < 0) /* Hack fuer label.c */
237 dp->gap1 = 0;
238 if (dp->gap2 < 0) /* Hack fuer label.c */
239 dp->gap2 = 0;
240 lp->dkl_gap1 = dp->gap1;
241 lp->dkl_gap2 = dp->gap2;
242 if (dp->interleave < 0) /* Hack fuer label.c */
243 dp->interleave = 1;
244 lp->dkl_intrlv = dp->interleave;
245 if (lp->dkl_intrlv == 0) /* Hack fuer Sony */
246 lp->dkl_intrlv = 1;
247 if (dp->lncyl <= 0) /* XXX kann spaeter weg */
248 raisecond("setlabel_from_val: lncyl", 0L);
249 if (dp->lpcyl <= 0 || dp->lpcyl > 0xFFFE)
250 get_lgeom_defaults(scgp, dp);
251 lp->dkl_ncyl = dp->lncyl;
252 lp->dkl_acyl = dp->lacyl;
253 lp->dkl_pcyl = dp->lpcyl;
254 lp->dkl_nhead = dp->lhead;
255 lp->dkl_nsect = dp->lspt;
256 lp->dkl_bhead = 0; /* Kopf auf dem das Label steht */
257 lp->dkl_ppart = 0; /* Nummer der physikalischen Partition */
258
259 setasciilabel(lp, labelbuf);
260
261 if (dp->labelread < 0) {
262 printf("Setting part '%c' to calculated values.\n", PARTOFF+2);
263 lp->dkl_map[2].dkl_nblk =
264 lp->dkl_ncyl * lp->dkl_nhead * lp->dkl_nsect;
265 lp->dkl_map[2].dkl_cylno = 0;
266 }
267
268 lp->dkl_magic = DKL_MAGIC;
269 lp->dkl_cksum = do_cksum(lp);
270 }
271
272 EXPORT void
makelabel(scgp,dp,lp)273 makelabel(scgp, dp, lp)
274 SCSI *scgp;
275 struct disk *dp;
276 register struct dk_label *lp;
277 {
278 char lbuf[80];
279
280 setlabel_from_val(scgp, dp, lp);
281
282 if (yes("Label: <%s> change ? ", labelbuf)) {
283 printf("Enter disk label: "); flush();
284 tty_insert(labelbuf);
285 (void) getline(lbuf, sizeof (lbuf));
286 strcpy(labelbuf, lbuf);
287 }
288 setasciilabel(lp, labelbuf);
289
290 #ifdef SVR4
291 strncpy(lbuf, lp->dkl_vtoc.v_volume, LEN_DKL_VVOL);
292 lbuf[LEN_DKL_VVOL] = '\0';
293 if (yes("Volume Name: <%s> change ? ", lbuf)) {
294 printf("Enter volume name: "); flush();
295 tty_insert(lbuf);
296 (void) getline(lbuf, LEN_DKL_VVOL+1);
297 strncpy(lp->dkl_vtoc.v_volume, lbuf, LEN_DKL_VVOL);
298 }
299 #endif
300
301 if (yes("Change partition table? ")) {
302 register int i;
303
304 for (i = 0; i < 8; i++) {
305 printpart(lp, i);
306 if (yes("Change ? "))
307 chpart(dp, lp, i);
308 }
309 }
310
311 lp->dkl_magic = DKL_MAGIC;
312 lp->dkl_cksum = do_cksum(lp);
313 }
314
315 LOCAL struct dk_label *cur_lp; /* for cvt_cyls() */
316 LOCAL long cur_part; /* for cvt_cyls() */
317
318 LOCAL void
chpart(dp,lp,idx)319 chpart(dp, lp, idx)
320 struct disk *dp;
321 register struct dk_label *lp;
322 register int idx;
323 {
324 long l;
325 long maxsect = lp->dkl_ncyl * lp->dkl_nhead * lp->dkl_nsect;
326
327 do {
328 top:
329 printf("Partition %c\n", idx+PARTOFF);
330
331 #ifdef SVR4
332 lp->dkl_vtoc.v_version = V_VERSION;
333 lp->dkl_vtoc.v_nparts = NDKMAP;
334 lp->dkl_vtoc.v_sanity = VTOC_SANE;
335
336 l = lp->dkl_vtoc.v_part[idx].p_tag;
337 getstrval("Enter partition id Tag", &l, vtags, 0);
338 lp->dkl_vtoc.v_part[idx].p_tag = l;
339 l = lp->dkl_vtoc.v_part[idx].p_flag;
340 getstrval("Enter partition permission Flags", &l, vflags, 0);
341 lp->dkl_vtoc.v_part[idx].p_flag = l;
342 #endif
343
344 cur_lp = lp;
345 cur_part = idx;
346 l = lp->dkl_map[idx].dkl_cylno;
347 getdiskcyls("Enter starting cylinder",
348 &l, 0L, (long)lp->dkl_ncyl);
349 lp->dkl_map[idx].dkl_cylno = l;
350
351 l = lp->dkl_map[idx].dkl_nblk;
352 getdiskblocks("Enter number of blocks",
353 &l, 0L,
354 (long)(maxsect -
355 (lp->dkl_map[idx].dkl_cylno*lp->dkl_nhead*lp->dkl_nsect)),
356 dp);
357 lp->dkl_map[idx].dkl_nblk = l;
358
359
360 if (lp->dkl_map[idx].dkl_nblk %
361 (long)(lp->dkl_nhead*lp->dkl_nsect))
362 printf("Not on a cylidner boundary!!!\n");
363
364 if (lp->dkl_map[idx].dkl_cylno*
365 (long)(lp->dkl_nhead*lp->dkl_nsect) +
366 lp->dkl_map[idx].dkl_nblk >
367 maxsect) {
368 printf("Partition exceeds end of disk.\n");
369 goto top;
370 }
371 printpart(lp, idx);
372 } while (!yes("Ok ? "));
373 }
374
375 #ifdef SVR4
376 LOCAL int
prvttab(f,lp,i,n)377 prvttab(f, lp, i, n)
378 register FILE *f;
379 register struct dk_label *lp;
380 int i;
381 int n;
382 {
383 struct strval *sp;
384
385 if (lp->dkl_vtoc.v_part[i].p_tag != default_vtmap[i].p_tag) {
386 if ((sp = strval(lp->dkl_vtoc.v_part[i].p_tag, vtags)) != 0) {
387 fprintf(f, "%s, ", sp->s_name);
388 if (n % 4)
389 n++;
390 }
391 }
392 if (lp->dkl_vtoc.v_part[i].p_flag != default_vtmap[i].p_flag) {
393 if ((sp = strval(lp->dkl_vtoc.v_part[i].p_flag, vflags)) != 0) {
394 fprintf(f, "%s, ", sp-> s_name);
395 if (n % 4)
396 n++;
397 }
398 }
399 return (n);
400 }
401 #endif
402
403 EXPORT void
prpartab(f,disk_type,lp)404 prpartab(f, disk_type, lp)
405 register FILE *f;
406 char *disk_type;
407 register struct dk_label *lp;
408 {
409 register int i;
410 register int n = 0;
411
412 getasciilabel(lp);
413 fprintf(f, "partition = \"%s\"\n", labelbuf);
414 fprintf(f, "\tdisk = \"%s\"\n\t", disk_type);
415 #ifdef nono
416 /* fprintf(f, "lrpm = %d : ", lp->dkl_rpm);*/
417 fprintf(f, "pcyl: %d\n", lp->dkl_pcyl);
418 fprintf(f, "apc: %d\n", lp->dkl_apc);
419 fprintf(f, "gap1: %d\n", lp->dkl_gap1);
420 fprintf(f, "gap2: %d\n", lp->dkl_gap2);
421 fprintf(f, "interleave: %d\n", lp->dkl_intrlv);
422 #endif
423 if (f == stdout) {
424 /*
425 * We don't want this to appear in the database.
426 */
427 fprintf(f, "lpcyl = %d : ", lp->dkl_pcyl);
428 }
429
430 fprintf(f, "lncyl = %d : ", lp->dkl_ncyl);
431 fprintf(f, "lacyl = %d : ", lp->dkl_acyl);
432 fprintf(f, "lhead = %d : ", lp->dkl_nhead);
433 fprintf(f, "lspt = %d : ", lp->dkl_nsect);
434 #ifdef nono
435 fprintf(f, "bhead: %d\n", lp->dkl_bhead);
436 fprintf(f, "ppart: %d\n", lp->dkl_ppart);
437 #endif
438
439 for (i = 0; i < NDKMAP; i++) {
440 if (lp->dkl_map[i].dkl_nblk) {
441
442 if (n++ % 4 == 0)
443 fprintf(f, "\n\t");
444 else
445 fprintf(f, " : ");
446 fprintf(f, "%c = ", i + PARTOFF);
447 #ifdef SVR4
448 n = prvttab(f, lp, i, n);
449 #endif
450 fprintf(f, "%ld, %ld",
451 (long)lp->dkl_map[i].dkl_cylno,
452 (long)lp->dkl_map[i].dkl_nblk);
453 }
454 }
455 fprintf(f, "\n");
456 }
457
458 EXPORT void
printlabel(lp)459 printlabel(lp)
460 register struct dk_label *lp;
461 {
462 printf("label: <%s>\n", lp->dkl_asciilabel);
463 #ifdef SVR4
464 printf("volname: '%.8s'\n", lp->dkl_vtoc.v_volume);
465 #endif
466 printf("rpm: %d\n", lp->dkl_rpm);
467 printf("pcyl: %d\n", lp->dkl_pcyl);
468 printf("apc: %d\n", lp->dkl_apc);
469 if ((short)lp->dkl_gap1 > 0 || (short)lp->dkl_gap2 > 0) {
470 printf("gap1: %d\n", lp->dkl_gap1);
471 printf("gap2: %d\n", lp->dkl_gap2);
472 }
473 printf("interleave: %d\n", lp->dkl_intrlv);
474 printf("ncyl: %d\n", lp->dkl_ncyl);
475 printf("acyl: %d\n", lp->dkl_acyl);
476 printf("nhead: %d\n", lp->dkl_nhead);
477 printf("nsect: %d\n", lp->dkl_nsect);
478 if (lp->dkl_bhead || lp->dkl_ppart) {
479 printf("bhead: %d\n", lp->dkl_bhead);
480 printf("ppart: %d\n", lp->dkl_ppart);
481 }
482
483 if (lp->dkl_nhead == 0 || lp->dkl_nsect == 0)
484 printf("ILLEGAL GEOMETRY\n");
485 else
486 printparts(lp);
487
488 if (lp->dkl_magic != DKL_MAGIC)
489 printf("WRONG MAGIC: 0x%X\n", lp->dkl_magic);
490
491 printf("Checksum: 0x%X", lp->dkl_cksum);
492 if (lp->dkl_cksum != do_cksum(lp))
493 printf(" (should be 0x%X)", do_cksum(lp));
494 printf("\n");
495 }
496
497 LOCAL void
printparthead()498 printparthead()
499 {
500 /*
501 * 0 root 00 0 - 34 0 49595 24.22MB (35)
502 */
503 #ifdef SVR4
504 printf("Part Tag Flag Cylinders Startsec # of Sec Size Blocks\n");
505 #else
506 printf("Part Cylinders Startsec # of Sec Size Blocks\n");
507 #endif
508 }
509
510 EXPORT void
printpart(lp,i)511 printpart(lp, i)
512 struct dk_label *lp;
513 int i;
514 {
515 printparthead();
516 _printpart(lp, i);
517 }
518
519 LOCAL void
_printpart(lp,i)520 _printpart(lp, i)
521 register struct dk_label *lp;
522 register int i;
523 {
524 register long a;
525 #ifdef SVR4
526 struct strval *sp;
527 char *tag = "ILLEGAL";
528 char *flag = "XX";
529 #endif
530
531 a = (lp->dkl_map[i].dkl_nblk-1)/(long)(lp->dkl_nhead*lp->dkl_nsect);
532 a += lp->dkl_map[i].dkl_cylno;
533 if (lp->dkl_map[i].dkl_nblk == 0)
534 a = 0;
535
536 #ifdef SVR4
537 sp = strval(lp->dkl_vtoc.v_part[i].p_tag, vtags);
538 if (sp)
539 tag = sp->s_name;
540 sp = strval(lp->dkl_vtoc.v_part[i].p_flag, vflags);
541 if (sp)
542 flag = sp->s_name;
543
544 /*
545 * Ugly, but Linux incude files violate POSIX and #define printf
546 * so we cannot include the #ifdef into the printf() arg list.
547 */
548 # define __PARTARGS1 (i + PARTOFF), tag, flag
549 # define __PARTFMT "%c %10s %2s %5ld -%5ld %8ld %8ld %6ld.%02ldMB ("
550 #else
551 # define __PARTARGS1 (i + PARTOFF)
552 # define __PARTFMT "%c %5ld -%5ld %8ld %8ld %6ld.%02ldMB ("
553 #endif
554 printf(__PARTFMT,
555 __PARTARGS1,
556 (long)lp->dkl_map[i].dkl_cylno, a,
557 (long)lp->dkl_map[i].dkl_cylno*lp->dkl_nsect*lp->dkl_nhead,
558 (long)lp->dkl_map[i].dkl_nblk,
559 (long)lp->dkl_map[i].dkl_nblk/(2*1024),
560 (long)(lp->dkl_map[i].dkl_nblk%(2*1024))*100/(2*1024));
561 a = lp->dkl_map[i].dkl_nblk/(long)(lp->dkl_nhead*lp->dkl_nsect);
562 printf("%ld", a);
563 a = lp->dkl_map[i].dkl_nblk%(long)(lp->dkl_nhead*lp->dkl_nsect);
564 printf("/%ld/%ld",
565 a / (long)lp->dkl_nsect,
566 a % (long)lp->dkl_nsect);
567 printf(")\n");
568 }
569
570 EXPORT void
printparts(lp)571 printparts(lp)
572 register struct dk_label *lp;
573 {
574 register int i;
575
576 printparthead();
577 for (i = 0; i < NDKMAP; i++) {
578 if (lp->dkl_map[i].dkl_nblk)
579 _printpart(lp, i);
580 }
581 }
582
583 EXPORT int
readlabel(name,lp)584 readlabel(name, lp)
585 char *name;
586 register struct dk_label *lp;
587 {
588 int f;
589
590 if ((f = open(name, O_RDONLY|O_NDELAY)) < 0) {
591 errmsg("Cannot open prototype '%s'\n", name);
592 return (0);
593 }
594 if (read(f, (char *)lp, sizeof (*lp)) != sizeof (*lp)) {
595 errmsg("Cannot read prototype '%s'\n", name);
596 close(f);
597 return (0);
598 }
599 close(f);
600 return (1);
601 }
602
603 /*
604 * This function is only used by the stand-alone 'label' program.
605 */
606 EXPORT void
writelabel(name,lp)607 writelabel(name, lp)
608 char *name;
609 register struct dk_label *lp;
610 {
611 register int f;
612 struct dk_allmap map;
613
614 if ((f = open(name, O_CREAT|O_WRONLY|O_NDELAY, (mode_t)0666)) < 0)
615 comerr("Cannot create '%s'\n", name);
616 if (write(f, (char *)lp, sizeof (*lp)) < 0)
617 errmsg("Cannot write '%s'\n", name);
618
619 #ifdef HAVE_IOCTL
620 if (ioctl(f, DKIOCGAPART, &map) >= 0) {
621 /*
622 * It seemes to be a disk!
623 */
624 writebackuplabel(f, lp);
625 if (ioctl(f, DKIOCSAPART,
626 (struct dk_allmap *)&lp->dkl_map[0]) < 0)
627 comerr("Cannot set partitions.\n");
628 (void) setgeom(f, lp);
629 }
630 #endif
631 close(f);
632 exit(0);
633 }
634
635 LOCAL void
writebackuplabel(f,lp)636 writebackuplabel(f, lp)
637 int f;
638 register struct dk_label *lp;
639 {
640 struct dk_allmap map;
641 long backup_label_blk;
642 int i;
643
644 backup_label_blk = lp->dkl_ncyl + lp->dkl_acyl - 1;
645 backup_label_blk *= lp->dkl_nhead * lp->dkl_nsect;
646 backup_label_blk += (lp->dkl_nhead-1) * lp->dkl_nsect;
647
648 #ifdef HAVE_IOCTL
649 ioctl(f, DKIOCGAPART, &map);
650 /*
651 * If he's not using partition '2' (the whole disk)
652 * he will fail later on.
653 */
654 map.dka_map[2].dkl_cylno = 0;
655 map.dka_map[2].dkl_nblk = backup_label_blk + 10;
656
657 if (ioctl(f, DKIOCSAPART, &map) >= 0) {
658 for (i = 1; i < 10; i += 2) {
659 if (lseek(f, (off_t)(512*(backup_label_blk + i)),
660 SEEK_SET) < 0) {
661 errmsg("Seek error for backup label\n");
662 continue;
663 }
664 if (write(f, (char *)lp, sizeof (*lp)) < 0)
665 errmsg("Cannot write backup label\n");
666 }
667 }
668 #endif
669 }
670
671 EXPORT int
setlabel(name,lp)672 setlabel(name, lp)
673 char *name;
674 register struct dk_label *lp;
675 {
676 register int f;
677 int err;
678 struct dk_allmap map;
679
680 if ((f = open(name, O_RDONLY|O_NDELAY)) < 0) {
681 err = geterrno();
682 errmsgno(err, "Cannot open '%s'\n", name);
683 return (err);
684 }
685
686 #ifdef HAVE_IOCTL
687 if (ioctl(f, DKIOCGAPART, &map) < 0) {
688 err = geterrno();
689 errmsgno(err, "Cannot get partitions from '%s'.\n", name);
690 close(f);
691 return (err);
692 }
693
694 if (ioctl(f, DKIOCSAPART, (struct dk_allmap *)&lp->dkl_map[0]) < 0) {
695 err = geterrno();
696 errmsgno(err, "Cannot set partitions on '%s'.\n", name);
697 close(f);
698 return (err);
699 }
700 #endif
701 err = setgeom(f, lp);
702 close(f);
703 return (err);
704 }
705
706 LOCAL int
setgeom(f,lp)707 setgeom(f, lp)
708 int f;
709 register struct dk_label *lp;
710 {
711 struct dk_geom geom;
712 register struct dk_geom *gp;
713
714 gp = &geom;
715
716 gp->dkg_ncyl = lp->dkl_ncyl;
717 gp->dkg_acyl = lp->dkl_acyl;
718 /* gp->dkg_bcyl = lp->dkl_bcyl;*/
719 gp->dkg_bcyl = 0;
720 gp->dkg_nhead = lp->dkl_nhead;
721 gp->dkg_bhead = lp->dkl_bhead;
722 gp->dkg_nsect = lp->dkl_nsect;
723 gp->dkg_intrlv = lp->dkl_intrlv;
724 gp->dkg_gap1 = lp->dkl_gap1;
725 gp->dkg_gap2 = lp->dkl_gap2;
726 gp->dkg_apc = lp->dkl_apc;
727 gp->dkg_rpm = lp->dkl_rpm;
728 gp->dkg_pcyl = lp->dkl_pcyl;
729
730 #ifdef HAVE_IOCTL
731 if (ioctl(f, DKIOCSGEOM, gp) < 0) {
732 int err = geterrno();
733
734 errmsgno(err, "Cannot set geometry\n");
735 return (err);
736 }
737 #endif
738 return (0);
739 }
740
741 EXPORT char *
getasciilabel(lp)742 getasciilabel(lp)
743 register struct dk_label *lp;
744 {
745 register char *idx;
746
747 labelbuf[0] = '\0';
748 if (lp->dkl_magic != DKL_MAGIC || lp->dkl_cksum != do_cksum(lp))
749 return ((char *)0);
750 if ((idx = strstr(lp->dkl_asciilabel, " cyl")) != NULL) {
751 strncpy(labelbuf, lp->dkl_asciilabel, idx-lp->dkl_asciilabel);
752 labelbuf[idx - lp->dkl_asciilabel] = '\0';
753 return (labelbuf);
754 }
755 strcpy(labelbuf, lp->dkl_asciilabel);
756 return (labelbuf);
757 }
758
759 EXPORT void
setasciilabel(lp,lname)760 setasciilabel(lp, lname)
761 register struct dk_label *lp;
762 char *lname;
763 {
764 char lbuf[150];
765
766 sprintf(lbuf, "%.80s cyl %d alt %d hd %d sec %d",
767 lname,
768 lp->dkl_ncyl, lp->dkl_acyl,
769 lp->dkl_nhead, lp->dkl_nsect);
770 sprintf(lp->dkl_asciilabel, "%.128s", lbuf);
771 }
772
773 EXPORT BOOL
setval_from_label(dp,lp)774 setval_from_label(dp, lp)
775 struct disk *dp;
776 register struct dk_label *lp;
777 {
778 if (lp->dkl_magic != DKL_MAGIC || lp->dkl_cksum != do_cksum(lp))
779 return (FALSE);
780
781 getasciilabel(lp);
782
783 /*
784 * Die nicht direkt der evt. gef�lschten Labelgeometrie zugeordneten
785 * Werte d�rfen nicht die schon vorhandenen echten Werte �berschreiben.
786 */
787 if (dp->rpm <= 0 && lp->dkl_rpm != ((unsigned short)-1) &&
788 lp->dkl_rpm > 0)
789 dp->rpm = lp->dkl_rpm;
790
791 if (dp->pcyl <= 0 && lp->dkl_pcyl != ((unsigned short)-1)) {
792 if (lp->dkl_pcyl > 0) {
793 dp->pcyl = lp->dkl_pcyl;
794 } else {
795 dp->pcyl = lp->dkl_ncyl + lp->dkl_acyl;
796 if (dp->atrk >= 0 && dp->nhead > 0)
797 dp->pcyl += dp->atrk/dp->nhead;
798 if (dp->int_cyl >= 0)
799 dp->pcyl += dp->int_cyl;
800 }
801 if (dp->lpcyl < 0)
802 dp->lpcyl = dp->pcyl;
803 }
804
805 if (dp->gap1 < 0 && lp->dkl_gap1 != ((unsigned short)-1))
806 dp->gap1 = lp->dkl_gap1;
807 if (dp->gap2 < 0 && lp->dkl_gap1 != ((unsigned short)-1))
808 dp->gap2 = lp->dkl_gap2;
809
810 if (dp->interleave < 0 && lp->dkl_intrlv != ((unsigned short)-1))
811 dp->interleave = lp->dkl_intrlv;
812
813 /*
814 * Hier folgen die evt. gef�lschten Werte f�r die Labegeometrie.
815 */
816 dp->lncyl = lp->dkl_ncyl;
817 dp->lacyl = lp->dkl_acyl;
818 dp->lhead = lp->dkl_nhead;
819 dp->lspt = lp->dkl_nsect;
820 /*
821 *XXX
822 * Alternates pro Zylinder sind von SUN noch nicht vollst�ndig
823 * implementiert. Es ist noch nicht klar, wie
824 */
825 /* dp->aspz = lp->dkl_apc * dp->tpz / lp->dkl_nhead;*/
826 if (dp->spt < 0)
827 dp->spt = dp->lspt /*+ lp->dkl_apc / lp->dkl_nhead*/;
828
829 if (dp->int_cyl < 0 && dp->nhead > 0) {
830 dp->int_cyl = dp->pcyl - dp->lncyl
831 - dp->lacyl
832 - dp->atrk/dp->nhead;
833 }
834 return (TRUE);
835 }
836
837 EXPORT void
label_null(lp)838 label_null(lp)
839 register struct dk_label *lp;
840 {
841 fillbytes((caddr_t)lp, sizeof (*lp), '\0');
842
843 lp->dkl_rpm = -1; /* rotations per minute */
844 lp->dkl_pcyl = -1; /* # physical cylinders */
845 lp->dkl_apc = -1; /* alternates per cylinder */
846 lp->dkl_gap1 = -1; /* used to be gap1 */
847 lp->dkl_gap2 = -1; /* used to be gap2 */
848 lp->dkl_intrlv = -1; /* interleave factor */
849 lp->dkl_ncyl = -1; /* # of data cylinders */
850 lp->dkl_acyl = -1; /* # of alternate cylinders */
851 lp->dkl_nhead = -1; /* # of heads in this partition */
852 lp->dkl_nsect = -1; /* # of 512 byte sectors per track */
853 lp->dkl_bhead = -1; /* used to be label head offset */
854 lp->dkl_ppart = -1; /* used to by physical partition */
855 }
856
857 #define loff(a) ((size_t)&((struct dk_label *)0)->a)
858
859 EXPORT int
label_cmp(lp1,lp2)860 label_cmp(lp1, lp2)
861 register struct dk_label *lp1;
862 register struct dk_label *lp2;
863 {
864 int ret = 0;
865
866 /*
867 * If Partition differs return (0)
868 */
869 if (cmpbytes(lp1->dkl_map, lp2->dkl_map, sizeof (lp1->dkl_map)) <
870 sizeof (lp1->dkl_map))
871 return (0);
872
873 #ifdef SVR4
874 if (cmpbytes(&lp1->dkl_vtoc, &lp2->dkl_vtoc, sizeof (lp1->dkl_vtoc)) >=
875 sizeof (lp1->dkl_vtoc))
876 ret++;
877 #endif
878
879 if (cmpbytes(lp1->dkl_pad, lp2->dkl_pad,
880 loff(dkl_map[0]) - loff(dkl_pad[0])) >=
881 loff(dkl_map[0]) - loff(dkl_pad[0]))
882 ret++;
883
884 if (streql(lp1->dkl_asciilabel, lp2->dkl_asciilabel))
885 ret++;
886
887 return (ret);
888 }
889
890 EXPORT BOOL
labelgeom_ok(lp,print)891 labelgeom_ok(lp, print)
892 register struct dk_label *lp;
893 BOOL print;
894 {
895 if (lp->dkl_ncyl == (unsigned short) -1) {
896 if (print) lerror(lp, "lncyl");
897 return (FALSE);
898 }
899 if (lp->dkl_acyl == (unsigned short) -1) {
900 if (print) lerror(lp, "lacyl");
901 return (FALSE);
902 }
903 if (lp->dkl_nhead == (unsigned short) -1) {
904 if (print) lerror(lp, "lnhead");
905 return (FALSE);
906 }
907 if (lp->dkl_nsect == (unsigned short) -1) {
908 if (print) lerror(lp, "lspt");
909 return (FALSE);
910 }
911 return (TRUE);
912 }
913
914 LOCAL void
lerror(lp,name)915 lerror(lp, name)
916 register struct dk_label *lp;
917 char *name;
918 {
919 error("Missing '%s' in label \"%s\".\n", name, getasciilabel(lp));
920 }
921
922 LOCAL void
tty_insert(s)923 tty_insert(s)
924 char *s;
925 {
926 #ifdef TIOCSTI
927 while (*s)
928 ioctl(fdown(stdin), TIOCSTI, s++);
929 #endif
930 }
931
932
933 LOCAL long
getprevpart()934 getprevpart()
935 {
936 long part = cur_part - 1;
937
938 /*
939 * Look for previous partition that is in use
940 * and ends before end of the disk.
941 */
942 while (part > 0 &&
943 (cur_lp->dkl_map[part].dkl_nblk == 0 ||
944 (cur_lp->dkl_map[part].dkl_cylno +
945 (cur_lp->dkl_map[part].dkl_nblk-1) /
946 (long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect))
947 >= (long)(cur_lp->dkl_ncyl - 1))) {
948 part--;
949 }
950 return (part);
951 }
952
953 LOCAL long
getnextpart()954 getnextpart()
955 {
956 long part = cur_part + 1;
957
958 /*
959 * Look for next partition that is in use
960 * and starts after the beginning of the current partition.
961 */
962 while (part < NDKMAP &&
963 (cur_lp->dkl_map[part].dkl_nblk == 0 ||
964 cur_lp->dkl_map[part].dkl_cylno <=
965 cur_lp->dkl_map[cur_part].dkl_cylno)) {
966 part++;
967 }
968 return (part);
969 }
970
971 /*---------------------------------------------------------------------------
972 |
973 | Hier wird der Anfang einer Partition festgelegt
974 |
975 +---------------------------------------------------------------------------*/
976
977 EXPORT BOOL
cvt_cyls(linep,lp,mini,maxi,dp)978 cvt_cyls(linep, lp, mini, maxi, dp)
979 char *linep;
980 long *lp;
981 long mini;
982 long maxi;
983 struct disk *dp;
984 {
985 long l;
986 long part = 0L;
987 BOOL doshift = FALSE;
988
989 if (linep[0] == '?') {
990 printf("To enter cylinders as simple number:\n");
991 (void) cvt_std(linep, lp, mini, maxi, dp);
992
993 printf("To start this partition past the end of a partition:\n");
994 printf("\tEnter '>' to start past the end of the previous valid partition (%ld).\n",
995 getprevpart());
996 printf("\tEnter '>g' to start past the end of partition 'g'.\n");
997 printf("\tEnter '>5' to start past the end of partition '5'.\n");
998
999 printf("To shift this partition to end at the beginning of a partition:\n");
1000 printf("\tEnter '>>' to shift to the beginning of the next valid partition (%ld).\n",
1001 getnextpart());
1002 printf("\tEnter '>>g' to shift to the beginning of partition 'g'.\n");
1003 printf("\tEnter '>>5' to shift to the beginning of partition '5'.\n");
1004 printf("\tEnter '>>%d' to shift to the the end of the disk.\n", NDKMAP);
1005 return (FALSE);
1006 }
1007 /*
1008 * If line does not begin with '>'
1009 * convert as int.
1010 */
1011 if (*linep != '>')
1012 return (cvt_std(linep, lp, mini, maxi, (void *)0));
1013
1014 if (linep[1] == '>') {
1015 doshift = TRUE;
1016 linep++;
1017 }
1018
1019 if (*++linep) {
1020
1021 /*
1022 * It's a > part 'x' end notation.
1023 */
1024 if (strchr("abcdefgh", linep[0]) && linep[1] == '\0')
1025 part = linep[0] - 'a';
1026 else
1027 if (!cvt_std(linep, &part, 0L, NDKMAP, (void *)0))
1028 return (FALSE);
1029 } else {
1030 if (doshift) {
1031 part = getnextpart();
1032 } else {
1033 part = getprevpart();
1034 if (part < 0) {
1035 *lp = mini;
1036 return (TRUE);
1037 }
1038 }
1039 }
1040 if ((doshift && (part <= 0 || part > NDKMAP)) ||
1041 (!doshift && (part < 0 || part >= NDKMAP))) {
1042 printf("partition '%ld' is out of range.\n", part);
1043 return (FALSE);
1044 }
1045 if (doshift)
1046 printf("shifting to partition %ld\n", part);
1047 else
1048 printf("appending to partition %ld\n", part);
1049
1050 if (doshift) {
1051 if (part == NDKMAP) {
1052 l = cur_lp->dkl_ncyl;
1053 } else {
1054 l = cur_lp->dkl_map[part].dkl_cylno;
1055 }
1056 /*
1057 * Round up to start at prev cylinder
1058 */
1059 l -= (cur_lp->dkl_map[cur_part].dkl_nblk-1) /
1060 (long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1061 l -= 1;
1062 } else {
1063 /*
1064 * Round up to start at next cylinder
1065 */
1066 l = cur_lp->dkl_map[part].dkl_cylno;
1067 l += (cur_lp->dkl_map[part].dkl_nblk-1) /
1068 (long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1069 l += 1;
1070 }
1071
1072 if (l < mini || l > maxi) {
1073 printf("'%ld' is out of range.\n", l);
1074 return (FALSE);
1075 }
1076 *lp = l;
1077 return (TRUE);
1078 }
1079
1080 /*---------------------------------------------------------------------------
1081 |
1082 | Hier wird das Ende einer Partition festgelegt
1083 |
1084 +---------------------------------------------------------------------------*/
1085
1086 EXPORT BOOL
cvt_bcyls(linep,lp,mini,maxi,dp)1087 cvt_bcyls(linep, lp, mini, maxi, dp)
1088 char *linep;
1089 long *lp;
1090 long mini;
1091 long maxi;
1092 struct disk *dp;
1093 {
1094 long l;
1095 long part = 0L;
1096
1097 if (linep[0] == '?') {
1098 printf("To fill up this partition to the beginning of a partition:\n");
1099 printf("\tEnter '>' to fill up to the beginning of the next valid partition (%ld).\n",
1100 getnextpart());
1101 printf("\tEnter '>g' to fill up to the beginning of partition 'g'.\n");
1102 printf("\tEnter '>5' to fill up to the beginning of partition '5'.\n");
1103 return (FALSE);
1104 }
1105 /*
1106 * If line does not begin with '>'
1107 * convert as int.
1108 */
1109 if (*linep != '>')
1110 return (cvt_std(linep, lp, mini, maxi, (void *)0));
1111
1112 if (*++linep) {
1113
1114 /*
1115 * It's a > part 'x' end notation.
1116 */
1117 if (strchr("abcdefgh", linep[0]) && linep[1] == '\0')
1118 part = linep[0] - 'a';
1119 else
1120 if (!cvt_std(linep, &part, 0L, NDKMAP, (void *)0))
1121 return (FALSE);
1122 } else {
1123 part = getnextpart();
1124 if (part >= NDKMAP) {
1125 *lp = maxi;
1126 return (TRUE);
1127 }
1128 }
1129 if (part < 0 || part >= NDKMAP) {
1130 printf("partition '%ld' is out of range.\n", part);
1131 return (FALSE);
1132 }
1133 printf("filling up to partition %ld\n", part);
1134
1135 l = cur_lp->dkl_map[part].dkl_cylno -
1136 cur_lp->dkl_map[cur_part].dkl_cylno;
1137
1138 l *= (long)(cur_lp->dkl_nhead * cur_lp->dkl_nsect);
1139
1140 if (l < mini || l > maxi) {
1141 printf("'%ld' is out of range.\n", l);
1142 return (FALSE);
1143 }
1144 *lp = l;
1145 return (TRUE);
1146 }
1147