summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2012-12-17 21:44:19 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2012-12-17 23:23:10 +0100
commit089b048e2e0f872a653b7b353f66f300578377aa (patch)
treebaf56f52eaf28f04352dd69593a4551d6012b3a1
parentb08ea85185321afe903e39786b3d092d94ba356f (diff)
downloadlem-089b048e2e0f872a653b7b353f66f300578377aa.tar.gz
lem-089b048e2e0f872a653b7b353f66f300578377aa.tar.xz
lem-089b048e2e0f872a653b7b353f66f300578377aa.zip
io: add file:lock() method
-rw-r--r--lem/io/core.c3
-rw-r--r--lem/io/file.c76
2 files changed, 79 insertions, 0 deletions
diff --git a/lem/io/core.c b/lem/io/core.c
index 6411094..dffbe5c 100644
--- a/lem/io/core.c
+++ b/lem/io/core.c
@@ -266,6 +266,9 @@ luaopen_lem_io_core(lua_State *L)
/* mt.seek = <file_seek> */
lua_pushcfunction(L, file_seek);
lua_setfield(L, -2, "seek");
+ /* mt.lock = <file_lock> */
+ lua_pushcfunction(L, file_lock);
+ lua_setfield(L, -2, "lock");
/* insert table */
lua_setfield(L, -2, "File");
diff --git a/lem/io/file.c b/lem/io/file.c
index 9c5eaef..043c1b9 100644
--- a/lem/io/file.c
+++ b/lem/io/file.c
@@ -37,6 +37,11 @@ struct file {
int whence;
} seek;
struct {
+ off_t start;
+ off_t len;
+ short type;
+ } lock;
+ struct {
struct stream *stream;
off_t size;
off_t offset;
@@ -380,3 +385,74 @@ file_seek(lua_State *T)
lua_settop(T, 1);
return lua_yield(T, 1);
}
+
+/*
+ * file:lock() method
+ */
+static void
+file_lock_work(struct lem_async *a)
+{
+ struct file *f = (struct file *)a;
+ struct flock fl = {
+ .l_type = f->lock.type,
+ .l_whence = SEEK_SET,
+ .l_start = f->lock.start,
+ .l_len = f->lock.len,
+ };
+ int ret = fcntl(f->fd, F_SETLK, &fl);
+
+ if (ret == -1)
+ f->ret = errno;
+ else
+ f->ret = 0;
+}
+
+static void
+file_lock_reap(struct lem_async *a)
+{
+ struct file *f = (struct file *)a;
+ lua_State *T = f->a.T;
+
+ f->a.T = NULL;
+
+ if (f->ret) {
+ lem_queue(T, io_strerror(T, f->ret));
+ return;
+ }
+
+ lua_pushboolean(T, 1);
+ lem_queue(T, 1);
+}
+
+static int
+file_lock(lua_State *T)
+{
+ static const short mode[] = { F_RDLCK, F_WRLCK, F_UNLCK };
+ static const char *const modenames[] = { "r", "w", "u", NULL };
+ struct file *f;
+ int op;
+ lua_Number start;
+ lua_Number len;
+
+ luaL_checktype(T, 1, LUA_TUSERDATA);
+ op = luaL_checkoption(T, 2, NULL, modenames);
+ start = luaL_optnumber(T, 3, 0);
+ len = luaL_optnumber(T, 4, 0);
+ f = lua_touserdata(T, 1);
+ f->lock.start = (off_t)start;
+ luaL_argcheck(T, (lua_Number)f->lock.start == start, 3,
+ "not an integer in proper range");
+ f->lock.len = (off_t)len;
+ luaL_argcheck(T, (lua_Number)f->lock.len == len, 4,
+ "not an integer in proper range");
+ if (f->fd < 0)
+ return io_closed(T);
+ if (f->a.T != NULL)
+ return io_busy(T);
+
+ f->lock.type = mode[op];
+ lem_async_do(&f->a, T, file_lock_work, file_lock_reap);
+
+ lua_settop(T, 1);
+ return lua_yield(T, 1);
+}