fs_info.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. my_get_dev_for_path
  2. my_get_dev_for_obj
  3. my_get_fs_info
  4. my_volume_new
  5. be_volume_s_new
  6. be_volume_s_boot
  7. be_volume_s_each
  8. be_volume_s_reverse
  9. my_get_stat
  10. be_volume_initialize
  11. be_volume_dev
  12. be_volume_root
  13. be_volume_flags
  14. be_volume_block_size
  15. be_volume_io_size
  16. be_volume_total_blocks
  17. be_volume_free_blocks
  18. be_volume_total_nodes
  19. be_volume_free_nodes
  20. be_volume_device_name
  21. be_volume_volume_name
  22. be_volume_fsh_name
  23. be_volume_removable_p
  24. be_volume_read_only_p
  25. be_volume_persistent_p
  26. be_volume_shared_p
  27. be_volume_knows_mime_p
  28. be_volume_knows_attr_p
  29. be_volume_knows_query_p
  30. be_volume_each_value
  31. be_volume_each_pair
  32. be_volume_members
  33. be_volume_values
  34. be_volume_cmp
  35. be_volume_inspect
  36. Init_fs_info

/*
 *  fs_info.c
 */

#include <fs_info.h>
#include "bfs.h"

#define VOLUME_P(x) rb_obj_is_kind_of((x), cVolume)


static VALUE cVolume;
static ID i_dev;


static dev_t
my_get_dev_for_path(const char *path)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev = dev_for_path(path);
  if (dev < 0) {
    my_sys_fail(dev, path);
  }
  return dev;
}


dev_t
my_get_dev_for_obj(VALUE obj)
/* [<][>][^][v][top][bottom][index][help] */
{
  if (FILE_P(obj)) {         /* obj == File obj */
    OpenFile *fptr;

    GetOpenFile(obj, fptr);
    return my_get_dev_for_path(fptr->path);
  }
  else if (NUMERIC_P(obj)) { /* obj == device num */
    return NUM2LONG(obj);
  }
  else if (VOLUME_P(obj)) {  /* obj == Volume obj */
    return NUM2LONG(rb_funcall2(obj, i_dev, 0, 0));
  }
  else if (DIR_P(obj)) {     /* obj == Dir obj */
    VALUE str;

    str = my_get_path_for_dirobj(obj);
    return my_get_dev_for_path(RSTRING(str)->ptr);
  }
  /* obj == path strings */
  return my_get_dev_for_path(STR2CSTR(obj));
}


static fs_info*
my_get_fs_info(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  fs_info *info;

  Data_Get_Struct(vol, fs_info, info);
  if (!info) {
    rb_raise(rb_eIOError,
             "This %s already released", rb_class2name(CLASS_OF(vol)));
  }
  return info;
}


static VALUE
my_volume_new(dev_t dev)
/* [<][>][^][v][top][bottom][index][help] */
{
  fs_info *info;

  rb_secure(2);
  info = ALLOC(fs_info);
  if (fs_stat_dev(dev, info) < 0) {
    char str[12+12];

    free(info);
    sprintf(str, "dev num: `%ld'", dev);
    rb_sys_fail(str);
  }
  return Data_Wrap_Struct(cVolume, 0, free, info);
}


static VALUE
be_volume_s_new(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE obj = Data_Wrap_Struct(klass, 0, free, 0);
  rb_obj_call_init(obj, argc, argv);
  return obj;
}


static VALUE
be_volume_s_boot(VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev = my_get_dev_for_path("/boot");
  return my_volume_new(dev);
}


static VALUE
be_volume_s_each(VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  int32 pos = 0;
  dev_t dev;

  my_check_block_given();
  while ((dev = next_dev(&pos)) >= 0) {
    rb_yield(my_volume_new(dev));
  }
  return klass;
}


static VALUE
be_volume_s_reverse(VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_ary_reverse(rb_Array(klass));
}


static fs_info*
my_get_stat(VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
  fs_info *info;
  dev_t dev;

  rb_secure(2);
  dev = my_get_dev_for_obj(path);
  info = ALLOC(fs_info);
  if (fs_stat_dev(dev, info) < 0) {
    free(info);
    rb_sys_fail(ROBJ_AS_CSTR(path));
  }
  return info;
}


static VALUE
be_volume_initialize(VALUE vol, VALUE path)
/* [<][>][^][v][top][bottom][index][help] */
{
  if (DATA_PTR(vol)) {
    free(DATA_PTR(vol));
    DATA_PTR(vol) = NULL;
  }
  DATA_PTR(vol) = my_get_stat(path);
  return vol;
}


static VALUE
be_volume_dev(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return INT2NUM(my_get_fs_info(vol)->dev);
}


static VALUE
be_volume_root(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->root);
}


static VALUE
be_volume_flags(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return UINT2NUM(my_get_fs_info(vol)->flags);
}


static VALUE
be_volume_block_size(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->block_size);
}


static VALUE
be_volume_io_size(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->io_size);
}


static VALUE
be_volume_total_blocks(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->total_blocks);
}


static VALUE
be_volume_free_blocks(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->free_blocks);
}


static VALUE
be_volume_total_nodes(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->total_nodes);
}


static VALUE
be_volume_free_nodes(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return LLONG2NUM(my_get_fs_info(vol)->free_nodes);
}


static VALUE
be_volume_device_name(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_tainted_str_new2(my_get_fs_info(vol)->device_name);
}


static VALUE
be_volume_volume_name(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_tainted_str_new2(my_get_fs_info(vol)->volume_name);
}


static VALUE
be_volume_fsh_name(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_tainted_str_new2(my_get_fs_info(vol)->fsh_name);
}


static VALUE
be_volume_removable_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_IS_REMOVABLE)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_read_only_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_IS_READONLY)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_persistent_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_IS_PERSISTENT)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_shared_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_IS_SHARED)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_knows_mime_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_HAS_MIME)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_knows_attr_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_HAS_ATTR)
           ? Qtrue:Qfalse);
}


static VALUE
be_volume_knows_query_p(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return ((my_get_fs_info(vol)->flags & B_FS_HAS_QUERY)
           ? Qtrue:Qfalse);
}


static struct {
    char *name;     VALUE (*func)();
} st_info[] = {
  { "dev",          be_volume_dev },
  { "root",         be_volume_root },
  { "flags",        be_volume_flags },
  { "block_size",   be_volume_block_size },
  { "io_size",      be_volume_io_size },
  { "total_blocks", be_volume_total_blocks },
  { "free_blocks",  be_volume_free_blocks },
  { "total_nodes",  be_volume_total_nodes },
  { "free_nodes",   be_volume_free_nodes },
  { "device_name",  be_volume_device_name },
  { "volume_name",  be_volume_volume_name },
  { "fsh_name",     be_volume_fsh_name },
  { 0,              0 }
};


static VALUE
be_volume_each_value(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  int i;

  my_check_block_given();
  for (i=0; st_info[i].name; i++) {
    rb_yield((*st_info[i].func)(vol));
  }
  return vol;
}


static VALUE
be_volume_each_pair(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  int i;

  my_check_block_given();
  for (i=0; st_info[i].name; i++) {
    rb_yield(rb_ary_new3(2, rb_str_new2(st_info[i].name),
                            (*st_info[i].func)(vol)));
  }
  return vol;
}


static VALUE
be_volume_members(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  int i;
  VALUE ary = rb_ary_new();

  for (i=0; st_info[i].name; i++) {
    rb_ary_push(ary, rb_str_new2(st_info[i].name));
  }
  return ary;
}


static VALUE
be_volume_values(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_Array(vol);
}


static VALUE
be_volume_cmp(VALUE vol, VALUE other)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev1 = my_get_fs_info(vol)->dev;
  dev_t dev2 = my_get_fs_info(other)->dev;

  if (dev1 == dev2) {
    return INT2FIX(0);
  }
  else if (dev1 < dev2) {
    return INT2FIX(-1);
  }
  return INT2FIX(1);
}


static VALUE
be_volume_inspect(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE str;
  int i;

  str = rb_str_new2("#<");
  rb_str_cat2(str, rb_class2name(CLASS_OF(vol)));
  rb_str_cat2(str, " ");

  rb_str_cat2(str, st_info[0].name);
  rb_str_cat2(str, "=");
  rb_str_append(str, rb_inspect((*st_info[0].func)(vol)));

  for (i=1; st_info[i].name; i++) {
    rb_str_cat2(str, ", ");
    rb_str_cat2(str, st_info[i].name);
    rb_str_cat2(str, "=");
    rb_str_append(str, rb_inspect((*st_info[i].func)(vol)));
  }
  rb_str_cat2(str, ">");
  OBJ_INFECT(str, vol);
  return str;
}


void
Init_fs_info()
/* [<][>][^][v][top][bottom][index][help] */
{
  i_dev = rb_intern("dev");
  cVolume = rb_define_class_under(mBfs, "Volume", rb_cObject);

  rb_extend_object(cVolume, rb_mEnumerable);
  rb_include_module(cVolume, rb_mEnumerable);
  rb_include_module(cVolume, rb_mComparable);

  rb_define_singleton_method(cVolume, "new", be_volume_s_new, -1);
  rb_define_singleton_method(cVolume, "boot", be_volume_s_boot, 0);
  rb_define_singleton_method(cVolume, "each", be_volume_s_each, 0);
  rb_define_singleton_method(cVolume, "reverse", be_volume_s_reverse, 0);

  rb_define_method(cVolume, "initialize", be_volume_initialize, 1);
  rb_define_method(cVolume, "dev", be_volume_dev, 0);
  rb_define_method(cVolume, "root", be_volume_root, 0);
  rb_define_method(cVolume, "flags", be_volume_flags, 0);
  rb_define_method(cVolume, "block_size", be_volume_block_size, 0);
  rb_define_method(cVolume, "io_size", be_volume_io_size, 0);
  rb_define_method(cVolume, "total_blocks", be_volume_total_blocks, 0);
  rb_define_method(cVolume, "free_blocks", be_volume_free_blocks, 0);
  rb_define_method(cVolume, "total_nodes", be_volume_total_nodes, 0);
  rb_define_method(cVolume, "free_nodes", be_volume_free_nodes, 0);
  rb_define_method(cVolume, "device_name", be_volume_device_name, 0);
  rb_define_method(cVolume, "volume_name", be_volume_volume_name, 0);
  rb_define_method(cVolume, "fsh_name", be_volume_fsh_name, 0);

  rb_define_method(cVolume, "removable?", be_volume_removable_p, 0);
  rb_define_method(cVolume, "read_only?", be_volume_read_only_p, 0);
  rb_define_method(cVolume, "persistent?", be_volume_persistent_p, 0);
  rb_define_method(cVolume, "shared?", be_volume_shared_p, 0);
  rb_define_method(cVolume, "knows_mime?", be_volume_knows_mime_p, 0);
  rb_define_method(cVolume, "knows_attr?", be_volume_knows_attr_p, 0);
  rb_define_method(cVolume, "knows_query?", be_volume_knows_query_p, 0);

  rb_define_method(cVolume, "to_i", be_volume_dev, 0);
  rb_define_method(cVolume, "each", be_volume_each_value, 0);
  rb_define_method(cVolume, "each_value", be_volume_each_value, 0);
  rb_define_method(cVolume, "each_pair", be_volume_each_pair, 0);
  rb_define_method(cVolume, "members", be_volume_members, 0);
  rb_define_method(cVolume, "values", be_volume_values, 0);
  rb_define_method(cVolume, "<=>", be_volume_cmp, 1);
  rb_define_method(cVolume, "inspect", be_volume_inspect, 0);
}

/* [<][>][^][v][top][bottom][index][help] */