📄 df.c
字号:
/* DF.C - file to disk / disk to file using DISKLIB
This file is part of the BETA version of DISKLIB
Copyright (C) 1998, Gregg Jennings
See README.TXT for information about re-distribution.
See DISKLIB.TXT for information about usage.
An "industry standard" floppy image writer/reader. Image format
is track 0, side 0; track 0, side 1; track 1, side 0; etc.
2.3 22-Nov-1998 greggj finally compiled (fixed error handling bugs)
for Windows 95/98
2.2 22-Nov-1998 greggj added options -s and -n
2.1 19-Nov-1998 greggj
2.0 05-Nov-1998 greggj uses DISKLIB
1.1 27-Feb-1998 greggj better error handling
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <io.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include "dosio.h"
#include "disklib.h"
#include "lib.h"
#include "fat.h"
#ifdef __WATCOMC__
#define _open open
#define _read read
#define _write write
#define _close close
#endif
#define NO_WRITE 0 /* for testing */
void options(int argc, char *argv[]);
int file2disk(int fd, int disk, int tracks, int heads, int sectors,
size_t bufsz, char *buffer);
int disk2file(int fd, int disk, int tracks, int heads, int sectors,
size_t bufsz, char *buffer);
int trackread(int disk, int track, int head, int nsectors, char *buffer);
int trackwrite(int disk, int track, int head, int nsectors, char *buffer);
void die(const char *msg, const char *fmt, int arg);
void setlast(int disk, int *track, int *head, int sysonly);
void erase(int n);
void usage(void);
jmp_buf Jmpbuf; /* abort place holder */
int Keep; /* keep going on bad sectors */
int Last; /* stop at last allocated sector */
int Disk; /* disk number */
int File; /* file number relative to argv */
int MaxTrack,MaxHead;
int Reset;
int Zero;
int Verify;
int Disk,File,ToDisk;
long int Bytes;
int SysOnly;
int NoAsk;
void usage(void)
{
printf("\n");
printf("usage: diskfile [-{options}] <file> <drive>\n");
printf(" diskfile [-{options}] <drive> <file>\n");
printf("\n");
printf("write file to floppy, or write floppy to file\n");
printf("\n");
printf("options: r reset drive before and after\n");
printf(" v verify disk writes\n");
printf(" z zero buffers before reads\n");
printf(" k keep writing even if errors\n");
printf(" l read disk up to last allocated cluster (FAT disks only)\n");
printf(" s write system tracks of disk to file\n");
printf(" n do not ask for confirmation (unless to overwrite file)\n");
exit(1);
}
int main(int argc, char **argv)
{
int fd,i;
char *buffer;
size_t bufsz;
int tracks,sectors,heads;
#if defined __WATCOMC__ || defined __GNUC__
setvbuf(stdout,NULL,_IONBF,0); /* flush stdout every printf */
#endif
Reset = 0;
Zero = 0;
Keep = 0;
Last = 0;
Verify = 0;
MaxTrack = MaxHead = -1;
Bytes = 0;
Disk = File = ToDisk = -1;
SysOnly = 0;
NoAsk = 0;
options(argc,argv);
if ((i = disk_get_physical(Disk,&tracks,§ors,&heads)) != DISK_OK)
die("BIOS error: ",disk_error(i),0);
if ((buffer = malloc(bufsz = sectors * 512)) == NULL)
die("Not enough memory found!"," (%u)",bufsz);
printf("\n");
if (Reset)
{
printf("Reseting controller...");
disk_reset(Disk);
printf(" Homing disk...");
if ((i = disk_read_p(Disk,0,1,0,buffer,1)) != DISK_OK)
die("BIOS error: ",disk_error(i),0);
printf(" OK.\n");
}
printf("Drive %c: has %u tracks and %u sides.\n",Disk+'A',tracks+1,heads+1);
if (Last)
setlast(Disk,&MaxTrack,&MaxHead,0);
if (SysOnly)
setlast(Disk,&MaxTrack,&MaxHead,1);
if (ToDisk == 1)
printf("\nWrite file \"%s\" to disk in %c:",argv[File],Disk+'A');
else
printf("\nWrite disk in %c: to file \"%s\"",Disk+'A',argv[File]);
if (!NoAsk && ask(NULL) == 0)
return 1;
if (ToDisk == 2) /* writing file */
{
if ((fd = _open(argv[File],_O_RDONLY)) != -1)
{
_close(fd);
printf("File \"%s\" exists",argv[File]);
if (ask("; overwrite?") == 0)
return 1;
}
fd = _open(argv[File],O_CREAT|O_RDWR|O_BINARY|O_TRUNC,S_IREAD|S_IWRITE);
}
else
{
fd = _open(argv[File],O_RDWR|O_BINARY);
}
if (fd == -1)
die("file error: ",strerror(errno),errno);
errno = 0;
putchar('\n');
/* on error we get back here with setjmp() returning non-zero */
if (setjmp(Jmpbuf) == 0)
{
/* now that everything is verified and prepared, this is the meat */
if (ToDisk == 1)
i = file2disk(fd,Disk,tracks,heads,sectors,bufsz,buffer);
else
i = disk2file(fd,Disk,tracks,heads,sectors,bufsz,buffer);
if (i == DISK_OK)
printf("\nDone. \n");
/* that's not hard is it... */
}
else
{
puts("\n\nStopped. \n");
getch(); /* eat key from kbhit() */
}
_close(fd);
#ifdef _WIN32
if (i)
#else
if ((i = disk_status(Disk)) != 0)
#endif
die("BIOS error: ",disk_error(i),0);
if (errno)
die("File error: ",strerror(errno),errno);
if (Reset)
{
printf("\nReseting controller...");
disk_reset(Disk);
printf(" Homing disk...\n");
disk_read_p(Disk,0,1,0,buffer,1);
}
printf("\n%ld bytes written\n",Bytes);
return 0;
}
int file2disk(int fd, int disk, int tracks, int heads, int sectors,
size_t bufsz, char *buffer)
{
int h,i,j,k;
for (i = 0; i <= tracks; i++)
{
for (h = 0; h <= heads; h++)
{
if (kbhit())
longjmp(Jmpbuf, 1);
if (Zero)
memset(buffer,0,bufsz);
if (i < tracks-1)
printf("\rreading file ");
if (_read(fd,buffer,bufsz) <= 0)
return 0; /* RETURN */
printf("\rtrack %d, side %d ",i,h);
if ((j = trackwrite(disk,i,h,sectors,buffer)) != DISK_OK)
return j; /* RETURN */
Bytes += ((sectors * 512) - (j * 512));
if (j != 0) /* (this actually never happens) */
{
printf(" %d bad sectors",j);
if (Keep)
printf(" ignored");
else
return j; /* RETURN */
}
k = 0;
if (Verify)
{
printf("verifying...");
/* weird... verify is not zero based */
k = disk_verify_p(disk,i,1,h,sectors);
erase(12);
}
if (k != 0)
printf(" verify error (%xh)",k);
if (j || k)
printf("\n");
}
}
return 0;
}
int disk2file(int fd, int disk, int tracks, int heads, int sectors,
size_t bufsz, char *buffer)
{
int h,i,j,k;
for (i = 0; i <= tracks; i++)
{
for (h = 0; h <= heads; h++)
{
if (kbhit())
longjmp(Jmpbuf, 1);
if (Zero)
memset(buffer,0,bufsz);
printf("\rtrack %d, side %d ",i,h);
if ((j = trackread(disk,i,h,sectors,buffer)) != DISK_OK)
return j;
if (i < tracks-1 && (MaxTrack == -1 && i != MaxTrack && h != MaxHead))
printf("\rwriting file ");
if ((k = _write(fd,buffer,bufsz)) == -1)
return 0;
Bytes += k;
if (j != 0) /* (this actually never happens) */
{
printf("%d bad sectors\n",j);
if (Keep)
printf(" ignored\n");
else
return j;
}
if (MaxTrack != -1 && i == MaxTrack && h == MaxHead)
return 0;
}
}
return 0;
}
int trackread(int disk, int track, int head, int nsectors, char *buffer)
{
int i,j;
char *b;
#if NO_WRITE
return DISK_OK;
#endif
if ((i = disk_read_p(disk,track,1,head,buffer,nsectors)) != DISK_OK)
{
if (i == 0x80) /* abort if no disk in drive */
return i;
b = buffer;
for (j = 1; j <= nsectors; j++)
{
if (kbhit())
longjmp(Jmpbuf, 1);
putchar('.');
putchar('\b');
if ((i = disk_read_p(disk,track,j,head,b,1)) != DISK_OK)
{
putchar('x');
if (!Keep)
return i;
}
else
putchar('.');
b += 512;
}
for (j = 1; j <= nsectors; j++)
putchar('\b');
for (j = 1; j <= nsectors; j++)
putchar(' ');
for (j = 1; j <= nsectors; j++)
putchar('\b');
}
return DISK_OK;
}
int trackwrite(int disk, int track, int head, int nsectors, char *buffer)
{
int i,j;
char *b;
#if NO_WRITE
return DISK_OK;
#endif
if ((i = disk_write_p(disk,track,1,head,buffer,nsectors)) != DISK_OK)
{
if (i == 0x80) /* abort if no disk in drive */
return i;
b = buffer;
for (j = 1; j <= nsectors; j++)
{
if (kbhit())
longjmp(Jmpbuf, 1);
if ((i = disk_write_p(disk,track,j,head,b,1)) != DISK_OK)
{
if (!Keep)
return i;
}
b += 512;
}
}
return DISK_OK;
}
void setlast(int disk, int *track, int *head, int sysonly)
{
int i;
struct DEVICEPARAMS dp;
long fatsector,lastsec;
int secsfat,datasec;
unsigned int nclusters;
unsigned short maxcluster;
if ((i = disk_getparams(disk,&dp)) != DISK_OK)
{
/* LIB TODO: make a strliberror() function (like strerror()) */
lib_error("getlast()",i);
exit(1);
}
if (sysonly)
{
datasec = data_sector(&dp);
physical(track,NULL,head,datasec,dp.hidden_sectors,dp.secs_track,
dp.num_heads);
printf("System extends to track %d, side %d (logical sector %d).\n",
MaxTrack,MaxHead,datasec);
return;
}
nclusters = num_clusters(&dp);
fatsector = dp.reserved_secs;
secsfat = dp.secs_fat;
maxcluster = searchfat12(disk,(unsigned short)nclusters,
fatsector,secsfat,0);
if (maxcluster == 0)
die("There seems to be no data on the disk in ","%c:.",disk+'A');
datasec = data_sector(&dp);
lastsec = cluster_to_sector(maxcluster,datasec,dp.secs_cluster);
lastsec += (dp.secs_cluster-1);
physical(track,NULL,head,lastsec,dp.hidden_sectors,dp.secs_track,
dp.num_heads);
printf("Last allocated cluster, %u, is on ",maxcluster);
printf("track %d, side %d.\n",MaxTrack,MaxHead);
}
void options(int argc, char *argv[])
{
int i;
if (argc < 3)
{
printf("\nNot enough arguments.\n");
usage();
}
for (i = 1; i < argc; i++)
{
/* option? */
if (argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'r': Reset = 1; break;
case 'v': Verify = 1; break;
case 'z': Zero = 1; break;
case 'k': Keep = 1; break;
case 'l': Last = 1; break;
case 's': SysOnly = 1; break;
case 'n': NoAsk = 1; break;
default:
printf("\nInvalid option: '%c'.\n",
(argv[i][1]) ? argv[i][1] : '-');
usage();
break;
}
}
/* disk? */
else if (argv[i][1] == ':' && argv[i][2] == '\0')
{
if (Disk != -1)
{
printf("\nToo many drive specifications.\n");
usage();
}
Disk = toupper(argv[i][0]) - 'A';
}
/* file. */
else
{
/*
Note that File is and argv index, ToDisk is based
on argumnet order.
*/
if (File != -1)
{
printf("\nToo many file specifications.\n");
usage();
}
File = i;
ToDisk = (Disk == -1) ? 1 : 2;
}
}
/*
Note that Disk, File and ToDisk have to have been intitialzed
all to -1.
*/
if (Disk == -1)
{
printf("\nDrive specification not found.\n");
usage();
}
if (ToDisk == -1)
{
printf("\nFile specification not found.\n");
usage();
}
if (Disk < 0 || Disk > 1) /* floppies only */
{
printf("\nDrive specification not valid.\n");
usage();
}
if (Last && File == 1)
{
printf("\nIncompatible option '-l'.\n");
usage();
}
if (SysOnly && File == 1)
{
printf("\nIncompatible option '-s'.\n");
usage();
}
if (Verify && File == 2)
{
printf("\nIncompatible option '-v'.\n");
usage();
}
}
void erase(int n)
{
int j;
for (j = 1; j <= n; j++)
putchar('\b');
for (j = 1; j <= n; j++)
putchar(' ');
for (j = 1; j <= n; j++)
putchar('\b');
}
#if NO_WRITE
int _write(int fd, void *buffer, int bufsz)
{
return bufsz;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -