コード例 #1
0
ファイル: init.c プロジェクト: Danylyuk/first_app
static int
rsock_socket0(int domain, int type, int proto)
{
    int ret;

#ifdef SOCK_CLOEXEC
    static int try_sock_cloexec = 1;
    if (try_sock_cloexec) {
        ret = socket(domain, type|SOCK_CLOEXEC, proto);
        if (ret == -1 && errno == EINVAL) {
            /* SOCK_CLOEXEC is available since Linux 2.6.27.  Linux 2.6.18 fails with EINVAL */
            ret = socket(domain, type, proto);
            if (ret != -1) {
                try_sock_cloexec = 0;
            }
        }
    }
    else {
        ret = socket(domain, type, proto);
    }
#else
    ret = socket(domain, type, proto);
#endif
    if (ret == -1)
        return -1;

    rb_fd_fix_cloexec(ret);

    return ret;

}
コード例 #2
0
ファイル: init.c プロジェクト: DashYang/sim
                /* fall through to fix_cloexec */
            }
        }
    }
    else { /* cloexec_state == 0 */
        ret = socket(domain, type, proto);
    }
    if (ret == -1)
        return -1;
fix_cloexec:
    rb_maygvl_fd_fix_cloexec(ret);
update_max_fd:
    rb_update_max_fd(ret);

    return ret;
}
#else /* !SOCK_CLOEXEC */
static int
rsock_socket0(int domain, int type, int proto)
{
    int ret = socket(domain, type, proto);

    if (ret == -1)
        return -1;
    rb_fd_fix_cloexec(ret);

    return ret;
}
コード例 #3
0
ファイル: ossl_pkey.c プロジェクト: hilben/ruby_test
VALUE
ossl_pkey_new_from_file(VALUE filename)
{
    FILE *fp;
    EVP_PKEY *pkey;

    SafeStringValue(filename);
    if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
	ossl_raise(ePKeyError, "%s", strerror(errno));
    }
    rb_fd_fix_cloexec(fileno(fp));

    pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
    fclose(fp);
    if (!pkey) {
	ossl_raise(ePKeyError, NULL);
    }

    return ossl_pkey_new(pkey);
}
コード例 #4
0
/* try to use SOCK_NONBLOCK and SOCK_CLOEXEC */
static int my_socket(int domain)
{
	int fd;

retry:
	fd = socket(domain, MY_SOCK_STREAM, 0);

	if (fd < 0) {
		switch (errno) {
		case EMFILE:
		case ENFILE:
#ifdef ENOBUFS
		case ENOBUFS:
#endif /* ENOBUFS */
			errno = 0;
			rb_gc();
			fd = socket(domain, MY_SOCK_STREAM, 0);
			break;
		case EINVAL:
			if (MY_SOCK_STREAM != SOCK_STREAM) {
				MY_SOCK_STREAM = SOCK_STREAM;
				goto retry;
			}
		}
		if (fd < 0)
			rb_sys_fail("socket");
	}

	if (MY_SOCK_STREAM == SOCK_STREAM) {
		if (fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK) < 0)
			close_fail(fd, "fcntl(F_SETFL, O_RDWR | O_NONBLOCK)");
		rb_fd_fix_cloexec(fd);
	}

	return fd;
}
コード例 #5
0
ファイル: gdbm.c プロジェクト: knugie/ruby
/*
 * call-seq:
 *      GDBM.new(filename, mode = 0666, flags = nil)
 *
 * Creates a new GDBM instance by opening a gdbm file named _filename_.
 * If the file does not exist, a new file with file mode _mode_ will be
 * created. _flags_ may be one of the following:
 * * *READER*  - open as a reader
 * * *WRITER*  - open as a writer
 * * *WRCREAT* - open as a writer; if the database does not exist, create a new one
 * * *NEWDB*   - open as a writer; overwrite any existing databases
 *
 * The values *WRITER*, *WRCREAT* and *NEWDB* may be combined with the following
 * values by bitwise or:
 * * *SYNC*    - cause all database operations to be synchronized to the disk
 * * *NOLOCK*  - do not lock the database file
 *
 * If no _flags_ are specified, the GDBM object will try to open the database
 * file as a writer and will create it if it does not already exist
 * (cf. flag <tt>WRCREAT</tt>). If this fails (for instance, if another process
 * has already opened the database as a reader), it will try to open the
 * database file as a reader (cf. flag <tt>READER</tt>).
 */
static VALUE
fgdbm_initialize(int argc, VALUE *argv, VALUE obj)
{
    VALUE file, vmode, vflags;
    GDBM_FILE dbm;
    struct dbmdata *dbmp;
    int mode, flags = 0;

    if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
        mode = 0666;            /* default value */
    }
    else if (NIL_P(vmode)) {
        mode = -1;              /* return nil if DB does not exist */
    }
    else {
        mode = NUM2INT(vmode);
    }

    if (!NIL_P(vflags))
        flags = NUM2INT(vflags);

    SafeStringValue(file);

#ifdef GDBM_CLOEXEC
    /* GDBM_CLOEXEC is available since gdbm 1.10. */
    flags |= GDBM_CLOEXEC;
#endif

    if (flags & RUBY_GDBM_RW_BIT) {
        flags &= ~RUBY_GDBM_RW_BIT;
        dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
                        flags, mode, MY_FATAL_FUNC);
    }
    else {
        dbm = 0;
        if (mode >= 0)
            dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
                            GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
        if (!dbm)
            dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
                            GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
        if (!dbm)
            dbm = gdbm_open(RSTRING_PTR(file), MY_BLOCK_SIZE,
                            GDBM_READER|flags, 0, MY_FATAL_FUNC);
    }

    if (dbm) {
        rb_fd_fix_cloexec(gdbm_fdesc(dbm));
    }

    if (!dbm) {
        if (mode == -1) return Qnil;

        if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
            gdbm_errno == GDBM_CANT_BE_READER ||
            gdbm_errno == GDBM_CANT_BE_WRITER)
            rb_sys_fail_str(file);
        else
            rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
    }

    dbmp = ALLOC(struct dbmdata);
    free_dbm(DATA_PTR(obj));
    DATA_PTR(obj) = dbmp;
    dbmp->di_dbm = dbm;
    dbmp->di_size = -1;

    return obj;
}
コード例 #6
0
ファイル: dbm.c プロジェクト: Shopify/ruby
/*
 * call-seq:
 *   DBM.new(filename[, mode[, flags]]) -> dbm
 *
 * Open a dbm database with the specified name, which can include a directory
 * path. Any file extensions needed will be supplied automatically by the dbm
 * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two
 * physical files with extensions '.dir' and '.pag'.
 *
 * The mode should be an integer, as for Unix chmod.
 *
 * Flags should be one of READER, WRITER, WRCREAT or NEWDB.
 */
static VALUE
fdbm_initialize(int argc, VALUE *argv, VALUE obj)
{
    volatile VALUE file;
    VALUE vmode, vflags;
    DBM *dbm;
    struct dbmdata *dbmp;
    int mode, flags = 0;

    if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
	mode = 0666;		/* default value */
    }
    else if (NIL_P(vmode)) {
	mode = -1;		/* return nil if DB not exist */
    }
    else {
	mode = NUM2INT(vmode);
    }

    if (!NIL_P(vflags))
        flags = NUM2INT(vflags);

    FilePathValue(file);

    /*
     * Note:
     * gdbm 1.10 works with O_CLOEXEC.  gdbm 1.9.1 silently ignore it.
     */
#ifndef O_CLOEXEC
#   define O_CLOEXEC 0
#endif

    if (flags & RUBY_DBM_RW_BIT) {
        flags &= ~RUBY_DBM_RW_BIT;
        dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode);
    }
    else {
        dbm = 0;
        if (mode >= 0) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode);
        }
        if (!dbm) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0);
        }
        if (!dbm) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0);
        }
    }

    if (dbm) {
    /*
     * History of dbm_pagfno() and dbm_dirfno() in ndbm and its compatibles.
     * (dbm_pagfno() and dbm_dirfno() is not standardized.)
     *
     * 1986: 4.3BSD provides ndbm.
     *       It provides dbm_pagfno() and dbm_dirfno() as macros.
     * 1991: gdbm-1.5 provides them as functions.
     *       They returns a same descriptor.
     *       (Earlier releases may have the functions too.)
     * 1991: Net/2 provides Berkeley DB.
     *       It doesn't provide dbm_pagfno() and dbm_dirfno().
     * 1992: 4.4BSD Alpha provides Berkeley DB with dbm_dirfno() as a function.
     *       dbm_pagfno() is a macro as DBM_PAGFNO_NOT_AVAILABLE.
     * 1997: Berkeley DB 2.0 is released by Sleepycat Software, Inc.
     *       It defines dbm_pagfno() and dbm_dirfno() as macros.
     * 2011: gdbm-1.9 creates a separate dir file.
     *       dbm_pagfno() and dbm_dirfno() returns different descriptors.
     */
#if defined(HAVE_DBM_PAGFNO)
        rb_fd_fix_cloexec(dbm_pagfno(dbm));
#endif
#if defined(HAVE_DBM_DIRFNO)
        rb_fd_fix_cloexec(dbm_dirfno(dbm));
#endif

#if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC)
    /* Disable Berkeley DB error messages such as:
     * DB->put: attempt to modify a read-only database */
        ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL);
#endif
    }

    if (!dbm) {
	if (mode == -1) return Qnil;
	rb_sys_fail_str(file);
    }

    dbmp = ALLOC(struct dbmdata);
    DATA_PTR(obj) = dbmp;
    dbmp->di_dbm = dbm;
    dbmp->di_size = -1;

    return obj;
}
コード例 #7
0
ファイル: unixsocket.c プロジェクト: ayumin/ruby
/*
 * call-seq:
 *   unixsocket.recv_io([klass [, mode]]) => io
 *
 *   UNIXServer.open("/tmp/sock") {|serv|
 *     UNIXSocket.open("/tmp/sock") {|c|
 *       s = serv.accept
 *
 *       c.send_io STDOUT
 *       stdout = s.recv_io
 *
 *       p STDOUT.fileno #=> 1
 *       p stdout.fileno #=> 7
 *
 *       stdout.puts "hello" # outputs "hello\n" to standard output.
 *     }
 *   }
 *
 */
static VALUE
unix_recv_io(int argc, VALUE *argv, VALUE sock)
{
    VALUE klass, mode;
    rb_io_t *fptr;
    struct iomsg_arg arg;
    struct iovec vec[2];
    char buf[1];

    int fd;
#if FD_PASSING_BY_MSG_CONTROL
    struct {
	struct cmsghdr hdr;
        char pad[8+sizeof(int)+8];
    } cmsg;
#endif

    rb_scan_args(argc, argv, "02", &klass, &mode);
    if (argc == 0)
	klass = rb_cIO;
    if (argc <= 1)
	mode = Qnil;

    GetOpenFile(sock, fptr);

    arg.msg.msg_name = NULL;
    arg.msg.msg_namelen = 0;

    vec[0].iov_base = buf;
    vec[0].iov_len = sizeof(buf);
    arg.msg.msg_iov = vec;
    arg.msg.msg_iovlen = 1;

#if FD_PASSING_BY_MSG_CONTROL
    arg.msg.msg_control = (caddr_t)&cmsg;
    arg.msg.msg_controllen = (socklen_t)CMSG_SPACE(sizeof(int));
    arg.msg.msg_flags = 0;
    cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_RIGHTS;
    fd = -1;
    memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
#else
    arg.msg.msg_accrights = (caddr_t)&fd;
    arg.msg.msg_accrightslen = sizeof(fd);
    fd = -1;
#endif

    arg.fd = fptr->fd;
    while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) {
	if (!rb_io_wait_readable(arg.fd))
	    rb_sys_fail("recvmsg(2)");
    }

#if FD_PASSING_BY_MSG_CONTROL
    if (arg.msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr)) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
		 (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
    }
    if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_level=%d, %d expected)",
		 cmsg.hdr.cmsg_level, SOL_SOCKET);
    }
    if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_type=%d, %d expected)",
		 cmsg.hdr.cmsg_type, SCM_RIGHTS);
    }
    if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
		 (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
    }
    if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
		 (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
    }
    if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
	rsock_discard_cmsg_resource(&arg.msg, 0);
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_len=%d, %d expected)",
		 (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
    }
#else
    if (arg.msg.msg_accrightslen != sizeof(fd)) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (accrightslen) : %d != %d",
		 arg.msg.msg_accrightslen, (int)sizeof(fd));
    }
#endif

#if FD_PASSING_BY_MSG_CONTROL
    memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int));
#endif
    rb_fd_fix_cloexec(fd);

    if (klass == Qnil)
	return INT2FIX(fd);
    else {
	ID for_fd;
	int ff_argc;
	VALUE ff_argv[2];
	CONST_ID(for_fd, "for_fd");
	ff_argc = mode == Qnil ? 1 : 2;
	ff_argv[0] = INT2FIX(fd);
	ff_argv[1] = mode;
        return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
    }
}