Консультация № 184461
15.11.2011, 22:43
0.00 руб.
0 4 0
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Пишу в Microsoft Visual 2010 для 32битного. (Windows 7).
Задача заключается в следующем:
Программа выдает на экран и записывает в файл в удобной для восприятия форме схему размещения на диске заданного пользователем файла по кластерам, логическим и физическим секторам.
Ограничение или условия как бы опишу:
1. Выполняется только для fat16.
2. Выполняется только на флешках!!!.( Это очень строго во избежание всяких повреждений MBR.)
А теперь что у меня как бы получилось и до чего мозг немного докатился.
Вот код
Код:

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <locale>
#include <iostream>
#pragma warning(disable : 4996)

HANDLE hDisk = NULL;
BYTE Buffer[512];
BYTE BootRec[512];
char nFind[25];
char fName[25];
using namespace std;

bool ReadSector(int n, BYTE * lpBuf) {

LONG lFilePointer;

lFilePointer = n * 512;

SetFilePointer(hDisk, // handle of file
lFilePointer, // number of bytes to move file pointer
NULL, // address of high-order word of distance to move
FILE_BEGIN // how to move
);

DWORD nCount;
ReadFile(hDisk, lpBuf, 512, &nCount, NULL);
if (nCount != 512) {
return false;
}
return true;
}
void main(void);
void main() {
setlocale(LC_ALL,"RUSSIAN");
hDisk = CreateFile ("\\\\.\\H:",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
0);
if (hDisk == INVALID_HANDLE_VALUE) {
printf("error");
getch();
return;
}
std::cout<<" Введи имя файла: "<<' ';
std::cin>>nFind;


ReadSector(0, BootRec);
int nCopyFat, nFatSectors, nRes, nDirSectors,nLogSector,nHead;
nCopyFat = *(BootRec+16);
nFatSectors = *((WORD*)(BootRec+22));
nRes = *((WORD*)(BootRec+14));
nDirSectors = *((WORD*)(BootRec+17)) * 32 / 512;
//nLogSector = *(BootRec+13);
//nHead = *((WORD*)(BootRec+26))* 32 / 512;


printf ("Число Копий Fat %d\n", nCopyFat);
printf ("Число Секторов в одной копии Fat %d\n", nFatSectors);
printf ("Число резервных секторов %d\n", nRes);
printf ("Максимальное число элементов корневого каталога %d\n", nCopyFat);
//printf ("Число логических секторов %d\n",nLogSector);
//printf ("Число головок(сторон) %d\n",nHead);

int i, j;
char sName[16];
FILE *res = fopen("C:\\result.txt", "w+b");
for (i = 0; i < nDirSectors; i++) {
ReadSector(i + nRes + nFatSectors*nCopyFat, Buffer);
for (j=0; j < 16; j++) {

strncpy(sName, (char*)(Buffer+j*32), 11);
if (sName[0] == 0 || sName[0] == 0xE5) continue;
printf("%s\n", sName);
getch();
//fprintf(res,"%s\n",sName);

}
}
_getch();}


После этого начались вопросы, которые хотелось бы решить.
1. Как прочитать файлы находящиеся в папке. Мне объяснили, что папка содержит следующим номер кластера для чтения, и его ищем в таблице файлов, но компилятор отрицательно говорит со мной когда я это делаю.
Преподаватель сказал, что проще всего пойти через иерархический спуск. (может ошибаюсь в название).
2. Если какой-нибудь способ перевода из нижнего регистра в верхний если при вводе пользователь набрал мелким буквами.(функцию нашел но она не так как бы работает, а писать каждую букву не хотелось бы.)
Необходимо для организации поиска.
3. Я понял как считается логический сектор
<номер логического сектора> = <цилиндр>*<кол-во сторон>*<кол-во секторов на дорожке> + <сторона>*<кол-во секторов на дорожке> + <сектор> – 1.
А физический теперь как определить.
Помогите пожалуйста, любое вдалбливание в мозг информации продвигает ход мыслей.
Вот ссылка на методичку, там есть организация фат16.
Методичка

Обсуждение

Неизвестный
16.11.2011, 09:17
общий
16.11.2011, 09:17
1. Вам необходимо разобрать таблицу каталога. Для этого нужно следующее:
a) Определить структуру элемента таблицы:
struct CatalogItem
{
char FileName[8];
char Extension[3];
unsigned char Attributes;
unsigned char NotUsed[14];
unsigned short StartCluster;
unsigned FileSize;
};
б) Прочитать таблицу в буфер:
ReadSector(?, buffer);
в) Просмотреть каждую запись в цикле и найти очередной компонент заданного пути:
CatalogItem* catalog = reinterpret_cast<CatalogItem*>(buffer);
for (int k = 0; k < ?; ++k)
{
if (catalog[k].FileName[0] == 0) // запись не используется
if (catalog[k].FileName[0] == 0xE5) // запись удалена
// и так далее..
}
г) Если найденный элемент является каталогом, то надо по StartCluster найти таблицу подкаталога и повторить поиск. Если это искомый файл, то найти его размещение по FAT-таблице, начиная с StartCluster.

2. Есть C-функция _strupr и WINAPI функция CharUpperBuff.

3. Цилиндры и дорожки имеют смысл только для дискет.
Все современные накопители, в том числе флешки используют линейную адресацию секторов (то что в вашей методичке называется логическими секторами). Таким образом, задание распечатать физические сектора диска вообще говоря бессмысленно. Можно предложить два выхода:
- распечатать логические сектора диска. Если флешка имеет MBR, то логические сектора тома и
диска будут отличаться на определенное значение (смещение).
- распечатать физические сектора для некоторой выдуманной геометрии диска.


Также могу порекомендовать:
- открывать том только на чтение, т.е. передавать в функцию CreateFile только GENERIC_READ, тогда не надо будет бояться что-то испортить.
- сразу сделать функцию чтения кластера. Любая файловая система работает кластерами, поэтому надо
уметь преобразовывать кластера в сектора тома (или сразу в байтовые смещения).
Неизвестный
17.11.2011, 19:31
общий
Да что в мозг не хочет лезть так и не лезет.
Приведу пример, если не правильно то поправьте.
Допустим мы нашли каталог "Books" мы уверены в том что это каталог, так как отсутствует расширение, следующим шагом является нахождение данного каталога в таблице файлов, то есть ищем кластер с файлами в этой папке и читаем её. ( как бы алгоритм действия )
вот мне почему то кажется что это должны примерно словесно выглядеть так.
Если( имя_папки совпало с именем заданной папке) тогда {
читаем таблицу;
Если есть там эта папка, то смещаемся еще раз кластер и сектор в котором это находится
{ читаем файлы в папке. }

Если логика не правильно, то поправьте.
Неизвестный
17.11.2011, 20:58
общий
Давайте на конкретном примере, пусть на вход дали имя \Books\pushkin.txt. Последовательность действия должна быть такой:
1. Прочитать таблицу корневого каталога, её расположение вычисляется по данным загрузочного сектора.
2. В прочитанной таблице найти запись Books. То, что это каталог определяется по аттирибутам. Файл тоже может не иметь расширения.
3. Прочитать таблицу каталога Books. Первый кластер этой таблицы указан в поле StartCluster записи в корневом каталоге. Остальные кластеры находятся по таблице размещения файлов (FAT).
4. В прочитанной таблице найти запись pushkin с расширением txt.
5. Извлечь цепочку кластеров размещения файла из таблицы FAT начиная со StartCluster найденной записи (Здесь алгоритм аналогичен пункту 3).

Для пунктов 2 и 3 нужно организовать цикл, чтобы программа работала с путями любой вложености.
Неизвестный
17.11.2011, 21:33
общий
вон как теперь понял для чего '.' точка нужна и где её искать, ладно будем пытаться. спасибо за более подробное описание ход действий.
Форма ответа