|
@@ -0,0 +1,330 @@
|
|
|
|
+
|
|
|
|
+#include <errno.h>
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
+#include <sys/types.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <unistd.h>
|
|
|
|
+#include <sys/types.h>
|
|
|
|
+#include <dirent.h>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#include "esh.h"
|
|
|
|
+#include "toruby.h"
|
|
|
|
+#include "tr_macro.h"
|
|
|
|
+#include "monolog.h"
|
|
|
|
+#include "rh.h"
|
|
|
|
+#include "state.h"
|
|
|
|
+#include "server.h"
|
|
|
|
+#include "tr_file.h"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct tr_file {
|
|
|
|
+ FILE * file;
|
|
|
|
+ struct woe_config * cfg;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+typedef struct tr_file tr_file;
|
|
|
|
+
|
|
|
|
+static void file_close(tr_file * file) {
|
|
|
|
+ if (!file) return;
|
|
|
|
+ if (!file->file) return;
|
|
|
|
+ fclose(file->file);
|
|
|
|
+ file->file = NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void tr_file_free(mrb_state *mrb, void *ptr) {
|
|
|
|
+ struct tr_file * file = ptr;
|
|
|
|
+ file_close(file);
|
|
|
|
+ mrb_free(mrb, file);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static tr_file * file_open(mrb_state * mrb, char * filename, char * mode)
|
|
|
|
+{
|
|
|
|
+ struct woe_config * cfg;
|
|
|
|
+ struct woesb buf = { 0 };
|
|
|
|
+ tr_file * me = NULL;
|
|
|
|
+ if (!mrb) return NULL;
|
|
|
|
+ cfg = MRB_WOE_CONFIG(mrb);
|
|
|
|
+ if (!cfg) return NULL;
|
|
|
|
+
|
|
|
|
+ me = mrb_malloc(mrb, sizeof(struct tr_file));
|
|
|
|
+ if (!me) return NULL;
|
|
|
|
+ if (!woesb_new_join(&buf, cfg->data_dir, "/var/", filename, NULL)) {
|
|
|
|
+ LOG_ERROR("Cannot allocate space for file name.\n");
|
|
|
|
+ mrb_free(mrb, me);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (strstr(buf.text, "..")) {
|
|
|
|
+ mrb_free(mrb, me);
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ LOG_ERROR("Path may not contain '..' \n");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ me->file = fopen(buf.text, mode);
|
|
|
|
+ if (!me->file) {
|
|
|
|
+ LOG_ERROR("Cannot open file %s.\n", filename);
|
|
|
|
+ mrb_free(mrb, me);
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ me->cfg = cfg;
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ return me;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int woe_mkdir(struct woe_config * cfg, char * filename) {
|
|
|
|
+ int res;
|
|
|
|
+ DIR * dir;
|
|
|
|
+
|
|
|
|
+ struct woesb buf = { 0 };
|
|
|
|
+ if (!cfg) return -3;
|
|
|
|
+
|
|
|
|
+ if (!woesb_new_join(&buf, cfg->data_dir, "/var/", filename, NULL)) {
|
|
|
|
+ LOG_ERROR("Cannot allocate space for file name.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (strstr(buf.text, "..")) {
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ LOG_ERROR("Path may not contain '..' \n");
|
|
|
|
+ return -2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dir = opendir(buf.text);
|
|
|
|
+ if (dir) {
|
|
|
|
+ LOG_DEBUG("Dir %s already exists\n");
|
|
|
|
+ /* Directory already exists */
|
|
|
|
+ closedir(dir);
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ errno = 0;
|
|
|
|
+ res = mkdir(buf.text , 0770);
|
|
|
|
+
|
|
|
|
+ if (res < 0) {
|
|
|
|
+ LOG_ERROR("Cannot make dir %s.\n", filename);
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ return errno;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ woesb_free(&buf);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int woe_link(struct woe_config * cfg, char * old_filename, char * new_filename) {
|
|
|
|
+ int res;
|
|
|
|
+
|
|
|
|
+ struct woesb old_buf = { 0 };
|
|
|
|
+ struct woesb new_buf = { 0 };
|
|
|
|
+
|
|
|
|
+ if (!cfg) return -3;
|
|
|
|
+
|
|
|
|
+ if (!woesb_new_join(&old_buf, cfg->data_dir, "/var/", old_filename, NULL)) {
|
|
|
|
+ LOG_ERROR("Cannot allocate space for file name.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!woesb_new_join(&new_buf, cfg->data_dir, "/var/", new_filename, NULL)) {
|
|
|
|
+ woesb_free(&old_buf);
|
|
|
|
+ LOG_ERROR("Cannot allocate space for file name.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (strstr(old_buf.text, "..") || strstr(new_buf.text, "..")) {
|
|
|
|
+ woesb_free(&new_buf);
|
|
|
|
+ woesb_free(&old_buf);
|
|
|
|
+ LOG_ERROR("Path may not contain '..' \n");
|
|
|
|
+ return -2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ errno = 0;
|
|
|
|
+ res = link(old_buf.text, new_buf.text);
|
|
|
|
+
|
|
|
|
+ if (res < 0) {
|
|
|
|
+ LOG_ERROR("Cannot link %s to %s.\n", old_filename, new_filename);
|
|
|
|
+ woesb_free(&new_buf);
|
|
|
|
+ woesb_free(&old_buf);
|
|
|
|
+ return errno;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ woesb_free(&new_buf);
|
|
|
|
+ woesb_free(&old_buf);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct mrb_data_type tr_file_type = { "File", tr_file_free };
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_wrap(mrb_state *mrb, struct RClass *tc, tr_file * file) {
|
|
|
|
+ return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &tr_file_type, file));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+tr_file * tr_file_unwrap(mrb_state *mrb, mrb_value val) {
|
|
|
|
+ return DATA_CHECK_GET_PTR(mrb, val, &tr_file_type, tr_file);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_open(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ int res;
|
|
|
|
+ char * name, * mode;
|
|
|
|
+ tr_file * file;
|
|
|
|
+
|
|
|
|
+ mrb_get_args(mrb, "zz", &name, &mode);
|
|
|
|
+ file = file_open(mrb, name, mode);
|
|
|
|
+
|
|
|
|
+ if (!file) return mrb_nil_value();
|
|
|
|
+
|
|
|
|
+ return tr_file_wrap(mrb, mrb_class_get(mrb, "File"), file);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_close(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ file_close(tr_file_unwrap(mrb, self));
|
|
|
|
+ return mrb_nil_value();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_write(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int res, size;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ char * buf;
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "s", &buf, &size);
|
|
|
|
+ res = fwrite(buf, size, 1, file->file);
|
|
|
|
+ return mrb_fixnum_value(res);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_read(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int res, size;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ mrb_value buf;
|
|
|
|
+
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "i", &size);
|
|
|
|
+ buf = mrb_str_buf_new(mrb, size);
|
|
|
|
+
|
|
|
|
+ res = fread(RSTRING(buf), size, 1, file->file);
|
|
|
|
+ if (res > 0) {
|
|
|
|
+ mrb_str_resize(mrb, buf, res);
|
|
|
|
+ return buf;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (res == 0) {
|
|
|
|
+ return mrb_nil_value();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // if (res < 0)
|
|
|
|
+ LOG_ERROR("Failed to read from file.\n");
|
|
|
|
+ return mrb_nil_value();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_puts(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int res, size;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ char * buf;
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "z", &buf);
|
|
|
|
+ res = fputs(buf, file->file);
|
|
|
|
+ return mrb_fixnum_value(res);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_gets(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int size;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ char * buf;
|
|
|
|
+ char * check;
|
|
|
|
+ mrb_value res;
|
|
|
|
+
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "i", &size);
|
|
|
|
+ buf = calloc(size, 1);
|
|
|
|
+ if (!buf) {
|
|
|
|
+ return mrb_nil_value();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ check = fgets(buf, size, file->file);
|
|
|
|
+ if (check) {
|
|
|
|
+ res = mrb_str_new_cstr(mrb, buf);
|
|
|
|
+ free(buf);
|
|
|
|
+ return res;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ free(buf);
|
|
|
|
+ return mrb_nil_value();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_putc(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int res, chara = 0;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "i", &chara);
|
|
|
|
+ res = fputc(chara, file->file);
|
|
|
|
+ return mrb_fixnum_value(res);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_getc(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ mrb_int res;
|
|
|
|
+ tr_file * file;
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ res = fgetc(file->file);
|
|
|
|
+ return mrb_fixnum_value(res);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_eof(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ tr_file * file;
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ return rh_bool_value(feof(file->file));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_dir_mkdir(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ tr_file * file;
|
|
|
|
+ char * name;
|
|
|
|
+ struct woe_config * cfg;
|
|
|
|
+ cfg = MRB_WOE_CONFIG(mrb);
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "z", &name);
|
|
|
|
+ return mrb_fixnum_value(woe_mkdir(cfg, name));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static mrb_value tr_file_link(mrb_state * mrb, mrb_value self) {
|
|
|
|
+ tr_file * file;
|
|
|
|
+ char * old_name, * new_name;
|
|
|
|
+ struct woe_config * cfg;
|
|
|
|
+ cfg = MRB_WOE_CONFIG(mrb);
|
|
|
|
+ file = tr_file_unwrap(mrb, self);
|
|
|
|
+ mrb_get_args(mrb, "zz", &old_name, &new_name);
|
|
|
|
+ return mrb_fixnum_value(woe_link(cfg, old_name, new_name));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+int tr_init_file(mrb_state * mrb) {
|
|
|
|
+ struct RClass *krn;
|
|
|
|
+ struct RClass *dir;
|
|
|
|
+ struct RClass *fil;
|
|
|
|
+
|
|
|
|
+ fil = mrb_define_class(mrb, "File" , mrb_class_get(mrb, "Object"));
|
|
|
|
+ dir = mrb_define_class(mrb, "Dir" , mrb_class_get(mrb, "Object"));
|
|
|
|
+
|
|
|
|
+ TR_CLASS_METHOD_ARGC(mrb, fil, "open" , tr_file_open, 2);
|
|
|
|
+ TR_CLASS_METHOD_ARGC(mrb, fil, "link" , tr_file_link, 2);
|
|
|
|
+ TR_CLASS_METHOD_ARGC(mrb, dir, "mkdir", tr_dir_mkdir, 1);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ TR_METHOD_NOARG(mrb, fil, "close" , tr_file_close);
|
|
|
|
+ TR_METHOD_NOARG(mrb, fil, "eof?" , tr_file_eof);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "read" , tr_file_read, 1);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "write" , tr_file_read, 2);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "gets" , tr_file_gets, 1);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "puts" , tr_file_puts, 1);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "putc" , tr_file_putc, 1);
|
|
|
|
+ TR_METHOD_ARGC(mrb, fil, "getc" , tr_file_getc, 1);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|