Skip to content

Commit 04da124

Browse files
Mikachu2333ccmywish
authored andcommitted
修复 chsrc_make_tmpfile 在win上错误处理不完善的问题
1 parent 0a49c7b commit 04da124

File tree

1 file changed

+66
-12
lines changed

1 file changed

+66
-12
lines changed

src/framework/core.c

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,32 +1396,86 @@ chsrc_run_directly (const char *cmd)
13961396
FILE *
13971397
chsrc_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

Comments
 (0)