]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/FDISK/FDISK.C

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / FDISK / FDISK.C
1
2 /* \f */
3
4
5
6 /******************* START OF SPECIFICATIONS *******************/
7 /* */
8 /* SOURCE FILE NAME: FDISK */
9 /* */
10 /* DESCRIPTIVE NAME: FIXED DISK PARTITIONING UTILITY */
11 /* */
12 /* FUNCTION: */
13 /* Allows creation and deletion of DOS related partitions */
14 /* on fixed disk devices 80-81h (int 13h BIOS defined, */
15 /* DOS). Also allows display of all partitions, and will */
16 /* allow a partition to be marked active (bootable). The */
17 /* user will be prompted for action thru a full screen */
18 /* interface. The user can also create, delete and display */
19 /* logical DOS drives within a EXTENDED DOS Partition. If a*/
20 /* regular DOS partition is created, the beginning of the */
21 /* partition will be scanned to insure a contiguous area of*/
22 /* good sectors on the disk large enough to satisfy the */
23 /* DOS system requirements. If a bad spot is found, the */
24 /* start of the partition will be moved out until a good */
25 /* area is located */
26 /* */
27 /* NOTES: The program will work by setting up a logical image */
28 /* of all relevant disk information at initilization */
29 /* time. All operations will be performed on this */
30 /* logical image, thus reducing disk accesses to only */
31 /* those required to initially set up the logical image,*/
32 /* and to write the changed information at the end. The */
33 /* user will be informed if there is a problem writing */
34 /* the logical image back to the disk. */
35 /* */
36 /* FDISK will interface with the partition table in the */
37 /* master boot record as defined in the PC-DOS technical*/
38 /* reference manual. It will also create and manage the */
39 /* EXTENDED DOS partition architecture as defined in the*/
40 /* PC-DOS 3.30 functional spec (CP/DOS spec dcr pending)*/
41 /* */
42 /* ENTRY POINTS: MAIN */
43 /* LINKAGE: [d:] [path] FDISK */
44 /* */
45 /* EXTERNAL REFERENCES: */
46 /* Fixed Disk Master Boot Record */
47 /* EXTENDED Partition Volume Boot Records */
48 /* Note: Both of the above are physical data structures on */
49 /* the surface of the disk */
50 /* */
51 /* P.S. - To whoever winds up maintaining this, I will */
52 /* apoligize in advance. I had just learned 'C' when */
53 /* writing this, so out of ignorance of the finer points*/
54 /* of the langauge I did a lot of things by brute force.*/
55 /* Hope this doesn't mess you up too much - MT 5/20/86 */
56 /******************** END OF SPECIFICATIONS ********************/
57
58 #include <dos.h>
59 #include <fdisk.h>
60 #include <subtype.h>
61 #include <extern.h>
62 #include <doscall.h>
63 #include <ctype.h>
64 #include <string.h> /* AN000 */
65 #include <fdiskmsg.h> /* AN000 */
66 #include <msgret.h> /* AN000 */
67 #include <process.h> /* AN000 */
68 #include <stdio.h> /* AN000 */
69
70 /* \f */
71 /**************************************************************************/
72 /* */
73 /* UTILITY NAME: FDISK.com */
74 /* SOURCE FILE NAME: FDISK.c */
75 /* STATUS: FDISK utility, DOS 3.3 */
76 /* CHANGE HISTORY: UPDATED 5-29-87 DOS4.0 DRM */
77 /* SYNTAX (Command line) */
78 /* */
79 /* [d:][path]FDISK */
80 /* */
81 /* or */
82 /* */
83 /* [d:][path]FDISK d [/PRI:m | /EXT:n | /LOG:o ...] */
84 /* */
85 /* d: Drive to load FDISK utility from */
86 /* */
87 /* path path to the directory on specified drive to */
88 /* load FDISK from */
89 /* */
90 /* d Drive (1 or 2) that FDISK should operate on */
91 /* */
92 /* /PRI:m Size of Primary DOS partition to create in K */
93 /* */
94 /* /EXT:n Size of Extended DOS partition to create in K */
95 /* */
96 /* /LOG:o Size of Logical drive to create in K in the */
97 /* extended partition */
98 /* */
99 /* UTILITY FUNCTION: */
100 /* Allows you to create, set up, display, and delete the */
101 /* DOS partitions on a fixed disk. */
102 /* */
103 /**************************************************************************/
104
105 /* \f */
106 /******************* START OF SPECIFICATIONS *******************/
107 /* */
108 /* SUBROUTINE NAME: CHANGE_ACTIVE_PARTITION */
109 /* */
110 /* DESCRIPTIVE NAME: Change bootable partition */
111 /* */
112 /* FUNCTION: Will allow user to select the partition that will */
113 /* recieve control when system is IPL'd. This is */
114 /* only for the first hardfile as far as booting is */
115 /* concerned, although partitions can be set active */
116 /* the second. There are reserved partitions that may*/
117 /* not be set active and this routine will enforce */
118 /* that. */
119 /* */
120 /* NOTES: If no valid partition is specified, then the active */
121 /* partition setting is left unchanged. Screen can be */
122 /* exited via the ESC command before active partition */
123 /* is changed and no action will take place */
124 /* */
125 /* The following screen is managed */
126 /* */
127 /* ³0000000000111111111122222222223333333333³ */
128 /* ³0123456789012345678901234567890123456789³ */
129 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
130 /* 00³ ³ */
131 /* 01³ ³ */
132 /* 02³ ³ */
133 /* 03³ ³ */
134 /* 04³Change Active Partition ³ */
135 /* 05³ ³ */
136 /* 06³Current Fixed Disk Drive: # ³ */
137 /* 07³ ³ */
138 /* 08³Partition Status Type Start End Size³ */
139 /* 09³ # # ####### #### #### ####³ */
140 /* 10³ ³ */
141 /* 11³ ³ */
142 /* 12³ ³ */
143 /* 13³ ³ */
144 /* 14³Total disk space is #### cylinders. ³ */
145 /* 15³ ³ */
146 /* 16³ ³ */
147 /* 17³ ³ */
148 /* 18³Enter the number of the partition you ³ */
149 /* 19³want to make active...............: [#] ³ */
150 /* 20³ ³ */
151 /* 21³ ³ */
152 /* 22³ ³ */
153 /* 23³Press ESC to return to FDISK Options ³ */
154 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
155 /* */
156 /* ENTRY POINTS: Change_Active_Partition */
157 /* LINKAGE: change_active_partition () */
158 /* NEAR CALL */
159 /* */
160 /* INPUT: None */
161 /* */
162 /* EXIT-NORMAL: ERROR=FALSE */
163 /* */
164 /* EXIT-ERROR: ERROR=TRUE */
165 /* GOTO internal_program_error if invalid num */
166 /* input is returned to this level */
167 /* */
168 /* EFFECTS: Display prompts needed to guide user input, and */
169 /* gets input from user. */
170 /* */
171 /* */
172 /* INTERNAL REFERENCES: */
173 /* ROUTINES: */
174 /* clear_screen */
175 /* display */
176 /* get_num_input */
177 /* table_display */
178 /* wait_for_ESC */
179 /* internal_program_error */
180 /* */
181 /* EXTERNAL REFERENCES: */
182 /* ROUTINES: */
183 /* */
184 /******************** END OF SPECIFICATIONS ********************/
185
186 /* \f */
187 void change_active_partition()
188
189 BEGIN
190
191 char temp;
192 char default_value;
193 char input;
194 unsigned i;
195 unsigned x;
196 char num_partitions;
197 char valid_partitions;
198 char num_of_bootable_partitions;
199 char valid_input;
200 char input_default;
201
202
203
204 input = c(NUL);
205 /* Clear screen */
206 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
207
208 /* Display header */
209 display(menu_23);
210
211 /* Setup and print current disk */
212 insert[0] = cur_disk+1+'0';
213 display(menu_5);
214
215 /* print ESC prompt */
216 display(menu_11);
217
218 /* Only allow active partitions on the first (and bootable) disk */
219 if (cur_disk == c(0)) /* AC000 */
220
221 BEGIN
222 /* Display partition info and see if any partitions exist*/
223 if (table_display())
224
225 BEGIN
226 /* See if active partition is bootable */
227 for (i=u(0); i < u(4); i++) /* AC000 */
228 BEGIN
229 if (part_table[0][i].sys_id != uc(0) &&
230 part_table[0][i].boot_ind == uc(0x80)) /* AC000 */
231 BEGIN
232 if ((part_table[0][i].sys_id == uc(BAD_BLOCK)) ||
233 (part_table[0][i].sys_id==uc(EXTENDED))) /* AC000 */
234 BEGIN
235 /* The active partition is not bootable, so warn user */
236 display(error_24);
237 END
238 END
239 END
240
241 /* Check to see if only one partition */
242 num_partitions = c(0) ; /* AC000 */
243 num_of_bootable_partitions = c(0); /* AC000 */
244 for (i=u(0); i < u(4); i++) /* AC000 */
245
246 BEGIN
247 if (part_table[0][i].sys_id != uc(0)) /* AC000 */
248 BEGIN
249 /* Get a count of partitions */
250 num_partitions++;
251
252 /* Get a count of the number of defined partitions but don't*/
253 /* count those we know aren't bootable */
254 if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) &&
255 (part_table[0][i].sys_id != uc(EXTENDED))) /* AC000 */
256 BEGIN
257 num_of_bootable_partitions++;
258 END
259 END
260 END
261 /* If only one partition found, see if it is active already */
262 if (num_of_bootable_partitions == c(1)) /* AC000 */
263 BEGIN
264
265 /* Find the partition and see if it is already active */
266 for (i=u(0); i < u(4); i++) /* AC000 */
267
268 BEGIN
269 if (part_table[0][i].sys_id !=uc(0) &&
270 part_table[0][i].boot_ind == uc(0x80)) /* AC000 */
271
272 BEGIN
273 /* Make sure it is not unbootable partition again*/
274 if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) &&
275 (part_table[0][i].sys_id!=uc(EXTENDED))) /* AC000 */
276
277 BEGIN
278 /* Once it is found, put out the message */
279 display(error_15);
280
281 /* Wait for ESC, then get out */
282 wait_for_ESC();
283
284 /* clear the screen before going back to main menu*/
285 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
286 return;
287 END
288 END
289 END
290 END
291 /* See if any bootable partitions exist */
292 if (num_of_bootable_partitions == c(0)) /* AC000 */
293 BEGIN
294 /* At this point, we know at least one partition does exist due to*/
295 /* getting past the table_display call, so the only ones around */
296 /* must be unbootable */
297
298 /* Display this fact then get out of here */
299 display(error_25);
300 END
301 else
302 BEGIN
303 /* All is okay to go and set one, do display prompts */
304 number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */
305 display(menu_15);
306
307 /* Put up input prompt*/
308 display(menu_24);
309
310 /* Assume bad input until proven otherwise */
311 valid_input = FALSE;
312 valid_partitions = num_partitions;
313 input_default = c(NUL); /* AC000 */
314
315 while (!valid_input)
316 BEGIN
317 /* Go get partition to make active */
318 input = get_num_input(input_default,num_partitions,input_row,input_col);
319
320 /* Save the input for next time in case CR pressed */
321 input_default = input-'0';
322
323 clear_screen(u(18),u(0),u(23),u(79)); /* AC000 */
324
325 if (input != c(ESC)) /* AC000 */
326 BEGIN
327 /* See if known unbootable partition */
328 /* Set the new one */
329 valid_partitions = c(0); /* AC000 */
330
331 /* Make sure the partitions are in physical order*/
332 sort_part_table(c(4)); /* AC000 */
333
334 /* Go find existing partitiona */
335 for (i=u(0);i < u(4); i++) /* AC000 */
336 BEGIN
337 /* First we have to find it */
338 if (part_table[0][sort[i]].sys_id != uc(0)) /* AC000 */
339 BEGIN
340 /* If this is the 'input'th one, then we got it */
341 if (valid_partitions == (input-'1'))
342 BEGIN
343 /* See if it is an unbootable partition */
344 if ((part_table[0][sort[i]].sys_id != uc(BAD_BLOCK)) &&
345 (part_table[0][sort[i]].sys_id != uc(EXTENDED))) /* AC000 */
346
347 BEGIN
348 /* Its bootable, so we have good input */
349 valid_input = c(TRUE); /* AC000 */
350
351 /* Remove the active indicator from the old partition */
352 for (x=u(0); x < u(4); x++) /* AC000 */
353 BEGIN
354
355 if (part_table[0][x].boot_ind == uc(0x80)) /* AC000 */
356 BEGIN
357 part_table[0][x].changed = TRUE;
358 part_table[0][x].boot_ind = uc(0); /* AC000 */
359 END
360 END
361
362 /* Put in new active indicator */
363 part_table[0][sort[i]].boot_ind = uc(0x80); /* AC000 */
364
365 /* Indicate that it is changed */
366 part_table[0][sort[i]].changed = TRUE;
367
368 /* Update the partition info display */
369 table_display();
370
371 /* Clear off the old prompts */
372 clear_screen(u(16),u(0),u(21),u(79)); /* AC000 */
373
374 /* Say you did it */
375 insert[0] = input;
376 display(status_4);
377 break;
378 END
379 else
380 BEGIN
381 /* It is, so setup message and tell user */
382 insert[0] = input;
383 display(error_17);
384 break;
385 END
386 END
387 else
388 BEGIN
389 /* Indicate we found one but keep going */
390 valid_partitions++;
391 END
392 END
393 END
394 END
395 else
396 BEGIN
397 /* Mark ESC as ok input so we can get out of here */
398 valid_input = c(TRUE); /* AC000 */
399 END
400 END /* While loop */
401 END
402 END /* table display test endif */
403 else
404 BEGIN
405 /* No partitions to make active */
406 display(error_16);
407 END
408 END
409 else
410 BEGIN
411 display(error_26);
412 END
413 /* clear the screen before going back to main menu */
414 if (input != c(ESC)) /* AC000 */
415 BEGIN
416 wait_for_ESC();
417 END
418 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
419 return;
420 END
421
422
423 /* \f */
424 /******************* START OF SPECIFICATIONS *******************/
425 /* */
426 /* SUBROUTINE NAME: DISPLAY_PARTITION_INFORMATION */
427 /* */
428 /* DESCRIPTIVE NAME: Display partition information */
429 /* */
430 /* FUNCTION: Displays defined partition information and prompt */
431 /* user to display disk volumes if they exist */
432 /* */
433 /* NOTES: */
434 /* */
435 /* The following screen is managed */
436 /* */
437 /* ³0000000000111111111122222222223333333333³ */
438 /* ³0123456789012345678901234567890123456789³ */
439 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
440 /* 00³ ³ */
441 /* 01³ ³ */
442 /* 02³ ³ */
443 /* 03³ ³ */
444 /* 04³Display Partition Information ³ */
445 /* 05³ ³ */
446 /* 06³Current Fixed Disk Drive: # ³ */
447 /* 07³ ³ */
448 /* 08³Partition Status Type Start End Size³ */
449 /* 09³ # # ####### #### #### ####³ */
450 /* 10³ ³ */
451 /* 11³ ³ */
452 /* 12³ ³ */
453 /* 13³ ³ */
454 /* 14³Total disk space is #### cylinders. ³ */
455 /* 15³ ³ */
456 /* 16³ ³ */
457 /* 17³ ³ */
458 /* 18³The EXTENDED DOS partition contains DOS ³ */
459 /* 19³disk volumes. Do you want to display ³ */
460 /* 20³the volume information............? [Y] ³ */
461 /* 21³ ³ */
462 /* 22³ ³ */
463 /* 23³Press ESC to return to FDISK Options ³ */
464 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
465 /* */
466 /* ENTRY POINTS: Display_Partition_Information */
467 /* LINKAGE: display_partition_information () */
468 /* NEAR CALL */
469 /* */
470 /* INPUT: None */
471 /* */
472 /* EXIT-NORMAL: ERROR=FALSE */
473 /* */
474 /* EXIT-ERROR: ERROR=TRUE */
475 /* GOTO internal_program_error if invalid input */
476 /* returned to this routine */
477 /* */
478 /* EFFECTS: No data directly modified by this routine, but */
479 /* child routines will modify data. */
480 /* */
481 /* INTERNAL REFERENCES: */
482 /* ROUTINES: */
483 /* clear_screen */
484 /* wait_for_ESC */
485 /* display */
486 /* table_display */
487 /* get_yn_input */
488 /* find_partition_type */
489 /* display_volume_information */
490 /* internal_program_error */
491 /* */
492 /* EXTERNAL REFERENCES: */
493 /* ROUTINES: */
494 /* */
495 /******************** END OF SPECIFICATIONS ********************/
496
497 /* \f */
498 void display_partition_information()
499
500 BEGIN
501
502 char input;
503 char temp;
504
505 input = c(NUL); /* AC000 */
506 /* Clear_screen */
507 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
508
509 /* Display Header */
510 display(menu_35);
511
512 /* Setup and print current disk */
513 insert[0] = cur_disk+1+'0';
514 display(menu_5);
515
516 /* print ESC prompt */
517 display(menu_11);
518
519 /* Display information */
520 if (table_display())
521 BEGIN
522
523 /* Setup and print disk space msg */
524 number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */
525 display(menu_15);
526
527 /* See if any logical drive stuff to display */
528 if (find_partition_type(uc(EXTENDED))) /* AC000 */
529 BEGIN
530 /* See if any logical drives exist */
531 if (find_logical_drive())
532 BEGIN
533
534 /* Prompt to see if they want to see EXTENDED info */
535 display(menu_36);
536
537 /* Get Y/N input, default is YES */
538 input = get_yn_input(c(Yes),input_row,input_col); /* AC000 AC011 */
539 switch(input)
540 BEGIN
541
542 case 1: display_volume_information(); /* AC000 */
543 break;
544
545 case 0: break; /* AC000 */
546
547 case ESC: break;
548
549 default: internal_program_error();
550 break;
551 END
552 END
553 else
554 input = wait_for_ESC();
555 END
556 else
557 input = wait_for_ESC();
558 END
559 else
560 input = wait_for_ESC();
561 /* clear the screen before going back to main menu */
562 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
563 return;
564 END
565
566
567
568 /* \f */
569 /******************* START OF SPECIFICATIONS *******************/
570 /* */
571 /* SUBROUTINE NAME: DISPLAY_VOLUME_INFORMATION */
572 /* */
573 /* DESCRIPTIVE NAME: Display DOS disk Volume Information */
574 /* */
575 /* FUNCTION: Displays disk volume size and existence */
576 /* */
577 /* NOTES: */
578 /* */
579 /* The following screen is managed */
580 /* */
581 /* ³0000000000111111111122222222223333333333³ */
582 /* ³0123456789012345678901234567890123456789³ */
583 /* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */
584 /* 01³Display DOS Disk Volume Information ³ */
585 /* 02³ ³ */
586 /* 03³Vol Start End Size Vol Start End Size³ */
587 /* 04³ # #### #### #### # #### #### ####³ */
588 /* 05³ ³ */
589 /* 06³ ³ */
590 /* 07³ ³ */
591 /* 08³ ³ */
592 /* 09³ ³ */
593 /* 10³ ³ */
594 /* 11³ ³ */
595 /* 12³ ³ */
596 /* 13³ ³ */
597 /* 14³ ³ */
598 /* 15³ ³ */
599 /* 16³ ³ */
600 /* 17³ ³ */
601 /* 18³ ³ */
602 /* 19³ ³ */
603 /* 20³ ³ */
604 /* 21³ ³ */
605 /* 22³ ³ */
606 /* 23³Press ESC to return to FDISK Options ³ */
607 /* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
608 /* */
609 /* ENTRY POINTS: Display_Volume_Information */
610 /* LINKAGE: display_volume_information () */
611 /* NEAR CALL */
612 /* */
613 /* INPUT: None */
614 /* */
615 /* EXIT-NORMAL: ERROR=FALSE */
616 /* */
617 /* EXIT-ERROR: ERROR=TRUE */
618 /* */
619 /* EFFECTS: No data directly modified by this routine, but */
620 /* child routines will modify data. */
621 /* */
622 /* INTERNAL REFERENCES: */
623 /* ROUTINES: */
624 /* clear_screen */
625 /* wait_for_ESC */
626 /* display */
627 /* volume_display */
628 /* */
629 /* EXTERNAL REFERENCES: */
630 /* ROUTINES: */
631 /* */
632 /******************** END OF SPECIFICATIONS ********************/
633
634 /* \f */
635 void display_volume_information()
636
637 BEGIN
638
639 char input;
640 char temp;
641
642 input = c(NUL); /* AC000 */
643 /* clear the screen */
644 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
645
646 /* Display Header */
647 display(menu_37);
648
649 /* Display information */
650 temp = volume_display();
651
652 /* Set up partition size message */
653 sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) );
654 display(menu_21);
655
656 /* print ESC prompt */
657 display(menu_11);
658
659 /* Wait to exit */
660 input = wait_for_ESC();
661 return;
662 END
663
664 /* \f */
665 char check_valid_environment()
666 BEGIN
667
668 /* See if the net is there */
669 regs.x.ax = u(INSTALLATION_CHECK); /* AC000 */
670 int86((int)NETWORK,&regs,&regs); /* AC000 */
671
672 #ifdef DEBUG /* AN006 */
673 regs.h.al = uc(0); /* AN006 */
674 #endif /* AN006 */
675
676 /* Is it ? */
677 if (regs.h.al != uc(0)) /* AC000 */
678 BEGIN
679
680 /* See if server is loaded, otherwise okay */
681 if ((regs.x.bx & SERVER_CHECK) != u(0)) /* AC000 */
682 BEGIN
683 no_fatal_error = FALSE;
684 display_msg((int)4,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class)); /* AN000 AC014*/
685 return(FALSE);
686 END
687 END
688 return(TRUE);
689 END
690
691
692
693 /* \f */
694 void init_partition_tables()
695 BEGIN
696
697 unsigned i;
698 unsigned char j;
699 unsigned k;
700 unsigned l;
701 unsigned partition_location;
702 char temp;
703 char more_drives_exist;
704 char num_logical_drives;
705 unsigned insert;
706 unsigned index;
707
708 /* initialize first drive found to "C" */
709 next_letter = c(SEA); /* AC000 */
710
711 /* Look at both disks */
712 for (j = uc(0); j < number_of_drives; j++) /* AC000 */
713 BEGIN
714
715 /* Initialize the cur_disk field to the drive in question so */
716 /* that the calls to the partition information routines will work */
717 cur_disk = ((char)(j));
718
719 /* Read in the master boot record and see if it was okay */
720 if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */
721 BEGIN
722
723 /* See if there was a valid boot record there */
724 if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */
725 BEGIN
726
727 /* What was on the disk is a valid boot record, so save it */
728 for (i=u(0);i < u(BYTES_PER_SECTOR); i++) /* AC000 */
729 BEGIN
730 master_boot_record[j][i] = boot_record[i];
731 END
732 END
733 /* We've now got a copy of the master boot record saved. Now we need */
734 /* to translate what in the boot record to the area that it's going */
735 /* to be worked on (part_table) */
736
737 /* Read in the data from the master boot record partition entries*/
738 for (i=u(0); i < u(4); i++) /* AC000 */
739 BEGIN
740 index = i*16;
741
742 /* Get boot ind */
743 part_table[j][i].boot_ind = master_boot_record[j][0x1BE+index];
744
745 /* Start head */
746 part_table[j][i].start_head = master_boot_record[j][0x1BF+index];
747
748 /* Start sector - unscramble it from INT 13 format*/
749 part_table[j][i].start_sector= (master_boot_record[j][0x1C0+index] & 0x3F);
750
751 /* Start cyl - unscramble it from INT 13 format*/
752 part_table[j][i].start_cyl= ((((unsigned)master_boot_record[j][0x1C0+index]) & 0x00C0) << 2)
753 + ((unsigned)master_boot_record[j][0x1C1+index]);
754
755 /* System id */
756 part_table[j][i].sys_id = master_boot_record[j][0x1C2+index];
757
758 /* End head */
759 part_table[j][i].end_head = master_boot_record[j][0x1C3+index];
760
761 /* End sector - unscramble it from INT 13 format*/
762 part_table[j][i].end_sector= (master_boot_record[j][0x1C4+index] & 0x3F);
763
764 /* End cyl - unscramble it from INT 13 format*/
765 part_table[j][i].end_cyl= ((((unsigned)master_boot_record[j][0x1C4+index]) & 0x00C0) << 2)
766 + ((unsigned)master_boot_record[j][0x1C5+index]);
767
768 /* Relative sectors */
769
770 part_table[j][i].rel_sec =
771 ((unsigned long)master_boot_record[j][0x1C9+index]) << 24;
772
773 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
774 (((unsigned long)master_boot_record[j][0x1C8+index]) << 16);
775
776 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
777 (((unsigned long)master_boot_record[j][0x1C7+index]) << 8);
778
779 part_table[j][i].rel_sec = part_table[j][i].rel_sec +
780 ((unsigned long)master_boot_record[j][0x1C6+index]);
781
782 /* Number of sectors */
783 part_table[j][i].num_sec =
784 ((unsigned long)master_boot_record[j][0x1CD+index]) << 24;
785
786 part_table[j][i].num_sec = part_table[j][i].num_sec +
787 (((unsigned long)master_boot_record[j][0x1CC+index]) << 16);
788
789 part_table[j][i].num_sec = part_table[j][i].num_sec +
790 (((unsigned long)master_boot_record[j][0x1CB+index]) << 8);
791
792 part_table[j][i].num_sec = part_table[j][i].num_sec +
793 ((unsigned long)master_boot_record[j][0x1CA+index]);
794
795 part_table[j][i].mbytes_used =
796 cylinders_to_mbytes(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1),
797 cur_disk); /* AN004 */
798
799 part_table[j][i].percent_used =
800 cylinders_to_percent(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1),
801 total_disk[cur_disk]); /* AN000 */
802
803 /* Set drive letter */
804 if ( (part_table[j][i].sys_id == DOS12) || /* AN000 */
805 (part_table[j][i].sys_id == DOS16) || /* AN000 */
806 (part_table[j][i].sys_id == DOSNEW) ) /* AN000 */
807 part_table[j][i].drive_letter = next_letter++; /* AN000 */
808
809 /* Set changed flag */
810 part_table[j][i].changed = FALSE;
811 END
812 END
813 else
814 BEGIN
815 return;
816 END
817 END
818
819 /* Look at both disks */
820 for (j = uc(0); j < number_of_drives; j++) /* AC000 */
821 BEGIN
822
823 /* Initialize the cur_disk field to the drive in question so */
824 /* that the calls to the partition information routines will work */
825 cur_disk = ((char)(j));
826
827 /* Read in the master boot record and see if it was okay */
828 if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */
829 BEGIN
830 /* Now, go read in extended partition info */
831 if (find_partition_type(uc(EXTENDED))) /* AC000 */
832 BEGIN
833 /* Initialize the array to zero's - include one dummy entry */
834 for (i=u(0); i < u(24); i++) /* AC000 */
835 BEGIN
836 ext_table[j][i].boot_ind = uc(0); /* AC000 */
837 ext_table[j][i].start_head = uc(0); /* AC000 */
838 ext_table[j][i].start_sector = uc(0); /* AC000 */
839 ext_table[j][i].start_cyl = u(0); /* AC000 */
840 ext_table[j][i].sys_id = uc(0); /* AC000 */
841 ext_table[j][i].end_head = uc(0); /* AC000 */
842 ext_table[j][i].end_sector = uc(0); /* AC000 */
843 ext_table[j][i].end_cyl = u(0); /* AC000 */
844 ext_table[j][i].rel_sec = ul(0); /* AC000 */
845 ext_table[j][i].num_sec = ul(0); /* AC000 */
846 ext_table[j][i].mbytes_used = f(0); /* AN000 */
847 ext_table[j][i].percent_used = u(0); /* AN000 */
848 ext_table[j][i].changed = FALSE;
849 ext_table[j][i].drive_letter = NUL; /* AN000 */
850
851 strcpy(ext_table[cur_disk][i].system,NUL); /* AN000 */
852 strcpy(ext_table[cur_disk][i].vol_label,NUL); /* AN000 */
853
854 END
855
856 /* Find where the first extended boot record is */
857 temp = find_partition_location(uc(EXTENDED)); /* AC000 */
858 partition_location = part_table[j][temp].start_cyl;
859
860 /* Go find extended boot records as long as there are more of them */
861 more_drives_exist = TRUE;
862
863 /* Init the number of logical drives, for a array index */
864 num_logical_drives = c(0); /* AC000 */
865
866 while (more_drives_exist)
867 BEGIN
868 /* Assume we won't find another logical drive */
869 more_drives_exist = FALSE;
870
871 /*Read in the extended boot record */
872 if (read_boot_record(partition_location,
873 j,
874 uc(0),
875 uc(1))) /* AC000 */
876 BEGIN
877 load_logical_drive(num_logical_drives,j);
878
879
880 /* find the next logical drive */
881 for (i = u(0); i < u(4); i++) /* AC000 */
882 BEGIN
883 index = i*16;
884 /* See if a sys id byte of exteneded exists */
885 if (boot_record[0x1C2+index] == uc(EXTENDED)) /* AC000 */
886 BEGIN
887 /* Found another drive, now get its location */
888 partition_location= (((((unsigned)(boot_record[0x1C0 + index])) & 0x00C0) << 2));
889 partition_location = partition_location + ((unsigned)(boot_record[0x1C1+index]));
890
891 /* Indicate we found another one */
892 more_drives_exist = TRUE;
893
894 /* Up the count of found ones */
895 num_logical_drives++;
896 break;
897 END
898 END
899 END
900 END
901 END
902 END
903 END
904 return;
905 END
906
907
908 /* \f */
909 void load_logical_drive(point,drive)
910
911 char point;
912 unsigned char drive;
913
914 BEGIN
915
916 char volume_label[13]; /* AC000 *//*Used be 11*/
917 unsigned ext_part_num; /* AN000 */
918 unsigned i;
919 unsigned j; /* AN000 */
920 unsigned k; /* AN000 */
921 unsigned length; /* AN000 */
922 unsigned index;
923 unsigned dx_pointer; /* AN000 */
924 unsigned partition_location; /* AN000 */
925
926 /* Check to see if anything is there */
927 if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */
928 BEGIN
929 /* The boot record is there - read in the logical drive if it is there */
930 for (i = u(0); i < u(4); i++) /* AC000 */
931 BEGIN
932
933 index = i*16;
934 /* See if it is a defined extended drive*/
935 if ((boot_record[0x1C2 + index] != uc(0)) && (boot_record[0x1C2 + index] != uc(EXTENDED))) /* AC000 */
936 BEGIN
937 /* Get boot ind */
938 ext_table[drive][point].boot_ind = boot_record[0x1BE + index];
939
940 /* Start head */
941 ext_table[drive][point].start_head = boot_record[0x1BF + index];
942
943 /* Start sector - unscramble it from INT 13 format*/
944 ext_table[drive][point].start_sector= (boot_record[0x1C0 + index] & 0x3F);
945
946 /* Start cyl - unscramble it from INT 13 format*/
947 ext_table[drive][point].start_cyl= ((((unsigned)boot_record[0x1C0+index]) & 0x00C0) << 2)
948 + ((unsigned)boot_record[0x1C1+index]);
949
950
951 /* System id */
952 ext_table[drive][point].sys_id = boot_record[0x1C2+index];
953
954 /* End head */
955 ext_table[drive][point].end_head = boot_record[0x1C3+index];
956
957 /* End sector - unscramble it from INT 13 format*/
958 ext_table[drive][point].end_sector= (boot_record[0x1C4+index] & 0x3F);
959
960
961 /* End cyl - unscramble it from INT 13 format*/
962 ext_table[drive][point].end_cyl= ((((unsigned)boot_record[0x1C4+index]) & 0x00C0) << 2)
963 + ((unsigned)boot_record[0x1C5+index]);
964
965 /* Relative sectors */
966 ext_table[drive][point].rel_sec =
967 ((unsigned long)boot_record[0x1C9+index]) << 24;
968
969 ext_table[drive][point].rel_sec =
970 ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C8+index]) << 16);
971
972 ext_table[drive][point].rel_sec =
973 ext_table[drive][point].rel_sec + (((unsigned long)boot_record[0x1C7+index]) << 8);
974
975 ext_table[drive][point].rel_sec =
976 ext_table[drive][point].rel_sec + ((unsigned long)boot_record[0x1C6+index]);
977
978 /* Number of sectors */
979
980 ext_table[drive][point].num_sec =
981 ((unsigned long)boot_record[0x1CD+index]) << 24;
982
983 ext_table[drive][point].num_sec =
984 ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CC+index]) << 16);
985
986 ext_table[drive][point].num_sec =
987 ext_table[drive][point].num_sec + (((unsigned long)boot_record[0x1CB+index]) << 8);
988
989 ext_table[drive][point].num_sec =
990 ext_table[drive][point].num_sec + ((unsigned long)boot_record[0x1CA+index]);
991
992 ext_table[drive][point].mbytes_used =
993 cylinders_to_mbytes(((ext_table[drive][point].end_cyl - ext_table[drive][point].start_cyl)+1),
994 cur_disk); /* AN004 */
995
996 ext_part_num = find_partition_location(uc(EXTENDED));
997
998 ext_table[drive][point].percent_used =
999 cylinders_to_percent(((ext_table[drive][point].end_cyl-ext_table[drive][point].start_cyl)+1),
1000 ((part_table[drive][ext_part_num].end_cyl-part_table[drive][ext_part_num].start_cyl)+1)); /* AN000 */
1001
1002 ext_table[drive][point].drive_letter = next_letter++; /* AN000 */
1003
1004 partition_location = ext_table[drive][point].start_cyl;
1005
1006 if (read_boot_record(ext_table[drive][point].start_cyl,
1007 drive,
1008 ext_table[drive][point].start_head,
1009 ext_table[drive][point].start_sector));
1010 BEGIN /* AN000 */
1011 /* See if the disk has already been formated */
1012 if (check_format(ext_table[drive][point].drive_letter) == TRUE ) /* AN002 */
1013 BEGIN /* AN000 */
1014 /* get volume and system info */
1015
1016 /* AC000 Just for cleaning up purposes */
1017
1018 for (k = u(0); k < u(12); k++) /* AC000 */
1019 BEGIN /* AC000 */
1020 ext_table[drive][point].vol_label[k]=u(0); /* AC000 */
1021 END /* AC000 */
1022
1023 for (k = u(0); k < u(9); k++) /* AC000 */
1024 BEGIN /* AC000 */
1025 ext_table[drive][point].system[k]=u(0); /* AC000 */
1026 END /* AC000 */
1027
1028 get_volume_string(ext_table[drive][point].drive_letter,&volume_label[0]); /* AN000 AC015 */
1029
1030 for (k = u(0); k < strlen(volume_label); k++) /* AC000 AC015 */
1031 BEGIN /* AC000 AC015 */
1032 ext_table[drive][point].vol_label[k]=volume_label[k]; /* AC000 AC015 */
1033 END /* AC000 AC015 */
1034
1035 /* Now try to get it using GET MEDIA ID function */
1036 if (get_fs_and_vol(ext_table[drive][point].drive_letter)) /* AN000 */
1037
1038 BEGIN /* AN000 */
1039 /* AC000 Just use more conceptually simple logic */
1040 for (k=u(0); k < u(8); k++) /* AC000 */
1041
1042 BEGIN /* AC000 */
1043 if (dx_buff.file_system[k] != ' ') /* AC000 */
1044 length = k+1; /* AC000 */
1045 END /* AC000 */
1046
1047 strncpy(ext_table[drive][point].system,&dx_buff.file_system[0],u(length)); /* AN000 */
1048 END /* AN000 */
1049
1050 else /* AN000 */
1051
1052 BEGIN /* AN000 */
1053 if (ext_table[drive][point].num_sec > (unsigned long)FAT16_SIZE) /* AN000 */
1054 strcpy(ext_table[drive][point].system,FAT16); /* AN000 */
1055 else
1056 strcpy(ext_table[drive][point].system,FAT12); /* AN000 */
1057 END /* AN000 */
1058 END /* AN000 */
1059 else /* AN000 */
1060 BEGIN /* AN000 */
1061 /* set up array to say no file system or volume label */
1062 strcpy(ext_table[drive][point].vol_label,NOVOLUME); /* AN000 */
1063 strcpy(ext_table[drive][point].system,NOFORMAT); /* AN000 */
1064 END /* AN000 */
1065
1066 regs.x.dx = u(0);
1067 regs.x.ax = NETWORK_IOCTL;
1068 regs.h.bl = ((ext_table[drive][point].drive_letter - 'A') + 1);
1069 intdos(&regs,&regs);
1070 if (regs.x.dx & 0x1000) strcpy(ext_table[drive][point].vol_label,"* Remote * ");
1071 END
1072 read_boot_record(ext_table[drive][point].start_cyl,
1073 drive,
1074 uc(0),
1075 uc(1)); /* AN000 */
1076 END
1077 END
1078 END
1079
1080 return;
1081
1082 END
1083
1084
1085
1086 /* \f */
1087 void reboot_system()
1088 BEGIN
1089
1090
1091 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
1092 if (quiet_flag == FALSE)
1093 BEGIN
1094 display(menu_38);
1095 getch();
1096 reboot();
1097 END
1098 else
1099 BEGIN
1100 cur_disk = c(0); /* AN001 */
1101 reset_video_information(); /* AN006 */
1102 if ( (find_partition_type(uc(DOS12))) ||
1103 (find_partition_type(uc(DOS16))) ||
1104 (find_partition_type(uc(DOSNEW))) ) /* AN001 */
1105 exit(ERR_LEVEL_0); /* AN001 */
1106 else /* AN001 */
1107 exit(ERR_LEVEL_1); /* AN001 */
1108 END
1109 END
1110
1111
1112 /* \f */
1113 void internal_program_error()
1114
1115 BEGIN
1116 display(internal_error);
1117 DOSEXIT(u(0),u(0)); /* AC000 */
1118 return;
1119 END
1120
1121