@@ -1396,32 +1396,86 @@ chsrc_run_directly (const char *cmd)
13961396FILE *
13971397chsrc_make_tmpfile (char * filename , char * postfix , bool loud , char * * tmpfilepath )
13981398{
1399+ char * tmpfile = NULL ;
1400+ FILE * f = NULL ;
1401+
13991402#ifdef XY_Build_On_Windows
14001403 /**
1401- * Windows 上没有 mkstemps(),只有 mkstemp() 和 _mktemp_s(),这后两者效果是等价的,只不过传参不同,
1402- * 这意味着我们无法给一个文件名后缀(postfix),只能生成一个临时文件名
1403- * 然而 PowerShell 的执行,即使加了 -File 参数,也必须要求你拥有 .ps1 后缀
1404- * 这使得我们在 Windows 上只能创建一个假的临时文件
1404+ * Windows 上使用 GetTempPath 和 GetTempFileName 创建临时文件
1405+ * 这是 Windows API 推荐的标准方法
1406+ *
1407+ * 由于 GetTempFileName 不支持自定义后缀,我们需要:
1408+ * 1. 使用 GetTempFileName 生成唯一的临时文件名
1409+ * 2. 将其重命名为带有正确后缀的文件名(PowerShell 需要 .ps1 后缀)
14051410 */
1406- char * tmpfile = xy_strcat (3 , "chsrc_tmp_" , filename , postfix );
1407- FILE * f = fopen (tmpfile , "w+" );
1411+ char temp_path [MAX_PATH ];
1412+ char temp_filename [MAX_PATH ];
1413+
1414+ /* 获取系统临时目录 */
1415+ DWORD ret = GetTempPathA (MAX_PATH , temp_path );
1416+ if (ret == 0 || ret > MAX_PATH )
1417+ {
1418+ char * msg = CHINESE ? "无法获取系统临时目录" : "Unable to get system temp directory" ;
1419+ chsrc_error2 (msg );
1420+ exit (Exit_ExternalError );
1421+ }
1422+
1423+ /* 生成唯一的临时文件名 (会自动创建文件) */
1424+ ret = GetTempFileNameA (temp_path , "chsrc_" , 0 , temp_filename );
1425+ if (ret == 0 )
1426+ {
1427+ char * msg = CHINESE ? "无法生成临时文件名" : "Unable to generate temporary filename" ;
1428+ chsrc_error2 (msg );
1429+ exit (Exit_ExternalError );
1430+ }
1431+
1432+ tmpfile = xy_strcat (4 , temp_filename , "_" , filename , postfix );
1433+
1434+ /* 删除 GetTempFileName 自动创建的文件 */
1435+ DeleteFileA (temp_filename );
1436+
1437+ /* 创建带有正确后缀的文件 */
1438+ f = fopen (tmpfile , "w+" );
1439+
1440+ if (!f )
1441+ {
1442+ char * msg = CHINESE ? "无法创建临时文件: " : "Unable to create temporary file: " ;
1443+ msg = xy_2strcat (msg , tmpfile );
1444+ chsrc_error2 (msg );
1445+ exit (Exit_ExternalError );
1446+ }
14081447#else
1409- char * tmpfile = xy_strcat (5 , "/tmp/" , "chsrc_tmp_" , filename , "_XXXXXX" , postfix );
1448+ /**
1449+ * 非 Windows 平台使用 mkstemps() 创建临时文件
1450+ * 这是 POSIX 标准方法,可以指定后缀名
1451+ */
1452+ tmpfile = xy_strcat (5 , "/tmp/" , "chsrc_tmp_" , filename , "_XXXXXX" , postfix );
14101453 size_t postfix_len = strlen (postfix );
14111454
1412- /* 和 _mktemp_s () 参数不同,前者是整个缓存区大小,这里的长度是后缀长度 */
1455+ /* mkstemps () 会原子性地创建文件并返回文件描述符 */
14131456 int fd = mkstemps (tmpfile , postfix_len );
1414- FILE * f = fdopen (fd , "w+" );
1415- #endif
14161457
1417- if (! f )
1458+ if (fd == -1 )
14181459 {
14191460 char * msg = CHINESE ? "无法创建临时文件: " : "Unable to create temporary file: " ;
14201461 msg = xy_2strcat (msg , tmpfile );
14211462 chsrc_error2 (msg );
14221463 exit (Exit_ExternalError );
14231464 }
1424- else if (loud )
1465+
1466+ f = fdopen (fd , "w+" );
1467+
1468+ if (!f )
1469+ {
1470+ close (fd ); /* 关闭文件描述符以避免泄漏 */
1471+ char * msg = CHINESE ? "无法打开临时文件: " : "Unable to open temporary file: " ;
1472+ msg = xy_2strcat (msg , tmpfile );
1473+ chsrc_error2 (msg );
1474+ exit (Exit_ExternalError );
1475+ }
1476+ #endif
1477+
1478+ if (loud )
14251479 {
14261480 char * msg = CHINESE ? "已创建临时文件: " : "Temporary file created: " ;
14271481 msg = xy_2strcat (msg , tmpfile );
0 commit comments