From e28b0347a1977975e5a921e8c3d56239cd48cd40 Mon Sep 17 00:00:00 2001 From: forever2k38 Date: Sat, 10 Oct 2026 20:40:48 +0200 Subject: permission bits while installing --- src/pow_lua.c | 142 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 35 deletions(-) (limited to 'src/pow_lua.c') diff --git a/src/pow_lua.c b/src/pow_lua.c index 0cd1019..122c62a 100644 --- a/src/pow_lua.c +++ b/src/pow_lua.c @@ -30,7 +30,30 @@ #include "stdlib.h" #include "unistd.h" #include "string.h" -#include "sys/sendfile.h" +#include "fcntl.h" +#include "sys/stat.h" +#include "errno.h" + +int parse_octal_string(const char *str) { + if (str[0] == '0' && (str[1] == 'o' || str[1] == 'O')) { + str += 2; + } else if (str[0] == '0') { + str += 1; + } + + int result = 0; + while (*str) { + int digit = *str - '0'; + if (digit < 0 || digit > 7) { + errno = EINVAL; + return -1; + } + result = result * 8 + digit; + str++; + } + + return result; +} int pow_lua_extract(lua_State *L) { int r; @@ -145,7 +168,6 @@ int pow_lua_extract(lua_State *L) { return 1; } - int pow_lua_install(lua_State *L) { if (!lua_isstring(L, 1)) { lua_pushnil(L); @@ -161,70 +183,120 @@ int pow_lua_install(lua_State *L) { return 2; } - char *src = strdup(lua_tostring(L, 1)); + if (!lua_isstring(L, 3)) { + pow_log_info("no permission bit specified for install function, defaulting to 644"); + } - if (!src) { - pow_log_error("failed to strdup source string"); + const char *src_str = lua_tostring(L, 1); + const char *dest_str = lua_tostring(L, 2); - return 2; + mode_t permission_bit = S_IRUSR | S_IWUSR | S_IROTH | S_IRGRP; + + if (lua_isstring(L, 3)) { + char *endptr; + unsigned long perms = strtoul(lua_tostring(L, 3), &endptr, 8); + if (*endptr != '\0') { + lua_pushnil(L); + lua_pushstring(L, "invalid octal permission string"); + + return 2; + } + permission_bit = (mode_t)perms; } - char *dest = strdup(lua_tostring(L, 2)); + pow_log_info("installing: %s to %s", src_str, dest_str); - if (!dest) { - free(src); + int src_fd = open(src_str, O_RDONLY); - pow_log_error("failed to strdup dest string"); + if (src_fd == -1) { + pow_log_error("failed to open source file %s while installing", src_str); return 2; } - pow_log_info("installing: %s to %s", src, dest); + struct stat src_stat = {0}; + if (fstat(src_fd, &src_stat) == -1) { + close(src_fd); - FILE *src_stream = fopen(src, "r"); + pow_log_error("failed to stat source file %s while installing", src_str); - if (!src_stream) { - free(src); - free(dest); + return 2; + } - pow_log_error("failed to open source file %s while installing", src); + int dest_fd = open(dest_str, O_WRONLY | O_CREAT | O_TRUNC, permission_bit); + + if (dest_fd == -1) { + close(src_fd); + + pow_log_error("failed to open destination file %s for writing while installing", dest_str); return 2; } - FILE *dest_stream = fopen(dest, "w"); + char buf[8192]; + off_t copied = 0; + ssize_t bytes_read; + ssize_t bytes_written; + off_t remaining = src_stat.st_size; + + while (remaining > 0) { + size_t to_read = remaining > sizeof(buf) ? sizeof(buf) : remaining; - if (!dest_stream) { - free(src); - free(dest); + bytes_read = read(src_fd, buf, to_read); - fclose(src_stream); + if (bytes_read == -1) { + if (errno == EINTR) { + continue; + } - pow_log_error("failed to open destination file %s for writing while installing", dest); + pow_log_error("err?"); - return 2; - } + close(dest_fd); + close(src_fd); - int src_fd = fileno(src_stream); - int dest_fd = fileno(dest_stream); + return 2; + } - struct stat src_stat = {0}; - int result = fstat(src_fd, &src_stat); + if (bytes_read == 0) { + pow_log_error("unexpected EOF during copy"); - off_t copied = 0; - while (result == 0 && copied < src_stat.st_size) { - ssize_t written = sendfile(dest_fd, src_fd, &copied, SIZE_MAX); - copied += written; + close(dest_fd); + close(src_fd); - if (written == -1) { - result = -1; + return 2; } + + ssize_t written = 0; + while (written < bytes_read) { + bytes_written = write(dest_fd, buf + written, bytes_read - written); + + if (bytes_written == -1) { + if (errno == EINTR) { + continue; + } + + pow_log_error("write failed during install"); + + close(dest_fd); + close(src_fd); + + return 2; + } + + written += bytes_written; + } + + copied += bytes_read; + remaining -= bytes_read; } - if (fchmod(dest_fd, src_stat.st_mode) == -1) { + if (fchmod(dest_fd, permission_bit) == -1) { pow_log_error("failed to set permission bits, expect breakage!"); } + close(dest_fd); + close(src_fd); + return 1; } -- cgit v1.3