Beispiel #1
0
static int read_check(struct io_args *a, long n, const char *msg, int io_wait)
{
	if (n == -1) {
		if (errno == EINTR) {
			a->fd = my_fileno(a->io);
			return -1;
		}
		rb_str_set_len(a->buf, 0);
		if (errno == EAGAIN) {
			if (io_wait) {
				(void)kgio_call_wait_readable(a->io);

				/* buf may be modified in other thread/fiber */
				rb_str_modify(a->buf);
				rb_str_resize(a->buf, a->len);
				a->ptr = RSTRING_PTR(a->buf);
				return -1;
			} else {
				a->buf = sym_wait_readable;
				return 0;
			}
		}
		rd_sys_fail(msg);
	}
	rb_str_set_len(a->buf, n);
	if (n == 0)
		a->buf = Qnil;
	return 0;
}
Beispiel #2
0
/**
Gets returns a line. this is okay for small lines,
but shouldn't really be used.

Limited to ~ 1Mb of a line length.
*/
static VALUE tfio_gets(VALUE self) {
  int fd = get_tmpfile(self);
  size_t pos = get_pos(self);
  size_t end = get_end(self);
  if (pos == end)
    return Qnil;
  size_t pos_e = pos;
  char c;
  int ret;
  VALUE buffer;

  do {
    ret = pread(fd, &c, 1, pos_e);
  } while (ret > 0 && c != '\n' && (++pos_e < end));
  set_pos(self, pos_e + 1);
  if (pos > pos_e) {
    buffer = rb_str_buf_new(pos_e - pos);
    // make sure the buffer is binary encoded.
    rb_enc_associate(buffer, BinaryEncoding);
    if (pread(fd, RSTRING_PTR(buffer), pos_e - pos, pos) < 0)
      return Qnil;
    rb_str_set_len(buffer, pos_e - pos);
    return buffer;
  }
  return Qnil;
}
/*
 * call-seq:
 *      remove_scope_id(ip_address)
 *
 * Returns copy of IP address with Scope ID removed,
 * if address has it (only IPv6 actually may have it).
 */
static VALUE remove_scope_id(const char *addr)
{
	VALUE rv = rb_str_new2(addr);
	long len = RSTRING_LEN(rv);
	char *ptr = RSTRING_PTR(rv);
	char *pct = memchr(ptr, '%', len);

	/*
	 * remove scoped portion
	 * Ruby equivalent: rv.sub!(/%([^\]]*)\]/, "]")
	 */
	if (pct) {
		size_t newlen = pct - ptr;
		char *rbracket = memchr(pct, ']', len - newlen);

		if (rbracket) {
			size_t move = len - (rbracket - ptr);

			memmove(pct, rbracket, move);
			newlen += move;

			rb_str_set_len(rv, newlen);
		} else {
			rb_raise(rb_eArgError,
				"']' not found in IPv6 addr=%s", ptr);
                }
        }
        return rv;
}
Beispiel #4
0
/*
 *  call-seq:
 *     cipher.update(data [, buffer]) -> string or buffer
 *
 *  === Parameters
 *  +data+ is a nonempty string.
 *  +buffer+ is an optional string to store the result.
 */
static VALUE 
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
    EVP_CIPHER_CTX *ctx;
    char *in;
    int in_len, out_len;
    VALUE data, str;

    rb_scan_args(argc, argv, "11", &data, &str);

    StringValue(data);
    in = RSTRING_PTR(data);
    if ((in_len = RSTRING_LEN(data)) == 0)
        rb_raise(rb_eArgError, "data must not be empty");
    GetCipher(self, ctx);
    out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);

    if (NIL_P(str)) {
        str = rb_str_new(0, out_len);
    } else {
        StringValue(str);
        rb_str_resize(str, out_len);
    }

    if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
	ossl_raise(eCipherError, NULL);
    assert(out_len < RSTRING_LEN(str));
    rb_str_set_len(str, out_len);

    return str;
}
Beispiel #5
0
static VALUE in_addr_set(VALUE io, struct sockaddr_storage *addr, socklen_t len)
{
	VALUE host;
	int host_len, rc;
	char *host_ptr;

	switch (addr->ss_family) {
	case AF_INET:
		host_len = (long)INET_ADDRSTRLEN;
		break;
	case AF_INET6:
		host_len = (long)INET6_ADDRSTRLEN;
		break;
	default:
		rb_raise(rb_eRuntimeError, "unsupported address family");
	}
	host = rb_str_new(NULL, host_len);
	host_ptr = RSTRING_PTR(host);
	rc = getnameinfo((struct sockaddr *)addr, len,
			 host_ptr, host_len, NULL, 0, NI_NUMERICHOST);
	if (rc != 0)
		rb_raise(rb_eRuntimeError, "getnameinfo: %s", gai_strerror(rc));
	rb_str_set_len(host, strlen(host_ptr));
	return rb_ivar_set(io, iv_kgio_addr, host);
}
Beispiel #6
0
/*
 *  call-seq:
 *     cipher.update(data [, buffer]) -> string or buffer
 *
 *  Encrypts data in a streaming fashion. Hand consecutive blocks of data
 *  to the +update+ method in order to encrypt it. Returns the encrypted
 *  data chunk. When done, the output of Cipher#final should be additionally
 *  added to the result.
 *
 *  === Parameters
 *  +data+ is a nonempty string.
 *  +buffer+ is an optional string to store the result.
 */
static VALUE
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
    EVP_CIPHER_CTX *ctx;
    unsigned char *in;
    long in_len, out_len;
    VALUE data, str;

    rb_scan_args(argc, argv, "11", &data, &str);

    StringValue(data);
    in = (unsigned char *)RSTRING_PTR(data);
    if ((in_len = RSTRING_LEN(data)) == 0)
        ossl_raise(rb_eArgError, "data must not be empty");
    GetCipher(self, ctx);
    out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
    if (out_len <= 0) {
	ossl_raise(rb_eRangeError,
		   "data too big to make output buffer: %ld bytes", in_len);
    }

    if (NIL_P(str)) {
        str = rb_str_new(0, out_len);
    } else {
        StringValue(str);
        rb_str_resize(str, out_len);
    }

    if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
	ossl_raise(eCipherError, NULL);
    assert(out_len < RSTRING_LEN(str));
    rb_str_set_len(str, out_len);

    return str;
}
Beispiel #7
0
static VALUE
rg_read_all(int argc, VALUE *argv, VALUE self)
{
        VALUE rbcount, cancellable, result;
        gsize count;
        GError *error = NULL;
        gsize bytes_read;

        rb_scan_args(argc, argv, "11", &rbcount, &cancellable);
        count = RVAL2GSIZE(rbcount);
        result = rb_str_new(NULL, count);
        if (!g_input_stream_read_all(_SELF(self),
                                     RSTRING_PTR(result),
                                     count,
                                     &bytes_read,
                                     RVAL2GCANCELLABLE(cancellable),
                                     &error))
                rbgio_raise_error(error);

        rb_str_set_len(result, bytes_read);
        rb_str_resize(result, bytes_read);
        OBJ_TAINT(result);

        return result;
}
Beispiel #8
0
static int
ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
{
    struct __siov *iov;
    VALUE result = (VALUE)fp->_bf._base;
    char *buf = (char*)fp->_p;
    size_t len, n;
    size_t blen = buf - RSTRING_PTR(result), bsiz = fp->_w;

    if (RBASIC(result)->klass) {
	rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
    }
    if ((len = uio->uio_resid) == 0)
	return 0;
    CHECK(len);
    buf += blen;
    fp->_w = bsiz;
    for (iov = uio->uio_iov; len > 0; ++iov) {
	MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
	buf += n;
	len -= n;
    }
    fp->_p = (unsigned char *)buf;
    rb_str_set_len(result, buf - RSTRING_PTR(result));
    return 0;
}
Beispiel #9
0
// This function is equivalent to rb_str_cat(), but unlike the real
// rb_str_cat(), it doesn't leak memory in some versions of Ruby.
// For more information, see:
//   https://bugs.ruby-lang.org/issues/11328
VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
    size_t oldlen = RSTRING_LEN(rb_str);
    rb_str_modify_expand(rb_str, len);
    char *p = RSTRING_PTR(rb_str);
    memcpy(p + oldlen, str, len);
    rb_str_set_len(rb_str, oldlen + len);
}
Beispiel #10
0
// Reads data from the IO, according to the Rack specifications for `#read`.
static VALUE tfio_read(int argc, VALUE *argv, VALUE self) {
  int fd = get_tmpfile(self);
  size_t pos = get_pos(self);
  size_t end = get_end(self);
  VALUE buffer = Qnil;
  char ret_nil = 0;
  ssize_t len = 0;
  // get the buffer object if given
  if (argc == 2) {
    Check_Type(argv[1], T_STRING);
    buffer = argv[1];
  }
  // get the length object, if given
  if (argc > 0 && argv[0] != Qnil) {
    Check_Type(argv[0], T_FIXNUM);
    len = FIX2LONG(argv[0]);
    if (len < 0)
      rb_raise(rb_eRangeError, "length should be bigger then 0.");
    ret_nil = 1;
  }
  // return if we're at the EOF.
  if (pos == end)
    goto no_data;
  // calculate length if it wasn't specified.
  if (len == 0) {
    // make sure we're not reading more then we have
    len = end - pos;
    // set position for future reads
    set_pos(self, end);
    if (len == 0)
      goto no_data;
  } else {
    // set position for future reads
    set_pos(self, pos + len);
  }
  // limit read to what we have
  if (len + pos > end)
    len = end - pos;
  // create the buffer if we don't have one.
  if (buffer == Qnil) {
    buffer = rb_str_buf_new(len);
    // make sure the buffer is binary encoded.
    rb_enc_associate(buffer, BinaryEncoding);
  } else {
    // make sure the buffer is binary encoded.
    rb_enc_associate(buffer, BinaryEncoding);
    if (rb_str_capacity(buffer) < len)
      rb_str_resize(buffer, len);
  }
  // read the data.
  if (pread(fd, RSTRING_PTR(buffer), len, pos) <= 0)
    goto no_data;
  rb_str_set_len(buffer, len);
  return buffer;
no_data:
  if (ret_nil)
    return Qnil;
  else
    return rb_str_buf_new(0);
}
Beispiel #11
0
/*
 * call-seq:
 *    ssl.sysread(length) => string
 *    ssl.sysread(length, buffer) => buffer
 *
 * === Parameters
 * * +length+ is a positive integer.
 * * +buffer+ is a string used to store the result.
 */
static VALUE
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
{
  SSL *ssl;
  int ilen, nread = 0;
  VALUE len, str;

  rb_scan_args(argc, argv, "11", &len, &str);
  ilen = NUM2INT(len);

  if(NIL_P(str)) {
    str = rb_str_new(0, ilen);
  } else {
    StringValue(str);
    rb_str_modify(str);
    rb_str_resize(str, ilen);
  }

  if(ilen == 0) return str;

  Data_Get_Struct(self, SSL, ssl);
  int fd = rb_io_fd(ossl_ssl_get_io(self));

  if (ssl) {
    if(SSL_pending(ssl) <= 0)
      rb_thread_wait_fd(fd);
    for (;;) {
      nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
      switch(ssl_get_error(ssl, nread)) {
      case SSL_ERROR_NONE:
        goto end;
      case SSL_ERROR_ZERO_RETURN:
        rb_eof_error();
      case SSL_ERROR_WANT_WRITE:
        rb_io_wait_writable(fd);
        continue;
      case SSL_ERROR_WANT_READ:
        rb_io_wait_readable(fd);
        continue;
      case SSL_ERROR_SYSCALL:
        if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
        rb_sys_fail(0);
      default:
        ossl_raise(eSSLError, "SSL_read:");
      }
    }
  }
  else {
    ID id_sysread = rb_intern("sysread");
    rb_warning("SSL session is not started yet.");
    return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
  }

end:
  rb_str_set_len(str, nread);
  OBJ_TAINT(str);

  return str;
}
Beispiel #12
0
Datei: pg.c Projekt: RapsIn4/pg
	/* Use somewhat faster version with access to string capacity on MRI */
	char *
	pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
	{
		long curr_len = curr_ptr - RSTRING_PTR(str);
		long curr_capa = rb_str_capacity( str );
		if( curr_capa < curr_len + expand_len ){
			rb_str_set_len( str, curr_len );
			rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
			curr_ptr = RSTRING_PTR(str) + curr_len;
		}
		if( end_ptr )
			*end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
		return curr_ptr;
	}
Beispiel #13
0
/*
 * call-seq:
 *    coder.encode( value [, encoding] )
 *
 * Encodes the given Ruby object into string representation, without
 * sending data to/from the database server.
 *
 * A nil value is passed through.
 *
 */
static VALUE
pg_coder_encode(int argc, VALUE *argv, VALUE self)
{
	VALUE res;
	VALUE intermediate;
	VALUE value;
	int len, len2;
	int enc_idx;
	t_pg_coder *this = DATA_PTR(self);

	if(argc < 1 || argc > 2){
		rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
	}else if(argc == 1){
		enc_idx = rb_ascii8bit_encindex();
	}else{
		enc_idx = rb_to_encoding_index(argv[1]);
	}
	value = argv[0];

	if( NIL_P(value) )
		return Qnil;

	if( !this->enc_func ){
		rb_raise(rb_eRuntimeError, "no encoder function defined");
	}

	len = this->enc_func( this, value, NULL, &intermediate, enc_idx );

	if( len == -1 ){
		/* The intermediate value is a String that can be used directly. */
		OBJ_INFECT(intermediate, value);
		return intermediate;
	}

	res = rb_str_new(NULL, len);
	PG_ENCODING_SET_NOCHECK(res, enc_idx);
	len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx );
	if( len < len2 ){
		rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)",
			rb_obj_classname( self ), len, len2 );
	}
	rb_str_set_len( res, len2 );
	OBJ_INFECT(res, value);

	RB_GC_GUARD(intermediate);

	return res;
}
Beispiel #14
0
/*
 *  call-seq:
 *     cipher.final -> string
 *
 *  Returns the remaining data held in the cipher object. Further calls to
 *  Cipher#update or Cipher#final will return garbage. This call should always
 *  be made as the last call of an encryption or decryption operation, after
 *  after having fed the entire plaintext or ciphertext to the Cipher instance.
 *
 *  If an authenticated cipher was used, a CipherError is raised if the tag
 *  could not be authenticated successfully. Only call this method after
 *  setting the authentication tag and passing the entire contents of the
 *  ciphertext into the cipher.
 */
static VALUE
ossl_cipher_final(VALUE self)
{
    EVP_CIPHER_CTX *ctx;
    int out_len;
    VALUE str;

    GetCipher(self, ctx);
    str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
    if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len))
	ossl_raise(eCipherError, NULL);
    assert(out_len <= RSTRING_LEN(str));
    rb_str_set_len(str, out_len);

    return str;
}
static VALUE
rg_peek(VALUE self, VALUE rboffset, VALUE rbcount)
{
        gsize offset = RVAL2GSIZE(rboffset);
        gsize count = RVAL2GSIZE(rbcount);
        VALUE result = rb_str_new(NULL, count);
        gsize bytes_peeked = g_buffered_input_stream_peek(_SELF(self),
                                                          RSTRING_PTR(result),
                                                          offset,
                                                          count);

        rb_str_set_len(result, bytes_peeked);
        rb_str_resize(result, bytes_peeked);
        OBJ_TAINT(result);

        return result;
}
Beispiel #16
0
VALUE mCDB_Reader_get(VALUE self, VALUE key) {
  struct cdb db;
  VALUE value;
  StringValue(key);
  int fd = open_cdb_fd(self);
  size_t vlen;
  cdb_init(&db,fd);
  if(cdb_find(&db,RSTRING_PTR(key),RSTRING_LEN(key)) > 0) {
    vlen = cdb_datalen(&db);
    value = rb_str_buf_new(vlen);
    cdb_read(&db,RSTRING_PTR(value),vlen,cdb_datapos(&db));
    rb_str_set_len(value,vlen);
    return value;
  }
  close(fd);
  return Qnil;
}
Beispiel #17
0
static VALUE
pkcs11_C_GetOperationState(VALUE self, VALUE session)
{
  CK_RV rv;
  CK_C_GetOperationState func;
  VALUE state;
  CK_ULONG size;

  GetFunction(self, C_GetOperationState, func);
  CallFunction(C_GetOperationState, func, rv, NUM2HANDLE(session), NULL_PTR, &size);
  if (rv != CKR_OK) pkcs11_raise(self,rv);
  state = rb_str_new(0, size);
  CallFunction(C_GetOperationState, func, rv, NUM2HANDLE(session), (CK_BYTE_PTR)RSTRING_PTR(state), &size);
  if (rv != CKR_OK) pkcs11_raise(self,rv);
  rb_str_set_len(state, size);

  return state;
}
Beispiel #18
0
VALUE mCDB_Reader_each_for_key(VALUE self,VALUE key) {
  struct cdb db;
  VALUE value;
  struct cdb_find find;
  StringValue(key);
  int fd = open_cdb_fd(self);
  size_t vlen;
  cdb_init(&db,fd);
  cdb_findinit(&find,&db,RSTRING_PTR(key),RSTRING_LEN(key));
  while(cdb_findnext(&find) > 0) {
    vlen = cdb_datalen(&db);
    value = rb_str_buf_new(vlen);
    cdb_read(&db,RSTRING_PTR(value),vlen,cdb_datapos(&db));
    rb_str_set_len(value,vlen);
    rb_yield(value);
  }
  close(fd);
  return Qnil;
}
Beispiel #19
0
static VALUE _receive(int rflags, int argc, VALUE *argv, VALUE self)
{
	struct posix_mq *mq = get(self, 1);
	struct rw_args x;
	VALUE buffer, timeout;
	struct timespec expire;

	if (mq->attr.mq_msgsize < 0) {
		if (mq_getattr(mq->des, &mq->attr) < 0)
			rb_sys_fail("mq_getattr");
	}

	rb_scan_args(argc, argv, "02", &buffer, &timeout);
	x.timeout = convert_timeout(&expire, timeout);

	if (NIL_P(buffer)) {
		buffer = rb_str_new(0, mq->attr.mq_msgsize);
	} else {
		StringValue(buffer);
		rb_str_modify(buffer);
		rb_str_resize(buffer, mq->attr.mq_msgsize);
	}
	OBJ_TAINT(buffer);
	x.msg_ptr = RSTRING_PTR(buffer);
	x.msg_len = (size_t)mq->attr.mq_msgsize;
	x.des = mq->des;

retry:
	WITHOUT_GVL(xrecv, &x, RUBY_UBF_IO, 0);
	if (x.received < 0) {
		if (errno == EINTR)
			goto retry;
		if (errno == EAGAIN && (rflags & PMQ_TRY))
			return Qnil;
		rb_sys_fail("mq_receive");
	}

	rb_str_set_len(buffer, x.received);

	if (rflags & PMQ_WANTARRAY)
		return rb_ary_new3(2, buffer, UINT2NUM(x.msg_prio));
	return buffer;
}
Beispiel #20
0
void
rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
{
    VALUE mesg;
    va_list args;
    int errno_save;

    errno_save = errno;

    if (!RTEST(ruby_verbose)) return;

    va_start(args, fmt);
    mesg = warning_string(enc, fmt, args);
    va_end(args);
    rb_str_set_len(mesg, RSTRING_LEN(mesg)-1);
    rb_str_catf(mesg, ": %s\n", strerror(errno_save));
    rb_write_error_str(mesg);
    errno = errno_save;
}
Beispiel #21
0
/*
 *  call-seq:
 *     dh.compute_key(pub_bn) -> aString
 *
 * Returns a String containing a shared secret computed from the other party's public value.
 * See DH_compute_key() for further information.
 *
 * === Parameters
 * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by
 * DH#public_key as that contains the DH parameters only.
 */
static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
{
    DH *dh;
    EVP_PKEY *pkey;
    BIGNUM *pub_key;
    VALUE str;
    int len;

    GetPKeyDH(self, pkey);
    dh = pkey->pkey.dh;
    pub_key = GetBNPtr(pub);
    len = DH_size(dh);
    str = rb_str_new(0, len);
    if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
	ossl_raise(eDHError, NULL);
    }
    rb_str_set_len(str, len);

    return str;
}
Beispiel #22
0
/*
 * call-seq:
 * entry.inspect  => String
 *
 * Produce a concise representation of the entry.
 */
VALUE
rb_ldap_entry_inspect (VALUE self)
{
  VALUE str;
  const char *c;

  c = rb_obj_classname (self);
  str = rb_str_new (0, strlen (c) + 10 + 16 + 1);	/* 10:tags 16:addr 1:nul */
  sprintf (RSTRING_PTR (str), "#<%s:0x%lx\n", c, self);

#if RUBY_VERSION_CODE < 190
  RSTRING(str)->len = strlen (RSTRING_PTR (str));
#else
  rb_str_set_len(str, strlen (RSTRING_PTR (str)));
#endif

  rb_str_concat (str, rb_inspect (rb_ldap_entry_to_hash (self)));
  rb_str_cat2 (str, ">");

  return str;
}
Beispiel #23
0
/*
 *  call-seq:
 *     dh.compute_key(pub_bn) -> aString
 *
 * Returns a String containing a shared secret computed from the other party's public value.
 * See DH_compute_key() for further information.
 *
 * === Parameters
 * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by
 * DH#public_key as that contains the DH parameters only.
 */
static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
{
    DH *dh;
    const BIGNUM *pub_key, *dh_p;
    VALUE str;
    int len;

    GetDH(self, dh);
    DH_get0_pqg(dh, &dh_p, NULL, NULL);
    if (!dh_p)
	ossl_raise(eDHError, "incomplete DH");
    pub_key = GetBNPtr(pub);
    len = DH_size(dh);
    str = rb_str_new(0, len);
    if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
	ossl_raise(eDHError, NULL);
    }
    rb_str_set_len(str, len);

    return str;
}
Beispiel #24
0
static VALUE
rb_nkf_convert(VALUE obj, VALUE opt, VALUE src)
{
    reinit();
    StringValue(opt);
    nkf_split_options(RSTRING_PTR(opt));
    if (!output_encoding) rb_raise(rb_eArgError, "no output encoding given");

    switch (nkf_enc_to_index(output_encoding)) {
    case UTF_8_BOM:    output_encoding = nkf_enc_from_index(UTF_8); break;
    case UTF_16BE_BOM: output_encoding = nkf_enc_from_index(UTF_16BE); break;
    case UTF_16LE_BOM: output_encoding = nkf_enc_from_index(UTF_16LE); break;
    case UTF_32BE_BOM: output_encoding = nkf_enc_from_index(UTF_32BE); break;
    case UTF_32LE_BOM: output_encoding = nkf_enc_from_index(UTF_32LE); break;
    }
    output_bom_f = FALSE;

    incsize = INCSIZE;

    input_ctr = 0;
    StringValue(src);
    input = (unsigned char *)RSTRING_PTR(src);
    i_len = RSTRING_LEN(src);
    result = rb_str_new(0, i_len*3 + 10);

    output_ctr = 0;
    output     = (unsigned char *)RSTRING_PTR(result);
    o_len      = RSTRING_LEN(result);
    *output    = '\0';

    kanji_convert(NULL);
    rb_str_set_len(result, output_ctr);
    OBJ_INFECT(result, src);

    rb_enc_associate(result, rb_nkf_enc_get(nkf_enc_name(output_encoding)));

    return result;
}
Beispiel #25
0
static VALUE
append_wstr(VALUE dst, const wchar_t *ws, size_t len, UINT cp, UINT path_cp, rb_encoding *path_encoding)
{
    long olen, nlen = (long)len;

    if (cp == path_cp) {
	nlen = WideCharToMultiByte(cp, 0, ws, len, NULL, 0, NULL, NULL);
	olen = RSTRING_LEN(dst);
	rb_str_modify_expand(dst, nlen);
	WideCharToMultiByte(cp, 0, ws, len, RSTRING_PTR(dst) + olen, nlen, NULL, NULL);
	rb_enc_associate(dst, path_encoding);
	rb_str_set_len(dst, olen + nlen);
    }
    else {
	const int replaceflags = ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE;
	char *utf8str = wstr_to_mbstr(CP_UTF8, ws, (int)len, &nlen);
	rb_econv_t *ec = rb_econv_open("UTF-8", rb_enc_name(path_encoding), replaceflags);
	dst = rb_econv_append(ec, utf8str, nlen, dst, replaceflags);
	rb_econv_close(ec);
	free(utf8str);
    }
    return dst;
}
Beispiel #26
0
/*
 *  call-seq:
 *      pkey.sign(digest, data) -> String
 *
 * To sign the +String+ +data+, +digest+, an instance of OpenSSL::Digest, must
 * be provided. The return value is again a +String+ containing the signature.
 * A PKeyError is raised should errors occur.
 * Any previous state of the +Digest+ instance is irrelevant to the signature
 * outcome, the digest instance is reset to its initial state during the
 * operation.
 *
 * == Example
 *   data = 'Sign me!'
 *   digest = OpenSSL::Digest::SHA256.new
 *   pkey = OpenSSL::PKey::RSA.new(2048)
 *   signature = pkey.sign(digest, data)
 */
static VALUE
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
{
    EVP_PKEY *pkey;
    EVP_MD_CTX ctx;
    unsigned int buf_len;
    VALUE str;

    if (rb_funcallv(self, id_private_q, 0, NULL) != Qtrue) {
	ossl_raise(rb_eArgError, "Private key is needed.");
    }
    GetPKey(self, pkey);
    EVP_SignInit(&ctx, GetDigestPtr(digest));
    StringValue(data);
    EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
    str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
    if (!EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey))
	ossl_raise(ePKeyError, NULL);
    assert((long)buf_len <= RSTRING_LEN(str));
    rb_str_set_len(str, buf_len);

    return str;
}
/*
 * Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
 *
 * This is an encoder class for conversion of base64 encoded data
 * to it's binary representation.
 *
 */
static int
pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
{
	int strlen;
	VALUE subint;
	t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
	t_pg_coder_enc_func enc_func = pg_coder_enc_func(this->elem);

	if(out){
		/* Second encoder pass, if required */
		strlen = enc_func(this->elem, value, out, intermediate);
		strlen = base64_decode( out, out, strlen );

		return strlen;
	} else {
		/* First encoder pass */
		strlen = enc_func(this->elem, value, NULL, &subint);

		if( strlen == -1 ){
			/* Encoded string is returned in subint */
			VALUE out_str;

			strlen = RSTRING_LENINT(subint);
			out_str = rb_str_new(NULL, BASE64_DECODED_SIZE(strlen));

			strlen = base64_decode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
			rb_str_set_len( out_str, strlen );
			*intermediate = out_str;

			return -1;
		} else {
			*intermediate = subint;

			return BASE64_DECODED_SIZE(strlen);
		}
	}
}
Beispiel #28
0
/*
 * IO.pread(fd, length, offset)
 *
 * This is similar to the IO.read method, except that it reads from a given
 * position in the file without changing the file pointer. And unlike IO.read,
 * the +fd+, +length+ and +offset+ arguments are all mandatory.
 */
static VALUE s_io_pread(VALUE klass, VALUE fd, VALUE nbyte, VALUE offset){
   struct pread_args args;
   VALUE str;
   ssize_t nread;

   args.fd = NUM2INT(fd);
   args.nbyte = NUM2ULONG(nbyte);
   args.offset = NUM2OFFT(offset);
   str = rb_str_new(NULL, args.nbyte);
   args.buf = RSTRING_PTR(str);

#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
   nread = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pread, &args, RUBY_UBF_IO, 0);
#else
   nread = (ssize_t)rb_thread_blocking_region(nogvl_pread, &args, RUBY_UBF_IO, 0);
#endif

   if (nread == -1)
      rb_sys_fail("pread");
   if ((size_t)nread != args.nbyte)
      rb_str_set_len(str, nread);

   return str;
}
Beispiel #29
0
VALUE
rb_str_format(int argc, const VALUE *argv, VALUE fmt)
{
    enum {default_float_precision = 6};
    rb_encoding *enc;
    const char *p, *end;
    char *buf;
    long blen, bsiz;
    VALUE result;

    long scanned = 0;
    int coderange = ENC_CODERANGE_7BIT;
    int width, prec, flags = FNONE;
    int nextarg = 1;
    int posarg = 0;
    int tainted = 0;
    VALUE nextvalue;
    VALUE tmp;
    VALUE str;
    volatile VALUE hash = Qundef;

#define CHECK_FOR_WIDTH(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "width given twice");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "width after precision"); \
    }
#define CHECK_FOR_FLAGS(f)				 \
    if ((f) & FWIDTH) {					 \
	rb_raise(rb_eArgError, "flag after width");	 \
    }							 \
    if ((f) & FPREC0) {					 \
	rb_raise(rb_eArgError, "flag after precision"); \
    }

    ++argc;
    --argv;
    if (OBJ_TAINTED(fmt)) tainted = 1;
    StringValue(fmt);
    enc = rb_enc_get(fmt);
    fmt = rb_str_new4(fmt);
    p = RSTRING_PTR(fmt);
    end = p + RSTRING_LEN(fmt);
    blen = 0;
    bsiz = 120;
    result = rb_str_buf_new(bsiz);
    rb_enc_copy(result, fmt);
    buf = RSTRING_PTR(result);
    memset(buf, 0, bsiz);
    ENC_CODERANGE_SET(result, coderange);

    for (; p < end; p++) {
	const char *t;
	int n;
	VALUE sym = Qnil;

	for (t = p; t < end && *t != '%'; t++) ;
	PUSH(p, t - p);
	if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
	    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
	    ENC_CODERANGE_SET(result, coderange);
	}
	if (t >= end) {
	    /* end of fmt string */
	    goto sprint_exit;
	}
	p = t + 1;		/* skip `%' */

	width = prec = -1;
	nextvalue = Qundef;
      retry:
	switch (*p) {
	  default:
	    if (rb_enc_isprint(*p, enc))
		rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
	    else
		rb_raise(rb_eArgError, "malformed format string");
	    break;

	  case ' ':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSPACE;
	    p++;
	    goto retry;

	  case '#':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FSHARP;
	    p++;
	    goto retry;

	  case '+':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FPLUS;
	    p++;
	    goto retry;

	  case '-':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FMINUS;
	    p++;
	    goto retry;

	  case '0':
	    CHECK_FOR_FLAGS(flags);
	    flags |= FZERO;
	    p++;
	    goto retry;

	  case '1': case '2': case '3': case '4':
	  case '5': case '6': case '7': case '8': case '9':
	    n = 0;
	    GETNUM(n, width);
	    if (*p == '$') {
		if (nextvalue != Qundef) {
		    rb_raise(rb_eArgError, "value given twice - %d$", n);
		}
		nextvalue = GETPOSARG(n);
		p++;
		goto retry;
	    }
	    CHECK_FOR_WIDTH(flags);
	    width = n;
	    flags |= FWIDTH;
	    goto retry;

	  case '<':
	  case '{':
	    {
		const char *start = p;
		char term = (*p == '<') ? '>' : '}';
		int len;

		for (; p < end && *p != term; ) {
		    p += rb_enc_mbclen(p, end, enc);
		}
		if (p >= end) {
		    rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
		}
#if SIZEOF_INT < SIZEOF_SIZE_T
		if ((size_t)(p - start) >= INT_MAX) {
		    const int message_limit = 20;
		    len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
		    rb_enc_raise(enc, rb_eArgError,
				 "too long name (%"PRIdSIZE" bytes) - %.*s...%c",
				 (size_t)(p - start - 2), len, start, term);
		}
#endif
		len = (int)(p - start + 1); /* including parenthesis */
		if (sym != Qnil) {
		    rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
				 len, start, rb_sym2str(sym));
		}
		CHECKNAMEARG(start, len, enc);
		get_hash(&hash, argc, argv);
		sym = rb_check_symbol_cstr(start + 1,
					   len - 2 /* without parenthesis */,
					   enc);
		if (sym != Qnil) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
		if (nextvalue == Qundef) {
		    rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
		}
		if (term == '}') goto format_s;
		p++;
		goto retry;
	    }

	  case '*':
	    CHECK_FOR_WIDTH(flags);
	    flags |= FWIDTH;
	    GETASTER(width);
	    if (width < 0) {
		flags |= FMINUS;
		width = -width;
	    }
	    p++;
	    goto retry;

	  case '.':
	    if (flags & FPREC0) {
		rb_raise(rb_eArgError, "precision given twice");
	    }
	    flags |= FPREC|FPREC0;

	    prec = 0;
	    p++;
	    if (*p == '*') {
		GETASTER(prec);
		if (prec < 0) {	/* ignore negative precision */
		    flags &= ~FPREC;
		}
		p++;
		goto retry;
	    }

	    GETNUM(prec, precision);
	    goto retry;

	  case '\n':
	  case '\0':
	    p--;
	  case '%':
	    if (flags != FNONE) {
		rb_raise(rb_eArgError, "invalid format character - %%");
	    }
	    PUSH("%", 1);
	    break;

	  case 'c':
	    {
		VALUE val = GETARG();
		VALUE tmp;
		unsigned int c;
		int n;

		tmp = rb_check_string_type(val);
		if (!NIL_P(tmp)) {
		    if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
			rb_raise(rb_eArgError, "%%c requires a character");
		    }
		    c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
		    RB_GC_GUARD(tmp);
		}
		else {
		    c = NUM2INT(val);
		    n = rb_enc_codelen(c, enc);
		}
		if (n <= 0) {
		    rb_raise(rb_eArgError, "invalid character");
		}
		if (!(flags & FWIDTH)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
		else if ((flags & FMINUS)) {
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		    FILL(' ', width-1);
		}
		else {
		    FILL(' ', width-1);
		    CHECK(n);
		    rb_enc_mbcput(c, &buf[blen], enc);
		    blen += n;
		}
	    }
	    break;

	  case 's':
	  case 'p':
	  format_s:
	    {
		VALUE arg = GETARG();
		long len, slen;

		if (*p == 'p') arg = rb_inspect(arg);
		str = rb_obj_as_string(arg);
		if (OBJ_TAINTED(str)) tainted = 1;
		len = RSTRING_LEN(str);
		rb_str_set_len(result, blen);
		if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
		    int cr = coderange;
		    scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
		    ENC_CODERANGE_SET(result,
				      (cr == ENC_CODERANGE_UNKNOWN ?
				       ENC_CODERANGE_BROKEN : (coderange = cr)));
		}
		enc = rb_enc_check(result, str);
		if (flags&(FPREC|FWIDTH)) {
		    slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
		    if (slen < 0) {
			rb_raise(rb_eArgError, "invalid mbstring sequence");
		    }
		    if ((flags&FPREC) && (prec < slen)) {
			char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
					     prec, enc);
			slen = prec;
			len = p - RSTRING_PTR(str);
		    }
		    /* need to adjust multi-byte string pos */
		    if ((flags&FWIDTH) && (width > slen)) {
			width -= (int)slen;
			if (!(flags&FMINUS)) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			CHECK(len);
			memcpy(&buf[blen], RSTRING_PTR(str), len);
			RB_GC_GUARD(str);
			blen += len;
			if (flags&FMINUS) {
			    CHECK(width);
			    while (width--) {
				buf[blen++] = ' ';
			    }
			}
			rb_enc_associate(result, enc);
			break;
		    }
		}
		PUSH(RSTRING_PTR(str), len);
		RB_GC_GUARD(str);
		rb_enc_associate(result, enc);
	    }
	    break;

	  case 'd':
	  case 'i':
	  case 'o':
	  case 'x':
	  case 'X':
	  case 'b':
	  case 'B':
	  case 'u':
	    {
		volatile VALUE val = GETARG();
                int valsign;
		char nbuf[64], *s;
		const char *prefix = 0;
		int sign = 0, dots = 0;
		char sc = 0;
		long v = 0;
		int base, bignum = 0;
		int len;

		switch (*p) {
		  case 'd':
		  case 'i':
		  case 'u':
		    sign = 1; break;
		  case 'o':
		  case 'x':
		  case 'X':
		  case 'b':
		  case 'B':
		    if (flags&(FPLUS|FSPACE)) sign = 1;
		    break;
		}
		if (flags & FSHARP) {
		    switch (*p) {
		      case 'o':
			prefix = "0"; break;
		      case 'x':
			prefix = "0x"; break;
		      case 'X':
			prefix = "0X"; break;
		      case 'b':
			prefix = "0b"; break;
		      case 'B':
			prefix = "0B"; break;
		    }
		}

	      bin_retry:
		switch (TYPE(val)) {
		  case T_FLOAT:
		    if (FIXABLE(RFLOAT_VALUE(val))) {
			val = LONG2FIX((long)RFLOAT_VALUE(val));
			goto bin_retry;
		    }
		    val = rb_dbl2big(RFLOAT_VALUE(val));
		    if (FIXNUM_P(val)) goto bin_retry;
		    bignum = 1;
		    break;
		  case T_STRING:
		    val = rb_str_to_inum(val, 0, TRUE);
		    goto bin_retry;
		  case T_BIGNUM:
		    bignum = 1;
		    break;
		  case T_FIXNUM:
		    v = FIX2LONG(val);
		    break;
		  default:
		    val = rb_Integer(val);
		    goto bin_retry;
		}

		switch (*p) {
		  case 'o':
		    base = 8; break;
		  case 'x':
		  case 'X':
		    base = 16; break;
		  case 'b':
		  case 'B':
		    base = 2; break;
		  case 'u':
		  case 'd':
		  case 'i':
		  default:
		    base = 10; break;
		}

                if (base != 10) {
                    int numbits = ffs(base)-1;
                    size_t abs_nlz_bits;
                    size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits);
                    long i;
                    if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */
                        rb_raise(rb_eArgError, "size too big");
                    if (sign) {
                        if (numdigits == 0)
                            numdigits = 1;
                        tmp = rb_str_new(NULL, numdigits);
                        valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
                                1, CHAR_BIT-numbits, INTEGER_PACK_BIG_ENDIAN);
                        for (i = 0; i < RSTRING_LEN(tmp); i++)
                            RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
                        s = RSTRING_PTR(tmp);
                        if (valsign < 0) {
                            sc = '-';
                            width--;
                        }
                        else if (flags & FPLUS) {
                            sc = '+';
                            width--;
                        }
                        else if (flags & FSPACE) {
                            sc = ' ';
                            width--;
                        }
                    }
                    else {
                        /* Following conditional "numdigits++" guarantees the
                         * most significant digit as
                         * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
                         * - '0' for zero
                         * - not '0' for positive numbers.
                         *
                         * It also guarantees the most significant two
                         * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
                         * or '00'.  */
                        if (numdigits == 0 ||
                                ((abs_nlz_bits != (size_t)(numbits-1) ||
                                  !rb_absint_singlebit_p(val)) &&
                                 (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
                            numdigits++;
                        tmp = rb_str_new(NULL, numdigits);
                        valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
                                1, CHAR_BIT-numbits, INTEGER_PACK_2COMP | INTEGER_PACK_BIG_ENDIAN);
                        for (i = 0; i < RSTRING_LEN(tmp); i++)
                            RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
                        s = RSTRING_PTR(tmp);
                        dots = valsign < 0;
                    }
                    len = rb_long2int(RSTRING_END(tmp) - s);
                }
                else if (!bignum) {
                    valsign = 1;
                    if (v < 0) {
                        v = -v;
                        sc = '-';
                        width--;
                        valsign = -1;
                    }
                    else if (flags & FPLUS) {
                        sc = '+';
                        width--;
                    }
                    else if (flags & FSPACE) {
                        sc = ' ';
                        width--;
                    }
                    snprintf(nbuf, sizeof(nbuf), "%ld", v);
                    s = nbuf;
		    len = (int)strlen(s);
		}
		else {
                    tmp = rb_big2str(val, 10);
                    s = RSTRING_PTR(tmp);
                    valsign = 1;
                    if (s[0] == '-') {
                        s++;
                        sc = '-';
                        width--;
                        valsign = -1;
                    }
                    else if (flags & FPLUS) {
                        sc = '+';
                        width--;
                    }
                    else if (flags & FSPACE) {
                        sc = ' ';
                        width--;
                    }
		    len = rb_long2int(RSTRING_END(tmp) - s);
		}

		if (dots) {
		    prec -= 2;
		    width -= 2;
		}

		if (*p == 'X') {
		    char *pp = s;
		    int c;
		    while ((c = (int)(unsigned char)*pp) != 0) {
			*pp = rb_enc_toupper(c, enc);
			pp++;
		    }
		}
		if (prefix && !prefix[1]) { /* octal */
		    if (dots) {
			prefix = 0;
		    }
		    else if (len == 1 && *s == '0') {
			len = 0;
			if (flags & FPREC) prec--;
		    }
		    else if ((flags & FPREC) && (prec > len)) {
			prefix = 0;
		    }
		}
		else if (len == 1 && *s == '0') {
		    prefix = 0;
		}
		if (prefix) {
		    width -= (int)strlen(prefix);
		}
		if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
		    prec = width;
		    width = 0;
		}
		else {
		    if (prec < len) {
			if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
			prec = len;
		    }
		    width -= prec;
		}
		if (!(flags&FMINUS)) {
		    CHECK(width);
		    while (width-- > 0) {
			buf[blen++] = ' ';
		    }
		}
		if (sc) PUSH(&sc, 1);
		if (prefix) {
		    int plen = (int)strlen(prefix);
		    PUSH(prefix, plen);
		}
		CHECK(prec - len);
		if (dots) PUSH("..", 2);
		if (!sign && valsign < 0) {
		    char c = sign_bits(base, p);
		    while (len < prec--) {
			buf[blen++] = c;
		    }
		}
		else if ((flags & (FMINUS|FPREC)) != FMINUS) {
		    while (len < prec--) {
			buf[blen++] = '0';
		    }
		}
		PUSH(s, len);
		RB_GC_GUARD(tmp);
		CHECK(width);
		while (width-- > 0) {
		    buf[blen++] = ' ';
		}
	    }
	    break;

	  case 'f':
	    {
		VALUE val = GETARG(), num, den;
		int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
		long len, done = 0;
		int prefix = 0;
		if (!RB_TYPE_P(val, T_RATIONAL)) {
		    nextvalue = val;
		    goto float_value;
		}
		if (!(flags&FPREC)) prec = default_float_precision;
		den = rb_rational_den(val);
		num = rb_rational_num(val);
		if (FIXNUM_P(num)) {
		    if ((SIGNED_VALUE)num < 0) {
			long n = -FIX2LONG(num);
			num = LONG2FIX(n);
			sign = -1;
		    }
		}
		else if (rb_num_negative_p(num)) {
		    sign = -1;
		    num = rb_funcallv(num, idUMinus, 0, 0);
		}
		if (den != INT2FIX(1) || prec > 1) {
		    const ID idDiv = rb_intern("div");
		    VALUE p10 = rb_int_positive_pow(10, prec);
		    VALUE den_2 = rb_funcall(den, idDiv, 1, INT2FIX(2));
		    num = rb_funcallv(num, '*', 1, &p10);
		    num = rb_funcallv(num, '+', 1, &den_2);
		    num = rb_funcallv(num, idDiv, 1, &den);
		}
		else if (prec >= 0) {
		    zero = prec;
		}
		val = rb_obj_as_string(num);
		len = RSTRING_LEN(val) + zero;
		if (prec >= len) ++len; /* integer part 0 */
		if (sign || (flags&FSPACE)) ++len;
		if (prec > 0) ++len; /* period */
		CHECK(len > width ? len : width);
		if (sign || (flags&FSPACE)) {
		    buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
		    prefix++;
		    done++;
		}
		len = RSTRING_LEN(val) + zero;
		t = RSTRING_PTR(val);
		if (len > prec) {
		    memcpy(&buf[blen], t, len - prec);
		    blen += len - prec;
		    done += len - prec;
		}
		else {
		    buf[blen++] = '0';
		    done++;
		}
		if (prec > 0) {
		    buf[blen++] = '.';
		    done++;
		}
		if (zero) {
		    FILL('0', zero);
		    done += zero;
		}
		else if (prec > len) {
		    FILL('0', prec - len);
		    memcpy(&buf[blen], t, len);
		    blen += len;
		    done += prec;
		}
		else if (prec > 0) {
		    memcpy(&buf[blen], t + len - prec, prec);
		    blen += prec;
		    done += prec;
		}
		if ((flags & FWIDTH) && width > done) {
		    int fill = ' ';
		    long shifting = 0;
		    if (!(flags&FMINUS)) {
			shifting = done;
			if (flags&FZERO) {
			    shifting -= prefix;
			    fill = '0';
			}
			blen -= shifting;
			memmove(&buf[blen + width - done], &buf[blen], shifting);
		    }
		    FILL(fill, width - done);
		    blen += shifting;
		}
		RB_GC_GUARD(val);
		break;
	    }
	  case 'g':
	  case 'G':
	  case 'e':
	  case 'E':
	    /* TODO: rational support */
	  case 'a':
	  case 'A':
	  float_value:
	    {
		VALUE val = GETARG();
		double fval;
		int i, need;
		char fbuf[32];

		fval = RFLOAT_VALUE(rb_Float(val));
		if (isnan(fval) || isinf(fval)) {
		    const char *expr;

		    if (isnan(fval)) {
			expr = "NaN";
		    }
		    else {
			expr = "Inf";
		    }
		    need = (int)strlen(expr);
		    if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
			need++;
		    if ((flags & FWIDTH) && need < width)
			need = width;

		    CHECK(need + 1);
		    snprintf(&buf[blen], need + 1, "%*s", need, "");
		    if (flags & FMINUS) {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen++] = '-';
			else if (flags & FPLUS)
			    buf[blen++] = '+';
			else if (flags & FSPACE)
			    blen++;
			memcpy(&buf[blen], expr, strlen(expr));
		    }
		    else {
			if (!isnan(fval) && fval < 0.0)
			    buf[blen + need - strlen(expr) - 1] = '-';
			else if (flags & FPLUS)
			    buf[blen + need - strlen(expr) - 1] = '+';
			else if ((flags & FSPACE) && need > width)
			    blen++;
			memcpy(&buf[blen + need - strlen(expr)], expr,
			       strlen(expr));
		    }
		    blen += strlen(&buf[blen]);
		    break;
		}

		fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
		need = 0;
		if (*p != 'e' && *p != 'E') {
		    i = INT_MIN;
		    frexp(fval, &i);
		    if (i > 0)
			need = BIT_DIGITS(i);
		}
		need += (flags&FPREC) ? prec : default_float_precision;
		if ((flags&FWIDTH) && need < width)
		    need = width;
		need += 20;

		CHECK(need);
		snprintf(&buf[blen], need, fbuf, fval);
		blen += strlen(&buf[blen]);
	    }
	    break;
	}
	flags = FNONE;
    }

  sprint_exit:
    RB_GC_GUARD(fmt);
    /* XXX - We cannot validate the number of arguments if (digit)$ style used.
     */
    if (posarg >= 0 && nextarg < argc) {
	const char *mesg = "too many arguments for format string";
	if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
	if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
    }
    rb_str_resize(result, blen);

    if (tainted) OBJ_TAINT(result);
    return result;
}
Beispiel #30
0
void
ruby_init_loadpath_safe(int safe_level, const char* szRoot)
{
    VALUE load_path;
    ID id_initial_load_path_mark;
    extern const char ruby_initial_load_paths[];
    const char *paths = ruby_initial_load_paths;
#if defined LOAD_RELATIVE
# if defined HAVE_DLADDR || (defined __CYGWIN__ && defined CCP_WIN_A_TO_POSIX)
#   define VARIABLE_LIBPATH 1
# else
#   define VARIABLE_LIBPATH 0
# endif
# if VARIABLE_LIBPATH
    char *libpath;
    VALUE sopath;
# else
    char libpath[MAXPATHLEN + 1];
# endif
    size_t baselen;
    char *p;
	if ( szRoot )
		strncpy(libpath, szRoot, sizeof(libpath) - 1);
	else
	{
#if defined _WIN32 || defined __CYGWIN__
# if VARIABLE_LIBPATH
    sopath = rb_str_new(0, MAXPATHLEN);
    libpath = RSTRING_PTR(sopath);
    GetModuleFileName(libruby, libpath, MAXPATHLEN);
# else
    GetModuleFileName(libruby, libpath, sizeof libpath);
# endif
#elif defined(__EMX__)
    _execname(libpath, sizeof(libpath) - 1);
#elif defined(HAVE_DLADDR)
    Dl_info dli;
    if (dladdr((void *)(VALUE)expand_include_path, &dli)) {
	VALUE fname = rb_str_new_cstr(dli.dli_fname);
	sopath = rb_file_absolute_path(fname, Qnil);
	rb_str_resize(fname, 0);
    }
    else {
	sopath = rb_str_new(0, 0);
    }
    libpath = RSTRING_PTR(sopath);
#endif
    }
//RHO

#if !VARIABLE_LIBPATH
    libpath[sizeof(libpath) - 1] = '\0';
#endif
#if defined DOSISH
    translit_char(libpath, '\\', '/');
#elif defined __CYGWIN__
    {
# if VARIABLE_LIBPATH
	const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
	size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
	if (newsize > 0) {
	    VALUE rubylib = rb_str_new(0, newsize);
	    p = RSTRING_PTR(rubylib);
	    if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
		rb_str_resize(sopath, 0);
		sopath = rubylib;
		libpath = p;
	    }
	}
# else
	char rubylib[FILENAME_MAX];
	cygwin_conv_to_posix_path(libpath, rubylib);
	strncpy(libpath, rubylib, sizeof(libpath));
# endif
    }
#endif
    p = strrchr(libpath, '/');
    if (p) {
	*p = 0;
	if (p - libpath > 3 && !(STRCASECMP(p - 4, "/bin") && strcmp(p - 4, "/lib"))) {
	    p -= 4;
	    *p = 0;
	}
    }
#if !VARIABLE_LIBPATH
    else {
	strlcpy(libpath, ".", sizeof(libpath));
	p = libpath + 1;
    }
    baselen = p - libpath;
#define PREFIX_PATH() rb_str_new(libpath, baselen)
#else
    baselen = p - libpath;
    rb_str_set_len(sopath, baselen);
    libpath = RSTRING_PTR(sopath);
#define PREFIX_PATH() sopath
#endif

#define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)

#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), path, len)
#else
    static const char exec_prefix[] = RUBY_EXEC_PREFIX;
#define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len)
#define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1)
#endif
    load_path = GET_VM()->load_path;

    if (safe_level == 0) {
	ruby_push_include(getenv("RUBYLIB"), identical_path);
    }

    id_initial_load_path_mark = rb_intern_const("@gem_prelude_index");
    while (*paths) {
	size_t len = strlen(paths);
	VALUE path = RUBY_RELATIVE(paths, len);
	rb_ivar_set(path, id_initial_load_path_mark, path);
	rb_ary_push(load_path, path);
	paths += len + 1;
    }

    rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH()));
}