diff options
Diffstat (limited to 'stdlib')
| -rw-r--r-- | stdlib/paths.c | 65 | ||||
| -rw-r--r-- | stdlib/paths.h | 6 |
2 files changed, 70 insertions, 1 deletions
diff --git a/stdlib/paths.c b/stdlib/paths.c index 62908151..813c2004 100644 --- a/stdlib/paths.c +++ b/stdlib/paths.c @@ -4,6 +4,8 @@ #include <fcntl.h> #include <gc.h> #include <glob.h> +#include <grp.h> +#include <pwd.h> #include <stdbool.h> #include <stdint.h> #include <string.h> @@ -215,6 +217,27 @@ public bool Path$is_symlink(Path_t path) return (sb.st_mode & S_IFMT) == S_IFLNK; } +public bool Path$can_read(Path_t path) +{ + path = Path$_expand_home(path); + const char *path_str = Path$as_c_string(path); + return (euidaccess(path_str, R_OK) == 0); +} + +public bool Path$can_write(Path_t path) +{ + path = Path$_expand_home(path); + const char *path_str = Path$as_c_string(path); + return (euidaccess(path_str, W_OK) == 0); +} + +public bool Path$can_execute(Path_t path) +{ + path = Path$_expand_home(path); + const char *path_str = Path$as_c_string(path); + return (euidaccess(path_str, X_OK) == 0); +} + public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks) { struct stat sb; @@ -340,6 +363,45 @@ public OptionalText_t Path$read(Path_t path) return Text$from_bytes(bytes); } +public OptionalText_t Path$owner(Path_t path, bool follow_symlinks) +{ + struct stat sb; + int status = path_stat(path, follow_symlinks, &sb); + if (status != 0) return NONE_TEXT; + struct passwd *pw = getpwuid(sb.st_uid); + return pw ? Text$from_str(pw->pw_name) : NONE_TEXT; +} + +public OptionalText_t Path$group(Path_t path, bool follow_symlinks) +{ + struct stat sb; + int status = path_stat(path, follow_symlinks, &sb); + if (status != 0) return NONE_TEXT; + struct group *gr = getgrgid(sb.st_uid); + return gr ? Text$from_str(gr->gr_name) : NONE_TEXT; +} + +public void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks) +{ + 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); + 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); + group_id = grp->gr_gid; + } + const char *path_str = Path$as_c_string(path); + int result = follow_symlinks ? chown(path_str, owner_id, group_id) : lchown(path_str, owner_id, group_id); + if (result < 0) + fail("Could not set owner!"); +} + public void Path$remove(Path_t path, bool ignore_missing) { path = Path$_expand_home(path); @@ -515,6 +577,7 @@ public Path_t Path$with_component(Path_t path, Text_t component) }; ARRAY_INCREF(result.components); Array$insert(&result.components, &component, I(0), sizeof(Text_t)); + clean_components(&result.components); return result; } @@ -690,7 +753,7 @@ public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text); else if (path->type == PATH_ABSOLUTE) text = Text$concat(Text("/"), text); - else if (path->type == PATH_RELATIVE && path->components.length > 0 && !Text$equal_values(*(Text_t*)(path->components.data), Text(".."))) + else if (path->type == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text("..")))) text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text); if (color) diff --git a/stdlib/paths.h b/stdlib/paths.h index 3efe10da..b971cdf5 100644 --- a/stdlib/paths.h +++ b/stdlib/paths.h @@ -24,6 +24,9 @@ bool Path$is_directory(Path_t path, bool follow_symlinks); bool Path$is_pipe(Path_t path, bool follow_symlinks); bool Path$is_socket(Path_t path, bool follow_symlinks); bool Path$is_symlink(Path_t path); +bool Path$can_read(Path_t path); +bool Path$can_write(Path_t path); +bool Path$can_execute(Path_t path); OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks); OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks); OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks); @@ -33,6 +36,9 @@ void Path$append(Path_t path, Text_t text, int permissions); void Path$append_bytes(Path_t path, Array_t bytes, int permissions); OptionalText_t Path$read(Path_t path); OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t limit); +void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks); +OptionalText_t Path$owner(Path_t path, bool follow_symlinks); +OptionalText_t Path$group(Path_t path, bool follow_symlinks); void Path$remove(Path_t path, bool ignore_missing); void Path$create_directory(Path_t path, int permissions); Array_t Path$children(Path_t path, bool include_hidden); |
