Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2009.03.15;
Скачать: [xml.tar.bz2];

Вниз

Как удалить файл без восстановления   Найти похожие ветки 

 
guav ©   (2008-03-24 11:42) [40]

> [39] guav ©   (24.03.08 11:36)
> (простой способ воспроизвести [14] - пробовать на сжатом файле).

Сейчас что-то не получается просто сжать и изменять, чтобы файл "переехал". Но явление тоже наблюдал.


 
Riply ©   (2008-03-24 15:09) [41]

> [40] guav ©   (24.03.08 11:42)
> Сейчас что-то не получается просто сжать и изменять, чтобы файл "переехал".
> Но явление тоже наблюдал.

Я уже написала процедуру, рекурсивно создающую дамп Run - ов всех объектов,
содержащихся в директории вместе с их именами и LCN - ми.
Осталось реализовать сравнение дампов,
и можно будет "во всеоружии" приступить к поимке переезжающих файлов :)


 
Игорь Шевченко ©   (2008-03-25 09:52) [42]

Riply ©   (24.03.08 15:09) [41]

"Я нашел,  как применить здесь нестирающиеся шины  из  полиструктурного  волокна  с  вырожденными аминными  связями и неполными кислородными группами.  Но я не знаю пока, как использовать регенерирующий реактор на субтепловых нейтронах.  Миша, Мишок!  Как быть с реактором?"
(с) А и Б Стругацкие


 
Riply ©   (2008-03-25 09:52) [43]

Мне не удалось воспроизвести "переезд" кластеров файла,
как прямое следствие записи в него.
Это означает только недостаточность моих знаний, но никак
не то, что данный "переезд" невозможен.
Уж не говоря о том, что не поймала сегодня - поймаю завтра :)
Повторюсь: эффект, я наблюдала и не раз.
Тогда он мне был совсем не нужен.
Я рассматривала возможности "безопасной прямой записи" данных в файл.
И то, что мне удалось зафиксировать "переезд"
ставило крест на моем способе "блокировки класеров".
Помню, расстроилась тогда :)

Зато мне удалось написать легко воспроизводимый пример,
доказывающий, что при обычной записи в файл,
никакой гарантии, что мы пишем в нужные кластеры нет :)

Я приведу только схему кода, т.к. в нем используется очень много
"самолапных" функций и классов (очень лень выдергивать все это. Sorry),
но попробую прокоментировать происходящее.
Приступим:
function ReadWippedFile(const pSourName: PUNICODE_STRING): NTSTATUS;
const
StuffExt: WideString = ".stuff";
sHelloDolly: WideString = "Hello Dolly !!!" + sLineBreak + "Wipped file: ";
var
SourLcn, StuffLcn: _LCN;
StuffName: UNICODE_STRING;
MFTDisk: TMFTScan;
hFileObj: THandle;
pBuffer: Pointer;
BufferSize, SourceClustersCount, StuffClustersCount: DWord;
begin
StuffLcn := -1;
SourLcn := -1;
SourceClustersCount := 4;
StuffClustersCount := SourceClustersCount * 2;
RtlInitUnicodeString(@StuffName, PWideChar(pSourName.Buffer + StuffExt));
// Создаем тестовый файл и временный файл, в который будем перемещать класеры.
// Задаем им размеры.
Result := Nt_FileCreateSized(pSourName, SourceClustersCount * BytesPerCluster, SET_SIZE_FLAG_INSTANCE, nil);
if NT_SUCCESS(Result) then Result := Nt_FileCreateSized(@StuffName, StuffClustersCount * BytesPerCluster, SET_SIZE_FLAG_INSTANCE, nil);
if NT_SUCCESS(Result) then
 begin
  MFTDisk := TMFTScan.Create;
  try // TMFTScan - класс для работы с диском
   Result := MFTDisk._Set_CallBackFunctions(pSourName, nil); // настраиваем
   if Result = STATUS_SUCCESS then Result := MFTDisk.NtGetObjectRetrievalPointers(@StuffName, 0);
   if Result = STATUS_SUCCESS then
    begin // получили RetrievalPointers. Проверяем их пригодность как буфера для перемещения
     with PRETRIEVAL_POINTERS_BUFFER(MFTDisk.IoData.pData)^ do
      if ExtentCount > 0 then
       with Extents[0] do
        if (Lcn.QuadPart > 0) and (NextVcn.QuadPart >= SourceClustersCount)
         then StuffLcn := Extents[0].Lcn.QuadPart;
     if StuffLcn <= 0 then
      begin
       ShowMessage("Stuff file is fragmented. Try again" + sLineBreak
                   + Pars_RETRIEVAL_POINTERS_BUFFER(MFTDisk.IoData.pData));
       Exit;
      end
     else Nt_DeleteFileU(@StuffName, 0);
     Result := MFTDisk.NtGetObjectRetrievalPointers(pSourName, 0);
     if Result = STATUS_SUCCESS then
      begin // Запоминаем исходные RetrievalPointers нашего файла и записываем их в лог
       with PRETRIEVAL_POINTERS_BUFFER(MFTDisk.IoData.pData)^ do
       if ExtentCount > 0 then SourLcn := Extents[0].Lcn.QuadPart;
       Log_WriteStatusNT("Try to move to: " + IntToStr(StuffLcn) + sLineBreak
                         + Pars_RETRIEVAL_POINTERS_BUFFER(MFTDisk.IoData.pData), Result);
      end;
     // Подготовка закончена, приступаем к работе
     if Result = STATUS_SUCCESS then
      begin // Открываем наш файл
       Result := Nt_OpenFile(pSourName, FILE_WRITE_DATA or SYNCHRONIZE, FILE_SHARE_ALX_NONE,
                             FILE_NON_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT, nil, nil, hFileObj);
       if Result = STATUS_SUCCESS then
        try
         BufferSize := SourceClustersCount * BytesPerCluster;
         pBuffer := GetMemory(BufferSize);
         if pBuffer <> nil then
          try
           Записываем в буфер приветствие для Dolly и имя файла.
           FillBuffer(pBuffer, BufferSize, sHelloDolly + sLineBreakW + pSourName.Buffer);
           Result := Nt_WriteFile(hFileObj, pBuffer, BufferSize, nil);
           FlushFileBuffers(hFileObj);
           // Записали данные в файл, приступаем к их уничтожению
           NT_SUCCESS_SET_WORST(Result, Nt_SetFilePointer(hFileObj, nil, nil));
           if NT_SUCCESS(Result) then
            begin
             FillChar(pBuffer^, BufferSize, 0); // Очистили буфер и записали первую половину файла
             Result := Nt_WriteFile(hFileObj, pBuffer, BufferSize div 2, nil);
             if Result = STATUS_SUCCESS then
              begin
               // Перемещаем кластеры нашего файла, записываем в лог новое расположение
               Result := MFTDisk.MoveObjectClusters(pSourName, StuffLcn);
               if NT_SUCCESS_SET_WORST(Result, MFTDisk.NtGetObjectRetrievalPointers(pSourName, 0))
                then Log_WriteMessage(Pars_RETRIEVAL_POINTERS_BUFFER(MFTDisk.IoData.pData));
               // и затираем вторую половину файла
               NT_SUCCESS_SET_WORST(Result, Nt_WriteFile(hFileObj, IncPtr(pBuffer, BufferSize div 2), BufferSize div 2, nil));
              end;
             FillChar(pBuffer^, BufferSize, 0);
             // читаем старые сектора нашего файла (прямое чтение)
             Result := MFTDisk.ReadClustersToBuffer(pBuffer, SourLcn, SourceClustersCount);
             if Result = STATUS_SUCCESS // и сохраняем их в др. файл
              then Result := Nt_CreateFileData(@StuffName, pBuffer, BufferSize, nil, nil);
            end;
          finally
           FreeMem(pBuffer);
          end
         else Result := STATUS_INSUFFICIENT_RESOURCES;
        finally
         NT_SUCCESS_SET_WORST(Result, NtClose(hFileObj));
        end;
      end;
    end;
  finally
   MFTDisk.Free;
  end;
 end;
end;

Читаем лог:
Try to move to: 623215
ExtentCount 1
Index 0 Lcn 1778061 Count 4
The operation completed successfully
ExtentCount 1
Index 0 Lcn 623215 Count 4
The operation completed successfully

и видим, что посреди операции записи в файл, его кластеры были успешно перемещены туда,
куда мы и хотели.

Смотрим данные, полученные прямым чтением старых секторов:
H e l l o   D o l l y   ! ! !
W i p p e d   f i l e :  
\ ? ? \ I : \ Z _ S c a n T e s t D i r \ S o u r c e \ C l u s t e r e d F i l e . t x t
(Привожу только кусок, на самом деле считано все полностью). В новых кластерах, разумеется нули :)

P.S.
Операции затирания, прямого чтения и перемещения можно "тасовать" как угодно
(разумеется не нарушая логики). Результат остается тем же.

P.P.S.
Пример собирался "на коленке" так что строго не судите :)
Если возникнет необходимость - напишу нормальный (пригодный для компиляции).
Но очень лень этим заниматься. :)


 
Riply ©   (2008-03-25 10:03) [44]

> [43] Riply ©   (25.03.08 09:52)

Несколько добавлений:
Как видно из примера для перемещения кластеров не использовался Handle файла.
MoveObjectClusters(pSourName, StuffLcn);
Это было сделано для того, чтобы показать, что "монопольное" открытие, тоже не спасает.
Перемещались кластеры "законными" методами с помощью FSCTL_MOVE_FILE


 
WipeInfo   (2008-03-25 10:09) [45]

Eraser
WipeInfo


 
Игорь Шевченко ©   (2008-03-25 10:26) [46]


> Зато мне удалось написать легко воспроизводимый пример,
> доказывающий, что при обычной записи в файл,
> никакой гарантии, что мы пишем в нужные кластеры нет


Вот же. А ошибку в примере ты уже нашла ?


 
Riply ©   (2008-03-25 10:32) [47]

>  [46] Игорь Шевченко ©   (25.03.08 10:26)
> Вот же. А ошибку в примере ты уже нашла ?

Ну вот. Как всегда :(
Пол ночи писала это дело, уже голова плохо соображает.
И где она (ошибка) ?


 
Riply ©   (2008-03-25 10:52) [48]

> [46] Игорь Шевченко ©   (25.03.08 10:26)

Ну нельзя же так издеваться над софорумчанкой :)
В чем эта чертова ошибка ?


 
guav ©   (2008-03-25 11:57) [49]

> [45] WipeInfo   (25.03.08 10:09)
> Eraser

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


 
Игорь Шевченко ©   (2008-03-25 11:59) [50]

Riply ©   (25.03.08 10:52) [48]

Ошибка в том, что при обычной записи в файл (несжатый) его кластеры автомагически не перемещаются. Ибо незачем.


 
Riply ©   (2008-03-25 12:14) [51]

> [50] Игорь Шевченко ©   (25.03.08 11:59)
> Riply ©   (25.03.08 10:52) [48]
> Ошибка в том, что при обычной записи в файл (несжатый)
> его кластеры автомагически не перемещаются. Ибо незачем.

К "несжатый" надо еще добавить "неразраженный", и очень вероятно "не фрагментированный" :)
Ведь не случайно эффект я наблюдала на фрагментированных файлах.

Насчет "незачем", я бы не была столь категорична, ибо пути системы неисповедимы. :)
Это относиться и к сторонним программам, установленным на компьютер.
И если кто угодно из них имеет возможность переместить наш файл, когда мы в него пишем,
то какая здесь может быть гарантия ?
В примере я специально использовала стандартный файл, даже не фрагментированный,
что бы показать, что и в этом случае запись может происходить "не туда".


 
Игорь Шевченко ©   (2008-03-25 13:03) [52]

Riply ©   (25.03.08 12:14) [51]


> Ведь не случайно эффект я наблюдала на фрагментированных
> файлах.


Воспроизводи. До тех пор, пока не воспроизвела, считается за глюк инструмента.


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


В примере ты его параллельно дварковала, причем влэндишным способом.


 
Riply ©   (2008-03-25 13:14) [53]

>  [52] Игорь Шевченко ©   (25.03.08 13:03)
> Воспроизводи. До тех пор, пока не воспроизвела, считается за глюк инструмента.

"Ох не легкая это работа, из болота тащить бегемота." (с)
Что ж делать, буду пытаться. Но требуется время (кроме удовольствия, еще, к сожалению, и работа существует :)

> В примере ты его параллельно дварковала, причем влэндишным способом.
:)
Дык дваркование из примера можно убрать и поместить
в другой порцесс. Просто так было легче совместить его с записью в файл :)


 
Игорь Шевченко ©   (2008-03-25 13:17) [54]

Давай сделаем проще:
Ты создашь файл, стандартным образом, скопируешь файл с исходным текстов какого-нибудь твоего примера, килобайт на 10 в файл с именем a.txt.

После этого ты его аккуратно откроешь на запись, и пропишешь от начала до конца нулями или произвольным символом.

var
 AFile: HFILE;
 FileSize, Worker: Cardinal;
 I: Integer;
 Buffer: array[0..1023] of char;
begin
 FillChar(Buffer, SizeOf(Buffer), 65);
 AFile := CreateFile("a.txt", GENERIC_READ or GENERIC_WRITE,
   FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 Win32Check(AFile <> INVALID_HANDLE_VALUE);
 try
   FileSize := GetFileSize(AFile, @Worker);
   if Worker <> 0 then
     raise Exception.Create("File too large to test");
   for I := 0 to (FileSize div SizeOf(Buffer)) - 1 do
     if not WriteFile(AFile, Buffer, SizeOf(Buffer), Worker, nil)
        or (Worker <> SizeOf(Buffer)) then
     raise Exception.Create("Write failed");
   if FileSize mod SizeOf(Buffer) <> 0 then
     if not WriteFile(AFile, Buffer, FileSize mod SizeOf(Buffer), Worker,
        nil) or (Worker <> FileSize mod SizeOf(Buffer)) then
     raise Exception.Create("Write failed");
 finally
   CloseHandle(AFile);
 end;
end;


После этого ты любым тебе доступным инструментом восстановишь содержимое этого файла :)

Потом то же самое с сжатым файлом и с разреженным.

Договорились ?


 
Игорь Шевченко ©   (2008-03-25 13:20) [55]

В дополнение к [54]

В параллель с файлом ты можешь делать все, что угодно. Но принцип такой, что после окончания всех процессов с файлом, ты, имея диск с NTFS, пытаешь восстановить. Разумеется, способ, когда ты заранее скопируешь кластеры, занимаемые файлом до его затирания, а потом перепишешь файл в другое место каким-либо способом, хотя бы и влэндишным, считается неспортивным.
Да, разумеется ход процесса восстановления надо в студию, чтобы пример был воспроизводимым.


 
Riply ©   (2008-03-25 13:28) [56]

> [54] Игорь Шевченко ©   (25.03.08 13:17)
> Договорились ?

Т.е. мне надо найти условия, при которых данное затирание
будет работать не сто процентно.
Причем такие, что сбой в затирании был воспроизводим
при разумном числе попыток ?

Если я правильно поняла и мне дается время, то согласна :)


 
Игорь Шевченко ©   (2008-03-25 13:32) [57]

Riply ©   (25.03.08 13:28) [56]

Тебе надо сделать

> После этого ты любым тебе доступным инструментом восстановишь
> содержимое этого файла


Время разумеется не ограничено :)


 
Riply ©   (2008-03-25 13:36) [58]

> [57] Игорь Шевченко ©   (25.03.08 13:32)
> После этого ты любым тебе доступным инструментом восстановишь
> содержимое этого файла

Может не обязательно полное содержимое, а хотя бы один сектор (ну или кластер) ?

> Время разумеется не ограничено :)

Ну а после этого уточнения, я полностью согласная :)


 
WipeInfo   (2008-03-25 14:38) [59]

Удалено модератором
Примечание: Offtopic


 
Riply ©   (2008-03-26 10:54) [60]

> [55] Игорь Шевченко © (25.03.08 13:20)
> В параллель с файлом ты можешь делать все, что угодно.

Могу ли я в середине цикла

for I := 0 to (FileSize div SizeOf(Buffer)) - 1 do
if not WriteFile(AFile, Buffer, SizeOf(Buffer), Worker, nil)
 or (Worker <> SizeOf(Buffer)) then
raise Exception.Create("Write failed");


вызвать из него свою процедуру ?

Идея, примерно, такая:
Для удобства, считаем, что на каждом шаге затирается один кластер.
Пусть исходно файл занимал кластеры с "номерами" 0 и 1.
Допустим, у нас в цикле только два шага.
Проходим первый шаг (как бы запись в класер 0).

Здесь надо симитировать, что в этот момент времени
другой процесс(поток), например, с более высоким приоритетом,
производит "перемещение" кластеров нашего файла в кластеры с "номерами" 1000 и 1001
NtFsControlFile(..., FSCTL_MOVE_FILE, ...)

Проходим второй шаг цикла (как бы запись в класер ??? ).
Завершили затирание.

Встает такой вопрос:
В какие кластеры реально велась запись ?
0, 1 или 1000, 1001 ? А может в 0, 1001 ?
Инфомация может считаться "уничтоженной без возможности восстановления"
только в двух случаях:
1. Запись велась в 0, 1 и они (уже затертые) переместились в 1000 и 1001.
2. Запись велась во все четыре кластера.
Пример, который я приводила показывает, что в общем случае это не первый и не второй варианты.
Да и не логичные они какие-то :)
Во всех остальны случаях информация уничтожена не полностью - т.е. не уничтожена :)

Я спрашиваю о "добавлении" вызова функции в процедуру затирания,
т.к. довольно сложно из другого процесса(потока) без синхронизации поймать нужный момент :)
Можно, конечно определять "момент такой" с помощью перехвата, но это уж очень некузяво :)
Самый простой способ - сразу вызывать NtFsControlFile, как впрочем я и делала :)


 
Игорь Шевченко ©   (2008-03-26 12:01) [61]


> Могу ли я в середине цикла
>
> for I := 0 to (FileSize div SizeOf(Buffer)) - 1 do
> if not WriteFile(AFile, Buffer, SizeOf(Buffer), Worker,
> nil)
>  or (Worker <> SizeOf(Buffer)) then
> raise Exception.Create("Write failed");
>
> вызвать из него свою процедуру ?


Нет, не можешь.


> Здесь надо симитировать, что в этот момент времени
> другой процесс(поток), например, с более высоким приоритетом,
>  
> производит "перемещение" кластеров нашего файла в кластеры
> с "номерами" 1000 и 1001
> NtFsControlFile(..., FSCTL_MOVE_FILE, ...)


Ну сделай файл на 1 гигабайт и запусти другой процесс параллельно.

Идея в том, чтобы получить данные затертого файла. Код затирания я привел, и вмешиваться в него не надо. Если без хитростей с перемещением не получится, то и браться не стоит :)


 
Riply ©   (2008-03-26 22:04) [62]

Вроде, удалось добиться нужного результата.
Опишу как я действовла, чтобы получить вердикт: спортивно или нет.
Если да и потребуется код, пригодный для компиляции, - буду писать,
если нет, то учту замечания и буду думать дальше :)

Все происходит на NTFS диске (не виртуальном).
Есть исходный файл, в котором хранятся наши секретные данные
SourName = "BaseDataFile.txt" размером DataSize = 7786 Byte.
Подготовка:
Копируем SourName в VictimName - этот файл будем затирать.
Создаем файл StuffName с размером ROUND_UP(DataSize, BytesPerCluster).
Затираем его нулями :)
Проверяем что он не фрагментирован и получаем "номер" его первого кластера StuffLcn.
Это временный файл, в чьи кластеры мы будем премещать подопытного.

Пишем две процедуры:
Первая устанавливает hEvent, сигнализирующий, что мы готовы к работе
и переходит к ожиданию открытия нового Handle - а.
Мы расчитываем, что он будет открыт
процедурой затирания от Игоря: WipeFileByShevchenko

function WaitCreateHandle(hEvent: THandle): NTSTATUS;
var
OldHandleCount, HandleCount: DWord;
//....
begin
Result := NtQueryInformationProcess(GetCurrentProcess, ProcessHandleCount,
                                    @OldHandleCount, SizeOf(DWord), nil);
if SetEvent(hEvent) then
 while NT_SUCCESS(Result) do
  begin
   Result := NtQueryInformationProcess(GetCurrentProcess, ProcessHandleCount,
                                       @HandleCount, SizeOf(DWord), nil);
   if HandleCount = Succ(OldHandleCount) then Exit;
   //....
  end
//....
end;

Вторая процедура у нас и будет заниматься перемещением и чтением.
Она будет работать внутри дополнительной нити.
Выглядит она примерно так:
function MoveAndReadWippedFile(const pVictim, pRestore: PUNICODE_STRING; hEvent: THandle; const VictimSize: DWord): NTSTATUS;
var
StuffName: UNICODE_STRING;
begin
//....
Result := Nt_DeleteFileU(@StuffName, 0); // уничтожаем файл - контейнер кластеров.
if Result = STATUS_SUCCESS then
 begin
  // сигнализируем, что готовы к работе и ждем открытия подопытного файла процедурой затирания
  Result := WaitCreateHandle(hEvent);
  if NT_SUCCESS(Result) then
   begin // Дождались, начинаем работу. (т.е. затиралка уже открыла файл и вовсю его трет. :))
    Result := MoveObjectClusters(pVictim, StuffLcn);
    // MoveObjectClusters - открывает файл pVictim,
    // получает его RETRIEVAL_POINTERS_BUFFER
    // после чего, перемещает его кластеры в подготовленные нами кластеры StuffName
    // закрывает файл
    ReadRetPointersToFile(IoData.pData, pRestore, VictimSize);
    // Считывает кластеры из старого расположения нашего подопытного (прямое чтение)
    // и сохраняет данные в файл pRestore
   end;
//....
end;

Процедура нити:
function MoveClusters(pParams: Pointer): integer;
begin
Result := 0;
with PMoveParams(pParams)^ do
 try
  MoveStatus := MoveAndReadWippedFile(@VictimName, @RestoreName, hMoveEvent, VictimSize)
 finally
  SetEvent(hMoveEvent);
 end;
end;

Ну и вызов всего этого безобразия:

hMoveEvent := CreateEvent(nil, False, False, nil);
if hMoveEvent <> 0 then
try
 hThread := BeginThread(nil, 0, MoveClusters, @MoveParams, 0, ThreadID);
 if hThread <> 0 then
  try // Ждем сигнала готовности
   if WaitForSingleObject(MoveParams.hMoveEvent, 100000) = WAIT_OBJECT_0 then
    with MoveParams do
     begin
      // Вызываем затирающую процедуру
      WipeFileByShevchenko(VictimName.Buffer);

Уфф. Вроде ничего не упустила.

Несколько тестов показали, что
при данных условиях, "затертые" данные восстанавливаются полностью.

P.S.
Понимаю некузявость кода. Он приведен толко как схема действий
для получения вердикта о спортивности поведения :)


 
Игорь Шевченко ©   (2008-03-26 23:03) [63]


> WipeFileByShevchenko


Я пишусь так: Schevchenko

Насчет спортивности - гораздо проще скопировать файл перед его затиранием. Не надо с кластерами возиться.

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

Неспортивно.


 
Riply ©   (2008-03-26 23:18) [64]

> [63] Игорь Шевченко ©   (26.03.08 23:03)
> Я пишусь так: Schevchenko

Sorry

> Насчет спортивности - гораздо проще скопировать файл перед его затиранием. Не надо с кластерами возиться.

Перед затиранием я ничего не делаю.

> Я вроде написал свои условия.

Я поняла так, что "В параллель с файлом ты можешь делать все, что угодно"

>А у тебя получается, что ты копируешь кластеры, параллельно затираешь файл, а потом из скопированных читаешь.

Нет, не так получается, а вот как: я вынуждаю функцию затирать не те кластеры, где располагался файл,
а новые, совершенно другие. Что она с успехом и делает :)
И считываю я не из "скопированных класеров" а из "старых", которые в результате
остались на диске безхозными и не затертыми. :)

> Неспортивно.
Подаю жалобу на перерассмотрение вердикта :)


 
Игорь Шевченко ©   (2008-03-27 00:26) [65]


> Нет, не так получается, а вот как: я вынуждаю функцию затирать
> не те кластеры, где располагался файл,
> а новые, совершенно другие. Что она с успехом и делает :
> )
> И считываю я не из "скопированных класеров" а из "старых",
>  которые в результате
> остались на диске безхозными и не затертыми. :)


Ну я говорю, проще скопировать файл перед затиранием. Неспортивно.
Под "делать все, что хочешь", я, разумеется не имел в виду создание копии незатертых данных.


 
Riply ©   (2008-03-27 01:14) [66]

>  [65] Игорь Шевченко ©   (27.03.08 00:26)
Еще раз попробую снять обвинение в неспортивом поведении :)

> Под "делать все, что хочешь", я, разумеется не имел в виду создание копии незатертых данных.

О какой копии идет речь ? Пока не начался цикл затирания, я даже файл не открываю.
Только после этого получаю Pointers даю команду на перемещение.
К этому времени в цикле уже обработана чать данных.
Было бы нелогично предполагать, что система будет перемещать старые(уже никому не нужные данные),
чтобы потом их затирать. Она просто скинет уже обработанные данные в новое место и продолжит запись
в новые кластеры. (Мой первый пример подтверждает это предположение)
Так что копии, в данном случае, не создается, а только переопределяется место записи. (Это надеюсь спортивно ? :)
Здесь, конечно, мне попалась облегченная задача.
Если бы буфер для затирания был не 1024, а равен кластеру,
еще лучше "объединению" кластеров (обычно это 16 кластеров), то было бы сложнее, но не безнадежно :)
Трудности возникли бы и с большими файлами.
Но мы же искали не способ затирания, а контрпример.
И с этой задачей, как мне кажется, нам удалось справиться.
Во всяком случае показано, что при обычной записи в файл,
не является фактом ведение записи именно в те кластеры где этот файл располагался.


 
Игорь Шевченко ©   (2008-03-27 01:33) [67]

Riply ©   (27.03.08 01:14) [66]


> Во всяком случае показано, что при обычной записи в файл,
>  
> не является фактом ведение записи именно в те кластеры где
> этот файл располагался.


Да, если при этом работает дефрагментатор, то тоже не является фактом.
Только я, убей бог, не понимаю, что это значит ?
Если параллельно с записью происходит копирование файла, то тоже не факт, что копия будет идентична оригиналу.

И что из этого следует ? Что не надо затирать файлы, когда их одновременно копируют ? Что система может произвольно при записи перераспределить кластеры файла ?

Нет, их перераспределит ТВОЙ ПРОЦЕСС или процесс дефрагментатора, но никак не система сама собой.

Если ты добьешься того, что при отсутствии параллельных процессов, перемещающих кластеры файла, система будет их перераспределять при записи того же файла по месту, тогда пост о том, что "кластеры могут меняться" будет считаться действительным.

Этак каждый гражданин себе веревок настрижет, польт не напасешься.


 
Riply ©   (2008-03-27 02:10) [68]

> [67] Игорь Шевченко ©   (27.03.08 01:33)
> Да, если при этом работает дефрагментатор, то тоже не является фактом.
> Только я, убей бог, не понимаю, что это значит ?

Это означает то, что ответ "записать в файл нули" на вопрос
"Как удалить файл со всем, чтобы восстановить было нельзя?"
является не совсем корректным. Только и всего :)

> Что система может произвольно при записи перераспределить кластеры файла ?
> Нет, их перераспределит ТВОЙ ПРОЦЕСС или процесс дефрагментатора, но никак не система сама собой.
К сожалению, я не знаю как поведет себя система. Ибо неисповедима :)
Вдруг она решит, что при записи именно в такой то файл, ей удобнее работать так-то и так-то. Черт ее знает :)

> Если ты добьешься того, что при отсутствии параллельных процессов, перемещающих кластеры файла,
> система будет их перераспределять при записи того же файла по месту,
> тогда пост о том, что "кластеры могут меняться" будет считаться действительным.

В такой постановке, это довольно не просто.
Этим процессом может оказаться драйвер, какого нибудь супер-пупер виртуального диска.
Но я буду иметь это ввиду и постоянно следить не имело ли это место.
Благо работаю то с файловой системой.

P.S.
Я могу не знать, ошибаться, не понимать чего-то, но никак не передергивать или подтасовывать факты.

P.P.S.
И вообще, у меня очень спортивное поведение.
Решила объявить это сама, а то вдруг кто не догадается :)


 
Игорь Шевченко ©   (2008-03-27 09:46) [69]

Riply ©   (27.03.08 02:10) [68]


> К сожалению, я не знаю как поведет себя система. Ибо неисповедима
> :)


Система вполне исповедима бо написана согласно детерминированным алгоритмам.

Я напомню из поста [14]

"Я воспроизводила, примерно, такое:
Создавала файл, например, занимающий восемь кластеров с "номерами":
0..3,  128...131.
И после "обычной" записи в него его картинка становилась: 0..7.
Я не утверждаю, что это происходит всегда,
но в моих тестах это повторилось несколько раз."

У меня небольшой вопрос, что значит "обычной" записи в твоих словах ?
С параллельно работающим дефрагментатором или иной перемещалкой кластеров ?


> В такой постановке, это довольно не просто.
> Этим процессом может оказаться драйвер, какого нибудь супер-
> пупер виртуального диска.
> Но я буду иметь это ввиду и постоянно следить не имело ли
> это место.
> Благо работаю то с файловой системой.


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


 
Riply ©   (2008-03-27 10:00) [70]

> [69] Игорь Шевченко ©   (27.03.08 09:46)
> У меня небольшой вопрос, что значит "обычной" записи в твоих словах ?
> С параллельно работающим дефрагментатором или иной перемещалкой кластеров ?

Игорь, к сожалению, я не могу дать четкого ответа.
В то время мне и голову не приходило, что кто-то кроме системы может это делать.
Едиственное, что могу сказать: дефрагментатор точно не был запущен :)
Насчет других "перемещалок кластеров" не уверена.
Например, я не знаю как работает "DAEMON Tools". (тогда он у меня стоял).
Что было еще не помню. "Norton Unerase" может ?

Соответственно не могу дать однозначного ответа и на это вопрос:
> Обычный диск, на нем обычная система NTFS, параллельно не запущено пермещающих кластеры процессов.
> Возможна ли ситуация, когда при записи файла (не сжатого, не разреженного)
> по месту, его распределение кластеров поменяется ?

Единственное, что могу утверждать, что "переезд" во время записи возможен.
А кто тому виной ... ответить не готова.   (Пока :)

P.S.
Есть один вариант теста... Надо хорошенько его обдумать.
Может он и поможет нам докапаться ло истины :)


 
Игорь Шевченко ©   (2008-03-27 10:14) [71]


> Единственное, что могу утверждать, что "переезд" во время
> записи возможен.


Пример в студию


 
Riply ©   (2008-03-27 10:19) [72]

>  [71] Игорь Шевченко ©   (27.03.08 10:14)
> Пример в студию

Тот, который я описывала выше ?
Мне понадобится время для написания кода, пригодного к компиляции.


 
clickmaker ©   (2008-03-27 10:37) [73]

а о чем речь вообще?
что нельзя так затереть файл, чтобы не было возможности восстановить?


 
Riply ©   (2008-03-27 11:01) [74]

> [70] Riply ©   (27.03.08 10:00)
> Единственное, что могу утверждать, что "переезд" во время записи возможен.

Чуть подумав, изменю формулировку:
"возможен "переезд" во время работы цикла while Condition do WriteFile"
Ибо именно это происходит в моем примере.


 
Riply ©   (2008-03-27 11:03) [75]

> [73] clickmaker ©   (27.03.08 10:37)
> а о чем речь вообще?
> что нельзя так затереть файл, чтобы не было возможности восстановить?

Обо всем понемножку. И об этом, в том числе :)
Точнее не "нельзя", а очень сложно :)


 
clickmaker ©   (2008-03-27 11:18) [76]


> [75] Riply ©   (27.03.08 11:03)

ну так, и документ, скормленный шредеру, тоже можно восстановить при желании )
только кому это интересно, кроме налоговой и ГРУ? )


 
Riply ©   (2008-03-27 11:24) [77]

> [76] clickmaker ©   (27.03.08 11:18)
> ну так, и документ, скормленный шредеру, тоже можно восстановить при желании )
> только кому это интересно, кроме налоговой и ГРУ? )

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


 
Игорь Шевченко ©   (2008-03-27 11:39) [78]

Riply ©   (27.03.08 10:19) [72]

Пример в студию, когда при обычной записи и при отсутствие процесса, перемещающего кластеры, распределение кластеров может измениться при перезаписи по месту несжатого и неразреженного файла.


 
Riply ©   (2008-03-27 11:47) [79]

> [78] Игорь Шевченко ©   (27.03.08 11:39)
> Пример в студию, когда при обычной записи и при отсутствие процесса, перемещающего кластеры,
> распределение кластеров может измениться при перезаписи по месту несжатого и неразреженного файла.

Игорь, так я же в том утверждении написала: "А кто тому виной ... ответить не готова."
Я имела ввиду, что не знаю кто перемещал "процесс, перемещающий кластеры" или система.
Sorry, если непонятно выразилась.


 
Игорь Шевченко ©   (2008-03-27 11:51) [80]

Riply ©   (27.03.08 11:47) [79]


> Я напомню из поста [14]
>
> "Я воспроизводила, примерно, такое:
> Создавала файл, например, занимающий восемь кластеров с
> "номерами":
> 0..3,  128...131.
> И после "обычной" записи в него его картинка становилась:
>  0..7.
> Я не утверждаю, что это происходит всегда,
> но в моих тестах это повторилось несколько раз."


Ты забыла указать, у тебя при этом, при "обычной" записи, параллельно кластеры перемещались ? Явно твоим процессом или дефрагментатором.



Страницы: 1 2 3 вся ветка

Форум: "WinAPI";
Текущий архив: 2009.03.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.7 MB
Время: 0.05 c
11-1197833483
Dodfr
2007-12-16 22:31
2009.03.15
getting size of compiled delphi code blocks ?


3-1216851431
Евгений Р.
2008-07-24 02:17
2009.03.15
view и параметры


8-1192288746
hahol_64_rus
2007-10-13 19:19
2009.03.15
работа с плейлистами


15-1231270757
KilkennyCat
2009-01-06 22:39
2009.03.15
Забавные часы


15-1231254060
@!!ex
2009-01-06 18:01
2009.03.15
Где можно купить Mac Book б/у??





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский