Commit c608c26a authored by Paolo Bosetti's avatar Paolo Bosetti

Merge branch 'master' of https://github.com/iij/mruby-io

parents 49494a73 8b48e2b4
...@@ -176,7 +176,7 @@ DEALINGS IN THE SOFTWARE. ...@@ -176,7 +176,7 @@ DEALINGS IN THE SOFTWARE.
| File#chmod | | | | File#chmod | | |
| File#chown | | | | File#chown | | |
| File#ctime | | | | File#ctime | | |
| File#flock | | | | File#flock | o | |
| File#lstat | | | | File#lstat | | |
| File#mtime | | | | File#mtime | | |
| File#path, File#to_path | o | | | File#path, File#to_path | o | |
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#define STAT(p, s) stat(p, s) #define STAT(p, s) stat(p, s)
extern mrb_value mrb_io_fileno(mrb_state *mrb, mrb_value io);
mrb_value mrb_value
mrb_file_s_umask(mrb_state *mrb, mrb_value klass) mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
{ {
...@@ -262,6 +265,36 @@ mrb_file__gethome(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); 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 void
mrb_init_file(mrb_state *mrb) mrb_init_file(mrb_state *mrb)
{ {
...@@ -282,6 +315,8 @@ 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, "_getwd", mrb_file__getwd, MRB_ARGS_NONE());
mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1)); 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"); 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_SH", mrb_fixnum_value(LOCK_SH));
mrb_define_const(mrb, cnst, "LOCK_EX", mrb_fixnum_value(LOCK_EX)); mrb_define_const(mrb, cnst, "LOCK_EX", mrb_fixnum_value(LOCK_EX));
......
...@@ -162,9 +162,9 @@ mrb_io_alloc(mrb_state *mrb) ...@@ -162,9 +162,9 @@ mrb_io_alloc(mrb_state *mrb)
struct mrb_io *fptr; struct mrb_io *fptr;
fptr = (struct mrb_io *)mrb_malloc(mrb, sizeof(struct mrb_io)); fptr = (struct mrb_io *)mrb_malloc(mrb, sizeof(struct mrb_io));
fptr->fd = -1; fptr->fd = -1;
fptr->fd2 = -1; fptr->fd2 = -1;
fptr->pid = 0; fptr->pid = 0;
return fptr; return fptr;
} }
...@@ -188,15 +188,17 @@ io_open(mrb_state *mrb, mrb_value path, int flags, int perm) ...@@ -188,15 +188,17 @@ io_open(mrb_state *mrb, mrb_value path, int flags, int perm)
mrb_value mrb_value
mrb_io_s_popen(mrb_state *mrb, mrb_value klass) 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 mode = mrb_str_new_cstr(mrb, "r");
mrb_value opt = mrb_hash_new(mrb); mrb_value opt = mrb_hash_new(mrb);
struct mrb_io *fptr; struct mrb_io *fptr;
const char *pname; const char *pname;
int pid, flags, fd, write_fd = -1; 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 doexec;
int saved_errno;
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt); 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)); 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) ...@@ -206,10 +208,13 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
doexec = (strcmp("-", pname) != 0); doexec = (strcmp("-", pname) != 0);
if (((flags & FMODE_READABLE) && pipe(pr) == -1) if ((flags & FMODE_READABLE) && pipe(pr) == -1) {
|| ((flags & FMODE_WRITABLE) && pipe(pw) == -1)) { mrb_sys_fail(mrb, "pipe");
mrb_sys_fail(mrb, "pipe_open failed."); }
return mrb_nil_value(); 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) { if (!doexec) {
...@@ -219,7 +224,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) ...@@ -219,7 +224,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
fflush(stderr); fflush(stderr);
} }
retry: result = mrb_nil_value();
switch (pid = fork()) { switch (pid = fork()) {
case 0: /* child */ case 0: /* child */
if (flags & FMODE_READABLE) { if (flags & FMODE_READABLE) {
...@@ -236,7 +241,6 @@ retry: ...@@ -236,7 +241,6 @@ retry:
close(pw[0]); close(pw[0]);
} }
} }
if (doexec) { if (doexec) {
for (fd = 3; fd < NOFILE; fd++) { for (fd = 3; fd < NOFILE; fd++) {
close(fd); close(fd);
...@@ -245,58 +249,51 @@ retry: ...@@ -245,58 +249,51 @@ retry:
mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", pname); mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", pname);
_exit(127); _exit(127);
} }
return mrb_nil_value(); result = 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.");
}
break; break;
default: /* parent */ default: /* parent */
if (pid < 0) { if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) {
mrb_sys_fail(mrb, "pipe_open failed."); close(pr[1]);
return mrb_nil_value(); fd = pr[0];
close(pw[0]);
write_fd = pw[1];
} else if (flags & FMODE_READABLE) {
close(pr[1]);
fd = pr[0];
} else { } else {
if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) { close(pw[0]);
close(pr[1]); fd = pw[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];
}
mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); 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, "@pos"), mrb_fixnum_value(0));
fptr = mrb_io_alloc(mrb); fptr = mrb_io_alloc(mrb);
fptr->fd = fd; fptr->fd = fd;
fptr->fd2 = write_fd; fptr->fd2 = write_fd;
fptr->pid = pid; fptr->pid = pid;
DATA_TYPE(io) = &mrb_io_type;
DATA_PTR(io) = fptr;
result = io;
break;
DATA_TYPE(io) = &mrb_io_type; case -1: /* error */
DATA_PTR(io) = fptr; saved_errno = errno;
return io; 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 result;
return mrb_nil_value();
} }
mrb_value mrb_value
...@@ -473,7 +470,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io) ...@@ -473,7 +470,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
{ {
struct mrb_io *fptr; struct mrb_io *fptr;
mrb_value str, buf; mrb_value str, buf;
int length; int fd, length;
mrb_get_args(mrb, "S", &str); mrb_get_args(mrb, "S", &str);
if (mrb_type(str) != MRB_TT_STRING) { if (mrb_type(str) != MRB_TT_STRING) {
...@@ -483,7 +480,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io) ...@@ -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); 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); return mrb_fixnum_value(length);
} }
......
...@@ -49,6 +49,17 @@ assert('File.extname') do ...@@ -49,6 +49,17 @@ assert('File.extname') do
assert_equal '', File.extname('.foo') assert_equal '', File.extname('.foo')
end end
assert('IO#flock') do
f = File.open $mrbtest_io_rfname
assert_equal(f.flock(File::LOCK_SH), 0)
assert_equal(f.flock(File::LOCK_UN), 0)
assert_equal(f.flock(File::LOCK_EX | File::LOCK_UN), 0)
assert_equal(f.flock(File::LOCK_UN), 0)
f.close
true
end
assert('File.size') do assert('File.size') do
File.size($mrbtest_io_rfname) == $mrbtest_io_msg.size + 1 and File.size($mrbtest_io_rfname) == $mrbtest_io_msg.size + 1 and
File.size($mrbtest_io_wfname) == 0 File.size($mrbtest_io_wfname) == 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment