Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.03.15;
Скачать: CL | DM;

Вниз

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

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

Riply ©   (27.03.08 11:47) [79]


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


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


 
guav ©   (2008-03-27 11:55) [81]

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


Я бы так сказал, что, скорее всего, простая перезапись приведёт к тому, что файл не будет восстановим. Но "скорее всего" может быть недостаточно, тогда затереть гарантировано может быть сложно. Нужно учитывать кучу всего.

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


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

guav ©   (27.03.08 11:55) [81]


> Соотвественно того же можно достичь не удаляя файл, а просто
> чита его через прямой доступ к тому сразу после затирания.
>


А можно просто скопировать его перед тем, как затереть :) Возни меньше.


 
guav ©   (2008-03-27 12:07) [83]

> [82] Игорь Шевченко ©   (27.03.08 12:00)

Я понимаю что не спортивно. Просто пример, что затереть не так просто :)
Чтобы устранить указаную в [81] проблему, в затиралках используют FILE_FLAG_NO_BUFFERING.

Я самопроизвольное перемещение наблюдал только на сжатых файлах.


 
Riply ©   (2008-03-27 12:08) [84]

> [80] Игорь Шевченко ©   (27.03.08 11:51)
> Ты забыла указать, у тебя при этом, при "обычной" записи, параллельно кластеры перемещались ?
> Явно твоим процессом или дефрагментатором.

Тогда я вела запись процедурой, аналогичной WipeFileBySchevchenko,
только не циклом, а буфером размером равным размеру файла.
Дефрагментатор запущен не был.
Насчет пермещающих кластеры процессов ничего сказать не могу.
Моих не было, а вот не мои могли быть
(например, стояли Norton Unerase, DAEMON Tools может еще что. Не помню).
Это те, на кого может пасть подозрение.
Тогда я о других процессах и не думала.
Я полагала, что это может делать только система и никто более,
соответственно не обращала внимания на то, кто еще работает.


 
clickmaker ©   (2008-03-27 12:11) [85]


> Чтобы устранить указаную в [81] проблему, в затиралках используют
> FILE_FLAG_NO_BUFFERING

что, он даже после CloseHandle может быть не записан?


 
guav ©   (2008-03-27 12:31) [86]

> [85] clickmaker ©   (27.03.08 12:11)

да.


 
Игорь Шевченко ©   (2008-03-27 12:59) [87]

guav ©   (27.03.08 12:31) [86]

Чудные дела творятся на свете. Файл после CloseHandle не записывается на диск...


 
guav ©   (2008-03-27 13:27) [88]

> [87] Игорь Шевченко ©   (27.03.08 12:59)

Ок, будет пример или опровержение.


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

Я  к чему - вроде пользуюсь системой тихо, мирно, ожидаю, что будет работать, как написано.

А написано примерно вот так:

"Buffers are normally maintained by the operating system, which determines the optimal time to write the data automatically to disk: when a buffer is full, when a stream is closed, or when a program terminates normally without closing the stream" (http://msdn2.microsoft.com/en-us/library/9yky46tz.aspx)

Обсуждение вопроса, будут ли буферы сброшены на диск после CloseHandle, прводится здесь:

http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-08/msg00925.html


 
guav ©   (2008-03-27 14:44) [90]

> [89] Игорь Шевченко ©   (27.03.08 14:06)

Ок. Как Вы объясните стабильно воспроизводимый вывод старого содержимого файла в этом примере (извините что С, Delphi нету. на FAT не работает, т.к. там из номера кластера смещение не получается простым умножением):

int _tmain(int argc, _TCHAR* argv[])
{
 HANDLE file;
 DWORD len, sectorlen;
 DWORD ret;
 BYTE *pBuffer;
 STARTING_VCN_INPUT_BUFFER startVcn;
 RETRIEVAL_POINTERS_BUFFER rp;
 HANDLE volume;

 DWORD clusterSize, sectorSize;
 DWORD freeClusters, totalClusters;

 // Узнаём размеры секотра и кластера.
 GetDiskFreeSpace(
   _T("D:\\"), &clusterSize, &sectorSize, &freeClusters, &totalClusters);

 // Открываем файл
 file = CreateFile(
   _T("D:\\placeholders.hpp"),
   GENERIC_READ | GENERIC_WRITE,
   FILE_SHARE_READ,
   NULL,
   OPEN_EXISTING,
   0,
   0);

 // Узнаём первый кластер
 startVcn.StartingVcn.QuadPart = 0;
 DeviceIoControl(
   file,
   FSCTL_GET_RETRIEVAL_POINTERS,
   &startVcn,
   sizeof(startVcn),
   &rp,
   sizeof(rp),
   &ret,
   NULL);

 // Узнаём размер
 sectorlen = len = GetFileSize(file, NULL);
 // Округляем sectorlen вверх до размера сектора
 if (sectorlen % sectorSize)
 {
   sectorlen += sectorSize - sectorlen % sectorSize;
 }
 pBuffer = malloc(sectorlen);
 // пишем
 memset(pBuffer, "A", len);
 WriteFile(file, pBuffer, len, &ret, NULL);

 // закрываем и сразу удаляем (если убрать DeleteFile, может начать выводиться новое содержимое).
 CloseHandle(file);
 DeleteFile(_T("D:\\placeholders.hpp"));

 // Теперь читаем напрямую.
 volume = CreateFile(
   _T("\\\\.\\D:"),
   GENERIC_READ,
   FILE_SHARE_READ | FILE_SHARE_WRITE,
   NULL,
   OPEN_EXISTING,
   0,
   NULL);
 rp.Extents[0].Lcn.QuadPart *= sectorSize * clusterSize;
 SetFilePointerEx(volume, rp.Extents[0].Lcn, NULL, FILE_BEGIN);
 memset(pBuffer, 0, sectorlen);
 ReadFile(volume, pBuffer, sectorlen, &ret, NULL);
 CloseHandle(volume);
 // тут выводятся старые данные.
 puts(pBuffer);
 free(pBuffer);
 return 0;
}


 
Игорь Шевченко ©   (2008-03-27 15:08) [91]

А давай после вот этого

WriteFile(file, pBuffer, len, &ret, NULL);

добавим

 FlushFileBuffers (file) ?


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


> Как Вы объясните стабильно воспроизводимый вывод


Кстати, об этом Riply писала, когда записывала в файл Hello Dolly, а потом читала по секторам. В начинающих ветка была.


 
guav ©   (2008-03-27 15:21) [93]

> [91] Игорь Шевченко ©   (27.03.08 15:08)

Ну так будет выдавать строку "AAAA...".
Но сама по себе CloseFile как в [54] буферы таки не сбрасывает сразу.


 
Игорь Шевченко ©   (2008-03-27 15:24) [94]

guav ©   (27.03.08 15:21) [93]

А если DeleteFile не делать ? Конечно надо логику смотреть, я не готов объяснить поведение вот так и сразу.


 
guav ©   (2008-03-27 15:26) [95]

> [94] Игорь Шевченко ©   (27.03.08 15:24)
> А если DeleteFile не делать ?

Результат не стабильный тогда, и старые и новые данные могут читаться.


 
guav ©   (2008-03-27 15:31) [96]

> [95] guav ©   (27.03.08 15:26)

Если перенести открытие тома в начало и убрать memset(pBuffer, 0, sectorlen), то будут старые чаще чем новые.


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

guav ©   (27.03.08 15:31) [96]

Значит что-то где-то кешируется. Весьма вероятно, что и старые сектора могут браться из кэша при прямом чтении диска, кстате


 
guav ©   (2008-03-27 16:55) [98]

> [97] Игорь Шевченко ©   (27.03.08 16:33)

Есть основания утверждать, что кэшируется именно запись.
При DeleteFile данные читаются долго после перезаписи.
FILE_FLAG_NO_BUFFERING или FlushFileBuffers работает.
Без FILE_FLAG_NO_BUFFERING запись кэшируется.
CloseFile этот кэш не сбрасывает.


 
guav ©   (2008-03-27 16:58) [99]

> [97] Игорь Шевченко ©   (27.03.08 16:33)
> Весьма вероятно, что и старые сектора могут браться из кэша
> при прямом чтении диска, кстате

При чтении с диска можно указать FILE_FLAG_NO_BUFFERING, на результат не повлияет.
Более того, я не просто так делаю
// Округляем sectorlen вверх до размера сектора
if (sectorlen % sectorSize)
{
  sectorlen += sectorSize - sectorlen % sectorSize;
}
Даже без FILE_FLAG_NO_BUFFERING том ведёт себя как с FILE_FLAG_NO_BUFFERING, а запись/чтение блока с размером некратным размеру сектора число без буфера не получится.


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

guav ©   (27.03.08 16:58) [99]

И все-таки мне интересно, почему нужен DeleteFile.


 
guav ©   (2008-03-27 18:47) [101]

> [100] Игорь Шевченко ©   (27.03.08 17:09)

Без DeleteFile тоже работает.
Но буфер с буквами A когда-нибудь будет записан.
А если файл сразу удалить, то буфер с буквами А уже не будет нужен.

"... Скажем, много лет назад существовала программа для Linux, которая заполняла нули в блоки данных перед их освобождением, однако ОС откладывала запись. Позднее ОС замечала, что блок свободен, и вообще не записывала нули на диск. Кроме того, многие программы предполагают, что при записи данных в существующий файл ОС будет использовать те же блоки данных. Однако ОС также может выделить новые блоки данных, и в этом случае содержимое файла останется на диске."
Брайан Кэрриэ, "Криминалистический анализ файловых систем", с 175


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


> Однако ОС также может выделить новые блоки данных, и в этом
> случае содержимое файла останется на диске


Вот этот момент надо бы подкрепить.


 
Riply ©   (2008-03-28 11:20) [103]

Допустим, система пытается записать на диск и
у нее не получается (например, кластер файла оказался помечен как плохой), а прочитать может.
Как она поступает в таком случае ?


 
Игорь Шевченко ©   (2008-03-28 12:51) [104]

Riply ©   (28.03.08 11:20) [103]


> Как она поступает в таком случае ?


в EventLog пишет



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

Текущий архив: 2009.03.15;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.022 c
15-1231874644
oxffff
2009-01-13 22:24
2009.03.15
Рекомендую. Copy-on-write data structures in Delphi


2-1232896639
И. Павел
2009-01-25 18:17
2009.03.15
Как показать модальное окно только после CreateRectRgn?


2-1232953232
Iriss
2009-01-26 10:00
2009.03.15
delphi из excel в stringgrid через буфер обмена


8-1191576151
Blind Guardian
2007-10-05 13:22
2009.03.15
Поворот изображения вокруг вертикальной серединной оси


3-1216004585
Viod
2008-07-14 07:03
2009.03.15
Вернуть значение поля внутри хранимой процедуры