Конференция "WinAPI" » Как удалить файл без восстановления [D7]
 
  • Игорь Шевченко © (27.03.08 11:51) [80]
    Riply ©   (27.03.08 11:47) [79]


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


    Ты забыла указать, у тебя при этом, при "обычной" записи, параллельно кластеры перемещались ? Явно твоим процессом или дефрагментатором.
  • guav © (27.03.08 11:55) [81]
    > [73] clickmaker ©   (27.03.08 10:37)
    > что нельзя так затереть файл, чтобы не было возможности
    > восстановить?


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

    Например, если после кода [54] файл сразу удалить, то файл может быть восстановим - запись происходит не сразу, может так получиться, что на момент записи писать будет уже некуда и незачем. Соотвественно того же можно достичь не удаляя файл, а просто чита его через прямой доступ к тому сразу после затирания.
  • Игорь Шевченко © (27.03.08 12:00) [82]
    guav ©   (27.03.08 11:55) [81]


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


    А можно просто скопировать его перед тем, как затереть :) Возни меньше.
  • guav © (27.03.08 12:07) [83]
    > [82] Игорь Шевченко ©   (27.03.08 12:00)

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

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

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

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

    что, он даже после CloseHandle может быть не записан?
  • guav © (27.03.08 12:31) [86]
    > [85] clickmaker ©   (27.03.08 12:11)

    да.
  • Игорь Шевченко © (27.03.08 12:59) [87]
    guav ©   (27.03.08 12:31) [86]

    Чудные дела творятся на свете. Файл после CloseHandle не записывается на диск...
  • guav © (27.03.08 13:27) [88]
    > [87] Игорь Шевченко ©   (27.03.08 12:59)

    Ок, будет пример или опровержение.
  • Игорь Шевченко © (27.03.08 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 © (27.03.08 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, §orSize, &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;
    }

  • Игорь Шевченко © (27.03.08 15:08) [91]
    А давай после вот этого

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

    добавим

     FlushFileBuffers (file) ?
  • Игорь Шевченко © (27.03.08 15:10) [92]

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


    Кстати, об этом Riply писала, когда записывала в файл Hello Dolly, а потом читала по секторам. В начинающих ветка была.
  • guav © (27.03.08 15:21) [93]
    > [91] Игорь Шевченко ©   (27.03.08 15:08)

    Ну так будет выдавать строку 'AAAA...'.
    Но сама по себе CloseFile как в [54] буферы таки не сбрасывает сразу.
  • Игорь Шевченко © (27.03.08 15:24) [94]
    guav ©   (27.03.08 15:21) [93]

    А если DeleteFile не делать ? Конечно надо логику смотреть, я не готов объяснить поведение вот так и сразу.
  • guav © (27.03.08 15:26) [95]
    > [94] Игорь Шевченко ©   (27.03.08 15:24)
    > А если DeleteFile не делать ?

    Результат не стабильный тогда, и старые и новые данные могут читаться.
  • guav © (27.03.08 15:31) [96]
    > [95] guav ©   (27.03.08 15:26)

    Если перенести открытие тома в начало и убрать memset(pBuffer, 0, sectorlen), то будут старые чаще чем новые.
  • Игорь Шевченко © (27.03.08 16:33) [97]
    guav ©   (27.03.08 15:31) [96]

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

    Есть основания утверждать, что кэшируется именно запись.
    При DeleteFile данные читаются долго после перезаписи.
    FILE_FLAG_NO_BUFFERING или FlushFileBuffers работает.
    Без FILE_FLAG_NO_BUFFERING запись кэшируется.
    CloseFile этот кэш не сбрасывает.
  • guav © (27.03.08 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, а запись/чтение блока с размером некратным размеру сектора число без буфера не получится.
 
Конференция "WinAPI" » Как удалить файл без восстановления [D7]
Есть новые Нет новых   [134433   +21][b:0.001][p:0.002]