aboutsummaryrefslogtreecommitdiff
path: root/src/pow_lua.c
diff options
context:
space:
mode:
authorforever2k38 <forever2k38@forever2k38.net>2026-10-10 20:40:48 +0200
committerforever2k38 <forever2k38@forever2k38.net>2026-10-10 20:40:48 +0200
commite28b0347a1977975e5a921e8c3d56239cd48cd40 (patch)
tree9a989ccfad861a6eb3024bb837c605f6ddc881cb /src/pow_lua.c
parenteb83bf8fd18946c4358f784fa39dad0731a6220a (diff)
permission bits while installing
Diffstat (limited to 'src/pow_lua.c')
-rw-r--r--src/pow_lua.c142
1 files changed, 107 insertions, 35 deletions
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);
+
+ pow_log_error("failed to stat source file %s while installing", src_str);
- FILE *src_stream = fopen(src, "r");
+ return 2;
+ }
+
+ int dest_fd = open(dest_str, O_WRONLY | O_CREAT | O_TRUNC, permission_bit);
- if (!src_stream) {
- free(src);
- free(dest);
+ if (dest_fd == -1) {
+ close(src_fd);
- pow_log_error("failed to open source file %s while installing", src);
+ 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;
- if (!dest_stream) {
- free(src);
- free(dest);
+ while (remaining > 0) {
+ size_t to_read = remaining > sizeof(buf) ? sizeof(buf) : remaining;
- fclose(src_stream);
+ bytes_read = read(src_fd, buf, to_read);
- pow_log_error("failed to open destination file %s for writing while installing", dest);
+ if (bytes_read == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
- return 2;
- }
+ pow_log_error("err?");
- int src_fd = fileno(src_stream);
- int dest_fd = fileno(dest_stream);
+ close(dest_fd);
+ close(src_fd);
- struct stat src_stat = {0};
- int result = fstat(src_fd, &src_stat);
+ return 2;
+ }
- 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;
+ if (bytes_read == 0) {
+ pow_log_error("unexpected EOF during copy");
+
+ 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;
}