Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 94 additions & 32 deletions src/framework/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
* SPDX-License-Identifier: GPL-3.0-or-later
* -------------------------------------------------------------
* File Name : core.c
* File Authors : 曾奥然 <ccmywish@qq.com>
* | 郭恒 <2085471348@qq.com>
* Contributors : Peng Gao <gn3po4g@outlook.com>
* | Happy Game <happygame10124@gmail.com>
* | Yangmoooo <yangmoooo@outlook.com>
* | BingChunMoLi <bingchunmoli@bingchunmoli.com>
* File Authors : 曾奥然 <ccmywish@qq.com>
* | 郭恒 <2085471348@qq.com>
* Contributors : Peng Gao <gn3po4g@outlook.com>
* | Happy Game <happygame10124@gmail.com>
* | Yangmoooo <yangmoooo@outlook.com>
* | BingChunMoLi <bingchunmoli@bingchunmoli.com>
* | Mikachu2333 <mikachu.23333@zohomail.com>
* |
* Created On : <2023-08-29>
* Last Modified : <2025-09-12>
* Last Modified : <2025-09-29>
*
* chsrc framework
* ------------------------------------------------------------*/
Expand Down Expand Up @@ -239,9 +240,9 @@ chsrc_init_framework ()


void
chsrc_log_write (const char *filename)
chsrc_log_write (const char *filename, bool is_overwrite)
{
char *msg = ENGLISH ? "WRITE" : "写入";
char *msg = is_overwrite ? (ENGLISH ? "OVERWRITE" : "覆写") : (ENGLISH ? "WRITE" : "写入");

xy_log_brkt (blue(App_Name), bdblue(msg), blue(filename));
}
Expand Down Expand Up @@ -1386,14 +1387,14 @@ chsrc_run_directly (const char *cmd)
* @brief 在本目录创建一个临时文件
*
* @param[in] filename 文件名,不包含后缀名
* @oaram[in] postfix 后缀名,需要自己加 '.'
* @oaram[in] loud 创建成功时是否提示用户
* @param[out] tmpfilename 生成的临时文件名,可以为 NULL
* @param[in] postfix 后缀名,需要自己加 '.'
* @param[in] loud 创建成功时是否提示用户
* @param[out] tmpfilepath 生成的临时文件名,非 Windows 可以为 NULL
*
* @return 返回一个 FILE*,调用者需要关闭该文件
*/
FILE *
chsrc_make_tmpfile (char *filename, char *postfix, bool loud, char **tmpfilename)
chsrc_make_tmpfile (char *filename, char *postfix, bool loud, char **tmpfilepath)
{
#ifdef XY_Build_On_Windows
/**
Expand Down Expand Up @@ -1429,18 +1430,18 @@ chsrc_make_tmpfile (char *filename, char *postfix, bool loud, char **tmpfilename

/**
* 允许生成文件后不了解其文件名,调用者只了解 FILE*
* 这样的话,其实是是无法删除该文件的,但是生成在 /tmp 目录下我们恰好可以不用清理
* 这样的话,其实是无法删除该文件的,但是生成在 /tmp 目录下我们恰好可以不用清理
* 但是在 Windows 上,就没有办法了,所以我们禁止在 Windows 上不指定返回出的临时文件名
*/
if (xy.on_windows && !tmpfilename)
if (xy.on_windows && !tmpfilepath)
{
chsrc_error2 ("在 Windows 上,创建临时文件时必须指定返回的临时文件名");
xy_unreached();
}

if (tmpfilename)
if (tmpfilepath)
{
*tmpfilename = xy_strdup (tmpfile);
*tmpfilepath = xy_normalize_path (xy_strdup (tmpfile));
}

return f;
Expand Down Expand Up @@ -1673,7 +1674,7 @@ chsrc_append_to_file (const char *str, const char *filename)

log_anyway:
/* 输出recipe指定的文件名 */
chsrc_log_write (filename);
chsrc_log_write (filename, false);

/*
char *cmd = NULL;
Expand All @@ -1689,6 +1690,9 @@ chsrc_append_to_file (const char *str, const char *filename)
*/
}

/**
* @note 本函数不会自动在 str 末尾添加换行符
*/
static void
chsrc_prepend_to_file (const char *str, const char *filename)
{
Expand All @@ -1701,20 +1705,68 @@ chsrc_prepend_to_file (const char *str, const char *filename)
char *dir = xy_parent_dir (file);
chsrc_ensure_dir (dir);

char *cmd = NULL;
if (xy.on_windows)
char *tmpfile_name = "prepend";
char *tmpfile_ext = ".txt";
char *tmpnull = "";
FILE *tmp = chsrc_make_tmpfile (tmpfile_name, tmpfile_ext, true, &tmpnull);
fclose (tmp);
char *temp_file = xy_strcat (3, "chsrc_tmp_", tmpfile_name, tmpfile_ext);

FILE *input = fopen (file, "r");
FILE *output = fopen (temp_file, "w");

if (!output)
{
xy_unimplemented();
if (input) fclose (input);
free (temp_file);
char *msg = ENGLISH ? xy_2strcat ("Create temp file before Write prepend failed ", file)
: xy_2strcat ("尝试在文件开头写入时创建临时文件失败:", file);
chsrc_error2 (msg);
exit (Exit_ExternalError);
}
else

// 先写入要插入的行
fprintf (output, "%s", str);

// 如果原文件存在,复制其内容
if (input)
{
cmd = xy_strcat (4, "sed -i '1i ", str, "' ", file);
fseek (input, 0, SEEK_END);
long file_size = ftell (input);
fseek (input, 0, SEEK_SET);

char *buffer = malloc(file_size);
if (buffer == NULL)
{
fclose (input);
return;
}

size_t bytes = fread(buffer, 1, file_size, input);
if (bytes > 0) fwrite(buffer, 1, bytes, output);

free (buffer);
fclose (input);
}

fclose (output);
remove (file);

if (rename (temp_file, file) != 0)
{
unlink (temp_file);
free (temp_file);
char *msg = ENGLISH ? xy_2strcat ("Write prepend failed to ", file)
: xy_2strcat ("在文件开头写入失败: ", file);
chsrc_error2 (msg);
exit (Exit_ExternalError);
}
chsrc_run_as_a_service (cmd);

free (temp_file);

log_anyway:
/* 输出recipe指定的文件名 */
chsrc_log_write (filename);
chsrc_log_write (filename, false);
}

static void
Expand All @@ -1729,20 +1781,30 @@ chsrc_overwrite_file (const char *str, const char *filename)
char *dir = xy_parent_dir (file);
chsrc_ensure_dir (dir);

char *cmd = NULL;
if (xy.on_windows)
FILE *f = fopen (file, "w");
if (NULL==f)
{
cmd = xy_strcat (4, "echo ", str, " > ", file);
char *msg = ENGLISH ? xy_2strcat ("Unable to open file to overwrite: ", file)
: xy_2strcat ("无法打开文件以覆盖: ", file);
chsrc_error2 (msg);
exit (Exit_UserCause);
}
else

size_t len = strlen (str);
size_t ret = fwrite (str, len, 1, f);
if (ret != 1)
{
cmd = xy_strcat (4, "echo '", str, "' > ", file);
char *msg = ENGLISH ? xy_2strcat ("Write failed to ", file)
: xy_2strcat ("写入文件失败: ", file);
chsrc_error2 (msg);
exit (Exit_UserCause);
}
chsrc_run_as_a_service (cmd);

fclose (f);

log_anyway:
/* 输出recipe指定的文件名 */
chsrc_log_write (filename);
chsrc_log_write (filename, true);
}

static void
Expand Down
46 changes: 23 additions & 23 deletions test/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,37 +48,37 @@ main (int argc, char const *argv[])
assert (chsrc_check_program_quietly_when_exist ("curl"));
chsrc_ensure_program ("curl");

#define bkup "README.md.bak"
chsrc_ensure_dir ("test");

chsrc_backup ("README.md");
assert (chsrc_check_file (bkup));
char *tmpfile_content = "Line2\n\nLine3\n";
char *tmpfile_name = "test";
char *tmpfile_ext = ".txt";
char *tmpfile = "";

chsrc_ensure_dir ("test");
FILE *tmp = chsrc_make_tmpfile (tmpfile_name, tmpfile_ext, true, &tmpfile);
fwrite (tmpfile_content, sizeof (char), strlen (tmpfile_content), tmp);
fclose (tmp);

chsrc_append_to_file ("append", bkup);
if (!xy.on_windows)
{
chsrc_prepend_to_file ("prepend", bkup);
}
chsrc_overwrite_file ("overwrite", bkup);
chsrc_view_file (bkup);
char *tmpfile_bk = xy_2strcat (tmpfile, ".bak");

assert (xy_file_exist (tmpfile));
chsrc_backup (tmpfile);\
assert (chsrc_check_file (tmpfile_bk));
remove (tmpfile_bk);

chsrc_append_to_file ("Line4\n", tmpfile);
assert_str (xy_file_to_str (tmpfile), "Line2\n\nLine3\nLine4\n");

chsrc_prepend_to_file ("Line1 \n", tmpfile);
assert_str (xy_file_to_str (tmpfile), "Line1 \nLine2\n\nLine3\nLine4\n");

chsrc_overwrite_file ("Line999 \nLine998\nLine997\n", tmpfile);
assert_str (xy_file_to_str (tmpfile), "Line999 \nLine998\nLine997\n");

chsrc_log (xy_2strcat ("CPU arch = ", chsrc_get_cpuarch ()));
print ("chsrc: CPU cores = ");
println (chsrc_get_cpucore ());

if (xy.on_windows)
{
chsrc_run ("del " bkup, RunOpt_No_Last_New_Line);
}
else
{
chsrc_run ("rm " bkup, RunOpt_No_Last_New_Line);
}

char *tmpfile = NULL;
FILE *tmp = chsrc_make_tmpfile ("tmpfile", ".txt", true, &tmpfile);
fclose (tmp);
remove (tmpfile);

// chsrc_run_in_inline_pwsh_shell ("Write-Host \"Hello from inline PowerShell\"");
Expand Down