fs_attr.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- my_fs_open_attr
- my_fs_fopen_attr
- my_open_attr
- my_read_attr
- my_get_attr
- my_attr_info2hash
- my_rgb_color2hash
- my_hash2rgb_color
- my_attr_s_read
- my_attr_s_write
- my_rb_type_guess
- be_attr_close
- my_init_attr
- my_get_fd
- my_fs_stat_attr
- free_attr
- be_attr_s_new
- be_attr_s_open
- be_attr_each
- be_attr_s_foreach
- be_attr_s_entries
- be_attr_initialize
- be_attr_read
- be_attr_rewind
- be_attr_reverse
- be_attr_s_read
- be_attr_s_write
- be_attr_s_remove
- be_attr_s_stat
- Init_fs_attr
/*
* fs_attr.c
*/
#include <fs_attr.h>
#include <GraphicsDefs.h>
/* #include <Mime.h> */
enum { B_MIME_STRING_TYPE = 'MIMS' };
#include "bfs.h"
static VALUE cAttr, rb_mMarshal;
static ID i_tv_sec, i_fileno, i_dump;
static DIR*
my_fs_open_attr(const char *path)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
dirp = fs_open_attr_dir(path);
if (!dirp) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
dirp = fs_open_attr_dir(path);
}
if (!dirp) {
rb_sys_fail(path);
}
}
return dirp;
}
static DIR*
my_fs_fopen_attr(int fd)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
dirp = fs_fopen_attr_dir(fd);
if (!dirp) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
dirp = fs_fopen_attr_dir(fd);
}
if (!dirp) {
char str[11+12];
sprintf(str, "fileno: `%d'", fd);
rb_sys_fail(str);
}
}
return dirp;
}
static DIR*
my_open_attr(VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
rb_secure(2);
if (NUMERIC_P(path)) { /* path == file no. (fd) */
return my_fs_fopen_attr(NUM2LONG(path));
}
else if (FILE_P(path)) { /* path == file obj */
OpenFile *fptr;
GetOpenFile(path, fptr);
return my_fs_open_attr(fptr->path);
}
else if (DIR_P(path)) { /* path == Dir obj */
VALUE str;
str = my_get_path_for_dirobj(path);
return my_fs_open_attr(RSTRING(str)->ptr);
}
/* path == path strings */
Check_SafeStr(path);
return my_fs_open_attr(RSTRING(path)->ptr);
}
static VALUE
my_read_attr(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
dirent_t *dp;
errno = 0;
dp = fs_read_attr_dir(dirp);
if (!dp && errno) {
rb_sys_fail(0);
}
if (dp) {
return rb_tainted_str_new2(dp->d_name);
}
return Qnil;
}
static DIR*
my_get_attr(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
Data_Get_Struct(attr, DIR, dirp);
my_check_dirp_closed(dirp, "closed attribute");
return dirp;
}
static VALUE
my_attr_info2hash(attr_info *info)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE h = rb_hash_new();
rb_hash_aset(h, rb_str_new2("type"), UINT2NUM(info->type));
rb_hash_aset(h, rb_str_new2("size"), LLONG2NUM(info->size));
return h;
}
static VALUE
my_rgb_color2hash(rgb_color *rgba)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE h = rb_hash_new();
rb_hash_aset(h, rb_str_new2("red"), UCHR2FIX(rgba->red));
rb_hash_aset(h, rb_str_new2("green"), UCHR2FIX(rgba->green));
rb_hash_aset(h, rb_str_new2("blue"), UCHR2FIX(rgba->blue));
rb_hash_aset(h, rb_str_new2("alpha"), UCHR2FIX(rgba->alpha));
return h;
}
static rgb_color
my_hash2rgb_color(VALUE h)
/* [<][>][^][v][top][bottom][index][help] */
{
rgb_color rgba;
Check_Type(h, T_HASH);
rgba.red = NUM2UCHR(rb_hash_aref(h, rb_str_new2("red")));
rgba.green = NUM2UCHR(rb_hash_aref(h, rb_str_new2("green")));
rgba.blue = NUM2UCHR(rb_hash_aref(h, rb_str_new2("blue")));
rgba.alpha = NUM2UCHR(rb_hash_aref(h, rb_str_new2("alpha")));
return rgba;
}
#define My_Fs_Read_Attr(buf, count) { \
if (fs_read_attr(fd, attrib, type, pos, buf, count) < 0) { \
rb_sys_fail(attrib); \
} \
}
static VALUE
my_attr_s_read(int fd, const char *attrib, uint32 type, off_t pos, size_t count)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE vresult;
switch (type) {
case B_BOOL_TYPE:
{
bool arg5 = false;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = (arg5 ? Qtrue:Qfalse);
}
break;
case B_CHAR_TYPE:
case B_INT8_TYPE:
{
char arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = CHR2FIX(arg5);
}
break;
case B_DOUBLE_TYPE:
{
double arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = rb_float_new(arg5);
}
break;
case B_FLOAT_TYPE:
{
float arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = rb_float_new(arg5);
}
break;
case B_INT64_TYPE:
{
int64 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = LLONG2NUM(arg5);
}
break;
case B_INT32_TYPE:
{
int32 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = INT2NUM(arg5);
}
break;
case B_INT16_TYPE:
{
int16 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = INT2FIX(arg5);
}
break;
case B_MIME_TYPE:
{
char *arg5 = ALLOCA_N(char, count);
My_Fs_Read_Attr(arg5, count);
vresult = rb_str_new2(arg5);
}
break;
case B_MONOCHROME_1_BIT_TYPE:
{
uchar arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = INT2FIX(arg5 & 0x01);
}
break;
case B_OFF_T_TYPE:
{
off_t arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = LLONG2NUM(arg5);
}
break;
case B_PATTERN_TYPE:
{
pattern arg5;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = rb_str_new(arg5.data, 8);
}
break;
case B_RGB_COLOR_TYPE:
{
rgb_color arg5;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = my_rgb_color2hash(&arg5);
}
break;
case B_SIZE_T_TYPE:
{
size_t arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = UINT2NUM(arg5);
}
break;
case B_SSIZE_T_TYPE:
{
ssize_t arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = INT2NUM(arg5);
}
break;
case B_STRING_TYPE:
case B_MIME_STRING_TYPE:
{
char *arg5 = ALLOCA_N(char, count);
My_Fs_Read_Attr(arg5, count);
vresult = rb_str_new2(arg5);
}
break;
case B_TIME_TYPE:
{
time_t arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = rb_time_new(arg5, 0);
}
break;
case B_UINT64_TYPE:
{
uint64 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = ULLONG2NUM(arg5);
}
break;
case B_RGB_32_BIT_TYPE:
case B_UINT32_TYPE:
{
uint32 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = UINT2NUM(arg5);
}
break;
case B_UINT16_TYPE:
{
uint16 arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = INT2FIX(arg5);
}
break;
case B_COLOR_8_BIT_TYPE:
case B_GRAYSCALE_8_BIT_TYPE:
case B_UINT8_TYPE:
{
uchar arg5 = 0;
My_Fs_Read_Attr(&arg5, sizeof(arg5));
vresult = UCHR2FIX(arg5);
}
break;
case B_MESSAGE_TYPE:
case B_MESSENGER_TYPE:
case B_RAW_TYPE:
case B_OBJECT_TYPE:
case B_POINTER_TYPE:
case B_POINT_TYPE:
case B_RECT_TYPE:
case B_REF_TYPE:
case B_ANY_TYPE:
case B_MEDIA_PARAMETER_TYPE:
case B_MEDIA_PARAMETER_WEB_TYPE:
case B_MEDIA_PARAMETER_GROUP_TYPE:
default:
{
char *arg5 = ALLOCA_N(char, count);
My_Fs_Read_Attr(arg5, count);
vresult = rb_str_new(arg5, count);
}
}
return vresult;
}
#define My_Fs_Write_Attr(buf, count) { \
result = fs_write_attr(fd, attrib, type, pos, buf, count); \
if (result < 0) { \
rb_sys_fail(attrib); \
} \
}
static VALUE
my_attr_s_write(int fd, const char *attrib, uint32 type, off_t pos, VALUE val)
/* [<][>][^][v][top][bottom][index][help] */
{
ssize_t result = 0;
switch (type) {
case B_BOOL_TYPE:
{
bool arg5 = RTEST(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_CHAR_TYPE:
case B_INT8_TYPE:
{
char arg5 = NUM2CHR(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_DOUBLE_TYPE:
{
double arg5 = NUM2DBL(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_FLOAT_TYPE:
{
float arg5 = NUM2DBL(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_INT64_TYPE:
{
int64 arg5 = NUM2LLONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_INT32_TYPE:
{
int32 arg5 = NUM2LONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_INT16_TYPE:
{
int16 arg5 = NUM2SHRT(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_MONOCHROME_1_BIT_TYPE:
{
uchar arg5 = NUM2UCHR(val);
arg5 = (arg5 & 0x01);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_OFF_T_TYPE:
{
off_t arg5 = NUM2LLONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_PATTERN_TYPE:
{
char *str;
int len = 0;
pattern arg5;
str = rb_str2cstr(val, &len);
memcpy(arg5.data, str, 8);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_RGB_COLOR_TYPE:
{
rgb_color arg5 = my_hash2rgb_color(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_SIZE_T_TYPE:
{
size_t arg5 = NUM2ULONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_SSIZE_T_TYPE:
{
ssize_t arg5 = NUM2LONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_MIME_TYPE:
case B_STRING_TYPE:
case B_MIME_STRING_TYPE:
{
char *arg5;
int len = 0;
arg5 = rb_str2cstr(val, &len);
My_Fs_Write_Attr(arg5, len+1);
}
break;
case B_TIME_TYPE:
{
time_t arg5;
if (TIME_P(val)) {
arg5 = NUM2LONG(rb_funcall2(val, i_tv_sec, 0, 0));
}
else {
arg5 = NUM2LONG(val);
}
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_UINT64_TYPE:
{
uint64 arg5 = NUM2ULLONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_RGB_32_BIT_TYPE:
case B_UINT32_TYPE:
{
uint32 arg5 = NUM2ULONG(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_UINT16_TYPE:
{
uint16 arg5 = NUM2USHRT(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_COLOR_8_BIT_TYPE:
case B_GRAYSCALE_8_BIT_TYPE:
case B_UINT8_TYPE:
{
uchar arg5 = NUM2UCHR(val);
My_Fs_Write_Attr(&arg5, sizeof(arg5));
}
break;
case B_MESSAGE_TYPE:
case B_MESSENGER_TYPE:
case B_RAW_TYPE:
case B_OBJECT_TYPE:
case B_POINTER_TYPE:
case B_POINT_TYPE:
case B_RECT_TYPE:
case B_REF_TYPE:
case B_ANY_TYPE:
case B_MEDIA_PARAMETER_TYPE:
case B_MEDIA_PARAMETER_WEB_TYPE:
case B_MEDIA_PARAMETER_GROUP_TYPE:
default:
{
char *arg5;
int len = 0;
arg5 = rb_str2cstr(val, &len);
My_Fs_Write_Attr(arg5, len+1);
}
}
return INT2NUM(result);
}
static uint32
my_rb_type_guess(VALUE val)
/* [<][>][^][v][top][bottom][index][help] */
{
if (TIME_P(val)) {
return B_TIME_TYPE;
}
switch (TYPE(val)) {
case T_TRUE:
case T_FALSE:
return B_BOOL_TYPE;
break;
case T_FLOAT:
return B_DOUBLE_TYPE;
break;
case T_STRING:
return B_STRING_TYPE;
break;
case T_FIXNUM:
case T_SYMBOL:
return B_INT32_TYPE;
break;
case T_BIGNUM:
return B_INT64_TYPE;
break;
case T_NIL:
case T_OBJECT:
case T_CLASS:
case T_MODULE:
case T_REGEXP:
case T_ARRAY:
case T_HASH:
case T_STRUCT:
case T_FILE:
case T_DATA:
default:
return B_RAW_TYPE;
}
return B_RAW_TYPE; /* not reached */
}
static VALUE
be_attr_close(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp = my_get_attr(attr);
if (fs_close_attr_dir(dirp) < 0) {
rb_sys_fail(ROBJ_AS_CSTR(attr));
}
DATA_PTR(attr) = NULL;
return Qnil;
}
static VALUE
my_init_attr(VALUE attr, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
if (DATA_PTR(attr)) {
be_attr_close(attr);
}
DATA_PTR(attr) = my_open_attr(path);
return attr;
}
static int
my_get_fd(VALUE fdsc)
/* [<][>][^][v][top][bottom][index][help] */
{
OpenFile *fptr;
if (NUMERIC_P(fdsc)) { /* fdsc == file no. (fd) */
return NUM2LONG(fdsc);
}
return NUM2LONG(rb_funcall2(fdsc, i_fileno, 0, 0));
}
static void
my_fs_stat_attr(int fd, const char *attrib, attr_info *ainfo)
/* [<][>][^][v][top][bottom][index][help] */
{
if (fs_stat_attr(fd, attrib, ainfo) < 0) {
rb_sys_fail(attrib);
}
}
static void
free_attr(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
if (dirp && (fs_close_attr_dir(dirp) < 0)) {
rb_warn("%s", strerror(errno));
}
}
static VALUE
be_attr_s_new(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE obj = Data_Wrap_Struct(klass, 0, free_attr, 0);
rb_obj_call_init(obj, argc, argv);
return obj;
}
static VALUE
be_attr_s_open(VALUE klass, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE attr;
attr = Data_Wrap_Struct(klass, 0, free_attr, 0);
my_init_attr(attr, path);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, attr, be_attr_close, attr);
}
return attr;
}
static VALUE
be_attr_each(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp;
VALUE d_name;
my_check_block_given();
dirp = my_get_attr(attr);
d_name = my_read_attr(dirp);
while (!NIL_P(d_name)) {
rb_yield(d_name);
my_check_dirp_closed(DATA_PTR(attr), "closed attribute");
d_name = my_read_attr(dirp);
}
return attr;
}
static VALUE
be_attr_s_foreach(VALUE klass, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE attr = rb_funcall(cAttr, i_open, 1, path);
rb_ensure(be_attr_each, attr, be_attr_close, attr);
return Qnil;
}
static VALUE
be_attr_s_entries(VALUE klass, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE attr = rb_funcall(cAttr, i_open, 1, path);
return rb_ensure(rb_Array, attr, be_attr_close, attr);
}
static VALUE
be_attr_initialize(VALUE attr, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
if (rb_block_given_p()) {
char *cname = rb_class2name(CLASS_OF(attr));
rb_warn("%s::new() does not take block; use %s::open() instead", cname, cname);
}
my_init_attr(attr, path);
return attr;
}
static VALUE
be_attr_read(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp = my_get_attr(attr);
return my_read_attr(dirp);
}
static VALUE
be_attr_rewind(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dirp = my_get_attr(attr);
fs_rewind_attr_dir(dirp);
return attr;
}
static VALUE
be_attr_reverse(VALUE attr)
/* [<][>][^][v][top][bottom][index][help] */
{
return rb_ary_reverse(rb_Array(attr));
}
static VALUE
be_attr_s_read(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
VALUE fdsc, attribute, loc;
attr_info info;
char *attrib;
off_t pos = 0;
int fd;
rb_scan_args(argc, argv, "21", &fdsc, &attribute, &loc);
fd = my_get_fd(fdsc);
Check_SafeStr(attribute);
attrib = RSTRING(attribute)->ptr;
if (argc > 2) {
pos = NUM2LLONG(loc);
}
my_fs_stat_attr(fd, attrib, &info);
return my_attr_s_read(fd, attrib, info.type, pos, info.size);
}
static VALUE
be_attr_s_write(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
uint32 type = 0;
off_t pos = 0;
VALUE fdsc, attribute, val, kind, loc;
int fd;
rb_scan_args(argc, argv, "32", &fdsc, &attribute, &val, &kind, &loc);
fd = my_get_fd(fdsc);
Check_SafeStr(attribute);
if (argc > 3) {
type = NUM2ULONG(kind);
}
if (argc > 4) {
pos = NUM2LLONG(loc);
}
if (type == 0) {
type = my_rb_type_guess(val);
switch (type) {
case B_RAW_TYPE:
val = rb_funcall(rb_mMarshal, i_dump, 1, val);
type = B_STRING_TYPE;
break;
}
}
return my_attr_s_write(fd, RSTRING(attribute)->ptr, type, pos, val);
}
static VALUE
be_attr_s_remove(VALUE klass, VALUE fdsc, VALUE attribute)
/* [<][>][^][v][top][bottom][index][help] */
{
int result, fd;
fd = my_get_fd(fdsc);
Check_SafeStr(attribute);
result = fs_remove_attr(fd, RSTRING(attribute)->ptr);
if (result < 0) {
rb_sys_fail(RSTRING(attribute)->ptr);
}
return Qnil;
}
static VALUE
be_attr_s_stat(VALUE klass, VALUE fdsc, VALUE attribute)
/* [<][>][^][v][top][bottom][index][help] */
{
attr_info info;
int fd;
fd = my_get_fd(fdsc);
Check_SafeStr(attribute);
my_fs_stat_attr(fd, RSTRING(attribute)->ptr, &info);
return my_attr_info2hash(&info);
}
void
Init_fs_attr()
/* [<][>][^][v][top][bottom][index][help] */
{
rb_mMarshal = rb_const_get(rb_cObject, rb_intern("Marshal"));
i_tv_sec = rb_intern("tv_sec");
i_fileno = rb_intern("fileno");
i_dump = rb_intern("dump");
cAttr = rb_define_class_under(mBfs, "Attr", rb_cObject);
rb_include_module(cAttr, rb_mEnumerable);
rb_define_singleton_method(cAttr, "new", be_attr_s_new, -1);
rb_define_singleton_method(cAttr, "open", be_attr_s_open, 1);
rb_define_singleton_method(cAttr, "foreach", be_attr_s_foreach, 1);
rb_define_singleton_method(cAttr, "entries", be_attr_s_entries, 1);
rb_define_method(cAttr, "initialize", be_attr_initialize, 1);
rb_define_method(cAttr, "read", be_attr_read, 0);
rb_define_method(cAttr, "each", be_attr_each, 0);
rb_define_method(cAttr, "rewind", be_attr_rewind, 0);
rb_define_method(cAttr, "close", be_attr_close, 0);
rb_define_method(cAttr, "reverse", be_attr_reverse, 0);
rb_define_singleton_method(cAttr, "read", be_attr_s_read, -1);
rb_define_singleton_method(cAttr, "write", be_attr_s_write, -1);
rb_define_singleton_method(cAttr, "addattr", be_attr_s_write, -1);
rb_define_singleton_method(cAttr, "remove", be_attr_s_remove, 2);
rb_define_singleton_method(cAttr, "rmattr", be_attr_s_remove, 2);
rb_define_singleton_method(cAttr, "delete", be_attr_s_remove, 2);
rb_define_singleton_method(cAttr, "stat", be_attr_s_stat, 2);
rb_define_const(mBfs, "MIME_STRING_TYPE", UINT2NUM(B_MIME_STRING_TYPE));
}