summaryrefslogtreecommitdiffhomepage
path: root/lib/fs.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-05-15 16:01:42 +0200
committerJo-Philipp Wich <jo@mein.io>2021-05-15 16:01:42 +0200
commitdfb73798cf0364f13f7c32d468de476b3a6b56bf (patch)
tree6c50e73385bf3f5eae61f31461bf85362626a75b /lib/fs.c
parent1ddf5b68fa60736c1dd9ffda5eba09bbd90309e1 (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.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/lib/fs.c b/lib/fs.c
index 707e6db..4f96a6c 100644
--- a/lib/fs.c
+++ b/lib/fs.c
@@ -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 }
};