summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTomoyuki Sahara <[email protected]>2013-09-30 10:17:21 +0900
committerTomoyuki Sahara <[email protected]>2013-09-30 10:17:21 +0900
commitb4f0a68fba4b222461ca79feb94d94e325341129 (patch)
treef63fc3799c9605a15f20168148f50fdec82beb9a
parent140da1c6caf1ba98f961470a1d87ba7e14f0fb25 (diff)
downloadmruby-b4f0a68fba4b222461ca79feb94d94e325341129.tar.gz
mruby-b4f0a68fba4b222461ca79feb94d94e325341129.zip
add File#flock.
-rw-r--r--README.md2
-rw-r--r--src/file.c35
-rw-r--r--test/file.rb11
3 files changed, 47 insertions, 1 deletions
diff --git a/README.md b/README.md
index e05577ef9..51b6d1851 100644
--- a/README.md
+++ b/README.md
@@ -176,7 +176,7 @@ DEALINGS IN THE SOFTWARE.
| File#chmod | | |
| File#chown | | |
| File#ctime | | |
-| File#flock | | |
+| File#flock | o | |
| File#lstat | | |
| File#mtime | | |
| File#path, File#to_path | o | |
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/test/file.rb b/test/file.rb
index 8fe7636e0..4b3458d1a 100644
--- a/test/file.rb
+++ b/test/file.rb
@@ -49,6 +49,17 @@ assert('File.extname') do
assert_equal '', File.extname('.foo')
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
File.size($mrbtest_io_rfname) == $mrbtest_io_msg.size + 1 and
File.size($mrbtest_io_wfname) == 0