aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-23 14:53:44 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-23 14:53:44 -0400
commit89c427172a25bdb7802d142c03f3504a53a304fc (patch)
tree78fe65ee8a6466649e0aa6ef7aebb31ffc1769fe
parentb432fc82c78bb890eca5938c7754950f089c7abe (diff)
Support creating parent directories as needed (mkdir -p) and also set a
better default permission for new dirs
-rw-r--r--docs/paths.md5
-rw-r--r--environment.c2
-rw-r--r--stdlib/paths.c23
3 files changed, 25 insertions, 5 deletions
diff --git a/docs/paths.md b/docs/paths.md
index a4437c6f..f53cc971 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 96c68c59..385e27b5 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 01228537..0119dbf0 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)