aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/paths.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-03-27 17:26:51 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-03-27 17:26:51 -0400
commit3c52a756339a2d96824d21a7d3ad5de7fc1085a0 (patch)
treee5299a25ebb76186d6372b700710d7c8c7fe0728 /src/stdlib/paths.c
parent2186e84de0c0fd47ba48eaa35f74ea2754c3b81f (diff)
Deprecate custom printf specifiers in favor of print() function that
uses _Generic() to generically convert any value to a string or print as a string.
Diffstat (limited to 'src/stdlib/paths.c')
-rw-r--r--src/stdlib/paths.c86
1 files changed, 39 insertions, 47 deletions
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index fae75e98..83e480e1 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -17,6 +17,7 @@
#include <unistd.h>
#include <unistr.h>
+#include "print.h"
#include "arrays.h"
#include "enums.h"
#include "files.h"
@@ -122,8 +123,7 @@ public Path_t Path$_concat(int n, Path_t items[n])
ARRAY_INCREF(result.components);
for (int i = 1; i < n; i++) {
if (items[i].type.$tag != PATH_RELATIVE)
- fail("Cannot concatenate an absolute or home-based path onto another path: (%s)\n",
- Path$as_c_string(items[i]));
+ fail("Cannot concatenate an absolute or home-based path onto another path: (", items[i], ")");
Array$insert_all(&result.components, items[i].components, I(0), sizeof(Text_t));
}
clean_components(&result.components);
@@ -146,8 +146,7 @@ public Path_t Path$resolved(Path_t path, Path_t relative_to)
public Path_t Path$relative_to(Path_t path, Path_t relative_to)
{
if (path.type.$tag != relative_to.type.$tag)
- fail("Cannot create a path relative to a different path with a mismatching type: (%k) relative to (%k)",
- (Text_t[1]){Path$as_text(&path, false, &Path$info)}, (Text_t[1]){Path$as_text(&relative_to, false, &Path$info)});
+ fail("Cannot create a path relative to a different path with a mismatching type: (", path, ") relative to (", relative_to, ")");
Path_t result = {.type.$tag=PATH_RELATIVE};
int64_t shared = 0;
@@ -274,13 +273,13 @@ static void _write(Path_t path, Array_t bytes, int mode, int permissions)
const char *path_str = Path$as_c_string(path);
int fd = open(path_str, mode, permissions);
if (fd == -1)
- fail("Could not write to file: %s\n%s", path_str, strerror(errno));
+ fail("Could not write to file: ", path_str, "\n", strerror(errno));
if (bytes.stride != 1)
Array$compact(&bytes, 1);
ssize_t written = write(fd, bytes.data, (size_t)bytes.length);
if (written != (ssize_t)bytes.length)
- fail("Could not write to file: %s\n%s", path_str, strerror(errno));
+ fail("Could not write to file: ", path_str, "\n", strerror(errno));
close(fd);
}
@@ -328,7 +327,7 @@ public OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t count)
content[sb.st_size] = '\0';
close(fd);
if (count.small && (int64_t)sb.st_size < target_count)
- fail("Could not read %ld bytes from %k (only got %zu)", target_count, &path, sb.st_size);
+ fail("Could not read ", target_count, " bytes from ", path, " (only got ", sb.st_size, ")");
int64_t len = count.small ? target_count : (int64_t)sb.st_size;
return (Array_t){.data=content, .atomic=1, .stride=1, .length=len};
} else {
@@ -358,7 +357,7 @@ public OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t count)
}
close(fd);
if (count.small != 0 && (int64_t)len < target_count)
- fail("Could not read %ld bytes from %k (only got %zu)", target_count, &path, len);
+ fail("Could not read ", target_count, " bytes from ", path, " (only got ", len, ")");
return (Array_t){.data=content, .atomic=1, .stride=1, .length=len};
}
}
@@ -393,14 +392,14 @@ public void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t gro
uid_t owner_id = (uid_t)-1;
if (owner.length >= 0) {
struct passwd *pwd = getpwnam(Text$as_c_string(owner));
- if (pwd == NULL) fail("Not a valid user: %k", &owner);
+ if (pwd == NULL) fail("Not a valid user: ", owner);
owner_id = pwd->pw_uid;
}
gid_t group_id = (gid_t)-1;
if (group.length >= 0) {
struct group *grp = getgrnam(Text$as_c_string(group));
- if (grp == NULL) fail("Not a valid group: %k", &group);
+ if (grp == NULL) fail("Not a valid group: ", group);
group_id = grp->gr_gid;
}
const char *path_str = Path$as_c_string(path);
@@ -415,17 +414,16 @@ static int _remove_files(const char *path, const struct stat *sbuf, int type, st
switch (type) {
case FTW_F: case FTW_SL: case FTW_SLN:
if (remove(path) < 0) {
- fail("Could not remove file: %s (%s)", path, strerror(errno));
+ fail("Could not remove file: ", path, " (", strerror(errno), ")");
return -1;
}
return 0;
case FTW_DP:
if (rmdir(path) != 0)
- fail("Could not remove directory: %s (%s)", path, strerror(errno));
+ fail("Could not remove directory: ", path, " (", strerror(errno), ")");
return 0;
default:
- printf("Type: %d\n", type);
- fail("Could not remove path: %s (not a file or directory)", path, strerror(errno));
+ fail("Could not remove path: ", path, " (not a file or directory)");
return -1;
}
}
@@ -437,19 +435,19 @@ public void Path$remove(Path_t path, bool ignore_missing)
struct stat sb;
if (lstat(path_str, &sb) != 0) {
if (!ignore_missing)
- fail("Could not remove file: %s (%s)", path_str, strerror(errno));
+ fail("Could not remove file: ", path_str, " (", strerror(errno), ")");
return;
}
if ((sb.st_mode & S_IFMT) == S_IFREG || (sb.st_mode & S_IFMT) == S_IFLNK) {
if (unlink(path_str) != 0 && !ignore_missing)
- fail("Could not remove file: %s (%s)", path_str, strerror(errno));
+ fail("Could not remove file: ", path_str, " (", strerror(errno), ")");
} else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
const int num_open_fd = 10;
if (nftw(path_str, _remove_files, num_open_fd, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
fail("Could not remove directory: %s (%s)", path_str, strerror(errno));
} else {
- fail("Could not remove path: %s (not a file or directory)", path_str, strerror(errno));
+ fail("Could not remove path: ", path_str, " (not a file or directory)");
}
}
@@ -459,7 +457,7 @@ public void Path$create_directory(Path_t path, int permissions)
const char *c_path = Path$as_c_string(path);
int status = mkdir(c_path, (mode_t)permissions);
if (status != 0 && errno != EEXIST)
- fail("Could not create directory: %s (%s)", c_path, strerror(errno));
+ fail("Could not create directory: ", c_path, " (", strerror(errno), ")");
}
static Array_t _filtered_children(Path_t path, bool include_hidden, mode_t filter)
@@ -471,7 +469,7 @@ static Array_t _filtered_children(Path_t path, bool include_hidden, mode_t filte
size_t path_len = strlen(path_str);
DIR *d = opendir(path_str);
if (!d)
- fail("Could not open directory: %k (%s)", &path, strerror(errno));
+ fail("Could not open directory: ", path, " (", strerror(errno), ")");
if (path_str[path_len-1] == '/')
--path_len;
@@ -516,13 +514,13 @@ public Path_t Path$unique_directory(Path_t path)
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
size_t len = strlen(path_str);
- if (len >= PATH_MAX) fail("Path is too long: %s", path_str);
+ if (len >= PATH_MAX) fail("Path is too long: ", 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));
+ if (!created) fail("Failed to create temporary directory: ", path_str, " (", strerror(errno), ")");
return Path$from_str(created);
}
@@ -531,7 +529,7 @@ public Path_t Path$write_unique_bytes(Path_t path, Array_t bytes)
path = Path$expand_home(path);
const char *path_str = Path$as_c_string(path);
size_t len = strlen(path_str);
- if (len >= PATH_MAX) fail("Path is too long: %s", path_str);
+ if (len >= PATH_MAX) fail("Path is too long: ", path_str);
char buf[PATH_MAX] = {};
strcpy(buf, path_str);
@@ -543,14 +541,14 @@ public Path_t Path$write_unique_bytes(Path_t path, Array_t bytes)
int fd = mkstemps(buf, suffixlen);
if (fd == -1)
- fail("Could not write to unique file: %s\n%s", buf, strerror(errno));
+ fail("Could not write to unique file: ", buf, "\n", strerror(errno));
if (bytes.stride != 1)
Array$compact(&bytes, 1);
ssize_t written = write(fd, bytes.data, (size_t)bytes.length);
if (written != (ssize_t)bytes.length)
- fail("Could not write to file: %s\n%s", buf, strerror(errno));
+ fail("Could not write to file: ", buf, "\n", strerror(errno));
close(fd);
return Path$from_str(buf);
}
@@ -736,42 +734,36 @@ public PUREFUNC bool Path$equal_values(Path_t a, Path_t b)
return Array$equal(&a.components, &b.components, Array$info(&Text$info));
}
-public const char *Path$as_c_string(Path_t path)
+public int Path$print(FILE *f, Path_t path)
{
if (path.components.length == 0) {
- if (path.type.$tag == PATH_ABSOLUTE) return "/";
- else if (path.type.$tag == PATH_RELATIVE) return ".";
- else if (path.type.$tag == PATH_HOME) return "~";
+ if (path.type.$tag == PATH_ABSOLUTE) return fputs("/", f);
+ else if (path.type.$tag == PATH_RELATIVE) return fputs(".", f);
+ else if (path.type.$tag == PATH_HOME) return fputs("~", f);
}
- size_t len = 0, capacity = 16;
- char *buf = GC_MALLOC_ATOMIC(capacity);
+ int n = 0;
if (path.type.$tag == PATH_ABSOLUTE) {
- buf[len++] = '/';
+ n += fputc('/', f);
} else if (path.type.$tag == PATH_HOME) {
- buf[len++] = '~';
- buf[len++] = '/';
+ n += fputs("~/", f);
} else if (path.type.$tag == PATH_RELATIVE) {
- if (!Text$equal_values(*(Text_t*)path.components.data, Text(".."))) {
- buf[len++] = '.';
- buf[len++] = '/';
- }
+ if (!Text$equal_values(*(Text_t*)path.components.data, Text("..")))
+ n += fputs("./", f);
}
for (int64_t i = 0; i < path.components.length; i++) {
Text_t *comp = (Text_t*)(path.components.data + i*path.components.stride);
- const char *comp_str = Text$as_c_string(*comp);
- size_t comp_len = strlen(comp_str);
- if (len + comp_len + 1 > capacity) {
- buf = GC_REALLOC(buf, (capacity += MIN(comp_len + 2, 16)));
- }
- memcpy(&buf[len], comp_str, comp_len);
- len += comp_len;
+ n += Text$print(f, *comp);
if (i + 1 < path.components.length)
- buf[len++] = '/';
+ n += fputc('/', f);
}
- buf[len++] = '\0';
- return buf;
+ return n;
+}
+
+public const char *Path$as_c_string(Path_t path)
+{
+ return String(path);
}
public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type)