diff --git a/docs/paths.md b/docs/paths.md index a4437c6..f53cc97 100644 --- a/docs/paths.md +++ b/docs/paths.md @@ -180,11 +180,12 @@ A list of paths for the children. ### `create_directory` **Description:** -Creates a new directory at the specified path with the given permissions. +Creates a new directory at the specified path with the given permissions. If +any of the parent directories do not exist, they will be created as needed. **Usage:** ```markdown -create_directory(path: Path, permissions=0o644[32]) -> Void +create_directory(path: Path, permissions=0o755[32]) -> Void ``` **Parameters:** diff --git a/environment.c b/environment.c index 96c68c5..385e27b 100644 --- a/environment.c +++ b/environment.c @@ -267,7 +267,7 @@ env_t *new_compilation_unit(CORD *libname) {"base_name", "Path$base_name", "func(path:Path)->Text"}, {"by_line", "Path$by_line", "func(path:Path)->(func()->Text?)?"}, {"children", "Path$children", "func(path:Path, include_hidden=no)->[Path]"}, - {"create_directory", "Path$create_directory", "func(path:Path, permissions=0o644[32])"}, + {"create_directory", "Path$create_directory", "func(path:Path, permissions=0o755[32])"}, {"escape_int", "Int$value_as_text", "func(i:Int)->Path"}, {"escape_path", "Path$escape_path", "func(path:Path)->Path"}, {"escape_text", "Path$escape_text", "func(text:Text)->Path"}, diff --git a/stdlib/paths.c b/stdlib/paths.c index 0122853..0119dbf 100644 --- a/stdlib/paths.c +++ b/stdlib/paths.c @@ -322,8 +322,27 @@ public void Path$remove(Path_t path, bool ignore_missing) public void Path$create_directory(Path_t path, int permissions) { path = Path$_expand_home(path); - if (mkdir(Text$as_c_string(path), (mode_t)permissions) != 0) - fail("Could not create directory: %k (%s)", &path, strerror(errno)); + char *c_path = Text$as_c_string(path); + char *end = c_path + strlen(c_path); + if (*end == '/' && end > c_path) { + *end = '\0'; + --end; + } + char *end_of_component = strchrnul(c_path + 1, '/'); + for (;;) { + if (end_of_component < end) + *end_of_component = '\0'; + + int status = mkdir(c_path, (mode_t)permissions); + if (status != 0 && errno != EEXIST) + fail("Could not create directory: %s (%s)", c_path, strerror(errno)); + + if (end_of_component >= end) + break; + + *end_of_component = '/'; + end_of_component = strchrnul(end_of_component + 1, '/'); + } } static Array_t _filtered_children(Path_t path, bool include_hidden, mode_t filter)