summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorPaolo Bosetti <[email protected]>2013-10-02 13:05:12 +0200
committerPaolo Bosetti <[email protected]>2013-10-02 13:05:12 +0200
commitc608c26ab47eb226cfed310c4cf16ed31be7fa0d (patch)
tree8a7027459758c8bdb98cdb85a60e68af9d99808d /src
parent49494a736733e94b88e20b2b2fe9769c90862b5a (diff)
parent8b48e2b4a42c9e1c697f94d3bb362a12484fe2e7 (diff)
downloadmruby-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.c35
-rw-r--r--src/io.c116
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));
diff --git a/src/io.c b/src/io.c
index 43820a9de..2438a1101 100644
--- a/src/io.c
+++ b/src/io.c
@@ -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);
}