diff options
| author | Paolo Bosetti <[email protected]> | 2013-10-02 13:05:12 +0200 |
|---|---|---|
| committer | Paolo Bosetti <[email protected]> | 2013-10-02 13:05:12 +0200 |
| commit | c608c26ab47eb226cfed310c4cf16ed31be7fa0d (patch) | |
| tree | 8a7027459758c8bdb98cdb85a60e68af9d99808d /src | |
| parent | 49494a736733e94b88e20b2b2fe9769c90862b5a (diff) | |
| parent | 8b48e2b4a42c9e1c697f94d3bb362a12484fe2e7 (diff) | |
| download | mruby-c608c26ab47eb226cfed310c4cf16ed31be7fa0d.tar.gz mruby-c608c26ab47eb226cfed310c4cf16ed31be7fa0d.zip | |
Merge branch 'master' of https://github.com/iij/mruby-io
Diffstat (limited to 'src')
| -rw-r--r-- | src/file.c | 35 | ||||
| -rw-r--r-- | src/io.c | 116 |
2 files changed, 94 insertions, 57 deletions
diff --git a/src/file.c b/src/file.c index 0fed5b21a..5c46aa965 100644 --- a/src/file.c +++ b/src/file.c @@ -36,6 +36,9 @@ #define STAT(p, s) stat(p, s) +extern mrb_value mrb_io_fileno(mrb_state *mrb, mrb_value io); + + mrb_value mrb_file_s_umask(mrb_state *mrb, mrb_value klass) { @@ -262,6 +265,36 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass) return mrb_str_new_cstr(mrb, home); } +mrb_value +mrb_file_flock(mrb_state *mrb, mrb_value self) +{ + mrb_int operation; + int fd; + + mrb_get_args(mrb, "i", &operation); + fd = mrb_fixnum(mrb_io_fileno(mrb, self)); + + while (flock(fd, operation) == -1) { + switch (errno) { + case EINTR: + /* retry */ + break; + case EAGAIN: /* NetBSD */ +#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: /* FreeBSD OpenBSD Linux */ +#endif + if (operation & LOCK_NB) { + return mrb_false_value(); + } + /* FALLTHRU - should not happen */ + default: + mrb_sys_fail(mrb, "flock failed"); + break; + } + } + return mrb_fixnum_value(0); +} + void mrb_init_file(mrb_state *mrb) { @@ -282,6 +315,8 @@ mrb_init_file(mrb_state *mrb) mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE()); mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1)); + cnst = mrb_define_module_under(mrb, file, "Constants"); mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH)); mrb_define_const(mrb, cnst, "LOCK_EX", mrb_fixnum_value(LOCK_EX)); @@ -162,9 +162,9 @@ mrb_io_alloc(mrb_state *mrb) struct mrb_io *fptr; fptr = (struct mrb_io *)mrb_malloc(mrb, sizeof(struct mrb_io)); - fptr->fd = -1; - fptr->fd2 = -1; - fptr->pid = 0; + fptr->fd = -1; + fptr->fd2 = -1; + fptr->pid = 0; return fptr; } @@ -188,15 +188,17 @@ io_open(mrb_state *mrb, mrb_value path, int flags, int perm) mrb_value mrb_io_s_popen(mrb_state *mrb, mrb_value klass) { - mrb_value cmd, io; + mrb_value cmd, io, result; mrb_value mode = mrb_str_new_cstr(mrb, "r"); mrb_value opt = mrb_hash_new(mrb); struct mrb_io *fptr; const char *pname; int pid, flags, fd, write_fd = -1; - int pr[2], pw[2]; + int pr[2] = { -1, -1 }; + int pw[2] = { -1, -1 }; int doexec; + int saved_errno; mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt); io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); @@ -206,10 +208,13 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) doexec = (strcmp("-", pname) != 0); - if (((flags & FMODE_READABLE) && pipe(pr) == -1) - || ((flags & FMODE_WRITABLE) && pipe(pw) == -1)) { - mrb_sys_fail(mrb, "pipe_open failed."); - return mrb_nil_value(); + if ((flags & FMODE_READABLE) && pipe(pr) == -1) { + mrb_sys_fail(mrb, "pipe"); + } + if ((flags & FMODE_WRITABLE) && pipe(pw) == -1) { + if (pr[0] != -1) close(pr[0]); + if (pr[1] != -1) close(pr[1]); + mrb_sys_fail(mrb, "pipe"); } if (!doexec) { @@ -219,7 +224,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) fflush(stderr); } -retry: + result = mrb_nil_value(); switch (pid = fork()) { case 0: /* child */ if (flags & FMODE_READABLE) { @@ -236,7 +241,6 @@ retry: close(pw[0]); } } - if (doexec) { for (fd = 3; fd < NOFILE; fd++) { close(fd); @@ -245,58 +249,51 @@ retry: mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", pname); _exit(127); } - return mrb_nil_value(); - case -1: /* error */ - if (errno == EAGAIN) { - goto retry; - } else { - int e = errno; - if (flags & FMODE_READABLE) { - close(pr[0]); - close(pr[1]); - } - if (flags & FMODE_WRITABLE) { - close(pw[0]); - close(pw[1]); - } - - errno = e; - mrb_sys_fail(mrb, "pipe_open failed."); - } + result = mrb_nil_value(); break; + default: /* parent */ - if (pid < 0) { - mrb_sys_fail(mrb, "pipe_open failed."); - return mrb_nil_value(); + if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) { + close(pr[1]); + fd = pr[0]; + close(pw[0]); + write_fd = pw[1]; + } else if (flags & FMODE_READABLE) { + close(pr[1]); + fd = pr[0]; } else { - if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) { - close(pr[1]); - fd = pr[0]; - close(pw[0]); - write_fd = pw[1]; - } else if (flags & FMODE_READABLE) { - close(pr[1]); - fd = pr[0]; - } else { - close(pw[0]); - fd = pw[1]; - } + close(pw[0]); + fd = pw[1]; + } - mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); - mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0)); + mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); + mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0)); - fptr = mrb_io_alloc(mrb); - fptr->fd = fd; - fptr->fd2 = write_fd; - fptr->pid = pid; + fptr = mrb_io_alloc(mrb); + fptr->fd = fd; + fptr->fd2 = write_fd; + fptr->pid = pid; + + DATA_TYPE(io) = &mrb_io_type; + DATA_PTR(io) = fptr; + result = io; + break; - DATA_TYPE(io) = &mrb_io_type; - DATA_PTR(io) = fptr; - return io; + case -1: /* error */ + saved_errno = errno; + if (flags & FMODE_READABLE) { + close(pr[0]); + close(pr[1]); } + if (flags & FMODE_WRITABLE) { + close(pw[0]); + close(pw[1]); + } + errno = saved_errno; + mrb_sys_fail(mrb, "pipe_open failed."); + break; } - - return mrb_nil_value(); + return result; } mrb_value @@ -473,7 +470,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io) { struct mrb_io *fptr; mrb_value str, buf; - int length; + int fd, length; mrb_get_args(mrb, "S", &str); if (mrb_type(str) != MRB_TT_STRING) { @@ -483,7 +480,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io) } fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type); - length = write(fptr->fd, RSTRING_PTR(buf), RSTRING_LEN(buf)); + if (fptr->fd2 == -1) { + fd = fptr->fd; + } else { + fd = fptr->fd2; + } + length = write(fd, RSTRING_PTR(buf), RSTRING_LEN(buf)); return mrb_fixnum_value(length); } |
