[CRIU] [PATCH 1/5] util: Add mkdirpat_precise helper

Cyrill Gorcunov gorcunov at gmail.com
Tue Feb 26 12:13:31 MSK 2019


To know where new dirents are created.

Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
 criu/include/util.h |  6 +++++-
 criu/util.c         | 41 +++++++++++++++++++++++++++--------------
 2 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/criu/include/util.h b/criu/include/util.h
index 57192c5f273d..694b5358cf68 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -253,7 +253,11 @@ static inline bool issubpath(const char *path, const char *sub_path)
 /*
  * mkdir -p
  */
-int mkdirpat(int fd, const char *path, int mode);
+int mkdirpat_precise(int fd, const char *path, int mode, const char **new);
+static inline int mkdirpat(int fd, const char *path, int mode)
+{
+	return mkdirpat_precise(fd, path, mode, NULL);
+}
 
 /*
  * Tests whether a path is a prefix of another path. This is different than
diff --git a/criu/util.c b/criu/util.c
index 1cc4ecd4427e..fd9bd78326b5 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -1001,38 +1001,51 @@ struct vma_area *alloc_vma_area(void)
 	return p;
 }
 
-int mkdirpat(int fd, const char *path, int mode)
+/*
+ * Make the whole @path to the specified directory, report
+ * the position of newly created directories via @new.
+ */
+int mkdirpat_precise(int fd, const char *path, int mode, const char **new)
 {
-	size_t i;
-	char made_path[PATH_MAX], *pos;
+	char made_path[PATH_MAX];
+	char *pos = made_path, *end;
+	const char *where = path;
 
 	if (strlen(path) >= PATH_MAX) {
 		pr_err("path %s is longer than PATH_MAX\n", path);
 		return -ENOSPC;
 	}
 
-	strcpy(made_path, path);
+	strcpy(pos, path);
 
-	i = 0;
-	if (made_path[0] == '/')
-		i++;
+	end = pos + strlen(path);
+	if (pos[0] == '/')
+		pos++;
 
-	for (; i < strlen(made_path); i++) {
-		pos = strchr(made_path + i, '/');
+	for (; pos < end; pos++) {
+		pos = strchr(pos, '/');
 		if (pos)
 			*pos = '\0';
-		if (mkdirat(fd, made_path, mode) < 0 && errno != EEXIST) {
-			int ret = -errno;
-			pr_perror("couldn't mkdirpat directory %s", made_path);
-			return ret;
+		if (mkdirat(fd, made_path, mode) < 0) {
+			if (errno == EEXIST) {
+				where = path;
+			} else {
+				int ret = -errno;
+				pr_perror("couldn't mkdirpat directory %s", made_path);
+				return ret;
+			}
 		}
 		if (pos) {
 			*pos = '/';
-			i = pos - made_path;
+			if (where == path)
+				where = &path[pos - made_path + 1];
 		} else
 			break;
 	}
 
+	if (new)
+		*new = where;
+
 	return 0;
 }
 
-- 
2.20.1



More information about the CRIU mailing list