#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
#include "sysp.h"

void main(int argc, char *argv[]);
void show(DFCB far *);

void main(int argc, char *argv[]) {

	 CVT far *cvt;
	 DFT far *dft;
	 unsigned i,j,k;
	 DFCB far *dfcb, far *file_dfcb;
	 int handle, flag, disk;

	 BOOT far *boot_rec;
	 int status;
	 char *buf;

	 char drive[_MAX_DRIVE], dir[_MAX_DIR];
	 char fname[_MAX_FNAME], ext[_MAX_EXT];
	 char name[12];

	 printf("Информация об открытых файлах DOS\n"
			  "Copyright Frolov A. (C),1990\n");

	 printf("Исследуем расположение файла '%s'\n", argv[1]);

// Открываем файл, для которого будем получать список кластеров

	 handle = open(argv[1], O_BINARY);
	 if(handle == 0) {
		printf("Ошибка при открытии файла!\n");
		exit(-1);
	 }

// Разбиваем путь файла на составляющие компоненты:
//   - буква диска;
//   - каталог;
//   - имя файла;
//   - расширение имени

	 _splitpath(argv[1], drive, dir, fname, ext);

// Комбинируем строку из имени и расширения

	 strcpy(name,fname);
	 for(i=0; i<8; i++) {
		if(name[i] == 0) break;
	 }
	 for(; i<8; i++) name[i] = ' ';
	 name[8] = 0;
	 strcat(name, &ext[1]);

// Преобразуем строку имени в заглавные буквы

	 strupr(name);

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

	 drive[0] = toupper(drive[0]);
	 disk = drive[0] - 'A';

	 printf("%s - %s - %s - %s : %s\n",
		drive, dir, fname, ext, name);


	 cvt=get_mcvt();     // Адрес векторной таблицы связи
	 dft=get_fdft(cvt);  // Адрес начала таблицы файлов

// Сбрасываем флаг поиска файла

	 flag = 0;

	 for(;;) {
		if(dft == (DDCB far *)0) break;  // Конец таблицы файлов

		i=dft->file_count;

		for(j=0;j<i;j++) {   // Цикл по файловым управляющим блокам

			dfcb=(&(dft->dfcb))+j; // Адрес DFCB файла

// Ищем файл в таблице открытых файлов

			k = memcmp(name,dfcb->filename,11);
			if(k == 0) {

				printf("Файл найден!\n");
				printf("\nDFCB файла: %Fp\n\n",dfcb);

// Запоминаем адрес таблицы для найденного файла

				file_dfcb = dfcb;

// Показываем содержимое таблицы для найденного файла

				show(file_dfcb);
				flag = 1;
				break;
			}

		 }
		 dft=get_ndft(dft);

		 if(flag == 1) break;
	 }

	 if(flag == 0) {
		printf("Файл не найден");
		close(handle);
		exit(-1);
	 }

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

	 boot_rec = malloc(sizeof(*boot_rec));

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

	 status = getboot((BOOT far*)boot_rec, disk);

// Вычисляем размер кластера в байтах

	 i = boot_rec->bpb.clustsize * boot_rec->bpb.sectsize;
	 printf("\nРазмер кластера, байтов : %d",i);

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

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

	 buf = malloc(i);

	 printf("\nСписок кластеров файла:\n");

// Читаем файл по кластерам, выводим номер
// последнего прочитанного кластера, который
// берем из таблицы файлов

	 for(;;) {

		read(handle, buf, i);
		if(eof(handle)) break;
		printf("%d ",file_dfcb->last_clu);

	 }

	 close(handle);
	 free(boot_rec);
	 free(buf);
	 exit(0);
}

// Функция для отображения содержимого таблицы файлов

void show(DFCB far *dfcb) {

	int k;

	printf("Имя файла: ");
	for(k=0;k<11;k++) {
		putchar(dfcb->filename[k]);
	}

	printf("\nКоличество file handles:       %d\n"
		"Режим доступа:                 %d\n"
			"Поле reserv1:                  %04X\n"
			"Информация об устройстве:      %04X\n"
			"Адрес драйвера:                %Fp\n"
			"Начальный кластер:             %d\n"
			"Время:                         %04X\n"
			"Дата:                          %04X\n"
			"Размер файла в байтах:         %ld\n"
			"Текущее смещение в файле:      %ld\n"
			"Поле reserv2:                  %04X\n"
			"Последний прочитанный кластер: %d\n"
			"Сегмент PSP владельца файла:   %04X\n"
			"Поле reserv7:                  %d\n"
			"--------------------------------------\n\n",
			dfcb->handl_num,
			dfcb->access_mode,
			dfcb->reserv1,
			dfcb->dev_info,
			dfcb->driver,
			dfcb->first_clu,
			dfcb->time,
			dfcb->date,
			dfcb->fl_size,
			dfcb->offset,
			dfcb->reserv2,
			dfcb->last_clu,
			dfcb->ownr_psp,
			dfcb->reserv7);
}
