From 6f55306e04e51e2e9021a5fe29288e415a10a868 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Mon, 13 May 2019 18:38:22 +0200 Subject: [PATCH 1/2] gfileutils: Ignore ENOENT from all except the last element Ignore ENOENT errors up until the last element while trying to create each of the path elements in case a restricted file-system is being used where path elements can be hidden or non-accessible. --- glib/gfileutils.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 676c08c21..8bff0e9c5 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -248,9 +248,12 @@ g_mkdir_with_parents (const gchar *pathname, if (g_mkdir (fn, mode) == -1 && errno != EEXIST) { int errno_save = errno; - g_free (fn); - errno = errno_save; - return -1; + if (p && errno != ENOENT) + { + g_free (fn); + errno = errno_save; + return -1; + } } } else if (!g_file_test (fn, G_FILE_TEST_IS_DIR)) From ca98741251cacf0e70d054b1dac7a17ded120cbb Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Mon, 13 May 2019 18:36:55 +0200 Subject: [PATCH 2/2] gfileutils: Try creating complete path first Try to create the complete path right away and fall back to creating all path elements one by one. This also helps to avoid TOCTTOU problems and avoids walking the path all the time, providing a nice performance gain, by avoiding syscalls. --- glib/gfileutils.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 8bff0e9c5..16ee66384 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -226,6 +226,20 @@ g_mkdir_with_parents (const gchar *pathname, return -1; } + /* try to create the full path first */ + if (g_mkdir (pathname, mode) == 0) + return 0; + else if (errno == EEXIST) + { + if (!g_file_test (pathname, G_FILE_TEST_IS_DIR)) + { + errno = ENOTDIR; + return -1; + } + return 0; + } + + /* walk the full path and try creating each element */ fn = g_strdup (pathname); if (g_path_is_absolute (fn))