aboutsummaryrefslogtreecommitdiff
path: root/gdb/common
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-09-17 10:48:20 -0600
committerTom Tromey <tom@tromey.com>2018-10-27 11:58:41 -0600
commite418a61a67a3476826259163383e5deb661042cc (patch)
tree44214b56d20367f0979c8c00e469edcb290171a6 /gdb/common
parent29be4d9dee1263b36e33421dd8ea69b9b7308391 (diff)
downloadgdb-e418a61a67a3476826259163383e5deb661042cc.zip
gdb-e418a61a67a3476826259163383e5deb661042cc.tar.gz
gdb-e418a61a67a3476826259163383e5deb661042cc.tar.bz2
Move mkdir_recursive to common/filestuff.c
This moves mkdir_recursive from dwarf-index-cache.c to common/filestuff.c, and also changes it to return a boolean that says whether or not it worked. gdb/ChangeLog 2018-10-27 Tom Tromey <tom@tromey.com> * unittests/mkdir-recursive-selftests.c: New file. * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add unittests/mkdir-recursive-selftests.c. * dwarf-index-cache.c (mkdir_recursive): Move to common/filestuff.c. (index_cache::store): Check return value of mkdir_recursive. (create_dir_and_check, test_mkdir_recursive): Move to new file. (_initialize_index_cache): Don't register test. * common/filestuff.h (mkdir_recursive): Declare. * common/filestuff.c (mkdir_recursive): Move from dwarf-index-cache.c. Return bool.
Diffstat (limited to 'gdb/common')
-rw-r--r--gdb/common/filestuff.c45
-rw-r--r--gdb/common/filestuff.h10
2 files changed, 55 insertions, 0 deletions
diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c
index dfd86f9..d4bd1a8 100644
--- a/gdb/common/filestuff.c
+++ b/gdb/common/filestuff.c
@@ -447,3 +447,48 @@ is_regular_file (const char *name, int *errno_ptr)
*errno_ptr = EINVAL;
return false;
}
+
+/* See common/filestuff.h. */
+
+bool
+mkdir_recursive (const char *dir)
+{
+ gdb::unique_xmalloc_ptr<char> holder (xstrdup (dir));
+ char * const start = holder.get ();
+ char *component_start = start;
+ char *component_end = start;
+
+ while (1)
+ {
+ /* Find the beginning of the next component. */
+ while (*component_start == '/')
+ component_start++;
+
+ /* Are we done? */
+ if (*component_start == '\0')
+ return true;
+
+ /* Find the slash or null-terminator after this component. */
+ component_end = component_start;
+ while (*component_end != '/' && *component_end != '\0')
+ component_end++;
+
+ /* Temporarily replace the slash with a null terminator, so we can create
+ the directory up to this component. */
+ char saved_char = *component_end;
+ *component_end = '\0';
+
+ /* If we get EEXIST and the existing path is a directory, then we're
+ happy. If it exists, but it's a regular file and this is not the last
+ component, we'll fail at the next component. If this is the last
+ component, the caller will fail with ENOTDIR when trying to
+ open/create a file under that path. */
+ if (mkdir (start, 0700) != 0)
+ if (errno != EEXIST)
+ return false;
+
+ /* Restore the overwritten char. */
+ *component_end = saved_char;
+ component_start = component_end;
+ }
+}
diff --git a/gdb/common/filestuff.h b/gdb/common/filestuff.h
index e9328f5..ecfc18d 100644
--- a/gdb/common/filestuff.h
+++ b/gdb/common/filestuff.h
@@ -122,4 +122,14 @@ typedef std::unique_ptr<DIR, gdb_dir_deleter> gdb_dir_up;
we're expecting a regular file. */
extern bool is_regular_file (const char *name, int *errno_ptr);
+
+/* A cheap (as in low-quality) recursive mkdir. Try to create all the
+ parents directories up to DIR and DIR itself. Stop if we hit an
+ error along the way. There is no attempt to remove created
+ directories in case of failure.
+
+ Returns false on failure and sets errno. */
+
+extern bool mkdir_recursive (const char *dir);
+
#endif /* FILESTUFF_H */