diff --git a/README.md b/README.md index 780ec25..4803b18 100644 --- a/README.md +++ b/README.md @@ -620,10 +620,15 @@ probably confuse the process. open(Drv, Path, Flags, Mode) -> {ok, integer()} | {error, posix()} open(Drv, Pids, Path, Flags, Mode) -> {ok, integer()} | {error, posix()} - Types Flags = Mode = integer() + Types Flags = integer() | [atom() | integer()] + Mode = integer() open(2) : returns a file descriptor associated with a file + Lists of values are OR'ed: + + alcove:open(Drv, "/tmp/test", [o_wronly,o_creat], 8#644) + pid(Drv) -> [Pid] pid(Drv, Pids) -> [Pid] diff --git a/bin/alcove.escript b/bin/alcove.escript index 487bebb..5fddacd 100755 --- a/bin/alcove.escript +++ b/bin/alcove.escript @@ -482,8 +482,8 @@ specs() -> -spec mount_define(alcove_drv:ref(),atom()) -> 'unknown' | non_neg_integer(). -spec mount_define(alcove_drv:ref(),fork_path(),atom()) -> 'unknown' | non_neg_integer(). --spec open(alcove_drv:ref(),iodata(),integer(),integer()) -> {'ok',fd()} | {'error', file:posix()}. --spec open(alcove_drv:ref(),fork_path(),iodata(),integer(),integer()) -> {'ok',fd()} | {'error', file:posix()}. +-spec open(alcove_drv:ref(),iodata(),integer() | [define()],integer()) -> {'ok',fd()} | {'error', file:posix()}. +-spec open(alcove_drv:ref(),fork_path(),iodata(),integer() | [define()],integer()) -> {'ok',fd()} | {'error', file:posix()}. -spec pid(alcove_drv:ref()) -> [#alcove_pid{}]. -spec pid(alcove_drv:ref(),fork_path()) -> [#alcove_pid{}]. diff --git a/c_src/alcove.h b/c_src/alcove.h index 6da2749..e6ee234 100644 --- a/c_src/alcove.h +++ b/c_src/alcove.h @@ -176,6 +176,8 @@ int alcove_decode_list_header(const char *, size_t, int *, int *); int alcove_decode_tuple_header(const char *, size_t, int *, int *); int alcove_decode_iolist(const char *, size_t, int *, char *, size_t *); int alcove_decode_define(const char *, size_t, int *, int *, alcove_define_t *); +int alcove_decode_define_list(const char *, size_t, int *, int *, + alcove_define_t *); int alcove_encode_version(char *, size_t, int *); int alcove_encode_list_header(char *, size_t, int *, int); diff --git a/c_src/alcove_file.c b/c_src/alcove_file.c index d2c4228..dac55ce 100644 --- a/c_src/alcove_file.c +++ b/c_src/alcove_file.c @@ -48,7 +48,8 @@ alcove_open(alcove_state_t *ap, const char *arg, size_t len, return -1; /* flags */ - if (alcove_decode_int(arg, len, &index, &flags) < 0) + if (alcove_decode_define_list(arg, len, &index, &flags, + alcove_file_constants) < 0) return -1; /* mode */ diff --git a/c_src/alcove_term.c b/c_src/alcove_term.c index 556bc1f..a8714e1 100644 --- a/c_src/alcove_term.c +++ b/c_src/alcove_term.c @@ -313,6 +313,70 @@ alcove_decode_define(const char *buf, size_t len, int *index, int *val, return -1; } + return 0; +} + + int +alcove_decode_define_list(const char *buf, size_t len, int *index, int *val, + alcove_define_t *constants) +{ + int type = 0; + int arity = 0; + + if (alcove_get_type(buf, len, index, &type, &arity) < 0) + return -1; + + switch (type) { + case ERL_SMALL_INTEGER_EXT: + case ERL_INTEGER_EXT: + if (alcove_decode_int(buf, len, index, val) < 0) + return -1; + break; + + case ERL_STRING_EXT: { + char tmp[MAXMSGLEN] = {0}; + char *p = tmp; + + if (arity >= sizeof(tmp)) + return -1; + + if (ei_decode_string(buf, index, tmp) < 0) + return -1; + + for ( ; *p; p++) + *val |= *p; + + } + break; + + case ERL_LIST_EXT: { + int i = 0; + int length = 0; + int constant = 0; + + if (ei_decode_list_header(buf, index, &length) < 0) + return -1; + + for (i = 0; i < length; i++) { + if (alcove_decode_define(buf, len, index, &constant, + constants) < 0) + return -1; + + *val |= constant; + } + + /* [] */ + if (alcove_decode_list_header(buf, len, index, &length) < 0 + || length != 0) + return -1; + + } + break; + + default: + return -1; + } + return 0; } diff --git a/test/alcove_tests.erl b/test/alcove_tests.erl index a0e7028..6908c63 100644 --- a/test/alcove_tests.erl +++ b/test/alcove_tests.erl @@ -68,7 +68,8 @@ run(State) -> stdout(State), stderr(State), execve(State), - stream(State) + stream(State), + open(State) ]. start() -> @@ -594,6 +595,21 @@ stream(#state{pid = Drv}) -> Reply = stream_count(Drv, Chain, Count*2), ?_assertEqual(ok, Reply). +open(#state{pid = Drv}) -> + O_RDONLY = alcove:define(Drv, o_rdonly), + + File = "/nonexistent", + + Reply0 = alcove:open(Drv, File, 0, 0), + Reply1 = alcove:open(Drv, File, [0,0,0,0], 0), + Reply2 = alcove:open(Drv, File, [o_rdonly, o_rdonly, o_rdonly], 0), + + [ + ?_assertEqual({error,enoent}, Reply0), + ?_assertEqual({error,enoent}, Reply1), + ?_assertEqual({error,enoent}, Reply2) + ]. + %% %% Utility functions %%