#include <stdio.h>
#include <malloc.h>
#include <dos.h>
#include "sysp.h"

void main(void);
void main(void) {

  BOOT _far *boot_rec;
  int i,j, k, status, fat_sectors;
  long total_sectors;
  int fat, root_begin, root_sectors;
  char drive;
  unsigned _far *fat_buffer;
  FITEM _far *root_buffer, _far *rptr;

  union REGS reg;
  struct SREGS segreg;


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


// Заказываем буфер для чтения BOOT-записи.
// Адрес буфера присваиваем FAR-указателю.

  boot_rec = _fmalloc(sizeof(*boot_rec));

// Запрашиваем диск, для которого необходимо
// выполнить чтение загрузочной записи.

  printf("\n"
			"\nВведите обозначение диска, для просмотра"
			"\nкорневого каталога (A, B, ...):");

  drive = getche();

// Вычисляем номер дисковода

  drive = toupper(drive) - 'A';

// Читаем загрузочную запись в буфер

  status = getboot((BOOT _far*)boot_rec, drive);

// Если произошла ошибка (например, неправильно указано
// обозначение диска), завершааем работу программы

  if(status) {
		printf("\nОшибка при чтении BOOT-сектора");
		exit(-1);
  }

// Определяем формат таблицы FAT

  total_sectors = boot_rec->bpb.totsecs;

// Если мы работаем с расширенным разделом диска,
// общее количество секторов на диска берем из
// расширенного PBP

  if(total_sectors == 0) total_sectors = boot_rec->bpb.drvsecs;

// Формат FAT определяем исходя из общего
// количества секторов на логическом диске

  if(total_sectors > 20740) {
		printf("\nFAT имеет 16-битовый формат");
		fat=16;
  }
  else {
		printf("\nFAT имеет 12-битовый формат");
		fat=12;
  }

// Определяем количество секторов, занимаемых FAT

  fat_sectors = boot_rec->bpb.fatsize;

// Заказываем буфер для FAT

  fat_buffer = _fmalloc(fat_sectors * boot_rec->bpb.sectsize);

// Вычисляем номер первого сектора FAT

  j = boot_rec->bpb.ressecs;

// Читаем FAT в буфер fat_buffer

// Заполняем регистровые структуры для вызова
// прерывания DOS INT 25h

	 reg.x.ax = drive;
	 reg.x.bx = FP_OFF(fat_buffer);
	 segreg.ds = FP_SEG(fat_buffer);
	 reg.x.cx = fat_sectors;
	 reg.x.dx = j;
	 int86x(0x25, &reg, &reg, &segreg);

// Извлекаем из стека оставшееся там после
// вызова прерывания слово

	 _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 = _fmalloc(root_sectors * boot_rec->bpb.sectsize);


// Читаем корневой каталог в буфер root_buffer

	 reg.x.ax = drive;
	 reg.x.bx = FP_OFF(root_buffer);
	 segreg.ds = FP_SEG(root_buffer);
	 reg.x.cx = root_sectors;
	 reg.x.dx = root_begin;
	 int86x(0x25, &reg, &reg, &segreg);
	 _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(" %-5d   %lu",
			rptr->cluster_nu,
			rptr->size);

	}

// Освобождаем буфера

  _ffree(root_buffer);
  _ffree(boot_rec);
  _ffree(fat_buffer);
}
