fs_query.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- my_check_is_kind_of
- my_get_path_for_dirobj
- my_get_path_for_dirent
- my_fs_open_query
- my_fs_open_live_query
- my_open_query
- my_read_query
- my_get_query
- be_query_close
- my_init_query
- free_query
- be_query_s_new
- be_query_s_open
- be_query_each
- be_query_s_foreach
- be_query_s_entries
- be_query_initialize
- be_query_read
- be_query_reverse
- Init_fs_query
/*
* fs_query.c
*/
#include <fs_query.h>
#include "bfs.h"
static VALUE cQuery;
static void
my_check_is_kind_of(VALUE obj, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
if (!rb_obj_is_kind_of(obj, klass)) {
rb_raise(rb_eTypeError,
"wrong argument type %s (expected %s)",
rb_class2name(CLASS_OF(obj)), rb_class2name(klass));
}
}
VALUE
my_get_path_for_dirobj(VALUE dir)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
dirent_t *dp;
char buf[B_PATH_NAME_LENGTH];
size_t len = B_PATH_NAME_LENGTH;
status_t result;
my_check_is_kind_of(dir, rb_cDir);
Data_Get_Struct(dir, DIR, dirp);
my_check_dirp_closed(dirp, "closed directory");
errno = 0;
dp = readdir(dirp);
if (!dp && errno) {
rb_sys_fail(ROBJ_AS_CSTR(dir));
}
result = get_path_for_dirent(dp, buf, len);
if (result != B_OK) {
my_sys_fail(result, ROBJ_AS_CSTR(dir));
}
return rb_tainted_str_new2(buf);
}
static VALUE
my_get_path_for_dirent(dirent_t *dp)
/* [<][>][^][v][top][bottom][index][help] */
{
char buf[B_PATH_NAME_LENGTH];
size_t len = B_PATH_NAME_LENGTH;
status_t result;
result = get_path_for_dirent(dp, buf, len);
if (result != B_OK) {
my_sys_fail(result, (dp ? dp->d_name:0));
}
return rb_tainted_str_new2(buf);
}
static DIR*
my_fs_open_query(VALUE vol, const char *query, uint32 flags)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
dev_t dev;
rb_secure(2);
dev = my_get_dev_for_obj(vol);
dirp = fs_open_query(dev, query, flags);
if (!dirp) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
dirp = fs_open_query(dev, query, flags);
}
if (!dirp) {
rb_sys_fail(query);
}
}
return dirp;
}
static DIR*
my_fs_open_live_query(VALUE vol, const char *query, uint32 flags, port_id port, int32 token)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
dev_t dev;
rb_secure(2);
dev = my_get_dev_for_obj(vol);
dirp = fs_open_live_query(dev, query, flags, port, token);
if (!dirp) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
dirp = fs_open_live_query(dev, query, flags, port, token);
}
if (!dirp) {
rb_sys_fail(query);
}
}
return dirp;
}
static DIR*
my_open_query(int argc, VALUE *argv)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE vol, query, flags, port, token;
uint32 flgs = 0;
port_id prt = 0;
int32 tkn = 0;
rb_scan_args(argc, argv, "23", &vol, &query, &flags, &port, &token);
Check_SafeStr(query);
if (argc > 2) {
flgs = NUM2ULONG(flags);
}
if (argc > 3) {
prt = NUM2LONG(port);
if (argc > 4) {
tkn = NUM2LONG(token);
}
return my_fs_open_live_query(vol, RSTRING(query)->ptr, flgs, prt, tkn);
}
return my_fs_open_query(vol, RSTRING(query)->ptr, flgs);
}
static VALUE
my_read_query(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
dirent_t *dp;
errno = 0;
dp = fs_read_query(dirp);
if (!dp && errno) {
rb_sys_fail(0);
}
if (dp) {
return my_get_path_for_dirent(dp);
}
return Qnil;
}
static DIR*
my_get_query(VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
Data_Get_Struct(qry, DIR, dirp);
my_check_dirp_closed(dirp, "query closed");
return dirp;
}
static VALUE
be_query_close(VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp = my_get_query(qry);
if (fs_close_query(dirp) < 0) {
rb_sys_fail(ROBJ_AS_CSTR(qry));
}
DATA_PTR(qry) = NULL;
return Qnil;
}
static VALUE
my_init_query(int argc, VALUE *argv, VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
if (DATA_PTR(qry)) {
be_query_close(qry);
}
DATA_PTR(qry) = my_open_query(argc, argv);
return qry;
}
static void
free_query(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
if (dirp && (fs_close_query(dirp) < 0)) {
rb_warn("%s", strerror(errno));
}
}
static VALUE
be_query_s_new(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE obj = Data_Wrap_Struct(klass, 0, free_query, 0);
rb_obj_call_init(obj, argc, argv);
return obj;
}
static VALUE
be_query_s_open(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE qry;
qry = Data_Wrap_Struct(klass, 0, free_query, 0);
my_init_query(argc, argv, qry);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, qry, be_query_close, qry);
}
return qry;
}
static VALUE
be_query_each(VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
VALUE path;
my_check_block_given();
dirp = my_get_query(qry);
path = my_read_query(dirp);
while (!NIL_P(path)) {
rb_yield(path);
my_check_dirp_closed(DATA_PTR(qry), "closed query");
path = my_read_query(dirp);
}
return qry;
}
static VALUE
be_query_s_foreach(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE qry = rb_funcall2(cQuery, i_open, argc, argv);
rb_ensure(be_query_each, qry, be_query_close, qry);
return Qnil;
}
static VALUE
be_query_s_entries(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE qry = rb_funcall2(cQuery, i_open, argc, argv);
return rb_ensure(rb_Array, qry, be_query_close, qry);
}
static VALUE
be_query_initialize(int argc, VALUE *argv, VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
if (rb_block_given_p()) {
char *cname = rb_class2name(CLASS_OF(qry));
rb_warn("%s::new() does not take block; use %s::open() instead", cname, cname);
}
my_init_query(argc, argv, qry);
return qry;
}
static VALUE
be_query_read(VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp = my_get_query(qry);
return my_read_query(dirp);
}
static VALUE
be_query_reverse(VALUE qry)
/* [<][>][^][v][top][bottom][index][help] */
{
return rb_ary_reverse(rb_Array(qry));
}
void
Init_fs_query()
/* [<][>][^][v][top][bottom][index][help] */
{
cQuery = rb_define_class_under(mBfs, "Query", rb_cObject);
rb_include_module(cQuery, rb_mEnumerable);
rb_define_singleton_method(cQuery, "new", be_query_s_new, -1);
rb_define_singleton_method(cQuery, "open", be_query_s_open, -1);
rb_define_singleton_method(cQuery, "foreach", be_query_s_foreach, -1);
rb_define_singleton_method(cQuery, "entries", be_query_s_entries, -1);
rb_define_method(cQuery, "initialize", be_query_initialize, -1);
rb_define_method(cQuery, "read", be_query_read, 0);
rb_define_method(cQuery, "close", be_query_close, 0);
rb_define_method(cQuery, "each", be_query_each, 0);
rb_define_method(cQuery, "reverse", be_query_reverse, 0);
rb_define_const(mBfs, "LIVE_QUERY", UINT2NUM(B_LIVE_QUERY));
}