diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-09-09 02:43:15 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-09-09 02:43:15 -0400 |
| commit | a306f945571c8027badd2ca673304991f628900c (patch) | |
| tree | 328f8c57bec5e0b71d7c589213badb3b4d03b39c /builtins | |
| parent | 1fbe2cb5dd1aa4b20411ee0c3b00310677373a55 (diff) | |
Add mktemp functionality
Diffstat (limited to 'builtins')
| -rw-r--r-- | builtins/path.c | 59 | ||||
| -rw-r--r-- | builtins/path.h | 5 |
2 files changed, 60 insertions, 4 deletions
diff --git a/builtins/path.c b/builtins/path.c index d5305e30..fa15519a 100644 --- a/builtins/path.c +++ b/builtins/path.c @@ -28,6 +28,18 @@ PUREFUNC public Path_t Path$escape_text(Text_t text) return (Path_t)text; } +PUREFUNC public Path_t Path$concat(Path_t a, Path_t b) +{ + Path_t path = Text$concat(a, b); + while (Text$has(path, Pattern("/../"))) + path = Text$replace(path, Pattern("{!/}/../"), Text(""), Text(""), false); + + while (Text$has(path, Pattern("/./"))) + path = Text$replace(path, Pattern("/./"), Text("/"), Text(""), false); + + return path; +} + public Text_t Path$resolved(Path_t path, Path_t relative_to) { while (Text$has(path, Pattern("/../"))) @@ -129,13 +141,13 @@ static void _write(Path_t path, Text_t text, int mode, int permissions) const char *path_str = Text$as_c_string(path); int fd = open(path_str, mode, permissions); if (fd == -1) - fail("Could not write to file: %s\n%s", strerror(errno)); + fail("Could not write to file: %s\n%s", path_str, strerror(errno)); const char *str = Text$as_c_string(text); size_t len = strlen(str); ssize_t written = write(fd, str, len); if (written != (ssize_t)len) - fail("Could not write to file: %s\n%s", strerror(errno)); + fail("Could not write to file: %s\n%s", path_str, strerror(errno)); } public void Path$write(Path_t path, Text_t text, int permissions) @@ -161,7 +173,6 @@ public Text_t Path$read(Path_t path) fail("Could not read file: %k (%s)", &path, strerror(errno)); if ((sb.st_mode & S_IFMT) == S_IFREG) { // Use memory mapping if it's a real file: - printf("USING MMAP\n"); const char *mem = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); char *gc_mem = GC_MALLOC_ATOMIC((size_t)sb.st_size+1); memcpy(gc_mem, mem, (size_t)sb.st_size); @@ -270,6 +281,48 @@ public Array_t Path$subdirectories(Path_t path, bool include_hidden) return _filtered_children(path, include_hidden, S_IFDIR); } +public Path_t Path$unique_directory(Path_t path) +{ + if (Text$matches(path, Pattern("~/{..}"))) + path = Paths(Text$format("%s", getenv("HOME")), Text$slice(path, I(2), I(-1))); + const char *path_str = Text$as_c_string(path); + size_t len = strlen(path_str); + if (len >= PATH_MAX) fail("Path is too long: %s", path_str); + char buf[PATH_MAX] = {}; + strcpy(buf, path_str); + if (buf[len-1] == '/') + buf[--len] = '\0'; + char *created = mkdtemp(buf); + if (!created) fail("Failed to create temporary directory: %s (%s)", path_str, strerror(errno)); + return Text$format("%s/", created); +} + +public Text_t Path$write_unique(Path_t path, Text_t text) +{ + if (Text$matches(path, Pattern("~/{..}"))) + path = Paths(Text$format("%s", getenv("HOME")), Text$slice(path, I(2), I(-1))); + const char *path_str = Text$as_c_string(path); + size_t len = strlen(path_str); + if (len >= PATH_MAX) fail("Path is too long: %s", path_str); + char buf[PATH_MAX] = {}; + strcpy(buf, path_str); + + int64_t suffixlen = 0; + (void)Text$find(path, Pattern("{0+!X}{end}"), I(1), &suffixlen); + if (suffixlen < 0) suffixlen = 0; + + int fd = mkstemps(buf, suffixlen); + if (fd == -1) + fail("Could not write to unique file: %s\n%s", buf, strerror(errno)); + + const char *str = Text$as_c_string(text); + size_t write_len = strlen(str); + ssize_t written = write(fd, str, write_len); + if (written != (ssize_t)write_len) + fail("Could not write to file: %s\n%s", buf, strerror(errno)); + return Text$format("%s", buf); +} + public const TypeInfo Path$info = { .size=sizeof(Path_t), .align=__alignof__(Path_t), diff --git a/builtins/path.h b/builtins/path.h index ea1e99ae..0826f00d 100644 --- a/builtins/path.h +++ b/builtins/path.h @@ -13,7 +13,8 @@ #define Path(text) ((Path_t)Text(text)) #define Paths(...) ((Path_t)Texts(__VA_ARGS__)) -Path_t Path$escape_text(Text_t text); +PUREFUNC Path_t Path$concat(Path_t a, Path_t b); +PUREFUNC Path_t Path$escape_text(Text_t text); Path_t Path$resolved(Path_t path, Path_t relative_to); Path_t Path$relative(Path_t path, Path_t relative_to); bool Path$exists(Path_t path); @@ -30,6 +31,8 @@ void Path$create_directory(Path_t path, int permissions); Array_t Path$children(Path_t path, bool include_hidden); Array_t Path$files(Path_t path, bool include_hidden); Array_t Path$subdirectories(Path_t path, bool include_hidden); +Path_t Path$unique_directory(Path_t path); +Text_t Path$write_unique(Path_t path, Text_t text); extern const TypeInfo Path$info; |
