這兩天由於修改python解釋器的需求,需要用到tmpfile()來生成臨時文件的FILE*,但是又擔心這個臨時文件是否存在於磁盤的某個地方,終究會被人找到,所以就簡單做了以下幾點實驗,看看是否可以找到tmpfile臨時文件的路徑。
實驗環境:Win7 + VS2010
一、實驗一:跟蹤調試
寫了一小段簡單的tmpfile調用,然后跟蹤調試,在tmpfile_s內部也沒能發現這個臨時文件的路徑,當然,通過stream->_tmpfname,可以看到一個臨時文件的名稱,但是看不到路徑;根據這個名稱到WINDOWS\TEMP(或者C:\Users\xxx\AppData\Local\Temp)路徑下去查找,也沒有找到類似名稱的文件。
void TesttempfileFunc() { FILE *stream; char tempstring[] = "String to be written"; // Create temporary files. for(int i = 1; i <= 3; i++ ) { errno_t err = tmpfile_s(&stream); fwrite(tempstring, 1, strlen(tempstring), stream); if( err ) perror( "Could not open new temporary file\n" ); else printf( "Temporary file %d was created\n", i ); } // Remove temporary files. printf( "%d temporary files deleted\n", _rmtmp() ); }
二、實驗二,通過api提取FILE*的路徑
是否可以通過FILE*,然后通過某種API的調用,找到對應的文件名稱,bing搜了一把,有一篇類似的文章(通過文件句柄獲得文件路徑http://www.bkjia.com/cjjc/498250.html),但是這里是通過HANDLE來獲取文件路徑,而我需要的是從FILE*獲取文件路徑,想到下午了解到有一個函數(_get_osfhandle)可以將FILE*轉換為文件句柄,所以寫了如下代碼來驗證:
1)首先來嘗試針對普通文件的FILE*來提取他的路徑,提取成功,代碼如下:
BOOL GetFileNameFromHandle(HANDLE hFile) { TCHAR pszFileName[MAX_PATH]; HANDLE hFileMap; PVOID pMem; //獲取文件大小 DWORD dwFileSizeHigh = 0; DWORD dwFileSizeLow = 5;//GetFileSize(hFile, &dwFileSizeHigh); if (dwFileSizeLow == 0 && dwFileSizeHigh == 0) { printf("不能map文件大小為0的文件.\n"); return FALSE; } //創建Mapping對象 hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 1, NULL); if (!hFileMap) { printf("CreateFileMapping error: %d", GetLastError()); return FALSE; } pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1); if (!pMem) { printf("MapViewOfFile error: %d", GetLastError()); return FALSE; } //從Mapping對象獲得文件名 if (0 == GetMappedFileName(GetCurrentProcess(), pMem, pszFileName, //以設備名的形式獲得文件路徑,運行時設個斷點查看即可 MAX_PATH)) { printf("GetMappedFileName error: %d", GetLastError()); return FALSE; } TCHAR szTemp[MAX_PATH] = {0}; //獲取電腦上的所有驅動器,如"C:\" "D:\"等,連續放置的 if (0 == GetLogicalDriveStrings(BUFSIZE-1, szTemp)) { printf("GetLogicalDriveStrings error: %d", GetLastError()); return FALSE; } TCHAR szName[MAX_PATH]; TCHAR szDrive[3] = {0}; BOOL bFound = FALSE; //通過指針p的移動來順序訪問所有的驅動器目錄 TCHAR* p = szTemp; do { CopyMemory(szDrive, p, 2*sizeof(TCHAR)); //通過路徑查找設備名,如"C:" if (!QueryDosDevice(szDrive, szName, BUFSIZE)) { printf("QueryDosDrive error: %d", GetLastError()); return FALSE; } UINT uNameLen = lstrlen(szName); if (uNameLen < MAX_PATH) { //比較驅動器的設備名文件名與文件設備名是否匹配 bFound = _tcsnccmp(pszFileName, szName, uNameLen) == 0; if (bFound) { //如果匹配,說明已找到,構造路徑 TCHAR szTempFile[MAX_PATH]; wsprintf(szTempFile, TEXT("%s%s"), szDrive, pszFileName+uNameLen); lstrcpy(pszFileName, szTempFile); } } //這里不理解的話可以去看看GetLogicalDriveStrings while (*p++); }while (!bFound && *p); UnmapViewOfFile(pMem); CloseHandle(hFileMap); std::wcout<<_T("File Path is: ")<<pszFileName<<std::endl; //printf("File Path is %s\n", pszFileName); return TRUE; } void GetFileNameFromFILEPtr(FILE* pFile) { HANDLE hFile = (HANDLE)_get_osfhandle(fileno(pFile)); GetFileNameFromHandle(hFile); } void TestGetFilePathFromNormalFILEPtr() { FILE* fd = fopen("D:\\TestMemMapFile.txt", "r"); char c = fgetc(fd); GetFileNameFromFILEPtr(fd); }
2)然后嘗試對tmpfile生成的FILE* 提取文件路徑,提取失敗,因為這種臨時文件在獲取文件長度(GetFileSize)時就會失敗,無法轉換為內存映射文件,我懷疑可能是因為這個臨時文件本來就不在磁盤上,所以去做映射的時候就失敗了,相關代碼如下:
void TestGettempfilePath() { FILE *stream; char tempstring[] = "String to be written"; errno_t err = tmpfile_s(&stream); if( err ) { perror( "Could not open new temporary file\n" ); return; } else printf( "Temporary file was created\n"); fwrite(tempstring, 1, strlen(tempstring), stream); GetFileNameFromFILEPtr(stream); fclose(stream); }
三、結論
綜上,tmpfile()、tmpfile_s()生成的臨時文件沒有放在磁盤上,或者是沒有出現在文件系統中,或者至少是在一個非常隱蔽的地方,我暫時沒有辦法找到。
有了這層保障,后續使用tmpfile的時候,就不用太擔心泄密的問題了。
