diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-05-15 16:01:42 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2021-05-15 16:01:42 +0200 |
commit | dfb73798cf0364f13f7c32d468de476b3a6b56bf (patch) | |
tree | 6c50e73385bf3f5eae61f31461bf85362626a75b /lib/fs.c | |
parent | 1ddf5b68fa60736c1dd9ffda5eba09bbd90309e1 (diff) |
fs: implement chmod(), chown(), rename() and glob() functions
- The chmod() function expects a path string as first and an integer mode
value as second argument.
- The chown() function takes a path string as first argument, and either
a string, an integer or null as second user and third group argument
respectively.
If either user or group are given as string, they're resolved to an
uid/gid using getpwnam()/getgrnam() internally. If either lookup fails,
the ownership change is not performed.
If either user or group are null or -1, they're left unchanged.
- The rename() function takes two path strings, the old path being the
first argument and the new path the second one.
- The glob() function takes an arbitrary number of glob patterns and
resolves matching files for each one. In case of multiple patterns,
no efforts are made to remove duplicates or to globally sort the combined
match list. The list of matches for each individual pattern is sorted.
Returns an array containing all matched file paths.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib/fs.c')
-rw-r--r-- | lib/fs.c | 184 |
1 files changed, 184 insertions, 0 deletions
@@ -22,6 +22,9 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/sysmacros.h> +#include <grp.h> +#include <pwd.h> +#include <glob.h> #include "../module.h" @@ -655,6 +658,183 @@ uc_fs_chdir(uc_vm *vm, size_t nargs) return ucv_boolean_new(true); } +static uc_value_t * +uc_fs_chmod(uc_vm *vm, size_t nargs) +{ + uc_value_t *path = uc_get_arg(0); + uc_value_t *mode = uc_get_arg(1); + + if (ucv_type(path) != UC_STRING || + ucv_type(mode) != UC_INTEGER) + err_return(EINVAL); + + if (chmod(ucv_string_get(path), (mode_t)ucv_int64_get(mode)) == -1) + err_return(errno); + + return ucv_boolean_new(true); +} + +static bool +uc_fs_resolve_user(uc_value_t *v, uid_t *uid) +{ + struct passwd *pw = NULL; + int64_t n; + char *s; + + *uid = (uid_t)-1; + + switch (ucv_type(v)) { + case UC_INTEGER: + n = ucv_int64_get(v); + + if (n < -1) { + errno = ERANGE; + + return false; + } + + *uid = (uid_t)n; + + return true; + + case UC_STRING: + s = ucv_string_get(v); + pw = getpwnam(s); + + if (!pw) { + errno = ENOENT; + + return false; + } + + *uid = pw->pw_uid; + + return true; + + case UC_NULL: + return true; + + default: + errno = EINVAL; + + return false; + } +} + +static bool +uc_fs_resolve_group(uc_value_t *v, gid_t *gid) +{ + struct group *gr = NULL; + int64_t n; + char *s; + + *gid = (gid_t)-1; + + switch (ucv_type(v)) { + case UC_INTEGER: + n = ucv_int64_get(v); + + if (n < -1) { + errno = ERANGE; + + return false; + } + + *gid = (gid_t)n; + + return true; + + case UC_STRING: + s = ucv_string_get(v); + gr = getgrnam(s); + + if (!gr) { + errno = ENOENT; + + return false; + } + + *gid = gr->gr_gid; + + return true; + + case UC_NULL: + return true; + + default: + errno = EINVAL; + + return false; + } +} + +static uc_value_t * +uc_fs_chown(uc_vm *vm, size_t nargs) +{ + uc_value_t *path = uc_get_arg(0); + uc_value_t *user = uc_get_arg(1); + uc_value_t *group = uc_get_arg(2); + uid_t uid; + gid_t gid; + + if (ucv_type(path) != UC_STRING) + err_return(EINVAL); + + if (!uc_fs_resolve_user(user, &uid) || + !uc_fs_resolve_group(group, &gid)) + return NULL; + + if (chown(ucv_string_get(path), uid, gid) == -1) + return NULL; + + return ucv_boolean_new(true); +} + +static uc_value_t * +uc_fs_rename(uc_vm *vm, size_t nargs) +{ + uc_value_t *oldpath = uc_get_arg(0); + uc_value_t *newpath = uc_get_arg(1); + + if (ucv_type(oldpath) != UC_STRING || + ucv_type(newpath) != UC_STRING) + err_return(EINVAL); + + if (rename(ucv_string_get(oldpath), ucv_string_get(newpath))) + return NULL; + + return ucv_boolean_new(true); +} + +static uc_value_t * +uc_fs_glob(uc_vm *vm, size_t nargs) +{ + uc_value_t *pat, *arr; + glob_t gl = { 0 }; + size_t i; + + for (i = 0; i < nargs; i++) { + pat = uc_get_arg(i); + + if (ucv_type(pat) != UC_STRING) { + globfree(&gl); + err_return(EINVAL); + } + + glob(ucv_string_get(pat), i ? GLOB_APPEND : 0, NULL, &gl); + } + + arr = ucv_array_new(vm); + + for (i = 0; i < gl.gl_pathc; i++) + ucv_array_push(arr, ucv_string_new(gl.gl_pathv[i])); + + globfree(&gl); + + return arr; +} + + static const uc_cfunction_list proc_fns[] = { { "read", uc_fs_pread }, { "write", uc_fs_pwrite }, @@ -693,6 +873,10 @@ static const uc_cfunction_list global_fns[] = { { "unlink", uc_fs_unlink }, { "getcwd", uc_fs_getcwd }, { "chdir", uc_fs_chdir }, + { "chmod", uc_fs_chmod }, + { "chown", uc_fs_chown }, + { "rename", uc_fs_rename }, + { "glob", uc_fs_glob } }; |