2 * File...........: s390-tools/fdasd/fdasd.c
3 * Author(s)......: Volker Sameske <sameske@de.ibm.com>
4 * Horst Hummel <horst.hummel@de.ibm.com>
5 * Gerhard Tonn <ton@de.ibm.com>
6 * Copyright IBM Corp. 2001,2007
11 #include "zt_common.h"
15 /* global variables */
16 struct hd_geometry geo
;
17 char line_buffer
[LINE_LENGTH
];
18 char *line_ptr
= line_buffer
;
21 static const char tool_name
[] = "fdasd: zSeries DASD partitioning program";
23 /* Copyright notice */
24 static const char copyright_notice
[] = "Copyright IBM Corp. 2001, 2006";
27 * Print version information.
32 printf ("%s version %s\n", tool_name
, RELEASE_STRING
);
33 printf ("%s\n", copyright_notice
);
37 getpos (fdasd_anchor_t
*anc
, int dsn
)
39 return anc
->partno
[dsn
];
43 getdsn (fdasd_anchor_t
*anc
, int pos
)
47 for (i
=0; i
<USABLE_PARTITIONS
; i
++) {
48 if (anc
->partno
[i
] == pos
)
56 setpos (fdasd_anchor_t
*anc
, int dsn
, int pos
)
58 anc
->partno
[dsn
] = pos
;
61 static u_int32_t
get_usable_cylinders(fdasd_anchor_t
*anc
)
66 if (anc
->f4
->DS4DEVCT
.DS4DSCYL
== LV_COMPAT_CYL
&&
67 anc
->f4
->DS4DCYL
> anc
->f4
->DS4DEVCT
.DS4DSCYL
)
68 return anc
->f4
->DS4DCYL
;
70 if (anc
->f4
->DS4DEVCT
.DS4DEVFG
& ALTERNATE_CYLINDERS_USED
)
71 cyl
= anc
->f4
->DS4DEVCT
.DS4DSCYL
-
72 (u_int16_t
) anc
->f4
->DS4DEVAC
;
74 cyl
= anc
->f4
->DS4DEVCT
.DS4DSCYL
;
78 static void get_addr_of_highest_f1_f8_label(fdasd_anchor_t
*anc
, cchhb_t
*addr
)
82 /* We have to count the follwing labels:
85 * format 7 only if we have moren then BIG_DISK_SIZE tracks
86 * one for each format 1 or format 8 label == one for each partition
87 * one for each format 9 label before the last format 8
88 * We assume that all partitions use format 8 labels when
89 * anc->formatted_cylinders > LV_COMPAT_CYL
90 * Note: Record zero is special, so block 0 on our disk is record 1!
93 record
= anc
->used_partitions
+ 2;
96 if (anc
->formatted_cylinders
> LV_COMPAT_CYL
)
97 record
+= anc
->used_partitions
- 1;
98 vtoc_set_cchhb(addr
, VTOC_START_CC
, VTOC_START_HH
, record
);
102 * Check for valid volume serial characters (max. 6) - remove invalid.
103 * If volser is empty, fill with default volser.
106 fdasd_check_volser(char *volser
, int devno
)
110 for (from
=0, to
=0; volser
[from
] && from
< VOLSER_LENGTH
; from
++)
111 if ((volser
[from
] >= 0x23 &&
112 volser
[from
] <= 0x25) || /* # $ % */
113 (volser
[from
] >= 0x30 &&
114 volser
[from
] <= 0x39) || /* 0-9 */
115 (volser
[from
] >= 0x40 &&
116 volser
[from
] <= 0x5a) || /* @ A-Z */
117 (volser
[from
] >= 0x61 &&
118 volser
[from
] <= 0x7a)) /* a-z */
119 volser
[to
++] = toupper(volser
[from
]);
123 if (volser
[0] == 0x00) {
124 sprintf(volser
, "0X%04x", devno
);
130 * Free memory of fdasd anchor struct.
133 fdasd_cleanup (fdasd_anchor_t
*anchor
)
135 partition_info_t
*part_info
, *next
;
138 if (anchor
== NULL
) return;
140 if (anchor
->f4
!= NULL
) free(anchor
->f4
);
141 if (anchor
->f5
!= NULL
) free(anchor
->f5
);
142 if (anchor
->f7
!= NULL
) free(anchor
->f7
);
143 if (anchor
->vlabel
!= NULL
) free(anchor
->vlabel
);
145 part_info
= anchor
->first
;
146 for (i
= 1; i
<= USABLE_PARTITIONS
&& part_info
!= NULL
; i
++) {
147 next
= part_info
->next
;
158 fdasd_exit (fdasd_anchor_t
*anchor
, int rc
)
160 fdasd_cleanup(anchor
);
169 fdasd_error(fdasd_anchor_t
*anc
, enum fdasd_failure why
, char *str
)
171 char err_str
[ERROR_STRING_SIZE
];
175 snprintf(err_str
, ERROR_STRING_SIZE
,
176 "%s parser error\n%s\n", FDASD_ERROR
, str
);
178 case unable_to_open_disk
:
179 snprintf(err_str
, ERROR_STRING_SIZE
,
180 "%s open error\n%s\n", FDASD_ERROR
, str
);
182 case unable_to_seek_disk
:
183 snprintf(err_str
, ERROR_STRING_SIZE
,
184 "%s seek error\n%s\n", FDASD_ERROR
, str
);
186 case unable_to_read_disk
:
187 snprintf(err_str
, ERROR_STRING_SIZE
,
188 "%s read error\n%s\n", FDASD_ERROR
, str
);
191 snprintf(err_str
, ERROR_STRING_SIZE
,
192 "%s write error\n%s\n", FDASD_ERROR
, str
);
194 case unable_to_ioctl
:
195 snprintf(err_str
, ERROR_STRING_SIZE
,
196 "%s IOCTL error\n%s\n", FDASD_ERROR
, str
);
198 case wrong_disk_type
:
199 snprintf(err_str
, ERROR_STRING_SIZE
,
200 "%s Unsupported disk type\n%s\n",
203 case wrong_disk_format
:
204 snprintf(err_str
, ERROR_STRING_SIZE
,
205 "%s Unsupported disk format\n%s\n",
209 snprintf(err_str
, ERROR_STRING_SIZE
,
210 "%s Disk in use\n%s\n", FDASD_ERROR
, str
);
212 case config_syntax_error
:
213 snprintf(err_str
, ERROR_STRING_SIZE
,
214 "%s Config file syntax error\n%s\n",
217 case vlabel_corrupted
:
218 snprintf(err_str
, ERROR_STRING_SIZE
,
219 "%s Volume label is corrupted.\n%s\n",
222 case dsname_corrupted
:
223 snprintf(err_str
, ERROR_STRING_SIZE
,
224 "%s a data set name is corrupted.\n%s\n",
228 snprintf(err_str
, ERROR_STRING_SIZE
,
229 "%s space allocation\n%s\n", FDASD_ERROR
, str
);
231 case device_verification_failed
:
232 snprintf(err_str
, ERROR_STRING_SIZE
,
233 "%s device verification failed\n%s\n",
236 case volser_not_found
:
237 snprintf(err_str
, ERROR_STRING_SIZE
,
238 "%s VOLSER not found on device %s\n",
242 snprintf(err_str
, ERROR_STRING_SIZE
,
243 "%s Fatal error\n%s\n",
248 fputs(err_str
, stderr
);
255 * Read line from stdin into global line_buffer
256 * and set global line_ptr to first printing character except space.
261 bzero(line_buffer
, LINE_LENGTH
);
262 line_ptr
= line_buffer
;
263 if (!fgets(line_buffer
, LINE_LENGTH
, stdin
))
265 while (*line_ptr
&& !isgraph(*line_ptr
))
275 read_char(char *mesg
)
285 * Print question string an enforce y/n answer.
288 yes_no(char *question_str
)
293 printf("%s (y/n): ", question_str
);
294 rc
= scanf("%c", &answer
);
297 if (answer
== 'y') return 0;
298 if (answer
== 'n') return 1;
307 fdasd_partition_type (char *str
)
309 if (strncmp("NATIVE", str
, 6) == 0)
310 strcpy(str
, "Linux native");
311 else if (strncmp("NEW ", str
, 6) == 0)
312 strcpy(str
, "Linux native");
313 else if (strncmp("SWAP ", str
, 6) == 0)
314 strcpy(str
, "Linux swap");
316 strcpy(str
, "unknown");
323 * prints out the usage text
328 printf ("\nUsage: fdasd [OPTIONS] [DEVICE]\n"
330 "Partition a DASD device either in interactive mode or "
332 "DEVICE is the node of the device (e.g. '/dev/dasda')\n"
334 "-h, --help Print this help, then exit\n"
335 "-v, --version Print version information, "
337 "-s, --silent Suppress messages\n"
338 "-r, --verbose Provide more verbose output\n"
339 "-a, --auto Automatically create a partition "
340 "using the entire disk\n"
341 "-k, --keep_volser Keep current volume serial when "
342 "performing automatic\n"
344 "-l, --label VOLSER Set the volume serial to VOLSER "
346 " automatic partitioning\n"
347 "-c, --config CONFIGFILE Automatically create partition(s) "
348 "using information\n"
349 " found in CONFIGFILE\n"
350 "-i, --volser Print volume serial\n"
351 "-p, --table Print partition table\n");
361 printf("Command action\n"
362 " m print this menu\n"
363 " p print the partition table\n"
364 " n add a new partition\n"
365 " d delete a partition\n"
366 " v change volume serial\n"
367 " t change partition type\n"
368 " r re-create VTOC and delete all partitions\n"
369 " u re-create VTOC re-using existing partition sizes\n"
370 " s show mapping (partition number - data set name)\n"
371 " q quit without saving changes\n"
372 " w write table to disk and exit\n");
377 * initializes the anchor structure and allocates some
378 * memory for the labels
381 fdasd_initialize_anchor (fdasd_anchor_t
*anc
)
383 partition_info_t
*part_info
, *prev_part_info
;
384 volume_label_t
*vlabel
;
387 bzero(anc
, sizeof(fdasd_anchor_t
));
389 for (i
=0; i
<USABLE_PARTITIONS
; i
++)
392 anc
->f4
= malloc(sizeof(format4_label_t
));
394 fdasd_error(anc
, malloc_failed
,
395 "FMT4 DSCB memory allocation failed.");
397 anc
->f5
= malloc(sizeof(format5_label_t
));
399 fdasd_error(anc
, malloc_failed
,
400 "FMT5 DSCB memory allocation failed.");
402 anc
->f7
= malloc(sizeof(format7_label_t
));
404 fdasd_error(anc
, malloc_failed
,
405 "FMT7 DSCB memory allocation failed.");
407 /* template for all format 9 labels */
408 anc
->f9
= malloc(sizeof(format9_label_t
));
410 fdasd_error(anc
, malloc_failed
,
411 "FMT9 DSCB memory allocation failed.");
413 bzero(anc
->f4
, sizeof(format4_label_t
));
414 bzero(anc
->f5
, sizeof(format5_label_t
));
415 bzero(anc
->f7
, sizeof(format7_label_t
));
416 bzero(anc
->f9
, sizeof(format9_label_t
));
417 vtoc_init_format9_label(anc
->f9
);
419 vlabel
= malloc(sizeof(volume_label_t
));
421 fdasd_error(anc
, malloc_failed
,
422 "Volume label memory allocation failed.");
423 bzero(vlabel
, sizeof(volume_label_t
));
424 anc
->vlabel
= vlabel
;
426 for (i
=1; i
<=USABLE_PARTITIONS
; i
++) {
427 part_info
= malloc(sizeof(partition_info_t
));
428 if (part_info
== NULL
)
429 fdasd_error(anc
, malloc_failed
,
430 "Partition info memory allocation failed.");
431 part_info
->used
= 0x00;
432 part_info
->len_trk
= 0;
433 part_info
->start_trk
= 0;
434 part_info
->fspace_trk
= 0;
436 /* add part_info to double pointered list */
438 anc
->first
= part_info
;
439 part_info
->prev
= NULL
;
441 else if (i
== USABLE_PARTITIONS
) {
442 anc
->last
= part_info
;
443 part_info
->next
= NULL
;
444 part_info
->prev
= prev_part_info
;
445 prev_part_info
->next
= part_info
;
448 part_info
->prev
= prev_part_info
;
449 prev_part_info
->next
= part_info
;
452 part_info
->f1
= malloc(sizeof(format1_label_t
));
453 if (part_info
->f1
== NULL
)
454 fdasd_error(anc
, malloc_failed
,
455 "FMT1 DSCB memory allocation failed.");
456 bzero(part_info
->f1
, sizeof(format1_label_t
));
458 prev_part_info
= part_info
;
460 anc
->hw_cylinders
= 0;
461 anc
->formatted_cylinders
= 0;
466 * parses the command line options
469 fdasd_parse_options (fdasd_anchor_t
*anc
, struct fdasd_options
*options
,
470 int argc
, char *argv
[])
475 opt
= getopt_long(argc
, argv
, option_string
,
476 fdasd_long_options
, &index
);
486 fdasd_error(anc
, parser_failed
,
487 "Option 'label' specified more "
489 options
->volser
= optarg
;
492 anc
->auto_partition
++;
508 if (options
->conffile
)
509 fdasd_error(anc
, parser_failed
,
510 "Option 'config' specified more"
512 options
->conffile
= optarg
;
518 /* End of options string - start of devices list */
521 fprintf(stderr
, "Try 'fdasd --help' for more"
529 fdasd_error(anc
, parser_failed
,
530 "No device speficied.\n");
531 if (optind
+ 1 < argc
)
532 fdasd_error(anc
, parser_failed
,
533 "More than one device speficied.\n");
534 options
->device
= argv
[optind
];
542 fdasd_parse_conffile(fdasd_anchor_t
*anc
, struct fdasd_options
*options
)
544 char buffer
[USABLE_PARTITIONS
* LINE_LENGTH
];
545 char err_str
[ERROR_STRING_SIZE
], *c1
, *c2
;
549 /* if name of config file was not specified, select the default */
550 if (options
->conffile
== NULL
)
551 options
->conffile
= DEFAULT_FDASD_CONF
;
554 printf("parsing config file '%s'...\n", options
->conffile
);
555 fd
= open(options
->conffile
, O_RDONLY
);
557 snprintf(err_str
, ERROR_STRING_SIZE
,
558 "Could not open config file '%s' "
559 "in read-only mode!\n", options
->conffile
);
560 fdasd_error(anc
, unable_to_open_disk
, err_str
);
563 bzero(buffer
, sizeof(buffer
));
564 rc
= read(fd
, buffer
, sizeof(buffer
));
570 for (i
=0; i
<sizeof(buffer
); i
++)
571 buffer
[i
] = toupper(buffer
[i
]);
575 for (i
=0; i
<USABLE_PARTITIONS
; i
++) {
576 char *token
, *stopstring
;
578 c1
= strchr(c1
, '[');
581 printf("no config file entry for " \
582 "partition %d found...\n", i
+1);
587 c2
= strchr(c1
, ']');
589 snprintf(err_str
, ERROR_STRING_SIZE
,
590 "']' missing in config file " \
591 "%s\n", options
->conffile
);
592 fdasd_error(anc
, config_syntax_error
, err_str
);
596 token
= strtok(c1
, ",");
597 if (strstr(token
, "FIRST") != NULL
)
598 anc
->confdata
[i
].start
=FIRST_USABLE_TRK
;
600 anc
->confdata
[i
].start
=strtol(token
, &stopstring
, 10);
602 token
= strtok(NULL
, ",");
603 if (strstr(token
, "LAST") != NULL
)
604 anc
->confdata
[i
].stop
= anc
->formatted_cylinders
607 anc
->confdata
[i
].stop
= strtol(token
, &stopstring
, 10);
616 * checks input from config file
619 fdasd_check_conffile_input (fdasd_anchor_t
*anc
,
620 struct fdasd_options
*options
)
622 partition_info_t
*part_info
= anc
->first
;
625 if (anc
->verbose
) printf("checking config file data...\n");
626 for (i
=0; i
<USABLE_PARTITIONS
; i
++) {
627 unsigned long start
, stop
, first_trk
, last_trk
;
628 char err_str
[ERROR_STRING_SIZE
];
630 start
= anc
->confdata
[i
].start
;
631 stop
= anc
->confdata
[i
].stop
;
633 if ((start
== 0) || (stop
== 0)) break;
635 first_trk
= FIRST_USABLE_TRK
;
636 last_trk
= anc
->formatted_cylinders
* geo
.heads
- 1;
638 if ((start
< first_trk
) || (start
> last_trk
)) {
639 snprintf(err_str
, ERROR_STRING_SIZE
,
640 "One of the lower partition limits "
641 "(%ld) is not within the range of \n "
642 "available tracks on disk (%ld-%ld)!\n",
643 start
, first_trk
, last_trk
);
644 fdasd_error(anc
, config_syntax_error
, err_str
);
647 if ((stop
< first_trk
) || (stop
> last_trk
)) {
648 snprintf(err_str
, ERROR_STRING_SIZE
,
649 "One of the upper partition limits "
650 "(%ld) is not within the range of \n "
651 "available tracks on disk (%ld-%ld)!\n",
652 stop
, first_trk
, last_trk
);
653 fdasd_error(anc
, config_syntax_error
, err_str
);
657 snprintf(err_str
, ERROR_STRING_SIZE
,
658 "Lower partition limit (%ld) is not "
659 "less than upper partition \nlimit (%ld) "
660 "in config file %s!\n",
661 start
, stop
, options
->conffile
);
662 fdasd_error(anc
, config_syntax_error
, err_str
);
665 if ((i
> 0) && (start
<= anc
->confdata
[i
-1].stop
)) {
666 snprintf(err_str
, ERROR_STRING_SIZE
,
667 "Partitions overlap or are not in "
668 "ascending order!\n");
669 fdasd_error(anc
, config_syntax_error
, err_str
);
672 if ((i
< (USABLE_PARTITIONS
- 1)) &&
673 (anc
->confdata
[i
+1].start
> 0) &&
674 (stop
>= anc
->confdata
[i
+1].start
)) {
675 snprintf(err_str
, ERROR_STRING_SIZE
,
676 "Partitions overlap or are not in "
677 "ascending order!\n");
678 fdasd_error(anc
, config_syntax_error
, err_str
);
681 part_info
->used
= 0x01;
682 part_info
->start_trk
= start
;
683 part_info
->end_trk
= stop
;
684 part_info
->len_trk
= stop
- start
+ 1;
686 /* update the current free space counter */
688 anc
->fspace_trk
= start
- FIRST_USABLE_TRK
;
690 if (i
< USABLE_PARTITIONS
- 1) {
691 if (anc
->confdata
[i
+1].start
!= 0)
692 part_info
->fspace_trk
=
693 anc
->confdata
[i
+1].start
-stop
-1;
695 part_info
->fspace_trk
= last_trk
- stop
;
697 else if (i
== USABLE_PARTITIONS
- 1)
698 part_info
->fspace_trk
= last_trk
- stop
;
700 part_info
= part_info
->next
;
707 * Verifies the specified block device.
710 fdasd_verify_device (fdasd_anchor_t
*anc
, char *name
)
713 char err_str
[ERROR_STRING_SIZE
];
715 if ((stat(name
, &dst
)) < 0 ) {
716 snprintf(err_str
, ERROR_STRING_SIZE
,
717 "Unable to get device status for device '%s'\n",
719 fdasd_error(anc
, device_verification_failed
, err_str
);
722 if (!(S_ISBLK (dst
.st_mode
))) {
723 snprintf(err_str
, ERROR_STRING_SIZE
,
724 "Device '%s' (%d/%d) is not a block device\n", name
,
725 (unsigned short) major(dst
.st_rdev
),
726 (unsigned short) minor(dst
.st_rdev
));
727 fdasd_error(anc
, device_verification_failed
, err_str
);
730 if (minor (dst
.st_rdev
) & PARTN_MASK
) {
731 snprintf(err_str
, ERROR_STRING_SIZE
,
732 "Partition '%s' (%d/%d) detected where device is "
734 (unsigned short) major(dst
.st_rdev
),
735 (unsigned short) minor(dst
.st_rdev
));
737 fdasd_error(anc
, device_verification_failed
, err_str
);
741 printf("Verification successful for '%s' (%d/%d)\n", name
,
742 (unsigned short) major(dst
.st_rdev
),
743 (unsigned short) minor(dst
.st_rdev
));
748 * Verifies the specified fdasd command line option
752 * - 'version' and 'help' are priority options.
753 * All other paramters are ignored in that case.
754 * - 'silent' and 'verbose' are allways allowed in any
759 fdasd_verify_options (fdasd_anchor_t
*anc
)
761 /* Checked option combinations */
762 /* (inv = invalid / req = required / opt = optional) */
764 /* vols labe keep auto conf tabl */
768 /* volser - inv INV inv inv inv */
769 /* label - inv REQ INV inv */
770 /* keep_volser - REQ INV inv */
775 if (anc
->print_volser
&&
776 (options
.volser
|| anc
->keep_volser
|| anc
->auto_partition
||
777 options
.conffile
|| anc
->print_table
)) {
778 fdasd_error(anc
, parser_failed
,
779 "Option 'volser' cannot be used with other"
783 if (options
.volser
) {
784 if (!anc
->auto_partition
) {
785 fdasd_error(anc
, parser_failed
,
786 "Option 'auto' required when specifying"
789 if ((anc
->keep_volser
|| options
.conffile
||
791 fdasd_error(anc
, parser_failed
,
792 "Option 'label' cannot be used with "
793 "'keep_volser', 'config' and 'table'.\n");
797 if (anc
->keep_volser
) {
798 if (!anc
->auto_partition
) {
799 fdasd_error(anc
, parser_failed
,
800 "Option 'auto' required when specifying"
803 if (options
.conffile
|| anc
->print_table
) {
804 fdasd_error(anc
, parser_failed
,
805 "Option 'keep_volser' cannot be used"
806 " with 'config' and 'table'.\n");
809 if (anc
->auto_partition
&&
810 (options
.conffile
|| anc
->print_table
)) {
811 fdasd_error(anc
, parser_failed
,
812 "Option 'auto' cannot be used with "
813 "'config' and 'table'.\n");
816 if (options
.conffile
&&
817 (anc
->print_table
)) {
818 fdasd_error(anc
, parser_failed
,
819 "Option 'config' cannot be used with"
826 * print mapping: partition number - data set name
829 fdasd_show_mapping (fdasd_anchor_t
*anc
)
831 char str
[20], *dev
, dsname
[45], *strp
;
832 partition_info_t
*part_info
;
833 int i
=0, j
=0, dev_len
;
835 printf("\ndevice .........: %s\n",options
.device
);
836 bzero(str
, sizeof(str
));
837 vtoc_volume_label_get_label(anc
->vlabel
, str
);
838 printf("volume label ...: %.4s\n", str
);
839 bzero(str
, sizeof(str
));
840 vtoc_volume_label_get_volser(anc
->vlabel
, str
);
841 printf("volume serial ..: %s\n\n", str
);
843 dev_len
= strlen(options
.device
);
844 dev
= malloc(dev_len
+ 10);
846 fdasd_error(anc
, malloc_failed
,
847 "Show mapping: memory allocation failed.");
848 strcpy(dev
, options
.device
);
849 if (((strp
= strstr(dev
,DISC
)) != NULL
) ||
850 ((strp
= strstr(dev
,DEVICE
)) != NULL
))
853 printf("WARNING: This mapping may be NOT up-to-date,\n"
854 " if you have NOT saved your last changes!\n\n");
856 for (part_info
= anc
->first
; part_info
!= NULL
;
857 part_info
= part_info
->next
) {
859 if (part_info
->used
!= 0x01)
862 bzero(dsname
, sizeof(dsname
));
863 strncpy(dsname
, part_info
->f1
->DS1DSNAM
, 44);
864 vtoc_ebcdic_dec(dsname
, dsname
, 44);
866 if (getdsn(anc
, i
-1) < 0)
867 sprintf(dsname
, "new data set");
869 printf("%s%-2d - %-44s\n", dev
, i
, dsname
);
873 if (j
== 0) printf("No partitions defined.\n");
879 * prints only the volume serial
882 fdasd_print_volser (fdasd_anchor_t
*anc
)
884 char volser
[VOLSER_LENGTH
+ 1];
886 bzero(volser
, VOLSER_LENGTH
);
887 vtoc_ebcdic_dec(anc
->vlabel
->volid
, volser
, VOLSER_LENGTH
);
888 printf("%6.6s\n", volser
);
893 * print partition table
896 fdasd_list_partition_table (fdasd_anchor_t
*anc
)
898 partition_info_t
*part_info
;
899 char str
[20], *dev
, *strp
, *ch
;
900 int i
=0, dev_len
= strlen(options
.device
);
903 printf("\nDisk %s: \n"
904 " cylinders ............: %d\n"
905 " tracks per cylinder ..: %d\n"
906 " blocks per track .....: %d\n"
907 " bytes per block ......: %d\n",
908 options
.device
, anc
->formatted_cylinders
, geo
.heads
,
909 geo
.sectors
, anc
->blksize
);
911 vtoc_volume_label_get_label(anc
->vlabel
, str
);
912 printf(" volume label .........: %s\n", str
);
914 vtoc_volume_label_get_volser(anc
->vlabel
, str
);
916 printf(" volume serial ........: %s\n", str
);
917 printf(" max partitions .......: %d\n\n", USABLE_PARTITIONS
);
924 printf(" ------------------------------- tracks"
925 " -------------------------------\n");
926 printf("%*s start end length Id System\n",
927 dev_len
+ 1, "Device");
930 dev
= malloc(dev_len
+ 10);
932 fdasd_error(anc
, malloc_failed
,
933 "Print partition table: memory allocation failed.");
934 strcpy(dev
, options
.device
);
935 if (((strp
= strstr(dev
,DISC
)) != NULL
) ||
936 ((strp
= strstr(dev
,DEVICE
)) != NULL
))
939 for (part_info
= anc
->first
; part_info
!= NULL
;
940 part_info
= part_info
->next
) {
943 if ((part_info
== anc
->first
) && (anc
->fspace_trk
> 0))
944 printf("%*s %9ld%9ld%9ld unused\n",dev_len
,"",
945 (unsigned long) FIRST_USABLE_TRK
,
946 (unsigned long) FIRST_USABLE_TRK
+
950 if (part_info
->used
!= 0x01)
953 vtoc_ebcdic_dec(part_info
->f1
->DS1DSNAM
,
954 part_info
->f1
->DS1DSNAM
, 44);
955 ch
= strstr(part_info
->f1
->DS1DSNAM
, "PART");
957 strncpy(str
, ch
+ 9, 6);
960 strcpy(str
, "error");
962 vtoc_ebcdic_enc(part_info
->f1
->DS1DSNAM
,
963 part_info
->f1
->DS1DSNAM
, 44);
965 printf("%*s%-2d %9ld%9ld%9ld %2x %6s\n",
966 dev_len
, dev
, i
, part_info
->start_trk
,
967 part_info
->end_trk
, part_info
->len_trk
, i
,
968 fdasd_partition_type(str
));
970 if (part_info
->fspace_trk
> 0)
971 printf("%*s %9ld%9ld%9ld unused\n",
972 dev_len
, "" , part_info
->end_trk
+ 1,
973 part_info
->end_trk
+ part_info
->fspace_trk
,
974 part_info
->fspace_trk
);
980 * get volser from vtoc
983 fdasd_get_volser(fdasd_anchor_t
*anc
, char *devname
, char *volser
)
985 dasd_information_t dasd_info
;
988 volume_label_t vlabel
;
989 char err_str
[ERROR_STRING_SIZE
];
991 if ((fd
= open(devname
, O_RDONLY
)) == -1) {
992 snprintf(err_str
, ERROR_STRING_SIZE
,
993 "Could not open device '%s' "
994 "in read-only mode!\n", devname
);
995 fdasd_error(anc
, unable_to_open_disk
, err_str
);
998 if (ioctl(fd
, BIODASDINFO
, &dasd_info
) != 0) {
1000 fdasd_error(anc
, unable_to_ioctl
,
1001 "Could not retrieve disk information.");
1004 if (ioctl(fd
, BLKSSZGET
, &blksize
) != 0) {
1006 fdasd_error(anc
, unable_to_ioctl
,
1007 "Could not retrieve blocksize information.");
1012 if ((strncmp(dasd_info
.type
, "ECKD", 4) == 0) &&
1013 (!dasd_info
.FBA_layout
)) {
1014 /* OS/390 and zOS compatible disk layout */
1015 vtoc_read_volume_label(options
.device
,
1016 dasd_info
.label_block
* blksize
,
1018 vtoc_volume_label_get_volser(&vlabel
, volser
);
1028 * call IOCTL to re-read the partition table
1031 fdasd_reread_partition_table (fdasd_anchor_t
*anc
)
1033 char err_str
[ERROR_STRING_SIZE
];
1036 if (!anc
->silent
) printf("rereading partition table...\n");
1038 if ((fd
= open(options
.device
, O_RDONLY
)) < 0) {
1039 snprintf(err_str
, ERROR_STRING_SIZE
,
1040 "Could not open device '%s' "
1041 "in read-only mode!\n", options
.device
);
1042 fdasd_error(anc
, unable_to_open_disk
, err_str
);
1045 if (ioctl(fd
, BLKRRPART
, NULL
) != 0) {
1047 fdasd_error(anc
, unable_to_ioctl
, "Error while rereading "
1048 "partition table.\nPlease reboot!");
1055 * writes all changes to dasd
1058 fdasd_write_vtoc_labels (fdasd_anchor_t
*anc
)
1060 partition_info_t
*part_info
;
1061 unsigned long blk
, maxblk
;
1062 char dsno
[6], volser
[VOLSER_LENGTH
+ 1], s2
[45], *c1
, *c2
, *ch
;
1065 format1_label_t emptyf1
;
1067 if (!anc
->silent
) printf("writing VTOC...\n");
1068 if (anc
->verbose
) printf("DSCBs: ");
1070 blk
= (cchhb2blk(&anc
->vlabel
->vtoc
, &geo
) - 1) * anc
->blksize
;
1072 fdasd_error(anc
, vlabel_corrupted
, "");
1073 maxblk
= blk
+ anc
->blksize
* 9; /* f4+f5+f7+3*f8+3*f9 */
1075 /* write FMT4 DSCB */
1076 vtoc_write_label(options
.device
, blk
, NULL
, anc
->f4
, NULL
, NULL
, NULL
);
1077 if (anc
->verbose
) printf("f4 ");
1078 blk
+= anc
->blksize
;
1080 /* write FMT5 DSCB */
1081 vtoc_write_label(options
.device
, blk
, NULL
, NULL
, anc
->f5
, NULL
, NULL
);
1082 if (anc
->verbose
) printf("f5 ");
1083 blk
+= anc
->blksize
;
1085 /* write FMT7 DSCB */
1086 if (anc
->big_disk
) {
1087 vtoc_write_label(options
.device
, blk
, NULL
, NULL
,
1088 NULL
, anc
->f7
, NULL
);
1089 if (anc
->verbose
) printf("f7 ");
1090 blk
+= anc
->blksize
;
1093 /* loop over all partitions (format 1 or format 8 DCB) */
1094 for (part_info
= anc
->first
; part_info
!= NULL
;
1095 part_info
= part_info
->next
) {
1097 if (part_info
->used
!= 0x01) {
1102 strncpy((char *)part_info
->f1
->DS1DSSN
, anc
->vlabel
->volid
,
1105 ch
= part_info
->f1
->DS1DSNAM
;
1106 vtoc_ebcdic_dec(ch
, ch
, 44);
1109 if (getdsn(anc
, i
-1) > -1) {
1110 /* re-use the existing data set name */
1111 c2
= strchr(c1
, '.');
1113 strncpy(s2
, c2
, 31);
1115 fdasd_error(anc
, dsname_corrupted
, "");
1117 strncpy(volser
, anc
->vlabel
->volid
, VOLSER_LENGTH
);
1118 vtoc_ebcdic_dec(volser
, volser
, VOLSER_LENGTH
);
1119 volser
[VOLSER_LENGTH
] = ' ';
1120 strncpy(c1
, volser
, VOLSER_LENGTH
+ 1);
1121 c1
= strchr(ch
, ' ');
1122 strncpy(c1
, s2
, 31);
1125 char *tmp
= strstr(ch
, "SWAP");
1127 /* create a new data set name */
1128 while (getpos(anc
, k
) > -1)
1131 setpos(anc
, k
, i
-1);
1133 strncpy(ch
, "LINUX.V "
1136 strncpy(volser
, anc
->vlabel
->volid
, VOLSER_LENGTH
);
1137 vtoc_ebcdic_dec(volser
, volser
, VOLSER_LENGTH
);
1138 strncpy(c1
, volser
, VOLSER_LENGTH
);
1140 c1
= strchr(ch
, ' ');
1141 strncpy(c1
, ".PART", 5);
1144 sprintf(dsno
,"%04d", k
+1);
1145 strncpy(c1
, dsno
, 4);
1149 strncpy(c1
, ".SWAP", 5);
1151 strncpy(c1
, ".NATIVE", 7);
1153 vtoc_ebcdic_enc(ch
, ch
, 44);
1154 if (anc
->verbose
) printf("%2x ", part_info
->f1
->DS1FMTID
);
1156 if (part_info
->f1
->DS1FMTID
== 0xf8) {
1157 /* Now as we know where which label will be written, we
1158 * can add the address of the format 9 label to the
1159 * format 8 label. The f9 record will be written to the
1160 * block after the current blk. Remember: records are of
1161 * by one, so we have to add 2 and not just one.
1163 vtoc_set_cchhb(&f9addr
, VTOC_START_CC
, VTOC_START_HH
,
1164 ((blk
/ anc
->blksize
) % geo
.sectors
)
1166 vtoc_update_format8_label(&f9addr
, part_info
->f1
);
1167 vtoc_write_label(options
.device
, blk
, part_info
->f1
,
1168 NULL
, NULL
, NULL
, NULL
);
1169 blk
+= anc
->blksize
;
1170 vtoc_write_label(options
.device
, blk
, NULL
, NULL
,
1171 NULL
, NULL
, anc
->f9
);
1172 if (anc
->verbose
) printf("f9 ");
1173 blk
+= anc
->blksize
;
1175 vtoc_write_label(options
.device
, blk
, part_info
->f1
,
1176 NULL
, NULL
, NULL
, NULL
);
1177 blk
+= anc
->blksize
;
1181 /* write empty labels to the rest of the blocks */
1182 bzero(&emptyf1
, sizeof(emptyf1
));
1183 while (blk
< maxblk
) {
1184 vtoc_write_label(options
.device
, blk
, &emptyf1
, NULL
,
1186 if (anc
->verbose
) printf("empty ");
1187 blk
+= anc
->blksize
;
1190 if (anc
->verbose
) printf("\n");
1195 * writes all changes to dasd
1198 fdasd_write_labels (fdasd_anchor_t
*anc
)
1200 if (anc
->vlabel_changed
) {
1201 if (!anc
->silent
) printf("writing volume label...\n");
1202 vtoc_write_volume_label(options
.device
, anc
->label_pos
,
1206 if (anc
->vtoc_changed
)
1207 fdasd_write_vtoc_labels(anc
);
1209 if ((anc
->vtoc_changed
)||(anc
->vlabel_changed
))
1210 fdasd_reread_partition_table(anc
);
1215 * re-creates the VTOC and deletes all partitions
1217 static void fdasd_recreate_vtoc_unconditional(fdasd_anchor_t
*anc
)
1219 partition_info_t
*part_info
= anc
->first
;
1222 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
1223 geo
.cylinders
, anc
->formatted_cylinders
,
1224 geo
.heads
, geo
.sectors
,
1225 anc
->blksize
, anc
->dev_type
);
1227 vtoc_init_format5_label(anc
->f5
);
1228 vtoc_init_format7_label(anc
->f7
);
1229 vtoc_set_freespace(anc
->f4
,anc
->f5
, anc
->f7
, '+', anc
->verbose
,
1231 anc
->formatted_cylinders
* geo
.heads
- 1,
1232 anc
->formatted_cylinders
, geo
.heads
);
1234 while (part_info
!= NULL
) {
1236 bzero(part_info
->f1
, sizeof(format1_label_t
));
1238 if (part_info
->used
== 0x01) {
1239 part_info
->used
= 0x00;
1240 part_info
->start_trk
= 0;
1241 part_info
->end_trk
= 0;
1242 part_info
->len_trk
= 0;
1243 part_info
->fspace_trk
= 0;
1246 part_info
= part_info
->next
;
1249 anc
->used_partitions
= 0;
1250 anc
->fspace_trk
= anc
->formatted_cylinders
* geo
.heads
1253 for (i
=0; i
<USABLE_PARTITIONS
; i
++)
1256 anc
->vtoc_changed
++;
1260 * asks user for confirmation before recreating the vtoc
1262 static void fdasd_recreate_vtoc(fdasd_anchor_t
*anc
)
1264 char str
[INPUT_BUF_SIZE
];
1267 snprintf(str
, INPUT_BUF_SIZE
,
1268 "WARNING: All partitions on device '%s' will be "
1269 "deleted!\nDo you want to continue?",
1272 if (yes_no(str
) != 0)
1275 printf("creating new VTOC... ");
1277 fdasd_recreate_vtoc_unconditional(anc
);
1278 if (!anc
->silent
) printf("ok\n");
1283 * re-create all VTOC labels, but use the partition information
1284 * from existing VTOC
1287 fdasd_reuse_vtoc(fdasd_anchor_t
*anc
)
1289 partition_info_t
*part_info
= anc
->first
;
1294 char str
[INPUT_BUF_SIZE
];
1297 snprintf(str
, INPUT_BUF_SIZE
,
1298 "WARNING: this will re-create your VTOC "
1299 "entries using the partition\n "
1300 "information of your existing VTOC. Continue?");
1302 if (yes_no(str
) != 0)
1306 if (!anc
->silent
) printf("re-creating VTOC... ");
1308 vtoc_init_format4_label(&f4
, USABLE_PARTITIONS
,
1309 geo
.cylinders
, anc
->formatted_cylinders
,
1310 geo
.heads
, geo
.sectors
,
1311 anc
->blksize
, anc
->dev_type
);
1313 /* reuse some FMT4 values */
1314 f4
.DS4HPCHR
= anc
->f4
->DS4HPCHR
;
1315 f4
.DS4DSREC
= anc
->f4
->DS4DSREC
;
1317 /* re-initialize both free-space labels */
1318 vtoc_init_format5_label(&f5
);
1319 vtoc_init_format7_label(&f7
);
1321 if (anc
->fspace_trk
> 0)
1322 vtoc_set_freespace(&f4
, &f5
, &f7
, '+', anc
->verbose
,
1324 FIRST_USABLE_TRK
+ anc
->fspace_trk
- 1,
1325 anc
->formatted_cylinders
, geo
.heads
);
1327 while (part_info
!= NULL
) {
1328 if (part_info
->used
!= 0x01) {
1329 part_info
= part_info
->next
;
1333 if (anc
->formatted_cylinders
> LV_COMPAT_CYL
)
1334 vtoc_init_format8_label(anc
->vlabel
->volid
,
1336 &part_info
->f1
->DS1EXT1
, &f1
);
1338 vtoc_init_format1_label(anc
->vlabel
->volid
,
1340 &part_info
->f1
->DS1EXT1
, &f1
);
1343 strncpy(f1
.DS1DSNAM
, part_info
->f1
->DS1DSNAM
, 44);
1344 strncpy((char *)f1
.DS1DSSN
, (char *)part_info
->f1
->DS1DSSN
, 6);
1345 f1
.DS1CREDT
= part_info
->f1
->DS1CREDT
;
1347 memcpy(part_info
->f1
, &f1
, sizeof(format1_label_t
));
1349 if (part_info
->fspace_trk
> 0)
1350 vtoc_set_freespace(&f4
, &f5
, &f7
, '+', anc
->verbose
,
1351 part_info
->end_trk
+ 1,
1352 part_info
->end_trk
+
1353 part_info
->fspace_trk
,
1354 anc
->formatted_cylinders
, geo
.heads
);
1356 part_info
= part_info
->next
;
1359 /* over-write old labels with new ones */
1360 memcpy(anc
->f4
, &f4
, sizeof(format4_label_t
));
1361 memcpy(anc
->f5
, &f5
, sizeof(format5_label_t
));
1362 memcpy(anc
->f7
, &f7
, sizeof(format7_label_t
));
1364 if (!anc
->silent
) printf("ok\n");
1365 anc
->vtoc_changed
++;
1372 * Changes the volume serial (menu option)
1375 fdasd_change_volser (fdasd_anchor_t
*anc
)
1377 char volser
[VOLSER_LENGTH
+ 1];
1379 vtoc_volume_label_get_volser(anc
->vlabel
, volser
);
1380 printf("Please specify new volume serial (6 characters).\n");
1381 printf("current : %-6.6s\nnew [0X%04x]: ", volser
, anc
->devno
);
1384 fdasd_check_volser(line_ptr
, anc
->devno
);
1386 printf("\nvolume identifier changed to '%-6s'\n",line_ptr
);
1387 vtoc_volume_label_set_volser(anc
->vlabel
, line_ptr
);
1389 vtoc_set_cchhb(&anc
->vlabel
->vtoc
, VTOC_START_CC
, VTOC_START_HH
, 0x01);
1390 anc
->vlabel_changed
++;
1391 anc
->vtoc_changed
++;
1396 * changes the partition type
1399 fdasd_change_part_type (fdasd_anchor_t
*anc
)
1401 unsigned int part_id
, part_type
, i
;
1403 partition_info_t
*part_info
;
1405 fdasd_list_partition_table(anc
);
1407 /* ask for partition number */
1408 printf("\nchange partition type\n");
1409 while (!isdigit(part_id
= read_char("partition id (use 0 to exit): ")))
1410 printf("Invalid partition id '%c' detected.\n", part_id
);
1416 if (part_id
> anc
->used_partitions
) {
1417 printf("'%d' is not a valid partition id!\n", part_id
);
1421 part_info
= anc
->first
;
1422 for (i
=1; i
< part_id
; i
++)
1423 part_info
= part_info
->next
;
1425 /* ask for partition type */
1426 vtoc_ebcdic_dec(part_info
->f1
->DS1DSNAM
, part_info
->f1
->DS1DSNAM
, 44);
1427 ch
= strstr(part_info
->f1
->DS1DSNAM
, "PART") + 9;
1429 strncpy(str
, ch
, 6);
1432 strcpy(str
, "error");
1434 printf("current partition type is: %s\n\n", fdasd_partition_type(str
));
1435 printf(" 1 Linux native\n" \
1436 " 2 Linux swap\n\n");
1438 while ((part_type
< 1) || (part_type
> 2)) {
1439 while (!isdigit(part_type
=
1440 read_char("new partition type: ")));
1444 switch (part_type
) {
1446 strncpy(str
, "NATIVE", 6);
1449 strncpy(str
, "SWAP ", 6);
1452 printf("'%d' is not supported!\n", part_type
);
1455 ch
= strstr(part_info
->f1
->DS1DSNAM
, "PART") + 9;
1457 strncpy(ch
, str
, 6);
1458 vtoc_ebcdic_enc(part_info
->f1
->DS1DSNAM
, part_info
->f1
->DS1DSNAM
, 44);
1459 anc
->vtoc_changed
++;
1465 * initialize the VOL1 volume label
1468 fdasd_init_volume_label (fdasd_anchor_t
*anc
)
1470 volume_label_t
*vlabel
= anc
->vlabel
;
1471 char old_volser
[VOLSER_LENGTH
+ 1];
1473 vtoc_volume_label_init(vlabel
);
1474 vtoc_volume_label_set_key(vlabel
, "VOL1");
1475 vtoc_volume_label_set_label(vlabel
, "VOL1");
1477 if (anc
->keep_volser
) {
1478 if(fdasd_get_volser(anc
, options
.device
, old_volser
) == 0)
1479 vtoc_volume_label_set_volser(vlabel
, old_volser
);
1481 fdasd_error(anc
, volser_not_found
, options
.device
);
1485 if (options
.volser
== NULL
) {
1486 printf("\nPlease specify volume serial (6 characters)"
1490 fdasd_check_volser(line_ptr
, anc
->devno
);
1491 vtoc_volume_label_set_volser(vlabel
, line_ptr
);
1493 fdasd_check_volser(options
.volser
, anc
->devno
);
1494 vtoc_volume_label_set_volser(vlabel
, options
.volser
);
1499 vtoc_set_cchhb(&vlabel
->vtoc
, VTOC_START_CC
, VTOC_START_HH
, 0x01);
1500 anc
->vlabel_changed
++;
1505 * sets some important partition data
1506 * (like used, start_trk, end_trk, len_trk)
1507 * by calculating these values with the
1508 * information provided in the labels
1511 fdasd_update_partition_info (fdasd_anchor_t
*anc
)
1513 partition_info_t
*prev_part_info
= NULL
, *part_info
= anc
->first
;
1514 unsigned long max
= anc
->formatted_cylinders
* geo
.heads
- 1;
1517 anc
->used_partitions
= geo
.sectors
- 2 - anc
->f4
->DS4DSREC
;
1519 for (i
=1; i
<=USABLE_PARTITIONS
; i
++) {
1520 if (part_info
->f1
->DS1FMTID
!= 0xf1 &&
1521 part_info
->f1
->DS1FMTID
!= 0xf8) {
1523 /* there is no partition at all */
1524 anc
->fspace_trk
= max
- FIRST_USABLE_TRK
+ 1;
1526 /* previous partition was the last one */
1527 prev_part_info
->fspace_trk
=
1528 max
- prev_part_info
->end_trk
;
1532 /* this is a valid format 1 label */
1533 part_info
->used
= 0x01;
1534 part_info
->start_trk
= cchh2trk(&part_info
->f1
->DS1EXT1
.llimit
,
1536 part_info
->end_trk
= cchh2trk(&part_info
->f1
->DS1EXT1
.ulimit
,
1539 part_info
->len_trk
= part_info
->end_trk
-
1540 part_info
->start_trk
+ 1;
1543 /* first partition, there is at least one */
1545 part_info
->start_trk
- FIRST_USABLE_TRK
;
1547 if (i
== USABLE_PARTITIONS
)
1548 /* last possible partition */
1549 part_info
->fspace_trk
=
1550 max
- part_info
->end_trk
;
1552 /* set free space values of previous partition */
1553 prev_part_info
->fspace_trk
= part_info
->start_trk
-
1554 prev_part_info
->end_trk
- 1;
1557 prev_part_info
= part_info
;
1558 part_info
= part_info
->next
;
1563 * reorganizes all FMT1s, move all empty labels to the end
1566 fdasd_reorganize_FMT1s (fdasd_anchor_t
*anc
)
1569 format1_label_t
*f1_label
;
1570 partition_info_t
*part_info
;
1572 for (i
=1; i
<=USABLE_PARTITIONS
- 1; i
++) {
1573 part_info
= anc
->first
;
1574 for (j
=1; j
<=USABLE_PARTITIONS
- i
; j
++) {
1575 if (part_info
->f1
->DS1FMTID
<
1576 part_info
->next
->f1
->DS1FMTID
) {
1577 f1_label
= part_info
->f1
;
1578 part_info
->f1
= part_info
->next
->f1
;
1579 part_info
->next
->f1
= f1_label
;
1581 part_info
= part_info
->next
;
1588 * we have a invalid FMT4 DSCB and therefore we will re-create the VTOC
1591 fdasd_process_invalid_vtoc(fdasd_anchor_t
*anc
)
1593 printf(" invalid\ncreating new VTOC...\n");
1594 if (anc
->hw_cylinders
> LV_COMPAT_CYL
) {
1595 printf("Warning: Device has more then %u cylinders!\n",
1597 if (yes_no("Are you sure it was completely"
1598 " formatted with dasdfmt?") == 1) {
1599 if (!anc
->silent
) printf("exiting...\n");
1603 anc
->formatted_cylinders
= anc
->hw_cylinders
;
1604 anc
->fspace_trk
= anc
->formatted_cylinders
* geo
.heads
1606 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
1607 geo
.cylinders
, anc
->formatted_cylinders
,
1608 geo
.heads
, geo
.sectors
,
1609 anc
->blksize
, anc
->dev_type
);
1611 vtoc_init_format5_label(anc
->f5
);
1612 vtoc_init_format7_label(anc
->f7
);
1613 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+', anc
->verbose
,
1615 anc
->formatted_cylinders
* geo
.heads
- 1,
1616 anc
->formatted_cylinders
, geo
.heads
);
1618 anc
->vtoc_changed
++;
1626 fdasd_process_valid_vtoc(fdasd_anchor_t
*anc
, unsigned long blk
)
1628 int f1_counter
= 0, f7_counter
= 0, f5_counter
= 0;
1629 int i
, part_no
, f1_size
= sizeof(format1_label_t
);
1630 partition_info_t
*part_info
= anc
->first
;
1631 format1_label_t f1_label
;
1632 char part_no_str
[5], *part_pos
;
1634 if (!anc
->silent
) printf(" ok\n");
1636 if (anc
->f4
->DS4DEVCT
.DS4DSCYL
== LV_COMPAT_CYL
&&
1637 anc
->f4
->DS4DCYL
> anc
->f4
->DS4DEVCT
.DS4DSCYL
)
1638 anc
->formatted_cylinders
= anc
->f4
->DS4DCYL
;
1640 anc
->formatted_cylinders
= anc
->f4
->DS4DEVCT
.DS4DSCYL
;
1641 anc
->fspace_trk
= anc
->formatted_cylinders
* geo
.heads
1643 blk
+= anc
->blksize
;
1645 if (anc
->formatted_cylinders
< anc
->hw_cylinders
)
1646 printf("WARNING: This device is not fully formatted! "
1647 "Only %u of %u cylinders are available.\n",
1648 anc
->formatted_cylinders
, anc
->hw_cylinders
);
1650 if (anc
->verbose
) printf("VTOC DSCBs : ");
1652 for (i
= 1; i
<= geo
.sectors
; i
++) {
1653 bzero(&f1_label
, f1_size
);
1654 vtoc_read_label(options
.device
, blk
, &f1_label
, NULL
, NULL
,
1657 switch (f1_label
.DS1FMTID
) {
1662 f1_label
.DS1FMTID
== 0xf1 ? "f1" : "f8");
1663 if (part_info
== NULL
)
1665 memcpy(part_info
->f1
, &f1_label
, f1_size
);
1668 vtoc_ebcdic_dec(part_info
->f1
->DS1DSNAM
,
1669 part_info
->f1
->DS1DSNAM
, 44);
1670 part_pos
= strstr(part_info
->f1
->DS1DSNAM
, "PART");
1671 if (part_pos
!= NULL
) {
1672 strncpy(part_no_str
, part_pos
+ 4, 4);
1673 part_no_str
[4] = '\0';
1674 part_no
= atoi(part_no_str
) - 1;
1677 vtoc_ebcdic_enc(part_info
->f1
->DS1DSNAM
,
1678 part_info
->f1
->DS1DSNAM
, 44);
1680 if ((part_no
< 0) || (part_no
>= USABLE_PARTITIONS
))
1681 printf("WARNING: partition number (%i) found "
1682 "in data set name of an existing "
1683 "partition\ndoes not match range of "
1684 "possible partition numbers (1-%d)\n\n",
1685 part_no
+ 1, USABLE_PARTITIONS
);
1687 setpos(anc
, part_no
, f1_counter
);
1689 part_info
= part_info
->next
;
1693 if (anc
->verbose
) printf("f5 ");
1694 memcpy(anc
->f5
, &f1_label
, f1_size
);
1698 if (anc
->verbose
) printf("f7 ");
1699 if (f7_counter
== 0)
1700 memcpy(anc
->f7
, &f1_label
, f1_size
);
1704 /* each format 8 lable has an associated format 9 lable,
1705 * but they are of no further use to us.
1707 if (anc
->verbose
) printf("f9 ");
1710 if (f1_label
.DS1FMTID
> 0)
1711 printf("'%d' is not supported!\n",
1714 blk
+= anc
->blksize
;
1717 if (anc
->verbose
) printf("\n");
1719 if ((f5_counter
== 0) || (anc
->big_disk
))
1720 vtoc_init_format5_label(anc
->f5
);
1722 if (f7_counter
== 0)
1723 vtoc_init_format7_label(anc
->f7
);
1725 fdasd_reorganize_FMT1s(anc
);
1726 fdasd_update_partition_info(anc
);
1731 * we have a valid VTOC pointer, let's go and read the VTOC labels
1734 fdasd_valid_vtoc_pointer(fdasd_anchor_t
*anc
, unsigned long blk
)
1736 /* VOL1 label contains valid VTOC pointer */
1738 printf("reading vtoc ..........:");
1740 vtoc_read_label(options
.device
, blk
, NULL
, anc
->f4
, NULL
, NULL
);
1742 if (anc
->f4
->DS4IDFMT
!= 0xf4) {
1743 if (anc
->print_table
) {
1744 printf("Your VTOC is corrupted!\n");
1747 fdasd_process_invalid_vtoc(anc
);
1749 fdasd_process_valid_vtoc(anc
, blk
);
1759 fdasd_invalid_vtoc_pointer(fdasd_anchor_t
*anc
)
1761 /* VOL1 label doesn't contain valid VTOC pointer */
1762 if (yes_no("There is no VTOC yet, should I create one?") == 1) {
1763 if (!anc
->silent
) printf("exiting...\n");
1767 if (anc
->hw_cylinders
> LV_COMPAT_CYL
) {
1768 printf("Warning: Device has more then %u cylinders!\n",
1770 if (yes_no("Are you sure it was completely"
1771 " formatted with dasdfmt?") == 1) {
1772 if (!anc
->silent
) printf("exiting...\n");
1776 anc
->formatted_cylinders
= anc
->hw_cylinders
;
1777 anc
->fspace_trk
= anc
->formatted_cylinders
* geo
.heads
1779 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
1780 geo
.cylinders
, anc
->formatted_cylinders
,
1781 geo
.heads
, geo
.sectors
,
1782 anc
->blksize
, anc
->dev_type
);
1784 vtoc_init_format5_label(anc
->f5
);
1785 vtoc_init_format7_label(anc
->f7
);
1787 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+', anc
->verbose
,
1789 anc
->formatted_cylinders
* geo
.heads
- 1,
1790 anc
->formatted_cylinders
, geo
.heads
);
1792 vtoc_set_cchhb(&anc
->vlabel
->vtoc
, VTOC_START_CC
, VTOC_START_HH
, 0x01);
1794 anc
->vtoc_changed
++;
1795 anc
->vlabel_changed
++;
1800 * check the dasd for a volume label
1803 fdasd_check_volume (fdasd_anchor_t
*anc
)
1805 volume_label_t
*vlabel
= anc
->vlabel
;
1807 char str
[LINE_LENGTH
];
1808 char inp_buf
[INPUT_BUF_SIZE
];
1811 printf("reading volume label ..:");
1813 vtoc_read_volume_label(options
.device
, anc
->label_pos
, vlabel
);
1815 if (strncmp(vlabel
->vollbl
, vtoc_ebcdic_enc("VOL1",str
,4),4) == 0) {
1816 /* found VOL1 volume label */
1820 blk
= (cchhb2blk(&vlabel
->vtoc
, &geo
) - 1) * anc
->blksize
;
1823 rc
= fdasd_valid_vtoc_pointer(anc
, blk
);
1825 if (anc
->print_table
&& (rc
< 0))
1829 if (anc
->print_table
) {
1830 printf("\nFound invalid VTOC pointer.\n");
1833 fdasd_invalid_vtoc_pointer(anc
);
1836 /* didn't find VOL1 volume label */
1838 if (anc
->print_table
) {
1839 printf("\nCould not find VOL1 volume label.\n");
1843 if (strncmp(vlabel
->vollbl
,
1844 vtoc_ebcdic_enc("LNX1",str
,4),4) == 0) {
1847 strcpy(inp_buf
,"Overwrite inapplicable label?");
1851 printf(" no known label\n");
1852 strcpy(inp_buf
,"Should I create a new one?");
1854 if ((!anc
->print_volser
) && (!anc
->print_table
) &&
1855 (yes_no(inp_buf
) == 1)) {
1856 printf("You need a VOL1 volume label for " \
1857 "partitioning\nexiting...\n");
1858 fdasd_exit(anc
, -1);
1861 if (anc
->hw_cylinders
> LV_COMPAT_CYL
) {
1862 printf("Warning: Device has more then %u cylinders!\n",
1864 if (yes_no("Are you sure it was completely"
1865 " formatted with dasdfmt?") == 1) {
1866 if (!anc
->silent
) printf("exiting...\n");
1870 anc
->formatted_cylinders
= anc
->hw_cylinders
;
1871 anc
->fspace_trk
= anc
->formatted_cylinders
* geo
.heads
1874 fdasd_init_volume_label(anc
);
1876 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
1877 geo
.cylinders
, anc
->formatted_cylinders
,
1878 geo
.heads
, geo
.sectors
,
1879 anc
->blksize
, anc
->dev_type
);
1881 vtoc_init_format5_label(anc
->f5
);
1882 vtoc_init_format7_label(anc
->f7
);
1884 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+',
1885 anc
->verbose
, FIRST_USABLE_TRK
,
1886 anc
->formatted_cylinders
* geo
.heads
- 1,
1887 anc
->formatted_cylinders
, geo
.heads
);
1889 anc
->vtoc_changed
++;
1903 fdasd_check_disk_access (fdasd_anchor_t
*anc
)
1905 char err_str
[ERROR_STRING_SIZE
];
1909 if ((fd
= open(options
.device
, O_RDWR
)) == -1) {
1910 snprintf(err_str
, ERROR_STRING_SIZE
,
1911 "Could not open device '%s' " \
1912 "in read-only mode!\n", options
.device
);
1913 fdasd_error(anc
, unable_to_open_disk
, err_str
);
1916 pos
= anc
->blksize
* (2 * geo
.heads
- 1);
1917 /* last block in the second track */
1918 if (lseek(fd
, pos
, SEEK_SET
) == -1) {
1920 snprintf(err_str
, ERROR_STRING_SIZE
,
1921 "Could not seek device '%s'.", options
.device
);
1922 fdasd_error(anc
, unable_to_seek_disk
, err_str
);
1925 if (read(fd
, &f1
, sizeof(format1_label_t
)) !=
1926 sizeof(format1_label_t
)) {
1928 snprintf(err_str
, ERROR_STRING_SIZE
,
1929 "Could not read from device '%s'.", options
.device
);
1930 fdasd_error(anc
, unable_to_read_disk
, err_str
);
1933 if (lseek(fd
, pos
, SEEK_SET
) == -1) {
1935 snprintf(err_str
, ERROR_STRING_SIZE
,
1936 "Could not seek device '%s'.", options
.device
);
1937 fdasd_error(anc
, unable_to_seek_disk
, err_str
);
1940 if (ioctl(fd
, BLKROGET
, &ro
) != 0) {
1941 snprintf(err_str
, ERROR_STRING_SIZE
,
1942 "Could not get read-only status for device '%s'.",
1944 fdasd_error(anc
, unable_to_ioctl
, err_str
);
1946 if (ro
&& !anc
->print_volser
&& !anc
->print_table
)
1947 printf("\nWARNING: Device '%s' is a read-only device!\n"
1948 "You will not be able to save any changes.\n\n",
1956 * reads dasd geometry data
1959 fdasd_get_geometry (fdasd_anchor_t
*anc
)
1961 int fd
, blksize
= 0;
1962 dasd_information_t dasd_info
;
1963 char err_str
[ERROR_STRING_SIZE
];
1964 u_int64_t device_size
;
1966 if ((fd
= open(options
.device
,O_RDONLY
)) < 0) {
1967 snprintf(err_str
, ERROR_STRING_SIZE
,
1968 "Could not open device '%s' "
1969 "in read-only mode!\n", options
.device
);
1970 fdasd_error(anc
, unable_to_open_disk
, err_str
);
1973 if (ioctl(fd
, HDIO_GETGEO
, &geo
) != 0) {
1975 fdasd_error(anc
, unable_to_ioctl
,
1976 "Could not retrieve disk geometry information.");
1979 if (ioctl(fd
, BLKSSZGET
, &blksize
) != 0) {
1981 fdasd_error(anc
, unable_to_ioctl
,
1982 "Could not retrieve blocksize information.");
1985 if (ioctl(fd
, BLKGETSIZE64
, &device_size
) != 0) {
1987 fdasd_error(anc
, unable_to_ioctl
,
1988 "Could not retrieve device size information.");
1991 anc
->hw_cylinders
= ((device_size
/ blksize
) / geo
.sectors
) / geo
.heads
;
1994 if (ioctl(fd
, BIODASDINFO
, &dasd_info
) != 0) {
1996 fdasd_error(anc
, unable_to_ioctl
,
1997 "Could not retrieve disk information.");
2002 if (strncmp(dasd_info
.type
, "ECKD", 4) != 0) {
2003 snprintf(err_str
, ERROR_STRING_SIZE
,
2004 "%s is not an ECKD disk! This disk type "
2005 "is not supported!", options
.device
);
2006 fdasd_error(anc
,wrong_disk_type
, err_str
);
2009 if (anc
->verbose
) printf("disk type check : ok\n");
2011 if (dasd_info
.FBA_layout
!= 0) {
2012 snprintf(err_str
, ERROR_STRING_SIZE
,
2013 "%s is not formatted with z/OS compatible "
2014 "disk layout!", options
.device
);
2015 fdasd_error(anc
, wrong_disk_format
, err_str
);
2018 if (anc
->verbose
) printf("disk layout check : ok\n");
2020 if (dasd_info
.open_count
> 1) {
2021 if (anc
->auto_partition
) {
2022 snprintf(err_str
, ERROR_STRING_SIZE
,
2023 "DASD '%s' is in use. Unmount it first!",
2025 fdasd_error(anc
, disk_in_use
, err_str
);
2027 printf("\nWARNING: Your DASD '%s' is in use.\n"
2028 " If you proceed, you can heavily "
2029 "damage your system.\n If possible exit"
2030 " all applications using this disk\n "
2031 "and/or unmount it.\n\n", options
.device
);
2035 if (anc
->verbose
) printf("usage count check : ok\n");
2037 anc
->dev_type
= dasd_info
.dev_type
;
2038 anc
->blksize
= blksize
;
2039 anc
->label_pos
= dasd_info
.label_block
* blksize
;
2040 anc
->devno
= dasd_info
.devno
;
2045 * asks for partition boundaries
2047 static unsigned long
2048 fdasd_read_int (unsigned long low
, unsigned long dflt
, unsigned long high
,
2049 enum offset base
, char *mesg
, fdasd_anchor_t
*anc
)
2051 unsigned long long trk
= 0;
2052 unsigned int use_default
= 1;
2057 sprintf(msg_txt
, "%s ([%ld]-%ld): ", mesg
, low
, high
);
2060 sprintf(msg_txt
, "%s (%ld-[%ld]): ", mesg
, low
, high
);
2063 sprintf(msg_txt
, "%s (%ld-%ld): ", mesg
, low
, high
);
2068 while (!isdigit(read_char(msg_txt
))
2069 && (*line_ptr
!= '-' &&
2073 if ((*line_ptr
== '+' || *line_ptr
== '-') &&
2075 if (*line_ptr
== '+')
2077 trk
= atoi(line_ptr
);
2078 while (isdigit(*line_ptr
)) {
2083 switch (*line_ptr
) {
2091 trk
/= anc
->blksize
;
2097 trk
/= anc
->blksize
;
2103 printf("WARNING: '%c' is not a "
2104 "valid appendix and probably "
2105 "not what you want!\n",
2113 else if (*line_ptr
== '\0') {
2115 case lower
: trk
= low
; break;
2116 case upper
: trk
= high
; break;
2120 if (*line_ptr
== '+' || *line_ptr
== '-') {
2121 printf("\nWARNING: '%c' is not valid in \n"
2122 "this case and will be ignored!\n",
2127 trk
= atoi(line_ptr
);
2128 while (isdigit(*line_ptr
)) {
2133 if (*line_ptr
!= 0x0a)
2134 printf("\nWARNING: '%c' is not a valid "
2135 "appendix and probably not what "
2136 "you want!\n", *line_ptr
);
2139 printf("Using default value %lld\n", trk
= dflt
);
2141 printf("You have selected track %lld\n", trk
);
2143 if (trk
>= low
&& trk
<= high
)
2146 printf("Value out of range.\n");
2153 * returns unused partition info pointer if there
2154 * is a free partition, otherwise NULL
2156 static partition_info_t
*
2157 fdasd_get_empty_f1_label (fdasd_anchor_t
* anc
)
2159 if (anc
->used_partitions
< USABLE_PARTITIONS
)
2167 * asks for and sets some important partition data
2170 fdasd_get_partition_data (fdasd_anchor_t
*anc
, extent_t
*part_extent
,
2171 partition_info_t
*part_info
)
2173 unsigned long start
, stop
, limit
;
2176 cchh_t llimit
,ulimit
;
2177 partition_info_t
*part_tmp
;
2181 start
= FIRST_USABLE_TRK
;
2183 cyl
= get_usable_cylinders(anc
);
2184 head
= anc
->f4
->DS4DEVCT
.DS4DSTRK
;
2185 limit
= (head
* cyl
- 1);
2187 sprintf(mesg
, "First track (1 track = %d KByte)",
2188 geo
.sectors
* anc
->blksize
/ 1024);
2190 /* find default start value */
2191 for (part_tmp
= anc
->first
; part_tmp
->next
!= NULL
;
2192 part_tmp
= part_tmp
->next
) {
2193 if ((start
>= part_tmp
->start_trk
) &&
2194 (start
<= part_tmp
->end_trk
))
2195 start
= part_tmp
->end_trk
+ 1;
2198 if (start
> limit
) {
2199 printf("Not that easy, no free tracks available.\n");
2203 /* read start value */
2204 start
= fdasd_read_int(start
, start
, limit
, lower
, mesg
, anc
);
2206 /* check start value from user */
2207 for (part_tmp
= anc
->first
; part_tmp
->next
!= NULL
;
2208 part_tmp
= part_tmp
->next
) {
2209 if (start
>= part_tmp
->start_trk
&&
2210 start
<= part_tmp
->end_trk
) {
2211 /* start is within another partition */
2212 start
= part_tmp
->end_trk
+ 1;
2213 if (start
> limit
) {
2214 start
= FIRST_USABLE_TRK
;
2215 part_tmp
= anc
->first
;
2218 printf("value within another partition, " \
2219 "using %ld instead\n", start
);
2222 if (start
< part_tmp
->start_trk
) {
2223 limit
= part_tmp
->start_trk
- 1;
2232 sprintf(mesg
, "Last track or +size[c|k|M]");
2233 stop
= fdasd_read_int(start
, limit
, limit
, upper
, mesg
, anc
);
2236 /* update partition info */
2237 part_info
->len_trk
= stop
- start
+ 1;
2238 part_info
->start_trk
= start
;
2239 part_info
->end_trk
= stop
;
2241 cc
= start
/ geo
.heads
;
2242 hh
= start
- (cc
* geo
.heads
);
2243 vtoc_set_cchh(&llimit
, cc
, hh
);
2245 /* check for cylinder boundary */
2251 cc
= stop
/ geo
.heads
;
2252 hh
= stop
- cc
* geo
.heads
;
2253 vtoc_set_cchh(&ulimit
, cc
, hh
);
2255 /* it is always the 1st extent */
2258 vtoc_set_extent(part_extent
, b1
, b2
, &llimit
, &ulimit
);
2268 fdasd_enqueue_new_partition (fdasd_anchor_t
*anc
)
2270 partition_info_t
*part_tmp
= anc
->first
, *part_info
= anc
->last
;
2273 for (i
= 1; i
< USABLE_PARTITIONS
; i
++) {
2274 if ((part_tmp
->end_trk
== 0) ||
2275 (part_info
->start_trk
< part_tmp
->start_trk
))
2278 part_tmp
= part_tmp
->next
;
2283 if (anc
->first
== part_tmp
) anc
->first
= part_info
;
2285 if (part_info
!= part_tmp
) {
2286 anc
->last
->prev
->next
= NULL
;
2287 anc
->last
= anc
->last
->prev
;
2289 part_info
->next
= part_tmp
;
2290 part_info
->prev
= part_tmp
->prev
;
2291 part_tmp
->prev
= part_info
;
2293 if (part_info
->prev
!= NULL
)
2294 part_info
->prev
->next
= part_info
;
2297 part_info
->used
= 0x01;
2299 for (i
=0; i
<USABLE_PARTITIONS
; i
++) {
2300 int j
= getpos(anc
, i
);
2301 if (j
>= k
) setpos(anc
, i
, j
+ 1);
2304 /* update free-space counters */
2305 if (anc
->first
== part_info
) {
2306 /* partition is the first used partition */
2307 if (part_info
->start_trk
== FIRST_USABLE_TRK
) {
2308 /* partition starts right behind VTOC */
2309 part_info
->fspace_trk
= anc
->fspace_trk
-
2311 anc
->fspace_trk
= 0;
2314 /* there is some space between VTOC and partition */
2316 part_info
->fspace_trk
= anc
->fspace_trk
-
2317 part_info
->len_trk
- part_info
->start_trk
+
2319 anc
->fspace_trk
= part_info
->start_trk
-
2324 /* there are partitons in front of the new one */
2325 if (part_info
->start_trk
== part_info
->prev
->end_trk
+ 1) {
2326 /* new partition is right behind the previous one */
2327 part_info
->fspace_trk
= part_info
->prev
->fspace_trk
-
2329 part_info
->prev
->fspace_trk
= 0;
2332 /* there is some space between new and prev. part. */
2333 part_info
->fspace_trk
= part_info
->prev
->fspace_trk
-
2334 part_info
->len_trk
- part_info
->start_trk
+
2335 part_info
->prev
->end_trk
+ 1;
2336 part_info
->prev
->fspace_trk
= part_info
->start_trk
-
2337 part_info
->prev
->end_trk
- 1;
2347 fdasd_dequeue_old_partition (fdasd_anchor_t
*anc
, partition_info_t
*part_info
,
2352 if (part_info
!= anc
->first
&& part_info
!= anc
->last
) {
2353 /* dequeue any non-special element */
2354 part_info
->prev
->next
= part_info
->next
;
2355 part_info
->next
->prev
= part_info
->prev
;
2358 if (part_info
== anc
->first
) {
2359 /* dequeue first element */
2360 anc
->first
= part_info
->next
;
2361 part_info
->next
->prev
= NULL
;
2362 anc
->fspace_trk
+= (part_info
->len_trk
+
2363 part_info
->fspace_trk
);
2365 part_info
->prev
->fspace_trk
+= (part_info
->len_trk
+
2366 part_info
->fspace_trk
);
2368 if (part_info
!= anc
->last
) {
2369 part_info
->prev
= anc
->last
;
2370 part_info
->next
= NULL
;
2371 anc
->last
->next
= part_info
;
2372 anc
->last
= part_info
;
2375 for (i
=0; i
<USABLE_PARTITIONS
; i
++) {
2376 int j
= getpos(anc
, i
);
2377 if (j
>= k
) setpos(anc
, i
, j
- 1);
2380 part_info
->used
= 0x00;
2381 part_info
->len_trk
= 0x0;
2382 part_info
->start_trk
= 0x0;
2383 part_info
->end_trk
= 0x0;
2384 part_info
->fspace_trk
= 0x0;
2385 bzero(part_info
->f1
, sizeof(format1_label_t
));
2390 * adds a new partition to the 'partition table'
2393 fdasd_add_partition (fdasd_anchor_t
*anc
)
2396 partition_info_t
*part_info
;
2398 unsigned long start
, stop
;
2400 if ((part_info
= fdasd_get_empty_f1_label(anc
)) == NULL
) {
2401 printf("No more free partitions left,\n"
2402 "you have to delete one first!");
2406 if (fdasd_get_partition_data(anc
, &ext
, part_info
) != 0)
2409 if (anc
->formatted_cylinders
> LV_COMPAT_CYL
) {
2410 vtoc_init_format8_label(anc
->vlabel
->volid
, anc
->blksize
, &ext
,
2413 vtoc_init_format1_label(anc
->vlabel
->volid
, anc
->blksize
, &ext
,
2416 fdasd_enqueue_new_partition(anc
);
2417 anc
->used_partitions
+= 1;
2419 get_addr_of_highest_f1_f8_label(anc
, &hf1
);
2420 vtoc_update_format4_label(anc
->f4
, &hf1
, anc
->f4
->DS4DSREC
- 1);
2422 start
= cchh2trk(&ext
.llimit
, &geo
);
2423 stop
= cchh2trk(&ext
.ulimit
, &geo
);
2425 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '-', anc
->verbose
,
2426 start
, stop
, anc
->formatted_cylinders
, geo
.heads
);
2428 anc
->vtoc_changed
++;
2433 * removes a partition from the 'partition table'
2436 fdasd_remove_partition (fdasd_anchor_t
*anc
)
2439 unsigned int part_id
, i
;
2440 unsigned long start
, stop
;
2441 partition_info_t
*part_info
= anc
->first
;
2443 fdasd_list_partition_table(anc
);
2445 while (!isdigit(part_id
= read_char("\ndelete partition with id "
2446 "(use 0 to exit): ")))
2447 printf("Invalid partition id '%c' detected.\n", part_id
);
2451 if (part_id
== 0) return;
2452 if (part_id
> anc
->used_partitions
) {
2453 printf("'%d' is not a valid partition id!\n", part_id
);
2457 printf("deleting partition number '%d'...\n", part_id
);
2459 setpos(anc
, part_id
-1, -1);
2460 for (i
=1; i
<part_id
; i
++) part_info
=part_info
->next
;
2462 start
= cchh2trk(&part_info
->f1
->DS1EXT1
.llimit
, &geo
);
2463 stop
= cchh2trk(&part_info
->f1
->DS1EXT1
.ulimit
, &geo
);
2465 fdasd_dequeue_old_partition (anc
, part_info
, part_id
-1);
2466 anc
->used_partitions
-= 1;
2468 if (anc
->used_partitions
!= 0)
2469 get_addr_of_highest_f1_f8_label(anc
, &hf1
);
2471 bzero(&hf1
, sizeof(struct cchhb
));
2473 vtoc_update_format4_label(anc
->f4
, &hf1
, anc
->f4
->DS4DSREC
+ 1);
2474 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+', anc
->verbose
,
2475 start
, stop
, anc
->formatted_cylinders
, geo
.heads
);
2477 anc
->vtoc_changed
++;
2482 * writes a standard volume label and a standard VTOC with
2483 * only one partition to disc. With this function is it
2484 * possible to create one partiton in non-interactive mode,
2485 * which can be used within shell scripts
2488 fdasd_auto_partition(fdasd_anchor_t
*anc
)
2490 volume_label_t
*vlabel
= anc
->vlabel
;
2491 partition_info_t
*part_info
= anc
->first
;
2492 cchh_t llimit
,ulimit
;
2495 char volser
[VOLSER_LENGTH
+ 1];
2498 char old_volser
[VOLSER_LENGTH
+ 1];
2501 printf("auto-creating one partition for the whole disk...\n");
2503 vtoc_volume_label_init(vlabel
);
2504 vtoc_volume_label_set_key(vlabel
, "VOL1");
2505 vtoc_volume_label_set_label(vlabel
, "VOL1");
2507 if (anc
->keep_volser
) {
2508 if(fdasd_get_volser(anc
, options
.device
, old_volser
) == 0)
2509 vtoc_volume_label_set_volser(vlabel
, old_volser
);
2511 fdasd_error(anc
, volser_not_found
, options
.device
);
2515 if (options
.volser
== NULL
)
2516 sprintf(volser
, "0X%04x", anc
->devno
);
2518 bzero(volser
, VOLSER_LENGTH
+ 1);
2519 strncpy(volser
, options
.volser
, VOLSER_LENGTH
);
2520 fdasd_check_volser(volser
, anc
->devno
);
2522 vtoc_volume_label_set_volser(vlabel
, volser
);
2526 vtoc_set_cchhb(&vlabel
->vtoc
, VTOC_START_CC
, VTOC_START_HH
, 0x01);
2528 if (anc
->verbose
) printf("initializing labels...\n");
2529 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
2530 geo
.cylinders
, anc
->formatted_cylinders
,
2531 geo
.heads
, geo
.sectors
,
2532 anc
->blksize
, anc
->dev_type
);
2534 vtoc_init_format5_label(anc
->f5
);
2535 vtoc_init_format7_label(anc
->f7
);
2537 cyl
= get_usable_cylinders(anc
);
2538 head
= anc
->f4
->DS4DEVCT
.DS4DSTRK
;
2540 part_info
->used
= 0x01;
2541 part_info
->fspace_trk
= 0;
2542 part_info
->len_trk
= head
* cyl
- FIRST_USABLE_TRK
;
2543 part_info
->start_trk
= FIRST_USABLE_TRK
;
2544 part_info
->end_trk
= head
* cyl
- 1;
2546 vtoc_set_cchh(&llimit
, 0, FIRST_USABLE_TRK
);
2547 vtoc_set_cchh(&ulimit
, cyl
- 1, head
- 1);
2549 vtoc_set_extent(&ext
, 0x01, 0x00, &llimit
, &ulimit
);
2551 if (anc
->formatted_cylinders
> LV_COMPAT_CYL
) {
2552 vtoc_init_format8_label(anc
->vlabel
->volid
, anc
->blksize
, &ext
,
2555 vtoc_init_format1_label(anc
->vlabel
->volid
, anc
->blksize
, &ext
,
2557 anc
->fspace_trk
= 0;
2558 anc
->used_partitions
= 1;
2560 get_addr_of_highest_f1_f8_label(anc
, &hf1
);
2561 vtoc_update_format4_label(anc
->f4
, &hf1
, anc
->f4
->DS4DSREC
- 1);
2563 anc
->vlabel_changed
++;
2564 anc
->vtoc_changed
++;
2566 fdasd_write_labels(anc
);
2572 * does the partitioning regarding to the config file
2575 fdasd_auto_partition_conffile(fdasd_anchor_t
*anc
)
2577 volume_label_t
*vlabel
= anc
->vlabel
;
2578 partition_info_t
*part_info
= anc
->first
;
2579 char volser
[VOLSER_LENGTH
+ 1];
2580 cchh_t llimit
,ulimit
;
2581 unsigned long start
, stop
;
2584 char old_volser
[VOLSER_LENGTH
+ 1];
2586 vtoc_volume_label_init(vlabel
);
2587 vtoc_volume_label_set_key(vlabel
, "VOL1");
2588 vtoc_volume_label_set_label(vlabel
, "VOL1");
2590 if (anc
->keep_volser
) {
2591 if(fdasd_get_volser(anc
, options
.device
, old_volser
) == 0)
2592 vtoc_volume_label_set_volser(vlabel
, old_volser
);
2594 fdasd_error(anc
, volser_not_found
, options
.device
);
2598 if (options
.volser
== NULL
)
2599 sprintf(volser
, "0X%04x", anc
->devno
);
2601 bzero(volser
, VOLSER_LENGTH
+ 1);
2602 strncpy(volser
, options
.volser
, VOLSER_LENGTH
);
2603 fdasd_check_volser(volser
, anc
->devno
);
2605 vtoc_volume_label_set_volser(vlabel
, volser
);
2608 vtoc_set_cchhb(&vlabel
->vtoc
, VTOC_START_CC
, VTOC_START_HH
, 0x01);
2610 if (anc
->verbose
) printf("initializing labels...\n");
2611 vtoc_init_format4_label(anc
->f4
, USABLE_PARTITIONS
,
2612 geo
.cylinders
, anc
->formatted_cylinders
,
2613 geo
.heads
, geo
.sectors
,
2614 anc
->blksize
, anc
->dev_type
);
2616 vtoc_init_format5_label(anc
->f5
);
2617 vtoc_init_format7_label(anc
->f7
);
2619 if (anc
->fspace_trk
!= 0) {
2620 start
= FIRST_USABLE_TRK
;
2621 stop
= start
+ anc
->fspace_trk
- 1;
2623 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+',
2624 anc
->verbose
, start
, stop
,
2625 anc
->formatted_cylinders
, geo
.heads
);
2629 if (part_info
->used
!= 0x01)
2632 vtoc_set_cchh(&llimit
,
2633 part_info
->start_trk
/ geo
.heads
,
2634 part_info
->start_trk
% geo
.heads
);
2635 vtoc_set_cchh(&ulimit
,
2636 part_info
->end_trk
/ geo
.heads
,
2637 part_info
->end_trk
% geo
.heads
);
2639 vtoc_set_extent(&ext
, (vtoc_get_head_from_cchh(&llimit
) == 0
2641 0x00, &llimit
, &ulimit
);
2643 if (anc
->formatted_cylinders
> LV_COMPAT_CYL
) {
2644 vtoc_init_format8_label(vlabel
->volid
, anc
->blksize
,
2645 &ext
, part_info
->f1
);
2647 vtoc_init_format1_label(vlabel
->volid
, anc
->blksize
,
2648 &ext
, part_info
->f1
);
2649 anc
->used_partitions
+= 1;
2651 get_addr_of_highest_f1_f8_label(anc
, &hf1
);
2652 vtoc_update_format4_label(anc
->f4
, &hf1
,anc
->f4
->DS4DSREC
- 1);
2654 /* update free space labels */
2655 if (part_info
->fspace_trk
!= 0) {
2656 start
= part_info
->end_trk
+ 1;
2657 stop
= start
+ part_info
->fspace_trk
-1;
2659 vtoc_set_freespace(anc
->f4
, anc
->f5
, anc
->f7
, '+',
2660 anc
->verbose
, start
, stop
,
2661 anc
->formatted_cylinders
, geo
.heads
);
2663 } while ((part_info
= part_info
->next
) != NULL
);
2665 anc
->vlabel_changed
++;
2666 anc
->vtoc_changed
++;
2668 fdasd_write_labels(anc
);
2673 * quits fdasd without saving
2676 fdasd_quit(fdasd_anchor_t
*anc
)
2678 char str
[INPUT_BUF_SIZE
];
2680 if ((anc
->vtoc_changed
)||(anc
->vlabel_changed
)) {
2681 snprintf(str
, INPUT_BUF_SIZE
,
2682 "All changes will be lost! "
2683 "Do you really want to quit?");
2685 if (yes_no(str
) == 1)
2688 printf("exiting without saving...\n");
2691 if (!anc
->silent
) printf("exiting...\n");
2700 main(int argc
, char *argv
[])
2702 fdasd_anchor_t anchor
;
2705 fdasd_initialize_anchor(&anchor
);
2707 fdasd_parse_options (&anchor
, &options
, argc
, argv
);
2708 fdasd_verify_device (&anchor
, options
.device
);
2709 fdasd_verify_options (&anchor
);
2710 fdasd_get_geometry(&anchor
);
2711 fdasd_check_disk_access(&anchor
);
2713 /* check dasd for labels and vtoc */
2714 rc
= fdasd_check_volume(&anchor
);
2716 if ((anchor
.formatted_cylinders
* geo
.heads
) > BIG_DISK_SIZE
)
2719 if (anchor
.auto_partition
) {
2720 fdasd_recreate_vtoc_unconditional(&anchor
);
2721 fdasd_auto_partition(&anchor
);
2724 if (options
.conffile
) {
2725 fdasd_recreate_vtoc_unconditional(&anchor
);
2726 fdasd_parse_conffile(&anchor
, &options
);
2727 fdasd_check_conffile_input(&anchor
, &options
);
2728 fdasd_auto_partition_conffile(&anchor
);
2731 if (anchor
.print_table
) {
2733 fdasd_list_partition_table(&anchor
);
2734 fdasd_quit(&anchor
);
2737 if (anchor
.print_volser
) {
2738 fdasd_print_volser(&anchor
);
2739 fdasd_quit(&anchor
);
2746 switch (tolower(read_char("Command (m for help): "))) {
2748 fdasd_remove_partition(&anchor
);
2751 fdasd_add_partition(&anchor
);
2754 fdasd_change_volser(&anchor
);
2757 fdasd_change_part_type(&anchor
);
2760 fdasd_list_partition_table(&anchor
);
2763 fdasd_show_mapping(&anchor
);
2766 anchor
.option_reuse
++;
2769 anchor
.option_recreate
++;
2775 fdasd_quit(&anchor
);
2778 fdasd_write_labels(&anchor
);
2779 fdasd_exit(&anchor
, 0);
2781 printf("please use one of the following commands:\n");
2785 if (anchor
.option_reuse
) {
2786 fdasd_reuse_vtoc(&anchor
);
2787 anchor
.option_reuse
= 0;
2790 if (anchor
.option_recreate
) {
2791 fdasd_recreate_vtoc(&anchor
);
2792 anchor
.option_recreate
= 0;