MS-DOS для программиста

         

Программа FATSCAN


Программа FATSCAN (листинг 2.4) предназначена для исследования подкаталогов корневого каталога НМД, а также для демонстрации основных приемов работы с таблицей размещения файлов FAT . Вы можете использовать ее для исследования структуры каталогов диска.

Листинг 2.4. Файл rootview\ rootview.cpp

// // Для этой программы требуется модель // памяти Large // #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <malloc.h> #include <dos.h> #include <bios.h> #include <ctype.h> #include <string.h>

typedef struct _EBPB_ { unsigned sectsize; char clustsize; unsigned ressecs; char fatcnt; unsigned rootsize; unsigned totsecs; char media; unsigned fatsize; unsigned seccnt; unsigned headcnt; unsigned hiddensec_low; unsigned hiddensec_hi; unsigned long drvsecs; } EBPB;

typedef struct _BOOT_ { char jmp[3]; char oem[8]; EBPB bpb; char drive; char reserved; char signature; unsigned volser_lo; unsigned volser_hi; char label[11]; char fat_format[8]; char boot_code[450]; } BOOT;

typedef struct _FTIME_ { unsigned sec : 5, min : 6, hour : 5; } FTIME; typedef struct _FDATE_ { unsigned day : 5, month : 4, year : 7; } FDATE; typedef struct _FITEM_ { char name[8]; char ext[3]; char attr; char reserved[10]; FTIME time; FDATE date; unsigned cluster_nu; unsigned long size; } FITEM;

int getboot(BOOT far *boot, int drive); int fat(char far *b_fat, int t_fat, unsigned idx);

union REGS reg; struct SREGS segreg;

struct { unsigned long first_sect; unsigned nsect; void far* buf; } cb;

int main(void) { BOOT *boot_rec; int i,j, k, status, fat_sectors; unsigned total_sectors; int ffat, root_begin, root_sectors; char drive; unsigned far *fat_buffer; FITEM far *root_buffer, far *rptr; char cbuf[128]; char far *clust_buffer; unsigned cur_clust;

printf("\n\nЧтение каталогов логического диска" "\n (C)Фролов А., 1995\n");

// Заказываем буфер для чтения загрузочной записи boot_rec = (BOOT*)malloc(sizeof(BOOT)); if(boot_rec == NULL) { printf("\nМало памяти"); return -1; }


// Запрашиваем диск, для которого необходимо // выполнить чтение загрузочной записи. printf("\nВведите обозначение диска (C, D, ...):"); drive = getche(); drive = toupper(drive) - 'A'; if(drive < 2) { printf("\nМожно указывать только НМД"); free(boot_rec); return(-1); }

// Читаем загрузочную запись в буфер status = getboot((BOOT _far*)boot_rec, drive); if(status) { printf("\nОшибка при чтении загрузочного сектора"); free(boot_rec); return(-1); }

// Определяем формат таблицы FAT total_sectors = boot_rec->bpb.totsecs;



// Если мы работаем с расширенным разделом диска, // общее количество секторов на диска берем из // расширенного PBP if(total_sectors == 0) total_sectors = boot_rec->bpb.drvsecs;

// Определяем формат FAT if(!strncmp(boot_rec->fat_format, "FAT16", 5)) { printf("\nFAT имеет 16-битовый формат"); ffat = 16; } else { printf("\nFAT имеет 12-битовый формат"); ffat = 12; }

// Определяем количество секторов, занимаемых FAT fat_sectors = boot_rec->bpb.fatsize;

// Заказываем буфер для FAT fat_buffer = (unsigned int*) farmalloc((long)fat_sectors * boot_rec->bpb.sectsize); if(fat_buffer == NULL) { printf("\nМало памяти"); free(boot_rec); return -1; }

// Вычисляем номер первого сектора FAT j = boot_rec->bpb.ressecs;

// Читаем FAT в буфер fat_buffer // Заполняем регистровые структуры для вызова // прерывания DOS INT 25h cb.first_sect = j; cb.nsect = fat_sectors; cb.buf = (void far*)fat_buffer;

_BX = FP_OFF(&cb); _DS = FP_SEG(&cb); _CX = 0xffff; _DX = 0; _AX = drive; asm int 25h asm pop ax

// Вычисляем номер первого сектора корневого каталога root_begin = j + fat_sectors * boot_rec->bpb.fatcnt;

// Вычисляем длину корневого каталога root_sectors = (boot_rec->bpb.rootsize * 32) / boot_rec->bpb.sectsize;

// Заказываем буфер для корневого каталога root_buffer = (FITEM far *) farmalloc(root_sectors * boot_rec->bpb.sectsize); if(root_buffer == NULL) { printf("\nМало памяти"); free(boot_rec); farfree(fat_buffer); return -1; }



cb.first_sect = root_begin; cb.nsect = root_sectors; cb.buf = (void far*)root_buffer; _BX = FP_OFF(&cb); _DS = FP_SEG(&cb); _CX = 0xffff; _DX = 0; _AX = drive; asm int 25h asm pop ax

// Показываем содержимое корневого каталога printf("\n" "\nИмя файла Аттр. " "Дата Время Кластер Размер" "\n------------ ----- " "---------- -------- ------- ------");

for(rptr = root_buffer;;rptr++) { printf("\n");

// Признак конца каталога - нулевой байт в начале // имени файла if(rptr->name[0] == 0) break;

// Выводим содержимое дескриптора файла for(i=0; i<8; i++) printf("%c",rptr->name[i]); printf("."); for(i=0; i<3; i++) printf("%c",rptr->ext[i]); printf(" %02X %02d-%02d-%02d %02d:%02d:%02d ", rptr->attr, rptr->date.day, rptr->date.month, rptr->date.year + 1980, rptr->time.hour, rptr->time.min, rptr->time.sec * 2); printf(" %-6ld %lu", (long)rptr->cluster_nu, (long)rptr->size); }

// Получаем буфер для чтения кластеров каталога clust_buffer = (char far*) farmalloc(boot_rec->bpb.clustsize * boot_rec->bpb.sectsize);

if(clust_buffer == NULL) { printf("\nМало памяти"); farfree(root_buffer); free(boot_rec); farfree(fat_buffer); return -1; }

printf("\nНомер первого кластера каталога:"); gets(cbuf); cur_clust = atol(cbuf);

// Переменная k используется в качестве флага. // При первом просмотре каталога ее значение равно 0, // затем эта переменная устанавливается в 1. k = 0;

for(;;) { // Сохраняем номер кластера каталога unsigned long j = cur_clust;

// Вычисляем номер следующего кластера, распределенного // каталогу cur_clust = fat((char far*)fat_buffer, ffat, cur_clust); printf("%d ", cur_clust);

// Читаем кластер в буфер clust_buffer cb.first_sect = root_begin + root_sectors + ((j-2)*boot_rec->bpb.clustsize); cb.nsect = boot_rec->bpb.clustsize; cb.buf = (void far*)clust_buffer;

_BX = FP_OFF(&cb); _DS = FP_SEG(&cb); _CX = 0xffff; _DX = 0; _AX = drive; asm int 25h asm pop ax



// Показываем содержимое каталога rptr = (FITEM far *)clust_buffer;

// Первый дескриптор в каталоге указывает на // этот же каталог. В поле имени первого дескриптора // находится строка ". ". // Этот факт можно использовать // для проверки каталога. Если вы по ошибке указали // номер кластера, не принадлежащего каталогу, // программа завершит работу с сообщением об ошибке. if(k == 0) { k = 1; if(_fstrncmp(rptr->name,". ",8) != 0) { printf("\nЭто не каталог !"); farfree(root_buffer); free(boot_rec); farfree(fat_buffer); farfree(clust_buffer); return(-1); } }

printf("\n" "\nИмя файла Аттр. Дата " "Время Кластер Размер" "\n------------ ----- ---------- " "-------- ------- ------");

for(;;rptr++) { printf("\n");

// Признак конца каталога - нулевой байт в начале // имени файла if(rptr->name[0] == 0) break;

// Выводим содержимое дескриптора файла for(i=0; i<8; i++) printf("%c",rptr->name[i]); printf("."); for(i=0; i<3; i++) printf("%c",rptr->ext[i]); printf(" %02X %02d-%02d-%02d %02d:%02d:%02d ", rptr->attr, rptr->date.day, rptr->date.month, rptr->date.year + 1980, rptr->time.hour, rptr->time.min, rptr->time.sec * 2); printf(" %-6ld %lu", (long)rptr->cluster_nu, (long)rptr->size); }

// Если этот кластер - последний из распределенных // каталогу, завершаем работу программы if((cur_clust == 0xfff) (cur_clust == 0xffff)) break; }

farfree(root_buffer); free(boot_rec); farfree(fat_buffer); farfree(clust_buffer); return 0; }

int getboot(BOOT far *boot, int drive) { cb.first_sect = 0; cb.nsect = 1; cb.buf = (void far*)boot;

_BX = FP_OFF(&cb); _DS = FP_SEG(&cb); _CX = 0xffff; _DX = 0; _AX = drive; asm int 25h asm pop ax asm jc err

return 0; err: return 1; }

/** * fat * * Выбрать элемент из FAT * * Функция выбирает элемент с заданным номером из таблицы * размещения файлов FAT . Формат FAT передается * функции как параметр * * int fat(b_fat, t_fat, idx); * * char far *b_fat - буфер, содержащий FAT * * int t_fat - формат FAT (12 или 16) * * unsigned idx - номер элемента FAT , который * должен быть выбран * **/

int fat(char far *b_fat, int t_fat, unsigned idx) { div_t clust_nu ; int cluster;

if(t_fat == 12) { clust_nu = div(idx * 3, 2);

if(clust_nu.rem != 0) cluster = (*((int far*)(b_fat + clust_nu.quot)) >> 4) & 0xfff; else cluster = *((int far*)(b_fat + clust_nu.quot)) & 0xfff; } else if(t_fat == 16) { cluster = *((int far*)(b_fat + idx * 2)); } else { printf("Ошибка в формате FAT \n"); exit(-100); } return(cluster); }


Содержание раздела