class Kgio::File - kgio - kinder, gentler I/O for Ruby

# class Kgio::File

This subclass of the core File class adds the “tryopen” singleton method for opening files. A single “tryopen” and check for the return value may be used to avoid unnecessary stat(2) syscalls or File.open exceptions when checking for the existence of a file and opening it.

### Public Class Methods

Kgio::File.tryopen(filename, [, mode [, perm]]) → Kgio::File or Symbol click to toggle source

Returns a Kgio::File object on a successful open. `filename` is a path to any file on the filesystem. If specified, `mode` is a bitmask of flags (see IO.sysopen) and `perm` should be an octal number.

This does not raise errors for most failures, but installs returns a Ruby symbol for the constant in the Errno::* namespace.

Common error symbols are:

- :ENOENT

- :EACCES

See your open(2) manpage for more information on open(2) errors.

    static VALUE s_tryopen(int argc, VALUE *argv, VALUE klass)
    {
            long fd;
            VALUE pathname, flags, mode;
            struct open_args o;
            int retried = 0;
            VALUE rv;

            rb_scan_args(argc, argv, "12", &pathname, &flags, &mode);
            if (rb_respond_to(pathname, id_to_path))
                    pathname = rb_funcall(pathname, id_to_path, 0);
            o.pathname = StringValueCStr(pathname);

            switch (TYPE(flags)) {
            case T_NIL: o.flags = O_RDONLY; break;
            case T_FIXNUM: o.flags = FIX2INT(flags); break;
            case T_BIGNUM: o.flags = NUM2INT(flags); break;
            default: rb_raise(rb_eArgError, "flags must be an Integer");
            }
            switch (TYPE(mode)) {
            case T_NIL: o.mode = 0666; break;
            case T_FIXNUM: o.mode = FIX2INT(mode); break;
            case T_BIGNUM: o.mode = NUM2INT(mode); break;
            default: rb_raise(rb_eArgError, "mode must be an Integer");
            }

    retry:
            fd = (long)KGIO_WITHOUT_GVL(nogvl_open, &o, RUBY_UBF_IO, 0);
            if (fd < 0) {
                    if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
                            rb_gc();
                            if (retried)
                                    rb_sys_fail(o.pathname);
                            retried = 1;
                            goto retry;
                    }
                    if (fd < 0) {
                            int saved_errno = errno;

                            if (!st_lookup(errno2sym, (st_data_t)errno, &rv)) {
                                    errno = saved_errno;
                                    rb_sys_fail(o.pathname);
                            }
                            return rv;
                    }
            }
            rv = rb_funcall(klass, id_for_fd, 1, LONG2FIX(fd));
            set_file_path(rv, pathname);
            return rv;
    }