home *** CD-ROM | disk | FTP | other *** search
- /*
- Program to format a floppy disk
-
- Tested with BC++ 3.1 (compilable as C or as C++)
-
- Compile: bcc -ms cformat.c
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <bios.h>
- #include <dos.h>
- #include <stddef.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <dir.h>
-
- #include "cformat.h"
-
- Byte far* far* disk_ptr = (Byte far* far*) MK_FP(0, 0x1e * 4);
- Byte far* old_value = 0;
-
- const int retries = 3;
- int verify_flag = 0; /* change to non-zero if you want to verify tracks */
- int system_flag = 1; /* change to zero if you don't want to write system files */
-
- int main(void)
- {
- int drive_type = -1;
- int media_type = -1;
-
- int function_17_code;
-
- int drive;
- int ntracks, nsects;
- int track, head;
- int status;
-
- /* floppy-specific data */
- static struct disk_info info[] = {
- { 512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2 }, /* 360K floppy */
- { 512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2 }, /* 1.2M floppy */
- { 512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2 }, /* 720K floppy */
- { 512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2 } /* 1.44M floppy */
- };
-
- /* rows: drive type cols: media type */
- static struct validity valid[4][4] = {
- { {1, 1}, {0, 0}, {0, 0}, {0, 0} },
- { {1, 2}, {1, 3}, {0, 0}, {0, 0} },
- { {0, 0}, {0, 0}, {1, 4}, {0, 0} },
- { {0, 0}, {0, 0}, {1, 4}, {1, 4} }
- };
-
- static char* smedia[] = { "360K", "1.2M", "720K", "1.44M" };
-
- /* save original value of pointer to disk parameter table */
- old_value = *disk_ptr;
-
- atexit(cleanup); /* insure restoration of pointer, cursor */
- ctrlbrk(breakhandler);
-
- #ifdef __cplusplus
- harderr( (int (*)(int,int,int,int))errhandler );
- #else
- harderr( errhandler );
- #endif
-
- /* get drive (A or B floppy) */
- do
- {
- cprintf("Enter drive [A or B]: ");
- drive = toupper(getche()) - 'A';
- putch('\r');
- putch('\n');
- }
- while(drive < 0 || drive > 1);
-
- /* get media type */
- do
- {
- putch('\r');
- putch('\n');
-
- cputs("Select media type:\r\n");
- cputs(" 1) 360K floppy\r\n");
- cputs(" 2) 1.2M floppy\r\n");
- cputs(" 3) 720K floppy\r\n");
- cputs(" 4) 1.44M floppy\r\n");
- cputs(" 5) Exit program\r\n");
- cputs("Select [1-5]: ");
-
- media_type = getche() - '1';
-
- putch('\r');
- putch('\n');
- }
- while(media_type < 0 || media_type > 4);
-
- if(media_type == 4)
- return 0;
-
- putch('\r');
- putch('\n');
-
- /* reset the disk controller */
- if( reset(drive) )
- {
- fputs("Unable to reset floppy controller\n", STDERR);
- return 1;
- }
-
- /* this may fail if not an AT-compatible machine */
- drive_type = getdrivetype(drive);
- if(drive_type < 0 || drive_type > 3)
- {
- fputs("No floppy drive or unable to determine drive type\n", STDERR);
- return 1;
- }
-
- if( !valid[drive_type][media_type].OK )
- {
- fputs("Unable to format floppy in specified drive\n", STDERR);
- return 1;
- }
-
- function_17_code = valid[drive_type][media_type].disk_type_code;
-
- /* this may fail if not an AT-compatible machine */
- if( setdisktype(drive, function_17_code) )
- {
- fputs("Unable to set disk type\n", STDERR);
- return 1;
- }
-
- ntracks = info[media_type].total_sectors /
- info[media_type].sectors_per_track /
- info[media_type].heads;
- nsects = info[media_type].sectors_per_track;
-
- /* this may fail if not an AT-compatible machine */
- if( setmediatype(drive, ntracks, nsects) )
- {
- fputs("Unable to set media type\n", STDERR);
- return 1;
- }
-
- _setcursortype(_NOCURSOR); /* turn off the cursor */
-
- cprintf("Formatting %s floppy in drive %c:\r\n", smedia[media_type], drive+'A');
-
- /* format the floppy tracks */
- for(track=0; track<ntracks; track++)
- {
- for(head=0; head<2; head++)
- {
- cprintf("Track %2d Head %2d\r", track, head);
-
- if( (status = format(drive, head, track, nsects, &info[media_type])) != 0 )
- {
- fprintf(STDERR, "Unable to format track %d. Status: %d\n",
- track, status);
- return 1;
- }
-
- /* verify each track as it is formatted if verify_flag != 0 */
- if(verify_flag)
- if( (status = verify(drive, head, track, nsects)) != 0 )
- {
- fprintf(STDERR, "Unable to verify track %d. Status: %d\n",
- track, status);
- return 1;
- }
- }
- }
-
- putch('\r');
- clreol();
- gotoxy(1, wherey()-1);
- clreol();
-
- /* write the boot sector to the floppy */
- cputs("Writing boot sector.\r");
- status = write_boot(drive, &info[media_type]);
- if(status)
- {
- fprintf(STDERR, "Error writing boot sector: %d\n", status);
- return 1;
- }
-
- putch('\r');
- clreol();
-
- /* clear out the FAT tables on the floppy */
- cputs("Writing FAT tables.\r");
- status = write_FATs(drive, &info[media_type]);
- if(status)
- {
- fprintf(STDERR, "Error writing FAT tables: %d\n", status);
- return 1;
- }
-
- putch('\r');
- clreol();
-
- /* clear out the directory entries on the floppy */
- cputs("Writing root directory entries.\r");
- status = write_root(drive, &info[media_type]);
- if(status)
- {
- fprintf(STDERR, "Error writing root directory: %d\n", status);
- return 1;
- }
-
- putch('\r');
- clreol();
-
- /* write the system files (MS-DOS): io.sys, msdos.sys, command.com */
- if( system_flag )
- {
- cputs("Writing system files.\r");
- status = write_system(drive);
- if(status)
- {
- fputs("Error writing system files\n", STDERR);
- return 1;
- }
- putch('\r');
- clreol();
- }
-
- return 0;
- }
-
- int reset(int drive)
- {
- int status;
- int retry;
-
- for(retry=0; retry<retries; retry++)
- {
- if( (status = biosdisk(0, drive, 0, 0, 0, 0, 0)) == 0 )
- break;
- }
-
- if(retry == retries)
- return status;
-
- return 0;
- }
-
- int setdisktype(int drive, int type)
- {
- union REGS regs;
- int retry;
-
- for(retry=0; retry<retries; retry++)
- {
- regs.h.ah = 0x17;
- regs.h.al = type;
- regs.h.dl = drive;
- int86(0x13, ®s, ®s);
- if(!regs.x.cflag)
- break;
- biosdisk(0, drive, 0, 0, 0, 0, 0);
- }
-
- if(retry == retries)
- return regs.h.ah;
-
- return 0;
- }
-
- int setmediatype(int drive, int ntracks, int nsects)
- {
- union REGS regs;
- struct SREGS sregs;
- int retry;
-
- segread(&sregs);
-
- for(retry=0; retry<retries; retry++)
- {
- regs.h.ah = 0x18;
- regs.h.ch = ntracks - 1;
- regs.h.cl = nsects;
- regs.h.dl = drive;
- int86x(0x13, ®s, ®s, &sregs);
- if(!regs.x.cflag)
- break;
- biosdisk(0, drive, 0, 0, 0, 0, 0);
- }
-
- if(retry == retries)
- return regs.h.ah;
-
- /* set pointer to disk para,meter table for this kind of floppy */
- *disk_ptr = (Byte far *) MK_FP(sregs.es, regs.x.di);
-
- return 0;
- }
-
- int format(int drive, int head, int track, int nsects, struct disk_info* info)
- {
- int sects;
- int status;
- int retry;
-
- int sector_size_type = 0;
- int bytes_per_sector = 128;
-
- Byte* tdata = (Byte*) malloc( nsects*4*sizeof(Byte) );
- if(!tdata)
- return -1;
-
- /* compute sector size type for BIOS table */
- while(bytes_per_sector != info->bytes_per_sector && sector_size_type < 4)
- {
- ++sector_size_type;
- bytes_per_sector *= 2;
- }
-
- for(sects=0; sects<nsects; sects++)
- {
- tdata[sects*4 + 0] = track;
- tdata[sects*4 + 1] = head;
- tdata[sects*4 + 2] = sects + 1;
- tdata[sects*4 + 3] = sector_size_type;
- }
-
- for(retry=0; retry<retries; retry++)
- {
- status = biosdisk(5, drive, head, track, 1, nsects, tdata);
- if(!status)
- break;
- biosdisk(0, drive, 0, 0, 0, 0, 0);
- }
-
- free(tdata);
-
- if(retry == retries)
- return status;
-
- return 0;
- }
-
- int write_hts(int drive, int head, int track, int sect, int nsects, Byte* buf)
- {
- int status;
- int retry;
-
- for(retry=0; retry<retries; retry++)
- {
- status = biosdisk(3, drive, head, track, sect, nsects, buf);
- if(!status)
- break;
- biosdisk(0, drive, 0, 0, 0, 0, 0);
- }
-
- if(retry == retries)
- return status;
-
- return 0;
- }
-
- int verify(int drive, int head, int track, int nsects)
- {
- int status;
- int retry;
-
- for(retry=0; retry<retries; retry++)
- {
- status = biosdisk(4, drive, head, track, 1, nsects, 0);
- if(!status)
- break;
- biosdisk(0, drive, 0, 0, 0, 0, 0);
- }
-
- if(retry == retries)
- return status;
-
- return 0;
- }
-
- int write_boot(int drive, struct disk_info* info)
- {
- size_t result;
-
- /* memory is allocated for a full sector, */
- /* not just sizeof(struct boot_sector) */
- struct boot_sector* buf = (struct boot_sector*)
- malloc( info->bytes_per_sector );
-
- FILE* boot = fopen("boot.bin", "rb");
-
- if(!boot)
- {
- fputs("Unable to open file containing boot sector image\n", STDERR);
- return -1;
- }
-
- if(!buf)
- {
- fputs("Unable to allocate memory\n", STDERR);
- return -2;
- }
-
- /* read the boot sector image */
- result = fread(buf, info->bytes_per_sector, 1, boot);
- if( result != 1 )
- {
- fputs("Unable to read file containing boot sector image\n", STDERR);
- free(buf);
- return -3;
- }
-
- /* copy the floppy-specific parameters to boot sector image */
- memcpy((Byte*)buf + offsetof(struct boot_sector, parms),
- info, sizeof(struct disk_info));
-
- /* compute a serial number */
- buf->serial_number = serial_number();
-
- /* write data out to the floppy */
- result = write_hts(drive, 0, 0, 1, 1, (Byte*)buf);
-
- free(buf);
- return result;
- }
-
- long serial_number()
- {
- struct date d;
- struct time t;
-
- union { long value; size_t w[2]; } result;
-
- getdate(&d);
- gettime(&t);
-
- result.w[0] = *(size_t*)&d.da_day + *(size_t*)&t.ti_hund;
- result.w[1] = *(size_t*)&d.da_year + *(size_t*)&t.ti_min;
-
- return result.value;
- }
-
- int write_sector(int drive, int sector, Byte* buf, struct disk_info* info)
- {
- /* translate logical sector to head, track, sector */
- int head = (sector / info->sectors_per_track) % info->heads;
- int track = (sector / info->sectors_per_track) / info->heads;
- sector = (sector % info->sectors_per_track) + 1;
-
- return write_hts(drive, head, track, sector, 1, buf);
- }
-
- int write_FATs(int drive, struct disk_info* info)
- {
- int i, j;
-
- int sector;
- int status;
-
- Byte* buf = (Byte*) malloc( info->bytes_per_sector );
- if( !buf )
- {
- fputs("Unable to allocate memory\n", STDERR);
- return -1;
- }
-
- for(i=0; i<info->FATs; i++) /* for each FAT */
- {
- for(j=0; j<info->sectors_per_FAT; j++) /* for each sector of FAT */
- {
- memset(buf, 0, info->bytes_per_sector); /* clear it to 0 */
- if(j == 0) /* first sector gets some data */
- {
- buf[0] = info->media_descriptor;
- buf[1] = 0xff;
- buf[2] = 0xff;
- }
- sector = info->reserved_sectors + i*info->sectors_per_FAT + j;
- status = write_sector(drive, sector, buf, info);
- if(status)
- {
- free(buf);
- return status;
- }
- }
- }
-
- free(buf);
- return 0;
- }
-
- int write_root(int drive, struct disk_info* info)
- {
- int sector, status;
-
- /* root directory starts after the FATs */
- int start_sector = info->FATs * info->sectors_per_FAT +
- info->reserved_sectors;
-
- /* number of sectors required by root directory entries */
- int nsects = (info->root_directories * 32) / info->bytes_per_sector;
-
- Byte* buf = (Byte*) malloc( info->bytes_per_sector );
- if( !buf )
- {
- fputs("Unable to allocate memory\n", STDERR);
- return -1;
- }
-
- /* clear 'em to 0 */
- memset(buf, 0, info->bytes_per_sector);
-
- /* write 'em out */
- for(sector=start_sector; sector<nsects+start_sector; sector++)
- {
- status = write_sector(drive, sector, buf, info);
- if(status)
- {
- free(buf);
- return status;
- }
- }
-
- free(buf);
- return 0;
- }
-
- int write_system(int drive)
- {
- char* ifile1 = "\\io.sys"; /* these file names are MS-DOS specific */
- char* ifile2 = "\\msdos.sys"; /* and the files should be present in */
- char ifile3[MAXPATH]; /* the root directory (except for command.com) */
-
- char ofile1[13];
- char ofile2[13];
- char ofile3[] = "X:\\COMMAND.COM";
-
- /* make file name for io.sys on floppy */
- ofile1[0] = drive + 'A';
- ofile1[1] = ':';
- ofile1[2] = '\0';
- strcat(ofile1, ifile1);
-
- /* copy file to floppy */
- if(copy_file(ofile1, ifile1))
- return -1;
-
- /* make file name for msdos.sys on floppy */
- ofile2[0] = drive + 'A';
- ofile2[1] = ':';
- ofile2[2] = '\0';
- strcat(ofile2, ifile2);
-
- /* copy file to floppy */
- if(copy_file(ofile2, ifile2))
- return -1;
-
- /* get file name for current command processor */
- strcpy( ifile3, getenv("COMSPEC") );
-
- /* only copy it to the floppy if it is MS-DOS's command.com */
- if( strstr( strupr(ifile3), "COMMAND.COM") )
- {
- ofile3[0] = drive + 'A'; /* fill in drive letter */
-
- if(copy_file(ofile3, ifile3)) /* copy the file */
- return -1;
- }
-
- return 0;
- }
-
- int copy_file(char* dest, char* src)
- {
- int ihandle, ohandle;
- int ibytes, obytes;
- int attrib;
-
- struct ftime t;
-
- const int bufsz = 50*1024;
-
- char* buf = (char*) malloc( bufsz );
- if(!buf)
- {
- fputs("Unable to allocate memory\n", STDERR);
- return -1;
- }
-
- ihandle = _open(src, O_RDONLY);
- if(ihandle < 0)
- {
- fprintf(STDERR, "Unable to open %s\n", src);
- free(buf);
- return -1;
- }
-
- /* get attributes of source file */
- attrib = _chmod(src, 0);
-
- /* creates new file with specified attributes */
- ohandle = _creat(dest, attrib);
- if(ohandle < 0)
- {
- fprintf(STDERR, "Unable to open %s\n", dest);
- free(buf);
- return -1;
- }
-
- /* do the actual file copy */
- while( (ibytes = _read(ihandle, buf, bufsz)) != 0 )
- {
- obytes = _write(ohandle, buf, ibytes);
- if(obytes != ibytes)
- {
- fputs("Error copying file\n", STDERR);
- free(buf);
- return -1;
- }
- }
-
- /* it is assumed that the rest of this won't generate errors */
- /* if something goes wrong -> if it does, the errors are ignored */
-
- getftime(ihandle, &t); /* get original file time/date */
- setftime(ohandle, &t); /* set file time/date of file */
-
- _close(ihandle);
- _close(ohandle);
-
- free(buf);
- return 0;
- }
-
- void cleanup(void)
- {
- *disk_ptr = old_value; /* restore pointer to disk parameter table */
- _setcursortype(_NORMALCURSOR); /* restore cursor to normal */
- }
-
- int breakhandler(void)
- {
- cleanup(); /* do a little bit of clean up */
- return 0;
- }
-
- int errhandler(void)
- {
- cleanup(); /* do a little bit of clean up */
- hardresume(2); /* abort */
- return 0; /* should never get here */
- }
-
- int getdrivetype(int drive)
- {
- union REGS regs;
- struct SREGS sregs;
-
- segread(&sregs);
-
- regs.h.ah = 8;
- regs.h.dl = drive;
- int86x(0x13, ®s, ®s, &sregs);
-
- if(regs.x.cflag)
- return -1;
- else
- return regs.h.bl - 1;
- }
-