1 Star 0 Fork 47

wangfengtu/src-iSulad

forked from src-openEuler/iSulad 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0012-unpack-add-remove-target-file-in-handle-.wh.patch 13.00 KB
一键复制 编辑 原始数据 按行查看 历史
gaohuatao 提交于 2020-11-12 19:32 +08:00 . update from openeuler
From 9cbd114034321e232dfe2540216c9c8c3094e362 Mon Sep 17 00:00:00 2001
From: lifeng68 <lifeng68@huawei.com>
Date: Tue, 27 Oct 2020 16:31:37 +0800
Subject: [PATCH 12/28] unpack: add remove target file in handle .wh.
Signed-off-by: lifeng68 <lifeng68@huawei.com>
---
src/cmd/isulad/main.c | 2 +-
.../graphdriver/devmapper/driver_devmapper.c | 2 +-
src/utils/cutils/utils_file.c | 29 ++-
src/utils/cutils/utils_file.h | 3 +
src/utils/tar/util_archive.c | 172 +++++++++++++++++-
src/utils/tar/util_archive.h | 5 +-
6 files changed, 198 insertions(+), 15 deletions(-)
diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c
index 9297aad..5cad285 100644
--- a/src/cmd/isulad/main.c
+++ b/src/cmd/isulad/main.c
@@ -103,7 +103,7 @@ static int create_client_run_path(const char *group)
ret = -1;
goto out;
}
-
+
out:
return ret;
}
diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
index ec337a8..1674c28 100644
--- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
+++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
@@ -339,7 +339,7 @@ int devmapper_apply_diff(const char *id, const struct graphdriver *driver, const
goto out;
}
- options.whiteout_format = OVERLAY_WHITEOUT_FORMATE;
+ options.whiteout_format = REMOVE_WHITEOUT_FORMATE;
if (archive_unpack(content, layer_fs, &options) != 0) {
ERROR("devmapper: failed to unpack to :%s", layer_fs);
ret = -1;
diff --git a/src/utils/cutils/utils_file.c b/src/utils/cutils/utils_file.c
index 92e032b..9f7f5fe 100644
--- a/src/utils/cutils/utils_file.c
+++ b/src/utils/cutils/utils_file.c
@@ -282,7 +282,7 @@ static int recursive_rmdir_helper(const char *dirpath, int recursive_depth, int
struct dirent *pdirent = NULL;
DIR *directory = NULL;
int failure = 0;
- char fname[MAXPATHLEN];
+ char fname[PATH_MAX];
directory = opendir(dirpath);
if (directory == NULL) {
@@ -300,8 +300,8 @@ static int recursive_rmdir_helper(const char *dirpath, int recursive_depth, int
(void)memset(fname, 0, sizeof(fname));
- pathname_len = snprintf(fname, MAXPATHLEN, "%s/%s", dirpath, pdirent->d_name);
- if (pathname_len < 0 || pathname_len >= MAXPATHLEN) {
+ pathname_len = snprintf(fname, PATH_MAX, "%s/%s", dirpath, pdirent->d_name);
+ if (pathname_len < 0 || pathname_len >= PATH_MAX) {
ERROR("Pathname too long");
failure = 1;
continue;
@@ -1142,7 +1142,7 @@ static void recursive_cal_dir_size_helper(const char *dirpath, int recursive_dep
struct dirent *pdirent = NULL;
DIR *directory = NULL;
struct stat fstat;
- char fname[MAXPATHLEN];
+ char fname[PATH_MAX];
// cal dir self node and size
nret = lstat(dirpath, &fstat);
@@ -1169,8 +1169,8 @@ static void recursive_cal_dir_size_helper(const char *dirpath, int recursive_dep
(void)memset(fname, 0, sizeof(fname));
- pathname_len = snprintf(fname, MAXPATHLEN, "%s/%s", dirpath, pdirent->d_name);
- if (pathname_len < 0 || pathname_len >= MAXPATHLEN) {
+ pathname_len = snprintf(fname, PATH_MAX, "%s/%s", dirpath, pdirent->d_name);
+ if (pathname_len < 0 || pathname_len >= PATH_MAX) {
ERROR("Pathname too long");
continue;
}
@@ -1239,7 +1239,7 @@ static void recursive_cal_dir_size__without_hardlink_helper(const char *dirpath,
int nret = 0;
struct dirent *pdirent = NULL;
DIR *directory = NULL;
- char fname[MAXPATHLEN];
+ char fname[PATH_MAX];
directory = opendir(dirpath);
if (directory == NULL) {
@@ -1257,8 +1257,8 @@ static void recursive_cal_dir_size__without_hardlink_helper(const char *dirpath,
(void)memset(fname, 0, sizeof(fname));
- pathname_len = snprintf(fname, MAXPATHLEN, "%s/%s", dirpath, pdirent->d_name);
- if (pathname_len < 0 || pathname_len >= MAXPATHLEN) {
+ pathname_len = snprintf(fname, PATH_MAX, "%s/%s", dirpath, pdirent->d_name);
+ if (pathname_len < 0 || pathname_len >= PATH_MAX) {
ERROR("Pathname too long");
continue;
}
@@ -1610,3 +1610,14 @@ int util_set_file_group(const char *fname, const char *group)
out:
return ret;
}
+
+int util_recursive_remove_path(const char *path)
+{
+ int ret = 0;
+
+ if (unlink(path) != 0 && errno != ENOENT) {
+ ret = util_recursive_rmdir(path, 0);
+ }
+
+ return ret;
+}
\ No newline at end of file
diff --git a/src/utils/cutils/utils_file.h b/src/utils/cutils/utils_file.h
index 3aff3d6..a873114 100644
--- a/src/utils/cutils/utils_file.h
+++ b/src/utils/cutils/utils_file.h
@@ -100,6 +100,9 @@ int util_proc_file_line_by_line(FILE *fp, read_line_callback_t cb, void *context
int util_set_file_group(const char *fname, const char *group);
+// try to remove the path, path is file or dir
+int util_recursive_remove_path(const char *path);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c
index 0ae99be..04603a2 100644
--- a/src/utils/tar/util_archive.c
+++ b/src/utils/tar/util_archive.c
@@ -61,7 +61,7 @@ ssize_t read_content(struct archive *a, void *client_data, const void **buff)
return mydata->content->read(mydata->content->context, mydata->buff, sizeof(mydata->buff));
}
-static bool whiteout_convert_read(struct archive_entry *entry, const char *dst_path)
+static bool overlay_whiteout_convert_read(struct archive_entry *entry, const char *dst_path, map_t *unpacked_path_map)
{
bool do_write = true;
char *base = NULL;
@@ -143,6 +143,149 @@ static int copy_data(struct archive *ar, struct archive *aw)
}
}
+static int remove_files_in_opq_dir(const char *dirpath, int recursive_depth, map_t *unpacked_path_map)
+{
+ struct dirent *pdirent = NULL;
+ DIR *directory = NULL;
+ int ret = 0;
+ char fname[PATH_MAX] = { 0 };
+
+ if ((recursive_depth + 1) > MAX_PATH_DEPTH) {
+ ERROR("Reach max path depth: %s", dirpath);
+ return -1;
+ }
+
+ directory = opendir(dirpath);
+ if (directory == NULL) {
+ ERROR("Failed to open %s", dirpath);
+ return -1;
+ }
+ pdirent = readdir(directory);
+ for (; pdirent != NULL; pdirent = readdir(directory)) {
+ struct stat fstat;
+ int pathname_len;
+
+ if (!strcmp(pdirent->d_name, ".") || !strcmp(pdirent->d_name, "..")) {
+ continue;
+ }
+
+ (void)memset(fname, 0, sizeof(fname));
+
+ pathname_len = snprintf(fname, PATH_MAX, "%s/%s", dirpath, pdirent->d_name);
+ if (pathname_len < 0 || pathname_len >= PATH_MAX) {
+ ERROR("Pathname too long");
+ ret = -1;
+ continue;
+ }
+
+ // not exist in unpacked paths map, just remove the path
+ if (map_search(unpacked_path_map, (void *)fname) == NULL) {
+ if (util_recursive_remove_path(fname) != 0) {
+ ERROR("Failed to remove path %s", fname);
+ ret = -1;
+ }
+ continue;
+ }
+
+ if (lstat(fname, &fstat) != 0) {
+ ERROR("Failed to stat %s", fname);
+ ret = -1;
+ continue;
+ }
+
+ if (S_ISDIR(fstat.st_mode)) {
+ if (remove_files_in_opq_dir(fname, recursive_depth + 1, unpacked_path_map) != 0) {
+ ret = -1;
+ continue;
+ }
+ }
+ }
+
+ if (closedir(directory) != 0) {
+ ERROR("Failed to close directory %s", dirpath);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static bool remove_whiteout_convert(struct archive_entry *entry, const char *dst_path, map_t *unpacked_path_map)
+{
+ bool do_write = true;
+ char *base = NULL;
+ char *dir = NULL;
+ char *originalpath = NULL;
+
+ base = util_path_base(dst_path);
+ if (base == NULL) {
+ ERROR("Failed to get base of %s", dst_path);
+ goto out;
+ }
+
+ dir = util_path_dir(dst_path);
+ if (dir == NULL) {
+ ERROR("Failed to get dir of %s", dst_path);
+ goto out;
+ }
+
+ if (strcmp(base, WHITEOUT_OPAQUEDIR) == 0) {
+ if (remove_files_in_opq_dir(dir, 0, unpacked_path_map) != 0) {
+ SYSERROR("Failed to remove files in opq dir %s", dir);
+ goto out;
+ }
+ do_write = false;
+ goto out;
+ }
+
+ if (strncmp(base, WHITEOUT_PREFIX, strlen(WHITEOUT_PREFIX)) == 0) {
+ char *origin_base = &base[strlen(WHITEOUT_PREFIX)];
+ originalpath = util_path_join(dir, origin_base);
+ if (originalpath == NULL) {
+ ERROR("Failed to get original path of %s", dst_path);
+ goto out;
+ }
+
+ if (util_recursive_remove_path(originalpath) != 0) {
+ ERROR("Failed to delete original path %s", originalpath);
+ goto out;
+ }
+
+ do_write = false;
+ goto out;
+ }
+
+out:
+ free(base);
+ free(dir);
+ free(originalpath);
+ return do_write;
+}
+
+typedef bool (*whiteout_convert_call_back_t)(struct archive_entry *entry, const char *dst_path,
+ map_t *unpacked_path_map);
+
+struct whiteout_convert_map {
+ whiteout_format_type type;
+ whiteout_convert_call_back_t wh_cb;
+};
+
+struct whiteout_convert_map g_wh_cb_map[] = { { OVERLAY_WHITEOUT_FORMATE, overlay_whiteout_convert_read },
+ { REMOVE_WHITEOUT_FORMATE, remove_whiteout_convert }
+};
+
+static whiteout_convert_call_back_t get_whiteout_convert_cb(whiteout_format_type whiteout_type)
+{
+ size_t i = 0;
+
+ for (i = 0; i < sizeof(g_wh_cb_map) / sizeof(g_wh_cb_map[0]); i++) {
+ if (whiteout_type == g_wh_cb_map[i].type) {
+ return g_wh_cb_map[i].wh_cb;
+ }
+ }
+
+ return NULL;
+}
+
int archive_unpack_handler(const struct io_read_wrapper *content, const char *dstdir,
const struct archive_options *options)
{
@@ -153,6 +296,15 @@ int archive_unpack_handler(const struct io_read_wrapper *content, const char *ds
struct archive_entry *entry = NULL;
char *dst_path = NULL;
int flags;
+ whiteout_convert_call_back_t wh_handle_cb = NULL;
+ map_t *unpacked_path_map = NULL; // used for hanling opaque dir, marke paths had been unpacked
+
+ unpacked_path_map = map_new(MAP_STR_BOOL, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC);
+ if (unpacked_path_map == NULL) {
+ ERROR("Out of memory");
+ ret = -1;
+ goto out;
+ }
mydata = util_common_calloc_s(sizeof(struct archive_content_data));
if (mydata == NULL) {
@@ -187,6 +339,8 @@ int archive_unpack_handler(const struct io_read_wrapper *content, const char *ds
goto out;
}
+ wh_handle_cb = get_whiteout_convert_cb(options->whiteout_format);
+
for (;;) {
free(dst_path);
dst_path = NULL;
@@ -217,28 +371,42 @@ int archive_unpack_handler(const struct io_read_wrapper *content, const char *ds
goto out;
}
- if (options->whiteout_format == OVERLAY_WHITEOUT_FORMATE && !whiteout_convert_read(entry, dst_path)) {
+ if (wh_handle_cb != NULL && !wh_handle_cb(entry, dst_path, unpacked_path_map)) {
continue;
}
ret = archive_write_header(ext, entry);
if (ret != ARCHIVE_OK) {
ERROR("Fail to handle tar header: %s", archive_error_string(ext));
+ ret = -1;
+ goto out;
} else if (archive_entry_size(entry) > 0) {
ret = copy_data(a, ext);
if (ret != ARCHIVE_OK) {
ERROR("Failed to do copy tar data: %s", archive_error_string(ext));
+ ret = -1;
+ goto out;
}
}
ret = archive_write_finish_entry(ext);
if (ret != ARCHIVE_OK) {
ERROR("Failed to freeing archive entry: %s\n", archive_error_string(ext));
+ ret = -1;
+ goto out;
+ }
+
+ bool b = true;
+ if (!map_replace(unpacked_path_map, (void *)dst_path, (void *)(&b))) {
+ ERROR("Failed to replace unpacked path map element");
+ ret = -1;
+ goto out;
}
}
ret = 0;
out:
+ map_free(unpacked_path_map);
free(dst_path);
archive_read_close(a);
archive_read_free(a);
diff --git a/src/utils/tar/util_archive.h b/src/utils/tar/util_archive.h
index 4c4e4a1..6f65daa 100644
--- a/src/utils/tar/util_archive.h
+++ b/src/utils/tar/util_archive.h
@@ -30,8 +30,9 @@ extern "C" {
#endif
typedef enum {
- NONE_WHITEOUT_FORMATE = 0,
- OVERLAY_WHITEOUT_FORMATE = 1,
+ NONE_WHITEOUT_FORMATE = 0, // handle whiteouts as normal files
+ OVERLAY_WHITEOUT_FORMATE = 1, // handle whiteouts as the way as overlay
+ REMOVE_WHITEOUT_FORMATE = 2, // handle whiteouts by removing the target files
} whiteout_format_type;
struct archive_options {
--
2.20.1
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wangfengtu/src-iSulad.git
git@gitee.com:wangfengtu/src-iSulad.git
wangfengtu
src-iSulad
src-iSulad
master

搜索帮助