📄 mdcfs.c
字号:
set_fat(i, 0xFFF);
if(cluster)
set_fat(cluster, i);
return i; }
/* Didn't find, reset to start cluster, and try again */
end = begin;
begin = 2; }
while(end != 2);
#ifdef DEBUG
printf("Failed!\n");
#endif
return 0;
}
/*
* Release a chain of allocated clusters
*/
release(cluster)
int cluster;
{
unsigned i;
while(cluster && (cluster < 0xFF8)) {
i = get_fat(cluster);
set_fat(cluster, 0);
cluster = i; }
}
/*
* Get a FAT entry for a given cluster number
*/
int get_fat(cluster)
unsigned cluster;
{
unsigned sec, fat;
#ifdef DEBUG
printf("Get FAT for %u - ", cluster);
#endif
sec = (cluster *= 3)/2;
read_work(active_drive, (sec / bytsec) + 1);
fat = wrkbuff[sec % bytsec];
read_work(active_drive, (++sec / bytsec) + 1);
fat |= wrkbuff[sec % bytsec] << 8;
if(cluster & 1)
fat >>= 4;
#ifdef DEBUG
printf("%u\n", fat & 0xFFF);
#endif
return fat & 0xfff;
}
/*
* Set a FAT entry for a given cluster number
*/
set_fat(cluster, value)
unsigned cluster, value;
{
unsigned sec, x;
#ifdef DEBUG
printf("Set FAT for %u - %u\n", cluster, value);
#endif
sec = (cluster *= 3)/2;
/* Set LOW byte of FAT */
read_work(active_drive, (sec / bytsec) + 1);
x = sec % bytsec;
if(cluster & 1)
wrkbuff[x] = (wrkbuff[x] & 0x0F) | (value << 4);
else
wrkbuff[x] = value;
wrkchg = -1;
/* Set high byte of FAT */
read_work(active_drive, (++sec / bytsec) + 1);
x = sec % bytsec;
if(cluster & 1)
wrkbuff[x] = value >> 4;
else
wrkbuff[x] = (wrkbuff[x] & 0xF0) | ((value >> 8) & 0x0F);
wrkchg = -1;
}
/*
* Directory manipulation functions:
*
* lookup(file) - Locate a files directory entry
* file - Name of file to locate
* returns : Pointer to directory entry, 0 if failure.
*
* create_file(file,attrs) - Create a mew file
* file - Name of file to create
* attrs - Attributes for file (0 = normal)
* returns : Pointer to directory entry, 0 if failure.
*
* parse_filename(buffer,name) - Get filename in directory format
* buffer - Buffer for directory format filename (13 bytes)
* name - ASCII filename to convert
*
* memcmp(ptr1, ptr2, size) - Block memory compare
* ptr1 - Pointer to first block
* ptr2 - Pointer to second block
* size - Number of bytes to compare
* returns : -1 of match, 0 if different.
*/
/*
* Lookup a directory entry & return pointer to it
*/
struct Dentry *lookup(file)
char *file;
{
unsigned i, j, k;
char fbuffer[12];
parse_filename(fbuffer, file);
#ifdef DEBUG
printf("Lookup: '%s' ", fbuffer);
#endif
j = bytsec;
k = dirsec;
for(i=0; i < dirent; ++i) {
if(j >= bytsec) {
read_work(active_drive, k++);
j = 0; }
if(memcmp(wrkbuff+j, fbuffer, 11)) {
#ifdef DEBUG
printf("Found - Cluster: %u\n", *(int*)(wrkbuff+j+0x1A));
#endif
return wrkbuff+j; }
j += sizeof(struct Dentry); }
#ifdef DEBUG
printf("Not found\n");
#endif
return 0;
}
/*
* Create a file with the specified name
* NOTE: Does NOT check for duplicates. It is assumed that "lookup()"
* has been called first, to verify that the file does not already
* exist on the disk.
*/
struct Dentry *create_file(file, attrs)
char *file;
int attrs;
{
int i, j, k;
char fbuffer[12];
struct Dentry *dirptr;
parse_filename(fbuffer, file);
#ifdef DEBUG
printf("Create '%s' ", fbuffer);
#endif
j = bytsec;
k = dirsec;
for(i=0; i < dirent; ++i) {
if(j >= bytsec) {
read_work(active_drive, k++);
j = 0; }
if((*(dirptr = wrkbuff+j)->Dname == EMPTY) || !*dirptr->Dname) {
#ifdef DEBUG
printf("Dir entry #%u\n", i);
#endif
memset(dirptr, 0, sizeof(struct Dentry));
strcpy(dirptr, fbuffer);
dirptr->Dattr = attrs;
/* Set directory date of creation here - if you wish */
wrkchg = -1;
return wrkbuff+j; }
j += sizeof(struct Dentry); }
#ifdef DEBUG
printf("No directory!\n");
#endif
return 0;
}
/*
* Parse a filename into directory format (12 characters, space filled)
*/
parse_filename(buffer, name)
char buffer[], *name;
{
int i;
i = 0;
while(i < 8)
buffer[i++] = (*name && (*name != '.')) ? toupper(*name++) : ' ';
if(*name == '.')
++name;
while(i < 11)
buffer[i++] = *name ? toupper(*name++) : ' ';
buffer[i] = 0;
}
/*
* Memory to memory compare
*/
int memcmp(ptr1, ptr2, size)
char *ptr1, *ptr2;
unsigned size;
{
while(size--)
if(*ptr1++ != *ptr2++)
return 0;
return -1;
}
/*
* Internal "work" sector manipulation functions:
*
* read_work(sector) - Read sector into work buffer (if necessary)
* sector - Sector number to read.
*
* update_work() - Write work sector back to disk if changed
*/
/*
* Read a work sector into memory if it is not already in memory.
*/
read_work(drive, sector)
char drive;
int sector;
{
if((wrkdrv != drive) || (wrksec != sector)) {
update_work();
read_sector(wrkdrv = drive, wrksec = sector, wrkbuff); }
}
/*
* Write the work sector if it has been marked as modified
*/
update_work()
{
if(wrkchg) {
write_sector(wrkdrv, wrksec, wrkbuff);
wrkchg = 0; }
}
/*
* Low level disk I/O functions:
*
* disk_error(code) - Called if unrecoverable disk error
* code - Disk failure code (system depandant)
*
* read_sector(d, s, b) - Read a sector from the disk
* d - Drive to read (0=A, 1=B ...)
* s - Sector number to read (1-n)
* b - Pointer to buffer to receive data
*
* write_sector(d, s, b) - Write a sector to the disk
* d - Drive to write (0=A, 1=B ...)
* s - Sector number to write (1-n)
* b - Pointer to buffer containing the data
*
* These functions make use of the IBM PC BIOS, and are compatible
* with Microsoft MASM assembler. Use these if you are compiling the
* demo program with the MICRO-C DOS compiler.
*/
/*
* Report a disk error
*/
disk_error(code)
int code;
{
printf("Disk error - Code: %04x\n", code);
exit(-1);
}
/*
* Read a sector from the disk drive
*/
read_sector(drive, sector, buffer) asm
{
PUSH DS ; Save DS
POP ES ; Set ES
MOV BX,4[BP] ; Get buffer
MOV AX,6[BP] ; Get sector
XOR DX,DX ; Zero high
DIV WORD PTR _sectrk; Calculate track
MOV CL,DL ; CL = sector
INC CL ; 1-
XOR DX,DX ; Zero high
DIV WORD PTR _numhead; Compute head
MOV CH,AL ; CH = cylinder
MOV DH,DL ; DH = head
MOV DL,8[BP] ; DL = drive
MOV DI,3 ; Try three times
read1: MOV AX,0201h ; Read 1 sector
INT 13h ; Call BIOS
JNC read2 ; Success
DEC DI ; Reduce count
JNZ read1 ; Keep trying
PUSH AX ; Pass parameter
CALL _disk_error ; Report an error
POP AX ; Clean stack
read2: XOR AX,AX ; Zero return
}
/*
* Write a sector to the disk drive
*/
write_sector(drive, sector, buffer) asm
{
PUSH DS ; Save DS
POP ES ; Set ES
MOV BX,4[BP] ; Get buffer
MOV AX,6[BP] ; Get sector
XOR DX,DX ; Zero high
DIV WORD PTR _sectrk; Calculate track
MOV CL,DL ; CL = sector
INC CL ; 1-
XOR DX,DX ; Zero high
DIV WORD PTR _numhead; Compute head
MOV CH,AL ; CH = cylinder
MOV DH,DL ; DH = head
MOV DL,8[BP] ; DL = drive
MOV DI,3 ; Try three times
write1: MOV AX,0301h ; Write 1 sector
INT 13h ; Call BIOS
JNC write2 ; Success
DEC DI ; Reduce count
JNZ write1 ; Keep trying
PUSH AX ; Pass parameter
CALL _disk_error ; Report an error
POP AX ; Clean stack
write2: XOR AX,AX ; Zero return
}
/*
* Sample Main program (Not part of MDCFS) to demonstrate reading,
* writing and deleteing files. This also uses the standard file
* I/O of the MICRO-C DOS compiler, and will not run stand-alone.
*
* Demo command syntax:
* MCDFS W <file> - Copy file from current DOS dir to floppy
* MCDFS R <file> - Copy file from floppy to current DOS dir
* MCDFS D <file> - Delete file from floppy.
*
* All accesss to the floppy are performed via MCDFS.
*/
main(argc, argv)
int argc;
char *argv[];
{
int c;
struct Fblock *fp;
FILE *xfp;
open_drive(0); /* Change to (1) for drive B: */
switch((argc > 2) ? toupper(*argv[1]) : 0) {
case 'R' : /* Read file from floppy drive */
if(!(fp = open_file(argv[2], READ)))
abort("Couldn't read MDCFS file");
xfp = fopen(argv[2], "wbvq");
while((c = read_byte(fp)) >= 0)
putc(c, xfp);
close_file(fp);
fclose(xfp);
c = 0; /* Disk has not been modified */
break;
case 'W' : /* Write file to floppy drive */
xfp = fopen(argv[2], "rvbq");
if(!(fp = open_file(argv[2], WRITE)))
abort("Couldn't write MDCFS file");
while((c = getc(xfp)) >= 0)
write_byte(c, fp);
fclose(xfp);
close_file(fp);
c = -1; /* Note that disk may have been written */
break;
case 'D' : /* Delete file from floppy drive */
delete_file(argv[2]);
c = -1; /* Note that disk may have been written */
break;
default:
abort("Use: MDCFS (Read/Write/Delete) <filename>"); }
if(c) {
printf("\nNote: Since MDCFS bypasses DOS completely, DOS will be unaware\n");
printf("of any changes to the disk... Due to DOS buffering, files written\n");
printf("may not appear in DOS 'dir' command, or may have their sizes\n");
printf("reported incorrectly... Press CONTROL-C to force DOS to flush\n");
printf("its buffers before accessing the floppy disk"); }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -