这两天由于修改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: ")<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的时候,就不用太担心泄密的问题了。