Exemple #1
0
static VALUE
ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
			 VALUE reason, VALUE revtime,
			 VALUE thisupd, VALUE nextupd, VALUE ext)
{
    OCSP_BASICRESP *bs;
    OCSP_SINGLERESP *single;
    OCSP_CERTID *id;
    int st, rsn;
    ASN1_TIME *ths, *nxt, *rev;
    int error, i, rstatus = 0;
    VALUE tmp;

    st = NUM2INT(status);
    rsn = NIL_P(status) ? 0 : NUM2INT(reason);
    if(!NIL_P(ext)){
	/* All ary's members should be X509Extension */
	Check_Type(ext, T_ARRAY);
	for (i = 0; i < RARRAY_LEN(ext); i++)
	    OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
    }

    error = 0;
    ths = nxt = rev = NULL;
    if(!NIL_P(revtime)){
	tmp = rb_protect(rb_Integer, revtime, &rstatus);
	if(rstatus) goto err;
	rev = X509_gmtime_adj(NULL, NUM2INT(tmp));
    }
    tmp = rb_protect(rb_Integer, thisupd, &rstatus);
    if(rstatus) goto err;
    ths = X509_gmtime_adj(NULL, NUM2INT(tmp));
    tmp = rb_protect(rb_Integer, nextupd, &rstatus);
    if(rstatus) goto err;
    nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));

    GetOCSPBasicRes(self, bs);
    SafeGetOCSPCertId(cid, id);
    if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
	error = 1;
	goto err;
    }

    if(!NIL_P(ext)){
	X509_EXTENSION *x509ext;
	sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
	single->singleExtensions = NULL;
	for(i = 0; i < RARRAY_LEN(ext); i++){
	    x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
	    if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
		X509_EXTENSION_free(x509ext);
		error = 1;
		goto err;
	    }
	    X509_EXTENSION_free(x509ext);
	}
    }

 err:
    ASN1_TIME_free(ths);
    ASN1_TIME_free(nxt);
    ASN1_TIME_free(rev);
    if(error) ossl_raise(eOCSPError, NULL);
    if(rstatus) rb_jump_tag(rstatus);

    return self;
}
Exemple #2
0
/*
 *  call-seq:
 *    remote.fetch(refspecs = nil, options = {}) -> hash
 *
 *  Downloads new data from the remote for the given +refspecs+ and updates tips.
 *
 *  You can optionally pass in an alternative list of +refspecs+ to use instead of the fetch
 *  refspecs already configured for +remote+.
 *
 *  Returns a hash containing statistics for the fetch operation.
 *
 *  The following options can be passed in the +options+ Hash:
 *
 *  :credentials ::
 *    The credentials to use for the fetch operation. Can be either an instance of one
 *    of the Rugged::Credentials types, or a proc returning one of the former.
 *    The proc will be called with the +url+, the +username+ from the url (if applicable) and
 *    a list of applicable credential types.
 *
 *  :progress ::
 *    A callback that will be executed with the textual progress received from the remote.
 *    This is the text send over the progress side-band (ie. the "counting objects" output).
 *
 *  :transfer_progress ::
 *    A callback that will be executed to report clone progress information. It will be passed
 *    the amount of +total_objects+, +indexed_objects+, +received_objects+, +local_objects+,
 *    +total_deltas+, +indexed_deltas+ and +received_bytes+.
 *
 *  :update_tips ::
 *    A callback that will be executed each time a reference is updated locally. It will be
 *    passed the +refname+, +old_oid+ and +new_oid+.
 *
 *  :message ::
 *    The message to insert into the reflogs. Defaults to "fetch".
 *
 *  :signature ::
 *    The signature to be used for updating the reflogs.
 *
 *  Example:
 *
 *    remote = Rugged::Remote.lookup(@repo, 'origin')
 *    remote.fetch({
 *      transfer_progress: lambda { |total_objects, indexed_objects, received_objects, local_objects, total_deltas, indexed_deltas, received_bytes|
 *        # ...
 *      }
 *    })
 */
static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
{
	git_remote *remote, *tmp_remote = NULL;
	git_repository *repo;
	git_signature *signature = NULL;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
	struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };

	char *log_message = NULL;
	int error, i;

	VALUE rb_options, rb_refspecs, rb_result = Qnil, rb_repo = rugged_owner(self);

	rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);

	if (!NIL_P(rb_refspecs)) {
		Check_Type(rb_refspecs, T_ARRAY);
		for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);
			Check_Type(rb_refspec, T_STRING);
		}
	}

	Data_Get_Struct(self, git_remote, remote);
	rugged_check_repo(rb_repo);
	Data_Get_Struct(rb_repo, git_repository, repo);

	if (!NIL_P(rb_options)) {
		VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature"));
		if (!NIL_P(rb_val))
			signature = rugged_signature_get(rb_val, repo);

		rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
		if (!NIL_P(rb_val))
			log_message = StringValueCStr(rb_val);

		rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
	}

	if ((error = git_remote_dup(&tmp_remote, remote)) ||
		(error = git_remote_set_callbacks(tmp_remote, &callbacks)))
		goto cleanup;

	if (!NIL_P(rb_refspecs)) {
		git_remote_clear_refspecs(tmp_remote);
		for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) {
			VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);

			if ((error = git_remote_add_fetch(tmp_remote, StringValueCStr(rb_refspec))))
				goto cleanup;
		}
	}

	if ((error = git_remote_fetch(tmp_remote, signature, log_message)) == GIT_OK) {
		const git_transfer_progress *stats = git_remote_stats(tmp_remote);

		rb_result = rb_hash_new();
		rb_hash_aset(rb_result, CSTR2SYM("total_objects"),    UINT2NUM(stats->total_objects));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_objects"),  UINT2NUM(stats->indexed_objects));
		rb_hash_aset(rb_result, CSTR2SYM("received_objects"), UINT2NUM(stats->received_objects));
		rb_hash_aset(rb_result, CSTR2SYM("local_objects"),    UINT2NUM(stats->local_objects));
		rb_hash_aset(rb_result, CSTR2SYM("total_deltas"),     UINT2NUM(stats->total_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("indexed_deltas"),   UINT2NUM(stats->indexed_deltas));
		rb_hash_aset(rb_result, CSTR2SYM("received_bytes"),   INT2FIX(stats->received_bytes));
	}

	cleanup:

	git_signature_free(signature);
	git_remote_free(tmp_remote);

	if (payload.exception)
		rb_jump_tag(payload.exception);

	rugged_exception_check(error);

	return rb_result;
}
Exemple #3
0
/*
 * This is the method that actually puts your code into a loop and allows it
 * to run as a service.  The code that is actually run while in the mainloop
 * is what you defined in your own Daemon#service_main method.
 */
static VALUE daemon_mainloop(VALUE self)
{
   DWORD ThreadId;
   HANDLE events[2];
   DWORD index;
   VALUE result, EventHookHash;
   int status = 0;

   dwServiceState = 0;

   // Redirect STDIN, STDOUT and STDERR to the NUL device if they're still
   // associated with a tty. This helps newbs avoid Errno::EBADF errors.
   if(rb_funcall(rb_stdin, rb_intern("isatty"), 0) == Qtrue)
      rb_funcall(rb_stdin, rb_intern("reopen"), 1, rb_str_new2("NUL"));

   if(rb_funcall(rb_stdout, rb_intern("isatty"), 0) == Qtrue)
      rb_funcall(rb_stdout, rb_intern("reopen"), 1, rb_str_new2("NUL"));

   if(rb_funcall(rb_stderr, rb_intern("isatty"), 0) == Qtrue)
      rb_funcall(rb_stderr, rb_intern("reopen"), 1, rb_str_new2("NUL"));

   // Use a markable instance variable to prevent the garbage collector
   // from freeing the hash before Ruby_Service_Ctrl exits, or just
   // at any ole time while running the service
   EventHookHash = rb_hash_new();
   rb_ivar_set(self, rb_intern("@event_hooks"), EventHookHash);

   // Event hooks
   if(rb_respond_to(self, rb_intern("service_stop"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_STOP),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_stop"))));
   }

   if(rb_respond_to(self, rb_intern("service_pause"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PAUSE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_pause"))));
   }

   if(rb_respond_to(self, rb_intern("service_resume"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_CONTINUE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_resume"))));
   }

   if(rb_respond_to(self, rb_intern("service_interrogate"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_INTERROGATE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_interrogate"))));
   }

   if(rb_respond_to(self, rb_intern("service_shutdown"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_SHUTDOWN),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_shutdown"))));
   }

#ifdef SERVICE_CONTROL_PARAMCHANGE
   if(rb_respond_to(self, rb_intern("service_paramchange"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_PARAMCHANGE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_paramchange"))));
   }
#endif

#ifdef SERVICE_CONTROL_NETBINDADD
   if(rb_respond_to(self, rb_intern("service_netbindadd"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDADD),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindadd"))));
   }
#endif

#ifdef SERVICE_CONTROL_NETBINDREMOVE
   if(rb_respond_to(self, rb_intern("service_netbindremove"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDREMOVE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindremove"))));
   }
#endif

#ifdef SERVICE_CONTROL_NETBINDENABLE
   if(rb_respond_to(self, rb_intern("service_netbindenable"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDENABLE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbindenable"))));
   }
#endif

#ifdef SERVICE_CONTROL_NETBINDDISABLE
   if(rb_respond_to(self, rb_intern("service_netbinddisable"))){
      rb_hash_aset(EventHookHash, INT2NUM(SERVICE_CONTROL_NETBINDDISABLE),
         rb_ary_new3(2, self, INT2NUM(rb_intern("service_netbinddisable"))));
   }
#endif

   // Calling init here so that init failures never even tries to
   // start the service... of course that means that init methods
   // must be very quick, because the SCM will be receiving no
   // START_PENDING messages while init's running - I may fix this
   // later
   if(rb_respond_to(self, rb_intern("service_init")))
      rb_funcall(self, rb_intern("service_init"),0);

   // Create the event to signal the service to start.
   hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

   if(hStartEvent == NULL)
      rb_raise(cDaemonError, ErrorDescription(GetLastError()));

   // Create the event to signal the service to stop.
   hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

   if(hStopEvent == NULL)
      rb_raise(cDaemonError, ErrorDescription(GetLastError()));

   // Create the event to signal the service that stop has completed
   hStopCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

   if(hStopCompletedEvent == NULL)
      rb_raise(cDaemonError, ErrorDescription(GetLastError()));

   // Create Thread for service main
   hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &ThreadId);

   if(hThread == INVALID_HANDLE_VALUE)
      rb_raise(cDaemonError, ErrorDescription(GetLastError()));

   events[0] = hThread;
   events[1] = hStartEvent;

   // wait for Service_Main function to either start the service OR terminate
   while((index = WaitForMultipleObjects(2,events,FALSE,1000)) == WAIT_TIMEOUT)
   {
   }

   // thread exited, so the show is off
   if(index == WAIT_OBJECT_0)
      rb_raise(cDaemonError, "Service_Main thread exited abnormally");

   // from this point onward, stopevent must be triggered!

   // Create the green thread to poll for Service_Ctrl events
   rb_thread_create(Ruby_Service_Ctrl, (void *)self);

   result = rb_protect(daemon_mainloop_protect, self, &status);

   // service_main raised an exception
   if(status){
      daemon_mainloop_ensure(self);
      rb_jump_tag(status);
   }

   // service_main exited cleanly
   return daemon_mainloop_ensure(self);
}
Exemple #4
0
static VALUE zipruby_archive_s_open_buffer(int argc, VALUE *argv, VALUE self) {
  VALUE buffer, flags, comp_level;
  VALUE archive;
  struct zipruby_archive *p_archive;
  void *data = NULL;
  int len = 0, i_flags = 0;
  int errorp;
  int i_comp_level = Z_BEST_COMPRESSION;
  int buffer_is_temporary = 0;

  rb_scan_args(argc, argv, "03", &buffer, &flags, &comp_level);

  if (FIXNUM_P(buffer) && NIL_P(comp_level)) {
    comp_level = flags;
    flags = buffer;
    buffer = Qnil;
  }

  if (!NIL_P(flags)) {
    i_flags = NUM2INT(flags);
  }

  if (!NIL_P(comp_level)) {
    i_comp_level = NUM2INT(comp_level);

    if (i_comp_level != Z_DEFAULT_COMPRESSION && i_comp_level != Z_NO_COMPRESSION && (i_comp_level < Z_BEST_SPEED || Z_BEST_COMPRESSION < i_comp_level)) {
      rb_raise(rb_eArgError, "Wrong compression level %d", i_comp_level);
    }
  }

  if (i_flags & ZIP_CREATE) {
    if (!NIL_P(buffer)) {
      Check_Type(buffer, T_STRING);
    } else {
      buffer = rb_str_new("", 0);
      buffer_is_temporary = 1;
    }

    i_flags = (i_flags | ZIP_TRUNCATE);
  } else if (TYPE(buffer) == T_STRING) {
    data = RSTRING_PTR(buffer);
    len = RSTRING_LEN(buffer);
  } else if (rb_obj_is_instance_of(buffer, rb_cProc)) {
    data = (void *) buffer;
    len = -1;
  } else {
    rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Proc)", rb_class2name(CLASS_OF(buffer)));
  }

  archive = rb_funcall(Archive, rb_intern("new"), 0);
  Data_Get_Struct(archive, struct zipruby_archive, p_archive);

  if ((p_archive->tmpfilnam = zipruby_tmpnam(data, len)) == NULL) {
    rb_raise(Error, "Open archive failed: Failed to create temporary file");
  }

  if ((p_archive->archive = zip_open(p_archive->tmpfilnam, i_flags, &errorp)) == NULL) {
    char errstr[ERRSTR_BUFSIZE];
    zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
    rb_raise(Error, "Open archive failed: %s", errstr);
  }

  //  p_archive->archive->comp_level = i_comp_level;
  p_archive->path = rb_str_new2(p_archive->tmpfilnam);
  p_archive->flags = i_flags;
  p_archive->buffer = buffer;
  p_archive->sources = rb_ary_new();

  if (rb_block_given_p()) {
    VALUE retval;
    int status;

    retval = rb_protect(rb_yield, archive, &status);
    zipruby_archive_close(archive);

    if (status != 0) {
      rb_jump_tag(status);
    }

    return buffer_is_temporary ? buffer : retval;
  } else {
    return archive;
  }
}
Exemple #5
0
void
initialize_semaphore_set(semian_resource_t* res, const char* id_str, long permissions, int tickets, double quota)
{

  res->key = generate_key(id_str);
  res->strkey = (char*)  malloc((2 /*for 0x*/+ sizeof(uint64_t) /*actual key*/+ 1 /*null*/) * sizeof(char));
  sprintf(res->strkey, "0x%08x", (unsigned int) res->key);
  res->sem_id = semget(res->key, SI_NUM_SEMAPHORES, IPC_CREAT | IPC_EXCL | permissions);

  /*
  This approach is based on http://man7.org/tlpi/code/online/dist/svsem/svsem_good_init.c.html
  which avoids race conditions when initializing semaphore sets.
  */
  if (res->sem_id != -1) {
    // Happy path - we are the first worker, initialize the semaphore set.
    initialize_new_semaphore_values(res->sem_id, permissions);
  } else {
    // Something went wrong
    if (errno != EEXIST) {
      raise_semian_syscall_error("semget() failed to initialize semaphore values", errno);
    } else {
      // The semaphore set already exists, ensure it is initialized
      res->sem_id = wait_for_new_semaphore_set(res->key, permissions);
    }
  }

  set_semaphore_permissions(res->sem_id, permissions);

  /*
    Ensure that a worker for this process is registered.
    Note that from ruby we ensure that at most one worker may be registered per process.
  */
  if (perform_semop(res->sem_id, SI_SEM_REGISTERED_WORKERS, 1, SEM_UNDO, NULL) == -1) {
    rb_raise(eInternal, "error incrementing registered workers, errno: %d (%s)", errno, strerror(errno));
  }

  int state = 0;
  sem_meta_lock(res->sem_id); // Sets otime for the first time by acquiring the sem lock

  configure_tickets_args_t configure_tickets_args = (configure_tickets_args_t){
    .sem_id = res->sem_id,
    .tickets = tickets,
    .quota = quota,
  };
  rb_protect(
    configure_tickets,
    (VALUE)&configure_tickets_args,
    &state);

  sem_meta_unlock(res->sem_id);
  if (state) {
    rb_jump_tag(state);
  }
}

void
set_semaphore_permissions(int sem_id, long permissions)
{
  union semun sem_opts;
  struct semid_ds stat_buf;

  sem_opts.buf = &stat_buf;
  semctl(sem_id, 0, IPC_STAT, sem_opts);
  if ((stat_buf.sem_perm.mode & 0xfff) != permissions) {
    stat_buf.sem_perm.mode &= ~0xfff;
    stat_buf.sem_perm.mode |= permissions;
    semctl(sem_id, 0, IPC_SET, sem_opts);
  }
}

int
perform_semop(int sem_id, short index, short op, short flags, struct timespec *ts)
{
  struct sembuf buf = { 0 };

  buf.sem_num = index;
  buf.sem_op  = op;
  buf.sem_flg = flags;

  if (ts) {
    return semtimedop(sem_id, &buf, 1, ts);
  } else {
    return semop(sem_id, &buf, 1);
  }
}

int
get_sem_val(int sem_id, int sem_index)
{
  int ret = semctl(sem_id, sem_index, GETVAL);
  if (ret == -1) {
    rb_raise(eInternal, "error getting value of %s for sem %d, errno: %d (%s)", SEMINDEX_STRING[sem_index], sem_id, errno, strerror(errno));
  }
  return ret;
}
Exemple #6
0
/*
 * call-seq:
 *    parser.parse(yaml)
 *
 * Parse the YAML document contained in +yaml+.  Events will be called on
 * the handler set on the parser instance.
 *
 * See Psych::Parser and Psych::Parser#handler
 */
static VALUE parse(int argc, VALUE *argv, VALUE self)
{
    VALUE yaml, path;
    yaml_parser_t * parser;
    yaml_event_t event;
    int done = 0;
    int tainted = 0;
    int state = 0;
    int parser_encoding = YAML_ANY_ENCODING;
#ifdef HAVE_RUBY_ENCODING_H
    int encoding = rb_utf8_encindex();
    rb_encoding * internal_enc = rb_default_internal_encoding();
#endif
    VALUE handler = rb_iv_get(self, "@handler");

    if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
	if(rb_respond_to(yaml, id_path))
	    path = rb_funcall(yaml, id_path, 0);
	else
	    path = rb_str_new2("<unknown>");
    }

    Data_Get_Struct(self, yaml_parser_t, parser);

    yaml_parser_delete(parser);
    yaml_parser_initialize(parser);

    if (OBJ_TAINTED(yaml)) tainted = 1;

    if (rb_respond_to(yaml, id_read)) {
#ifdef HAVE_RUBY_ENCODING_H
	yaml = transcode_io(yaml, &parser_encoding);
	yaml_parser_set_encoding(parser, parser_encoding);
#endif
	yaml_parser_set_input(parser, io_reader, (void *)yaml);
	if (RTEST(rb_obj_is_kind_of(yaml, rb_cIO))) tainted = 1;
    } else {
	StringValue(yaml);
#ifdef HAVE_RUBY_ENCODING_H
	yaml = transcode_string(yaml, &parser_encoding);
	yaml_parser_set_encoding(parser, parser_encoding);
#endif
	yaml_parser_set_input_string(
		parser,
		(const unsigned char *)RSTRING_PTR(yaml),
		(size_t)RSTRING_LEN(yaml)
		);
    }

    while(!done) {
	if(!yaml_parser_parse(parser, &event)) {
	    VALUE exception;

	    exception = make_exception(parser, path);
	    yaml_parser_delete(parser);
	    yaml_parser_initialize(parser);

	    rb_exc_raise(exception);
	}

	switch(event.type) {
	    case YAML_STREAM_START_EVENT:
	      {
		  VALUE args[2];

		  args[0] = handler;
		  args[1] = INT2NUM((long)event.data.stream_start.encoding);
		  rb_protect(protected_start_stream, (VALUE)args, &state);
	      }
	      break;
	  case YAML_DOCUMENT_START_EVENT:
	    {
		VALUE args[4];
		/* Get a list of tag directives (if any) */
		VALUE tag_directives = rb_ary_new();
		/* Grab the document version */
		VALUE version = event.data.document_start.version_directive ?
		    rb_ary_new3(
			(long)2,
			INT2NUM((long)event.data.document_start.version_directive->major),
			INT2NUM((long)event.data.document_start.version_directive->minor)
			) : rb_ary_new();

		if(event.data.document_start.tag_directives.start) {
		    yaml_tag_directive_t *start =
			event.data.document_start.tag_directives.start;
		    yaml_tag_directive_t *end =
			event.data.document_start.tag_directives.end;
		    for(; start != end; start++) {
			VALUE handle = Qnil;
			VALUE prefix = Qnil;
			if(start->handle) {
			    handle = rb_str_new2((const char *)start->handle);
			    if (tainted) OBJ_TAINT(handle);
#ifdef HAVE_RUBY_ENCODING_H
			    PSYCH_TRANSCODE(handle, encoding, internal_enc);
#endif
			}

			if(start->prefix) {
			    prefix = rb_str_new2((const char *)start->prefix);
			    if (tainted) OBJ_TAINT(prefix);
#ifdef HAVE_RUBY_ENCODING_H
			    PSYCH_TRANSCODE(prefix, encoding, internal_enc);
#endif
			}

			rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
		    }
		}
		args[0] = handler;
		args[1] = version;
		args[2] = tag_directives;
		args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
		rb_protect(protected_start_document, (VALUE)args, &state);
	    }
	    break;
	  case YAML_DOCUMENT_END_EVENT:
	    {
		VALUE args[2];

		args[0] = handler;
		args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
		rb_protect(protected_end_document, (VALUE)args, &state);
	    }
	    break;
	  case YAML_ALIAS_EVENT:
	    {
		VALUE args[2];
		VALUE alias = Qnil;
		if(event.data.alias.anchor) {
		    alias = rb_str_new2((const char *)event.data.alias.anchor);
		    if (tainted) OBJ_TAINT(alias);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(alias, encoding, internal_enc);
#endif
		}

		args[0] = handler;
		args[1] = alias;
		rb_protect(protected_alias, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SCALAR_EVENT:
	    {
		VALUE args[7];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE plain_implicit, quoted_implicit, style;
		VALUE val = rb_str_new(
		    (const char *)event.data.scalar.value,
		    (long)event.data.scalar.length
		    );
		if (tainted) OBJ_TAINT(val);

#ifdef HAVE_RUBY_ENCODING_H
		PSYCH_TRANSCODE(val, encoding, internal_enc);
#endif

		if(event.data.scalar.anchor) {
		    anchor = rb_str_new2((const char *)event.data.scalar.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		if(event.data.scalar.tag) {
		    tag = rb_str_new2((const char *)event.data.scalar.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		plain_implicit =
		    event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;

		quoted_implicit =
		    event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.scalar.style);

		args[0] = handler;
		args[1] = val;
		args[2] = anchor;
		args[3] = tag;
		args[4] = plain_implicit;
		args[5] = quoted_implicit;
		args[6] = style;
		rb_protect(protected_scalar, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SEQUENCE_START_EVENT:
	    {
		VALUE args[5];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.sequence_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		tag = Qnil;
		if(event.data.sequence_start.tag) {
		    tag = rb_str_new2((const char *)event.data.sequence_start.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		implicit =
		    event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.sequence_start.style);

		args[0] = handler;
		args[1] = anchor;
		args[2] = tag;
		args[3] = implicit;
		args[4] = style;

		rb_protect(protected_start_sequence, (VALUE)args, &state);
	    }
	    break;
	  case YAML_SEQUENCE_END_EVENT:
	    rb_protect(protected_end_sequence, handler, &state);
	    break;
	  case YAML_MAPPING_START_EVENT:
	    {
		VALUE args[5];
		VALUE anchor = Qnil;
		VALUE tag = Qnil;
		VALUE implicit, style;
		if(event.data.mapping_start.anchor) {
		    anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
		    if (tainted) OBJ_TAINT(anchor);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(anchor, encoding, internal_enc);
#endif
		}

		if(event.data.mapping_start.tag) {
		    tag = rb_str_new2((const char *)event.data.mapping_start.tag);
		    if (tainted) OBJ_TAINT(tag);
#ifdef HAVE_RUBY_ENCODING_H
		    PSYCH_TRANSCODE(tag, encoding, internal_enc);
#endif
		}

		implicit =
		    event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;

		style = INT2NUM((long)event.data.mapping_start.style);

		args[0] = handler;
		args[1] = anchor;
		args[2] = tag;
		args[3] = implicit;
		args[4] = style;

		rb_protect(protected_start_mapping, (VALUE)args, &state);
	    }
	    break;
	  case YAML_MAPPING_END_EVENT:
	    rb_protect(protected_end_mapping, handler, &state);
	    break;
	  case YAML_NO_EVENT:
	    rb_protect(protected_empty, handler, &state);
	    break;
	  case YAML_STREAM_END_EVENT:
	    rb_protect(protected_end_stream, handler, &state);
	    done = 1;
	    break;
	}
	yaml_event_delete(&event);
	if (state) rb_jump_tag(state);
    }

    return self;
}
Exemple #7
0
static VALUE
rg_replace(gint argc, VALUE *argv, VALUE self)
{
    VALUE rb_string;
    VALUE rb_replacement;
    VALUE rb_options;
    VALUE rb_start_position;
    VALUE rb_match_options;
    VALUE rb_literal;
    GError *error = NULL;
    gchar *modified_string;
    const gchar *string;
    const gchar *replacement;
    gssize string_len = -1;
    gint start_position = 0;
    GRegexMatchFlags match_options = 0;


    if (rb_block_given_p()) {
        RGRegexEvalCallbackData data;

        rb_scan_args(argc, argv, "11", &rb_string, &rb_options);
        rbg_scan_options(rb_options,
                         "start_position", &rb_start_position,
                         "match_options", &rb_match_options,
                         NULL);

        string = RVAL2CSTR(rb_string);
        string_len = RSTRING_LEN(rb_string);

        if (!NIL_P(rb_start_position))
            start_position = NUM2INT(rb_start_position);
        if (!NIL_P(rb_match_options))
            match_options = RVAL2GREGEXMATCHOPTIONSFLAGS(rb_match_options);

        data.callback = rb_block_proc();
        data.status = 0;

        modified_string = g_regex_replace_eval(_SELF(self),
                                               string,
                                               string_len,
                                               start_position,
                                               match_options,
                                               rg_regex_eval_callback,
                                               &data,
                                               &error);
        if (!(data.status == 0 || data.status == RUBY_TAG_BREAK)) {
            if (error)
                g_error_free(error);
            g_free(modified_string);
            rb_jump_tag(data.status);
        }
    } else {
        rb_scan_args(argc, argv, "21", &rb_string, &rb_replacement, &rb_options);

        rbg_scan_options(rb_options,
                         "start_position", &rb_start_position,
                         "match_options", &rb_match_options,
                         "literal", &rb_literal,
                         NULL);

        string = RVAL2CSTR(rb_string);
        string_len = RSTRING_LEN(rb_string);
        replacement = RVAL2CSTR(rb_replacement);

        if (!NIL_P(rb_start_position))
            start_position = NUM2INT(rb_start_position);
        if (!NIL_P(rb_match_options))
            match_options = RVAL2GREGEXMATCHOPTIONSFLAGS(rb_match_options);

        if (RVAL2CBOOL(rb_literal)) {
            modified_string = g_regex_replace_literal(_SELF(self),
                                                      string,
                                                      string_len,
                                                      start_position,
                                                      replacement,
                                                      match_options,
                                                      &error);

        } else {
            modified_string = g_regex_replace(_SELF(self),
                                              string,
                                              string_len,
                                              start_position,
                                              replacement,
                                              match_options,
                                              &error);
        }
    }

    if (error)
        RAISE_GERROR(error);

    return CSTR2RVAL_FREE(modified_string);
}
static VALUE
fs_watcher_wait_for_change(VALUE self) {
	FSWatcher *watcher;
	pthread_t thr;
	ssize_t ret;
	int e, interrupted = 0;
	FSWatcherReadByteData read_data;
	
	Data_Get_Struct(self, FSWatcher, watcher);
	
	if (watcher->preparation_error) {
		return Qfalse;
	}
	
	/* Spawn a thread, and let the thread perform the blocking kqueue
	 * wait. When kevent() returns the thread will write its status to the
	 * notification pipe. In the mean time we let the Ruby interpreter wait
	 * on the other side of the pipe for us so that we don't block Ruby
	 * threads.
	 */
	
	e = pthread_create(&thr, NULL, fs_watcher_wait_on_kqueue, watcher);
	if (e != 0) {
		errno = e;
		rb_sys_fail("pthread_create()");
		return Qnil;
	}
	
	/* Note that rb_thread_wait() does not wait for the fd when the app
	 * is single threaded, so we must join the thread after we've read
	 * from the notification fd.
	 */
	rb_protect(fs_watcher_wait_fd, (VALUE) watcher->notification_fd[0], &interrupted);
	if (interrupted) {
		/* We got interrupted so tell the watcher thread to exit. */
		ret = write(watcher->interruption_fd[1], "x", 1);
		if (ret == -1) {
			e = errno;
			fs_watcher_real_close(watcher);
			errno = e;
			rb_sys_fail("write() to interruption pipe");
			return Qnil;
		}
		pthread_join(thr, NULL);
		
		/* Now clean up stuff. */
		fs_watcher_real_close(watcher);
		rb_jump_tag(interrupted);
		return Qnil;
	}
	
	read_data.fd = watcher->notification_fd[0];
	rb_protect(fs_watcher_read_byte_from_fd, (VALUE) &read_data, &interrupted);
	if (interrupted) {
		/* We got interrupted so tell the watcher thread to exit. */
		ret = write(watcher->interruption_fd[1], "x", 1);
		if (ret == -1) {
			e = errno;
			fs_watcher_real_close(watcher);
			errno = e;
			rb_sys_fail("write() to interruption pipe");
			return Qnil;
		}
		pthread_join(thr, NULL);
		
		/* Now clean up stuff. */
		fs_watcher_real_close(watcher);
		rb_jump_tag(interrupted);
		return Qnil;
	}
	
	pthread_join(thr, NULL);
	
	if (read_data.ret == -1) {
		fs_watcher_real_close(watcher);
		errno = read_data.error;
		rb_sys_fail("read()");
		return Qnil;
	} else if (read_data.ret == 0) {
		fs_watcher_real_close(watcher);
		errno = read_data.error;
		rb_raise(rb_eRuntimeError, "Unknown error: unexpected EOF");
		return Qnil;
	} else if (read_data.byte == 't') {
		/* termination_fd or interruption_fd became readable */
		return Qnil;
	} else if (read_data.byte == 'f') {
		/* a file or directory changed */
		return Qtrue;
	} else {
		fs_watcher_real_close(watcher);
		errno = read_data.error;
		rb_raise(rb_eRuntimeError, "Unknown error: unexpected notification data");
		return Qnil;
	}
}
static VALUE rb_libarchive_reader_s_open0(int (*archive_open)(struct rb_libarchive_archive_container *, void *), void *arg, int compression, int format, const char *cmd) {
  VALUE reader;
  struct rb_libarchive_archive_container *p;
  int r;
  reader = rb_funcall(rb_cArchiveReader, rb_intern("new"), 0);
  Data_Get_Struct(reader, struct rb_libarchive_archive_container, p);

  if ((p->ar = archive_read_new()) == NULL) {
    rb_raise(rb_eArchiveError, "Open reader failed: %s", strerror(errno));
  }

  if (cmd != NULL) {
    r = archive_read_support_compression_program(p->ar, cmd);
  } else if (compression != -1) {
    r = archive_read_support_compression(p->ar, compression);
  } else {
    r = archive_read_support_compression_all(p->ar);
  }

  if (r != ARCHIVE_OK) {
    char error_string[BUFSIZ];
    archive_copy_error_string(p->ar, error_string, BUFSIZ);
    rb_libarchive_reader_close0(p);
    rb_raise(rb_eArchiveError, "Support compression failed: %s", error_string);
  }

  if (format != -1) {
    r = archive_read_support_format(p->ar, format);
  } else {
    r = archive_read_support_format_all(p->ar);
  }

  if (r != ARCHIVE_OK) {
    char error_string[BUFSIZ];
    archive_copy_error_string(p->ar, error_string, BUFSIZ);
    rb_libarchive_reader_close0(p);
    rb_raise(rb_eArchiveError, "Support format failed: %s", error_string);
  }

  if (archive_open(p, arg) != ARCHIVE_OK) {
    char error_string[BUFSIZ];
    archive_copy_error_string(p->ar, error_string, BUFSIZ);
    rb_libarchive_reader_close0(p);
    rb_raise(rb_eArchiveError, "Open reader failed: %s", error_string);
  }

  if (rb_block_given_p()) {
    VALUE retval;
    int status;
    retval = rb_protect(rb_yield, reader, &status);
    rb_libarchive_reader_close0(p);

    if (status != 0) {
      rb_jump_tag(status);
    }

    return retval;
  } else {
    return reader;
  }
}
static VALUE rb_libarchive_reader_read_data(int argc, VALUE *argv, VALUE self) {
  VALUE v_size;
  struct rb_libarchive_archive_container *p;
  char *buff;
  size_t size = DATA_BUFFER_SIZE;
  ssize_t n;
  rb_scan_args(argc, argv, "01", &v_size);

  if (!NIL_P(v_size)) {
    size = NUM2INT(v_size);
  }

  Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
  Check_Archive(p);

  if (p->eof) {
    return Qnil;
  }

  if (rb_block_given_p()) {
    ssize_t len = 0;
    int status = 0;
    buff = xmalloc(size);

    while ((n = archive_read_data(p->ar, buff, size)) > 0) {
      rb_protect(rb_yield, rb_str_new(buff, n), &status);

      if (status != 0) {
        break;
      }

      len += n;
    }

    xfree(buff);

    if (status != 0) {
      rb_jump_tag(status);
    }

    if (n < 0) {
      rb_raise(rb_eArchiveError, "Read data failed: %s", archive_error_string(p->ar));
    }

    return LONG2NUM(len);
  } else {
    VALUE retval = rb_str_new("", 0);
    buff = xmalloc(size);

    while ((n = archive_read_data(p->ar, buff, size)) > 0) {
      rb_str_cat(retval, buff, n);
    }

    xfree(buff);

    if (n < 0) {
      rb_raise(rb_eArchiveError, "Read data failed: %s", archive_error_string(p->ar));
    }

    return retval;
  }
}
Exemple #11
0
static VALUE each(int argc, VALUE *argv, VALUE self)
{
    struct readerdata *reader;
    png_infop winfo;
    png_structp wpng;
    VALUE opts;
    int cmp, state;
    struct each_args args;
    uint32_t i, height, width;
    png_byte ctype;
    unsigned char **scanlines;
    size_t row_bytes;

    rb_scan_args(argc, argv, "01", &opts);

    Data_Get_Struct(self, struct readerdata, reader);

    raise_if_locked(reader);
    reader->locked = 1;

    wpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
                                   (png_error_ptr)error, (png_error_ptr)warning);
    winfo = png_create_info_struct(wpng);
    png_set_write_fn(wpng, 0, write_data_fn, flush_data_fn);

    cmp = png_get_channels(reader->png, reader->info);
    ctype = png_get_color_type(reader->png, reader->info);

    png_set_IHDR(wpng, winfo, reader->scale_width, reader->scale_height, 8,
                 ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

    width = png_get_image_width(reader->png, reader->info);
    height = png_get_image_height(reader->png, reader->info);
    row_bytes = png_get_rowbytes(reader->png, reader->info);

    args.reader = reader;
    args.wpng = wpng;
    args.winfo = winfo;
    args.inwidthbuf = malloc(row_bytes);
    args.outwidthbuf = malloc(reader->scale_width * cmp);

    xscaler_init(&args.xs, width, reader->scale_width, cmp, 0);

    if (png_get_interlace_type(reader->png, reader->info) == PNG_INTERLACE_NONE) {
        yscaler_init(&args.ys, height, reader->scale_height,
                     reader->scale_width * cmp);
        rb_protect((VALUE(*)(VALUE))each_interlace_none, (VALUE)&args, &state);
        yscaler_free(&args.ys);
    } else {
        scanlines = malloc(height * sizeof(unsigned char *));
        for (i=0; i<height; i++) {
            scanlines[i] = malloc(row_bytes);
        }

        args.scanlines = scanlines;
        rb_protect((VALUE(*)(VALUE))each_interlace, (VALUE)&args, &state);

        for (i=0; i<height; i++) {
            free(scanlines[i]);
        }
        free(scanlines);
    }

    xscaler_free(&args.xs);
    free(args.inwidthbuf);
    free(args.outwidthbuf);
    png_destroy_write_struct(&wpng, &winfo);

    if (state) {
        rb_jump_tag(state);
    }

    return self;
}