Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

NtReadFile NtFsControlFile. Разница возвращаемых данных.


Страницы:   1 2 3

Riply ©   (2008-04-04 21:34:00) 

Здравствуйте !
Давным давно я поднимала этот вопрос. Тогда ответа не нашли.
Может сейчас у кого-нибудь будут идеи, как объяснить(понять) следующий факт:

Читаем файловую запись двумя способами: NtReadFile и NtFsControlFile(..., FSCTL_GET_NTFS_FILE_RECORD, ...).
В первом случае получаем мусор, во втором корректные данные.
(какой именно FileRecord прочитала NtFsControlFile - проверяется).
Эффект довольно трудно, но воиспроизводим (я приводила диск в "непотребное" состояние :)

Когда я столкнулась с разницой между прямым чтением и чтении через API, подумла
что вот она - причина и списала этот вопрос на всевозможные "кеширования" и "буферизации".

Но сейчас, похоже, это объяснение не проходит.
Во всяком случае, эффект наблюдается (на тех одних и тех же файловых объектах)
как после длительной работы, так и сразу после холодного рестарта.

Очень бы хотелось понять происходящее. Кто что думает: какие могут быть причины ?


Riply   (2008-04-05 21:41:00) [21]

> [22] guav © (05.04.08 21:20)
> 1. 221120 судя по R.P. $Mft не принадлежит MFT.
Не принадлежит, учитывая фрагментированность. Если бы ее не было, то принадлежал бы.
Конечно это мало что значит, но всеже.
> Ошибка уже совершена когда это значение получено.
Это один из большого списка Lcn-ов, который так себя ведет.
К тому же этот список я получала как "законным" способом, так и "своим".
Они (списки) совпадают.
> 2. Формула, позволяющая получить из него номер в MFT - ошибочна.
Это не формула (как формула, она конечно ошибочна) а только
описание того что я с ним, кроме всего прочего, пыталась делать.
> 3. Для нумерации файлов и файлрекордов LCN не используется, используется MFT_SEGMENT_REFERENCE.
Это я знаю, но какого черта, если на него посмотреть
как на MFT_SEGMENT_REFERENCE, то получим то что нужно ?

Попробую еще раз описать, что происходит:
Сканируется "подпорченый" диск.
На директории, описание которой выше, при переборе Lcn-ов
на Lcn равным 221120 спотыкаемся (считываемая структура не валидна).
Начинаем изучать этот чертов 221120-ый. Почему именно на нем и чем он отличается от других ?
В ходе этого дела, выясняется, что если предпринять попытки из [18]
то мы получаем именно то, что и должны были получить, если бы этот LCN
"считывался" так же как и все остальные его собратья :)


guav   (2008-04-05 21:36:00) [22]

Если я не ошибся в анализе твоих заблуждений, то то что ты хочешь найти в 221120 находится в 306221 :)


guav   (2008-04-05 21:20:00) [23]

Ещё раз, на всякий случай:
1. 221120 судя по R.P. $Mft не принадлежит MFT. Ошибка уже совершена когда это значение получено.
2. Формула, позволяющая получить из него номер в MFT - ошибочна.
3. Для нумерации файлов и файлрекордов LCN не используется, используется MFT_SEGMENT_REFERENCE.


guav   (2008-04-05 21:09:00) [24]

> [20] Riply ©   (05.04.08 20:49)

Каким образом получено значение 221120 ?
Тебе приснилось что этот LCN соотвествует каким-то файлрекордам ?

"Подтверждение" вроде
> FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster)
> div BytesPerFileRecordSegment;

читается - не годится, т.к. формула предполагает то чего нету - непрерывность MFT.


Riply   (2008-04-05 20:49:00) [25]

>  [19] guav ©   (05.04.08 20:08)
> И более интересный вопрос - откуда взялось 221120 ?
Как откуда ? Мы об этом "сбойном" Lcn`е толко и говорим. :)

Просто, пока я не добралась до Delphi,
пыталась "на пальцах" показать, что я делала в программе для проверки.


guav   (2008-04-05 20:08:00) [26]

> В программе я поступаю так: высчитываю
> FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster)
> div BytesPerFileRecordSegment;

Это что ? Где ты это взяла ?
И более интересный вопрос - откуда взялось 221120 ?


> Кстати 221120 попадает в диапазон
> [MftStartLcn < 221120 < MftStartLcn + MftValidDataLength
> div BytesPerCluster]

И что ?


> Получается, что FileRefNumber...

Нет, не получается.

Не знаю как тебе ещё объяснить...
Что по-твоему значат поля File Reference ?


Riply   (2008-04-05 19:47:00) [27]

[17] guav © (05.04.08 18:11)
> > Значание TotalAllocated, при _CompressionUnit = 0 неопределено.

> Я бы не так сказал, не неопределено, а его просто нет, структура на него меньше.
> Разница между "не определно" и "нет" может быть важна.

Спасибо, учту. То что "не определено" я стырила у линуксоидов.
Скорее всего, не сумела правильно перевести.

> Т.е. это действиетльно LCN принадлежащий $Mft по твоему ?

Я уже не знаю что и думать :(
В программе я поступаю так: высчитываю
FileRefNumber := ((221120 - MftStartLcn) * BytesPerCluster) div BytesPerFileRecordSegment;
Кстати 221120 попадает в диапазон
[MftStartLcn < 221120 < MftStartLcn + MftValidDataLength div BytesPerCluster]
Т.е. если забыть про фрагментацию MFT, то он ей принадлежит.
Далее, по FileRef успешно считываю валидный FSCTL_GET_NTFS_FILE_RECORD
из которого получаю список, примерно из 80 файлов,
причем именно тех, которые и были "потеряны" .
Ни одним больше, ни одним меньше.

> Какой же тогда MFT номер у 221120 ?

Получается, что FileRefNumber...
Возможно нерезидентные данные, которые она вынуждена в себе
хранить учитываются каким-то особым образом ?


guav   (2008-04-05 18:11:00) [28]

> Значание TotalAllocated, при _CompressionUnit = 0 неопределено.

Я бы не так сказал, не неопределено, а его просто нет, структура на него меньше. Разница между "не определно" и "нет" может быть важна.


> [15] Riply ©   (05.04.08 16:13)


> Для получения "абсолютного смещения на диске" его надо умножить
> на BytesPerCluster

Т.е. это действиетльно LCN принадлежащий $Mft по твоему ?
Ок.
Берём R.P. $Mft из [8] и пытаемся найти его номер. Даже Dephi под рукой не надо, используем Calc:

lastLcn = fisrtLcn + count – 1
_221120_in = (fisrtLcn<=221120) AND (221120<=lastLcn)

firstLcn count lastLcn _221120_in
175371 45504 220874 ЛОЖЬ
220883 8 220890 ЛОЖЬ
305974 8697 314670 ЛОЖЬ
453599 8696 462294 ЛОЖЬ
403347 2639 405985 ЛОЖЬ
406065 8 406072 ЛОЖЬ
406123 440 406562 ЛОЖЬ
406577 8 406584 ЛОЖЬ


Какой же тогда MFT номер у 221120 ?
У кого в программе ошибка ?


Riply   (2008-04-05 17:44:00) [29]

Выскажу я одно предположение, только чур не смеяться.
Бывает несу чушь. Это от недосыпа :)

Трактовка Lcn`ов, возвращаемых FSCTL_GET_RETRIEVAL_POINTERS,
и, соответственно, алгоритм их чтения могут зависеть от состояния MFT.

Например, если пользователь так загнал MFT, что та аж вся форматированная
да еще и вынужденная хранить в себе данные, которые должны быть не резидентными. :)


Riply   (2008-04-05 16:13:00) [30]

> [13] guav ©   (05.04.08 16:04)
> В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?
Для получения "абсолютного смещения на диске" его надо умножить на BytesPerCluster


Riply   (2008-04-05 16:10:00) [31]

> [13] guav ©   (05.04.08 16:04)
> Кстати ни разу это ни TotalAllocated

Совершенно верно.
Значание TotalAllocated, при _CompressionUnit = 0 неопределено.
Руки не доходят подправить функцию парсинга,
чтобы она не выводила TotalAllocated при нулевом CompressionUnit


guav   (2008-04-05 16:04:00) [32]

> Может быть что в одном файлрекорде несколько кластеров :)

Может. Но я про конкретный случай.
В любом случае, 221120 на File Reference не похож, где тут последовательный номер ?

> TypeCode AT_DATA


> TotalAllocated 3531575320579784755

Кстати ни разу это ни TotalAllocated
переводим в 0x это 3102AD0B00B1C033
00B1C0 = 45504
02AD0B = 175371
, т.е.

> Index 0 Lcn 175371 Count 45504


Riply   (2008-04-05 15:58:00) [33]

> [11] guav ©   (05.04.08 15:36)
> Файлы нумеруются не через LCN
> Ссылка на файл - это то, что в MSDN называется MTF_SEGMENT_REFERENCE,
> или File Reference в документации линукса.

Sorry. Просто оговорилась.

> т.к. в одном кластере находятся несколько файлрекордов.

Это не всегда так.
Может быть что в одном файлрекорде несколько кластеров :)

Я сейчас за компьютером, у которого есть диск (NTFS)
с такими характеристиками :
BytesPerSector   512
BytesPerCluster   512
BytesPerFileRecordSegment 1024
ClustersPerFileRecordSegment 2

> Приведи значение этого File Reference
Хорошо. Только доберусь до компьютера, где Delphi установлена.


guav   (2008-04-05 15:36:00) [34]

Файлы нумеруются не через LCN, т.к. в одном кластере находятся несколько файлрекордов. Ссылка на файл - это то, что в MSDN называется MTF_SEGMENT_REFERENCE, или File Reference в документации линукса.

Вот есть у тебя File Reference, передаваемый в FSCTL_GET_NTFS_FILE_RECORD. Из него же ты получаешь смещение в MFT и соответственно смещение на диске. Приведи значение этого File Reference, значение смещения, по которому читаешь и результат что прочитывается в обоих случаях.


Riply   (2008-04-05 15:10:00) [35]

>  [9] Riply ©   (05.04.08 15:06)

Смайлик не тот. Должен быть :(


Riply   (2008-04-05 15:06:00) [36]

> [8] Riply ©   (05.04.08 15:02)

Опять форматирование "съехало" :)
Кодом надо было выделять, наверное.


Riply   (2008-04-05 15:02:00) [37]

> [7] guav © (05.04.08 11:31)
> То есть, ты смотришь содержимое :$I30:$INDEX_ALLOCATION этой директории,
> и потом проходишь по всем файлреференсам оттуда ?

Именно так.

> Или это R.P. для её ::$Data ?

Нет.

> Давай не так.

Давай :)

(Сканируется та же директория, только я ошиблась указывая "сбойный" LCN
На самом деле он - 221120 )

Вот первые данные:

Сам диск:

FSCTL_GET_NTFS_VOLUME_DATA
VolumeSerialNumber  7 967 016 108 593 429 977
NumberSectors   2 104 451
TotalClusters   526 112
FreeClusters   104
TotalReserved   0
BytesPerSector   512
BytesPerCluster   2048
BytesPerFileRecordSegment 1024
ClustersPerFileRecordSegment 0
MftValidDataLength  135 168 000
MftStartLcn   175 371
Mft2StartLcn   263 056
MftZoneStart   438 432
MftZoneEnd   438 560
ExtendedData 3.1


Часть атрибутов его MFT:

\??\D:\$MFT
MultiSectorHeader
NTFS_RECORD_HEADER
cbType  FILE
UpdateSequenceArrayOffset 48
UpdateSequenceArraySize 3
_Usn64 100853279
SequenceNumber 1
LinkCount  1
AttributesOffset 56
Flags  File
BytesInUse 472
BytesAllocated 1024
BaseFileRecordSegment
SegmentNumberLowPart 0
SegmentNumberHighPart 0
SequenceNumber 0
NextAttributeNumber 6
SelfRecord 0

TypeCode AT_STANDARD_INFORMATION
RecordLength 96
FormCode RESIDENT
Name  
Flags  STANDART
Instance 0
ValueLength 72
ValueOffset 24
_Flags Not Indexed: 0
CreationTime 2008.04.03 20.34.01
ChangeTime 2008.04.03 20.34.01
LastWriteTime 2008.04.03 20.34.01
LastAccessTime 2008.04.03 20.34.01
FileAttributes HS
MaxVersionsNum 0
VersionNum 0
ClassId 0
OwnerId  0
SecurityId 256
QuotaCharge 0
Usn64  0

TypeCode AT_FILE_NAME
RecordLength 104
FormCode RESIDENT
Name  
Flags  STANDART
Instance 3
ValueLength 74
ValueOffset 24
_Flags Indexed: 1
ParentDirectory
SegmentNumberLowPart 5
SegmentNumberHighPart 0
SequenceNumber 5
CreationTime 2008.04.03 20.34.01
ChangeTime 2008.04.03 20.34.01
LastWriteTime 2008.04.03 20.34.01
LastAccessTime 2008.04.03 20.34.01
AllocatedSize 16 384
DataSize  16 384
FileAttributes HS
AlignmentOrReserved 0
FILE_NAME_WIN32_AND_DOS = $MFT

TypeCode AT_DATA
RecordLength 112
FormCode NONRESIDENT
Name  
Flags  STANDART
Instance 1
LowestVcn 0
HighestVcn 65999
MappingPairsOffset 64
_CompressionUnit 0
AllocatedLength  135168000
FileSize  135168000
ValidDataLength 135168000
TotalAllocated 3531575320579784755

TypeCode AT_BITMAP
RecordLength 96
FormCode NONRESIDENT
Name  
Flags  STANDART
Instance 5
LowestVcn 0
HighestVcn 9
MappingPairsOffset 64
_CompressionUnit 0
AllocatedLength  20480
FileSize  16504
ValidDataLength 16504
TotalAllocated 8575189053052944689

RETRIEVAL_POINTERS_BUFFER
ExtentCount 8
Index 0 Lcn 175371 Count 45504
Index 1 Lcn 220883 Count 8
Index 2 Lcn 305974 Count 8697
Index 3 Lcn 453599 Count 8696
Index 4 Lcn 403347 Count 2639
Index 5 Lcn 406065 Count 8
Index 6 Lcn 406123 Count 440
Index 7 Lcn 406577 Count 8


Насчет самого объекта не поняла:
тебя интересуют данные того на кого указывает "сбойный" LCN
или данные того объекта, который выдает "сбойный" LCN ?


guav   (2008-04-05 11:31:00) [38]

> Пробегаюсь по ее Lcn-ам.

То есть, ты смотришь содержимое :$I30:$INDEX_ALLOCATION этой директории, и потом проходишь по всем файлреференсам оттуда ?
Или это R.P. для её ::$Data ?

Давай не так. Приведи пример с одним файлом, у которого известен:
1. Результат чтения через FSCTL_GET_NTFS_FILE_RECORD
2. Результат прямого чтения (с указанием читаемого смещения)
3. Результат FSCTL_GET_RETRIEVAL_POINTERS для $Mft, именно результат FSCTL_GET_RETRIEVAL_POINTERS а не своей работы (открывать можно с правами 0, тогда откроется)
4. Параметры ФС: размер кластера, размер сектора, размер файлрекорда

После этого можно внимательно сопоставить RETRIEVAL_POINTERS для $Mft с читаемым кластером, думаю тут и будет ошибка.


Riply   (2008-04-05 09:48:00) [39]

> [5] Германн ©   (05.04.08 02:16)
> Это что? Такая "шутка юмора"?

Нет. Это просто ачепятка :)


Германн   (2008-04-05 02:16:00) [40]


> Riply ©   (05.04.08 00:24) [3]


> Ты учитывай, что у меня Dual-up :)
>

Это что? Такая "шутка юмора"?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо