FILE_SHARE_DELETE
CreateFileのFILE_SHARE_DELETEというフラグが前から気になっていたので、チェックしてみることにした。
で、下のようなプログラムを書いてみた。
#include <stdio.h> #include <windows.h> #include <shlwapi.h> #include <tchar.h> void showError(const char* caption); #define CHECKERR(CALL) if(CALL) printf( #CALL " - OK\n"); else showError( #CALL ); int main(int argc, TCHAR* argv[]) { LPCTSTR fn = _T("test.txt"); HANDLE hFile = CreateFile( fn, GENERIC_WRITE | GENERIC_READ, // 読み書き可能 FILE_SHARE_DELETE | FILE_SHARE_READ, // ファイル削除可能・メモ帳で開くのはOK NULL, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, // いずれにしても終了時に削除 NULL); // 書き込んでみる(6バイト) DWORD dw; CHECKERR(WriteFile(hFile, "foobar", 6, &dw, NULL)); printf("dw=%u\n", dw); // ファイルを消す CHECKERR(DeleteFile(fn)); // 存在確認(1) by PathFileExists CHECKERR(PathFileExists(fn)); // 存在確認(2) by FindFirstFile WIN32_FIND_DATA wfd; HANDLE hFind; CHECKERR((hFind = FindFirstFile(fn, &wfd)) != INVALID_HANDLE_VALUE); if(hFind != INVALID_HANDLE_VALUE) CloseHandle(hFind); // 書き込んでみる(6バイト) CHECKERR(WriteFile(hFile, "foobar", 6, &dw, NULL)); printf("dw=%u\n", dw); CHECKERR(SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == 0); // 12バイトを読み込んでみる BYTE buf[12]; CHECKERR(ReadFile(hFile, buf, 12, &dw, NULL)); printf("dw=%u\n", dw); // 読める? HANDLE hFile2 = CreateFile( fn, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); if(hFile2 != INVALID_HANDLE_VALUE) { printf("open the same file!\n"); CloseHandle(hFile2); } else showError("cannot open the file"); // ここで同名のファイルを新規作成できるのか? hFile2 = CreateFile( fn, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL); if(hFile2 != INVALID_HANDLE_VALUE) { printf("create the same file!\n"); CloseHandle(hFile2); } else showError("cannot create the file"); CloseHandle(hFile); // ここで暗黙のDeleteFile } void showError(const char* caption) { DWORD err = GetLastError(); LPSTR buf = NULL; if(FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, LANG_USER_DEFAULT, (LPSTR)&buf, 0, NULL) && buf) { printf("%s: #%u %s\n", caption, err, buf); LocalFree(buf); } }
結果:
WriteFile(hFile, "foobar", 6, &dw, NULL) - OK dw=6 DeleteFile(fn) - OK PathFileExists(fn): #5 アクセスが拒否されました。 (hFind = FindFirstFile(fn, &wfd)) != INVALID_HANDLE_VALUE - OK WriteFile(hFile, "foobar", 6, &dw, NULL) - OK dw=6 SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == 0 - OK ReadFile(hFile, buf, 12, &dw, NULL) - OK dw=12 cannot open the file: #5 アクセスが拒否されました。 cannot create the file: #5 アクセスが拒否されました。
結論から言えば、消えてない。単にアクセス拒否を食らっているだけだ。UNIXのunlinkのような挙動を期待するのは無理そうだ。しかしながら、結構重要なデータをテンポラリファイルとして書き出さざるを得ない場合など、使えるシチュエーションはあると思われる。