Signed-off-by: jikai <jikai11@huawei.com> (cherry picked from commit 0a5748543c47e895a44afbc57de2d1ad6f9063d9)
628 lines
17 KiB
Diff
628 lines
17 KiB
Diff
From 713d31dfeb4425cfb40f565436504f4056ebe548 Mon Sep 17 00:00:00 2001
|
|
From: jake <jikai11@huawei.com>
|
|
Date: Tue, 21 Nov 2023 02:45:37 +0000
|
|
Subject: [PATCH 14/22] !288 use atomic write for config, secomp, oci_hook
|
|
files * use atomic write for config, secomp, oci_hook files
|
|
|
|
---
|
|
src/conf.c | 2 +-
|
|
src/lcrcontainer_extend.c | 150 ++++++++++-----------
|
|
src/utils.c | 268 +++++++++++++++++++++++++++++++++++++-
|
|
src/utils.h | 6 +-
|
|
4 files changed, 343 insertions(+), 83 deletions(-)
|
|
|
|
diff --git a/src/conf.c b/src/conf.c
|
|
index 10214f0..bfbfe1a 100644
|
|
--- a/src/conf.c
|
|
+++ b/src/conf.c
|
|
@@ -1241,7 +1241,7 @@ static int trans_one_oci_id_mapping(struct lcr_list *conf, const char *typ, cons
|
|
if (nret < 0 || (size_t)nret >= sizeof(subid)) {
|
|
return -1;
|
|
}
|
|
- nret = lcr_util_atomic_write_file(path, subid);
|
|
+ nret = lcr_util_flock_append_file(path, subid);
|
|
if (nret < 0) {
|
|
return -1;
|
|
}
|
|
diff --git a/src/lcrcontainer_extend.c b/src/lcrcontainer_extend.c
|
|
index 321be8c..b3202a7 100644
|
|
--- a/src/lcrcontainer_extend.c
|
|
+++ b/src/lcrcontainer_extend.c
|
|
@@ -346,7 +346,7 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
-static int lcr_spec_write_seccomp_line(int fd, const char *seccomp)
|
|
+static int lcr_spec_write_seccomp_line(FILE *fp, const char *seccomp)
|
|
{
|
|
size_t len;
|
|
char *line = NULL;
|
|
@@ -371,14 +371,17 @@ static int lcr_spec_write_seccomp_line(int fd, const char *seccomp)
|
|
ERROR("Sprintf failed");
|
|
goto cleanup;
|
|
}
|
|
+
|
|
if ((size_t)nret > len - 1) {
|
|
nret = (int)(len - 1);
|
|
}
|
|
+
|
|
line[nret] = '\n';
|
|
- if (write(fd, line, len) == -1) {
|
|
+ if (fwrite(line, 1, len ,fp) != len) {
|
|
SYSERROR("Write file failed");
|
|
goto cleanup;
|
|
}
|
|
+
|
|
ret = 0;
|
|
cleanup:
|
|
free(line);
|
|
@@ -389,9 +392,7 @@ static char *lcr_save_seccomp_file(const char *bundle, const char *seccomp_conf)
|
|
{
|
|
char seccomp[PATH_MAX] = { 0 };
|
|
char *real_seccomp = NULL;
|
|
- int fd = -1;
|
|
int nret;
|
|
- ssize_t written_cnt;
|
|
|
|
nret = snprintf(seccomp, sizeof(seccomp), "%s/seccomp", bundle);
|
|
if (nret < 0 || (size_t)nret >= sizeof(seccomp)) {
|
|
@@ -404,16 +405,9 @@ static char *lcr_save_seccomp_file(const char *bundle, const char *seccomp_conf)
|
|
goto cleanup;
|
|
}
|
|
|
|
- fd = lcr_util_open(real_seccomp, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
|
- if (fd == -1) {
|
|
- SYSERROR("Create file %s failed", real_seccomp);
|
|
- goto cleanup;
|
|
- }
|
|
-
|
|
- written_cnt = write(fd, seccomp_conf, strlen(seccomp_conf));
|
|
- close(fd);
|
|
- if (written_cnt == -1) {
|
|
- SYSERROR("write seccomp_conf failed");
|
|
+ if (lcr_util_atomic_write_file(real_seccomp, seccomp_conf, strlen(seccomp_conf),
|
|
+ CONFIG_FILE_MODE, false) != -1) {
|
|
+ ERROR("write seccomp_conf failed");
|
|
goto cleanup;
|
|
}
|
|
return real_seccomp;
|
|
@@ -605,34 +599,51 @@ out_free:
|
|
return NULL;
|
|
}
|
|
|
|
-
|
|
-static int lcr_open_config_file(const char *bundle)
|
|
+static FILE *lcr_open_tmp_config_file(const char *bundle, char **config_file, char **tmp_file)
|
|
{
|
|
char config[PATH_MAX] = { 0 };
|
|
- char *real_config = NULL;
|
|
int fd = -1;
|
|
int nret;
|
|
+ FILE *fp = NULL;
|
|
|
|
nret = snprintf(config, sizeof(config), "%s/config", bundle);
|
|
if (nret < 0 || (size_t)nret >= sizeof(config)) {
|
|
goto out;
|
|
}
|
|
|
|
- nret = lcr_util_ensure_path(&real_config, config);
|
|
+ nret = lcr_util_ensure_path(config_file, config);
|
|
if (nret < 0) {
|
|
ERROR("Failed to ensure path %s", config);
|
|
goto out;
|
|
}
|
|
|
|
- fd = lcr_util_open(real_config, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
|
+ *tmp_file = lcr_util_get_random_tmp_file(*config_file);
|
|
+ if (*tmp_file == NULL) {
|
|
+ ERROR("Failed to get random tmp file for %s", *config_file);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ fd = lcr_util_open(*tmp_file, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
|
if (fd == -1) {
|
|
- SYSERROR("Create file %s failed", real_config);
|
|
- lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", real_config);
|
|
+ SYSERROR("Create file %s failed", *tmp_file);
|
|
+ lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", *tmp_file);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ fp = fdopen(fd, "w");
|
|
+ if (fp == NULL) {
|
|
+ ERROR("FILE open failed");
|
|
goto out;
|
|
}
|
|
+
|
|
out:
|
|
- free(real_config);
|
|
- return fd;
|
|
+ if (fp == NULL) {
|
|
+ free(*tmp_file);
|
|
+ *tmp_file = NULL;
|
|
+ free(*config_file);
|
|
+ *config_file = NULL;
|
|
+ }
|
|
+ return fp;
|
|
}
|
|
|
|
// escape_string_encode unzip some escape characters
|
|
@@ -698,18 +709,17 @@ static char *escape_string_encode(const char *src)
|
|
return dst;
|
|
}
|
|
|
|
-static int lcr_spec_write_config(int fd, const struct lcr_list *lcr_conf)
|
|
+static int lcr_spec_write_config(FILE *fp, const struct lcr_list *lcr_conf)
|
|
{
|
|
- struct lcr_list *it = NULL;
|
|
size_t len;
|
|
- char *line = NULL;
|
|
- char *line_encode = NULL;
|
|
int ret = -1;
|
|
+ struct lcr_list *it = NULL;
|
|
+ char *line_encode = NULL;
|
|
+ char *line = NULL;
|
|
|
|
lcr_list_for_each(it, lcr_conf) {
|
|
lcr_config_item_t *item = it->elem;
|
|
int nret;
|
|
- size_t encode_len;
|
|
if (item != NULL) {
|
|
if (strlen(item->value) > ((SIZE_MAX - strlen(item->name)) - 4)) {
|
|
goto cleanup;
|
|
@@ -722,7 +732,6 @@ static int lcr_spec_write_config(int fd, const struct lcr_list *lcr_conf)
|
|
}
|
|
|
|
nret = snprintf(line, len, "%s = %s", item->name, item->value);
|
|
-
|
|
if (nret < 0 || (size_t)nret >= len) {
|
|
ERROR("Sprintf failed");
|
|
goto cleanup;
|
|
@@ -734,19 +743,21 @@ static int lcr_spec_write_config(int fd, const struct lcr_list *lcr_conf)
|
|
goto cleanup;
|
|
}
|
|
|
|
- encode_len = strlen(line_encode);
|
|
+ len = strlen(line_encode);
|
|
+ line_encode[len] = '\n';
|
|
|
|
- line_encode[encode_len] = '\n';
|
|
- if (write(fd, line_encode, encode_len + 1) == -1) {
|
|
+ if (fwrite(line_encode, 1, len + 1, fp) != len + 1) {
|
|
SYSERROR("Write file failed");
|
|
goto cleanup;
|
|
}
|
|
+
|
|
free(line);
|
|
line = NULL;
|
|
free(line_encode);
|
|
line_encode = NULL;
|
|
}
|
|
}
|
|
+
|
|
ret = 0;
|
|
cleanup:
|
|
free(line);
|
|
@@ -804,7 +815,9 @@ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list
|
|
const char *path = lcrpath ? lcrpath : LCRPATH;
|
|
char *bundle = NULL;
|
|
char *seccomp = NULL;
|
|
- int fd = -1;
|
|
+ char *config_file = NULL;
|
|
+ char *tmp_file = NULL;
|
|
+ FILE *fp = NULL;
|
|
int nret = 0;
|
|
|
|
if (name == NULL) {
|
|
@@ -829,71 +842,47 @@ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list
|
|
}
|
|
}
|
|
|
|
- fd = lcr_open_config_file(bundle);
|
|
- if (fd == -1) {
|
|
+ fp = lcr_open_tmp_config_file(bundle, &config_file, &tmp_file);
|
|
+ if (fp == NULL) {
|
|
goto out_free;
|
|
}
|
|
|
|
- if (lcr_spec_write_config(fd, lcr_conf)) {
|
|
+ if (lcr_spec_write_config(fp, lcr_conf)) {
|
|
goto out_free;
|
|
}
|
|
|
|
if (seccomp_conf != NULL) {
|
|
- nret = lcr_spec_write_seccomp_line(fd, seccomp);
|
|
+ nret = lcr_spec_write_seccomp_line(fp, seccomp);
|
|
if (nret) {
|
|
goto out_free;
|
|
}
|
|
}
|
|
|
|
- bret = true;
|
|
+ fclose(fp);
|
|
+ fp = NULL;
|
|
|
|
-out_free:
|
|
- free(bundle);
|
|
- free(seccomp);
|
|
- if (fd != -1) {
|
|
- close(fd);
|
|
- }
|
|
-
|
|
- return bret;
|
|
-}
|
|
-
|
|
-static int lcr_write_file(const char *path, const char *data, size_t len)
|
|
-{
|
|
- char *real_path = NULL;
|
|
- int fd = -1;
|
|
- int ret = -1;
|
|
-
|
|
- if (path == NULL || strlen(path) == 0 || data == NULL || len == 0) {
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if (lcr_util_ensure_path(&real_path, path) < 0) {
|
|
- ERROR("Failed to ensure path %s", path);
|
|
+ nret = rename(tmp_file, config_file);
|
|
+ if (nret != 0) {
|
|
+ ERROR("Failed to rename old file %s to target %s", tmp_file, config_file);
|
|
goto out_free;
|
|
}
|
|
|
|
- fd = lcr_util_open(real_path, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
|
- if (fd == -1) {
|
|
- ERROR("Create file %s failed", real_path);
|
|
- lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", real_path);
|
|
- goto out_free;
|
|
- }
|
|
-
|
|
- if (write(fd, data, len) == -1) {
|
|
- SYSERROR("write data to %s failed", real_path);
|
|
- goto out_free;
|
|
- }
|
|
-
|
|
- ret = 0;
|
|
+ bret = true;
|
|
|
|
out_free:
|
|
- if (fd != -1) {
|
|
- close(fd);
|
|
+ if (fp != NULL) {
|
|
+ fclose(fp);
|
|
}
|
|
- free(real_path);
|
|
- return ret;
|
|
-}
|
|
+ if (!bret && unlink(tmp_file) != 0 && errno != ENOENT) {
|
|
+ SYSERROR("Failed to remove temp file:%s", tmp_file);
|
|
+ }
|
|
+ free(config_file);
|
|
+ free(tmp_file);
|
|
+ free(seccomp);
|
|
+ free(bundle);
|
|
|
|
+ return bret;
|
|
+}
|
|
|
|
static bool lcr_write_ocihooks(const char *path, const oci_runtime_spec_hooks *hooks)
|
|
{
|
|
@@ -907,8 +896,9 @@ static bool lcr_write_ocihooks(const char *path, const oci_runtime_spec_hooks *h
|
|
goto out_free;
|
|
}
|
|
|
|
- if (lcr_write_file(path, json_hooks, strlen(json_hooks)) == -1) {
|
|
- SYSERROR("write json hooks failed");
|
|
+ if (lcr_util_atomic_write_file(path, json_hooks, strlen(json_hooks),
|
|
+ CONFIG_FILE_MODE, false) == -1) {
|
|
+ ERROR("write json hooks failed");
|
|
goto out_free;
|
|
}
|
|
|
|
diff --git a/src/utils.c b/src/utils.c
|
|
index df73985..68e9bc4 100644
|
|
--- a/src/utils.c
|
|
+++ b/src/utils.c
|
|
@@ -1248,7 +1248,7 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
-int lcr_util_atomic_write_file(const char *filepath, const char *content)
|
|
+int lcr_util_flock_append_file(const char *filepath, const char *content)
|
|
{
|
|
int fd;
|
|
int ret = 0;
|
|
@@ -1284,6 +1284,272 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static char *lcr_util_path_base(const char *path)
|
|
+{
|
|
+ char *dir = NULL;
|
|
+ int len = 0;
|
|
+ int i = 0;
|
|
+
|
|
+ if (path == NULL) {
|
|
+ ERROR("invalid NULL param");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ len = (int)strlen(path);
|
|
+ if (len == 0) {
|
|
+ return lcr_util_strdup_s(".");
|
|
+ }
|
|
+
|
|
+ dir = lcr_util_strdup_s(path);
|
|
+
|
|
+ // strip last slashes
|
|
+ for (i = len - 1; i >= 0; i--) {
|
|
+ if (dir[i] != '/') {
|
|
+ break;
|
|
+ }
|
|
+ dir[i] = '\0';
|
|
+ }
|
|
+
|
|
+ len = (int)strlen(dir);
|
|
+ if (len == 0) {
|
|
+ free(dir);
|
|
+ return lcr_util_strdup_s("/");
|
|
+ }
|
|
+
|
|
+ for (i = len - 1; i >= 0; i--) {
|
|
+ if (dir[i] == '/') {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (i < 0) {
|
|
+ return dir;
|
|
+ }
|
|
+
|
|
+ char *result = lcr_util_strdup_s(&dir[i + 1]);
|
|
+ free(dir);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static char *lcr_util_path_dir(const char *path)
|
|
+{
|
|
+ char *dir = NULL;
|
|
+ int len = 0;
|
|
+ int i = 0;
|
|
+
|
|
+ if (path == NULL) {
|
|
+ ERROR("invalid NULL param");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ len = (int)strlen(path);
|
|
+ if (len == 0) {
|
|
+ return lcr_util_strdup_s(".");
|
|
+ }
|
|
+
|
|
+ dir = lcr_util_strdup_s(path);
|
|
+
|
|
+ for (i = len - 1; i > 0; i--) {
|
|
+ if (dir[i] == '/') {
|
|
+ dir[i] = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (i == 0 && dir[0] == '/') {
|
|
+ free(dir);
|
|
+ return lcr_util_strdup_s("/");
|
|
+ }
|
|
+
|
|
+ return dir;
|
|
+}
|
|
+
|
|
+static int lcr_util_generate_random_str(char *id, size_t len)
|
|
+{
|
|
+ int fd = -1;
|
|
+ int num = 0;
|
|
+ size_t i;
|
|
+ const int m = 256;
|
|
+
|
|
+ if (id == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ len = len / 2;
|
|
+ fd = open("/dev/urandom", O_RDONLY);
|
|
+ if (fd == -1) {
|
|
+ ERROR("Failed to open /dev/urandom");
|
|
+ return -1;
|
|
+ }
|
|
+ for (i = 0; i < len; i++) {
|
|
+ int nret;
|
|
+ if (lcr_util_read_nointr(fd, &num, sizeof(int)) < 0) {
|
|
+ ERROR("Failed to read urandom value");
|
|
+ close(fd);
|
|
+ return -1;
|
|
+ }
|
|
+ unsigned char rs = (unsigned char)(num % m);
|
|
+ nret = snprintf((id + i * 2), ((len - i) * 2 + 1), "%02x", (unsigned int)rs);
|
|
+ if (nret < 0 || (size_t)nret >= ((len - i) * 2 + 1)) {
|
|
+ ERROR("Failed to snprintf random string");
|
|
+ close(fd);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ close(fd);
|
|
+ id[i * 2] = '\0';
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static char *lcr_util_path_join(const char *dir, const char *file)
|
|
+{
|
|
+ int nret = 0;
|
|
+ char path[PATH_MAX] = { 0 };
|
|
+ char cleaned[PATH_MAX] = { 0 };
|
|
+
|
|
+ if (dir == NULL || file == NULL) {
|
|
+ ERROR("NULL dir or file failed");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ nret = snprintf(path, PATH_MAX, "%s/%s", dir, file);
|
|
+ if (nret < 0 || (size_t)nret >= PATH_MAX) {
|
|
+ ERROR("dir or file too long failed");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (cleanpath(path, cleaned, sizeof(cleaned)) == NULL) {
|
|
+ ERROR("Failed to clean path: %s", path);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return lcr_util_strdup_s(cleaned);
|
|
+}
|
|
+
|
|
+char *lcr_util_get_random_tmp_file(const char *fname)
|
|
+{
|
|
+#define RANDOM_TMP_PATH 10
|
|
+ int nret = 0;
|
|
+ char *result = NULL;
|
|
+ char *base = NULL;
|
|
+ char *dir = NULL;
|
|
+ char rpath[PATH_MAX] = { 0x00 };
|
|
+ char random_tmp[RANDOM_TMP_PATH + 1] = { 0x00 };
|
|
+
|
|
+ if (fname == NULL) {
|
|
+ ERROR("Invalid NULL param");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ base = lcr_util_path_base(fname);
|
|
+ if (base == NULL) {
|
|
+ ERROR("Failed to get base of %s", fname);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ dir = lcr_util_path_dir(fname);
|
|
+ if (dir == NULL) {
|
|
+ ERROR("Failed to get dir of %s", fname);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (lcr_util_generate_random_str(random_tmp, (size_t)RANDOM_TMP_PATH)) {
|
|
+ ERROR("Failed to generate random str for random path");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ nret = snprintf(rpath, PATH_MAX, ".tmp-%s-%s", base, random_tmp);
|
|
+ if (nret < 0 || (size_t)nret >= PATH_MAX) {
|
|
+ ERROR("Failed to generate tmp base file");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = lcr_util_path_join(dir, rpath);
|
|
+
|
|
+out:
|
|
+ free(base);
|
|
+ free(dir);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static int do_atomic_write_file(const char *fname, const char *content, size_t content_len, mode_t mode, bool sync)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int dst_fd = -1;
|
|
+ ssize_t len = 0;
|
|
+
|
|
+ dst_fd = lcr_util_open(fname, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
|
+ if (dst_fd < 0) {
|
|
+ SYSERROR("Creat file: %s, failed", fname);
|
|
+ ret = -1;
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+ len = lcr_util_write_nointr(dst_fd, content, content_len);
|
|
+ if (len < 0 || ((size_t)len) != content_len) {
|
|
+ ret = -1;
|
|
+ SYSERROR("Write file failed");
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+ if (sync && (fdatasync(dst_fd) != 0)) {
|
|
+ ret = -1;
|
|
+ SYSERROR("Failed to sync data of file:%s", fname);
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+free_out:
|
|
+ if (dst_fd >= 0) {
|
|
+ close(dst_fd);
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int lcr_util_atomic_write_file(const char *fname, const char *content, size_t content_len, mode_t mode, bool sync)
|
|
+{
|
|
+ int ret = 0;
|
|
+ char *tmp_file = NULL;
|
|
+ char rpath[PATH_MAX] = { 0x00 };
|
|
+
|
|
+ if (fname == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+ if (content == NULL || content_len == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (cleanpath(fname, rpath, sizeof(rpath)) == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ tmp_file = lcr_util_get_random_tmp_file(fname);
|
|
+ if (tmp_file == NULL) {
|
|
+ ERROR("Failed to get tmp file for %s", fname);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = do_atomic_write_file(tmp_file, content, content_len, mode, sync);
|
|
+ if (ret != 0) {
|
|
+ ERROR("Failed to write content to tmp file for %s", tmp_file);
|
|
+ ret = -1;
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+ ret = rename(tmp_file, rpath);
|
|
+ if (ret != 0) {
|
|
+ ERROR("Failed to rename old file %s to target %s", tmp_file, rpath);
|
|
+ ret = -1;
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+free_out:
|
|
+ if (ret != 0 && unlink(tmp_file) != 0 && errno != ENOENT) {
|
|
+ SYSERROR("Failed to remove temp file:%s", tmp_file);
|
|
+ }
|
|
+ free(tmp_file);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/* swap in oci is memoy+swap, so here we need to get real swap */
|
|
int lcr_util_get_real_swap(int64_t memory, int64_t memory_swap, int64_t *swap)
|
|
{
|
|
diff --git a/src/utils.h b/src/utils.h
|
|
index 6a3764b..51e0dea 100644
|
|
--- a/src/utils.h
|
|
+++ b/src/utils.h
|
|
@@ -215,7 +215,11 @@ int lcr_util_safe_llong(const char *numstr, long long *converted);
|
|
char *lcr_util_strdup_s(const char *src);
|
|
int lcr_util_null_stdfds(void);
|
|
|
|
-int lcr_util_atomic_write_file(const char *filepath, const char *content);
|
|
+int lcr_util_flock_append_file(const char *filepath, const char *content);
|
|
+
|
|
+char *lcr_util_get_random_tmp_file(const char *fname);
|
|
+
|
|
+int lcr_util_atomic_write_file(const char *fname, const char *content, size_t content_len, mode_t mode, bool sync);
|
|
|
|
int lcr_util_get_real_swap(int64_t memory, int64_t memory_swap, int64_t *swap);
|
|
int lcr_util_trans_cpushare_to_cpuweight(int64_t cpu_share);
|
|
--
|
|
2.34.1
|
|
|