static void sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque) { RpmostreedSysroot *self = RPMOSTREED_SYSROOT (opaque); glnx_unref_object RpmostreedTransaction *transaction = NULL; transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor); if (!transaction) { rpmostree_output_default_handler (type, data, opaque); return; } switch (type) { case RPMOSTREE_OUTPUT_TASK_BEGIN: rpmostree_transaction_emit_task_begin (RPMOSTREE_TRANSACTION (transaction), ((RpmOstreeOutputTaskBegin*)data)->text); break; case RPMOSTREE_OUTPUT_TASK_END: rpmostree_transaction_emit_task_end (RPMOSTREE_TRANSACTION (transaction), ((RpmOstreeOutputTaskEnd*)data)->text); break; case RPMOSTREE_OUTPUT_PERCENT_PROGRESS: rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction), ((RpmOstreeOutputPercentProgress*)data)->text, ((RpmOstreeOutputPercentProgress*)data)->percentage); break; case RPMOSTREE_OUTPUT_PERCENT_PROGRESS_END: rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction)); break; } }
static RpmostreedTransaction * merge_compatible_txn (RpmostreedOSExperimental *self, GDBusMethodInvocation *invocation) { glnx_unref_object RpmostreedTransaction *transaction = NULL; /* If a compatible transaction is in progress, share its bus address. */ transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor); if (transaction != NULL) { if (rpmostreed_transaction_is_compatible (transaction, invocation)) return g_steal_pointer (&transaction); } return NULL; }
static gboolean sysroot_stdout_ready_cb (GPollableInputStream *pollable_stream, StdoutClosure *closure) { glnx_unref_object RpmostreedSysroot *sysroot = NULL; glnx_unref_object RpmostreedTransaction *transaction = NULL; GMemoryInputStream *memory_stream; GBufferedInputStream *buffered_stream; char buffer[1024]; gconstpointer stream_buffer; gsize stream_buffer_size; gsize total_bytes_read = 0; gboolean have_line = FALSE; GError *local_error = NULL; sysroot = g_weak_ref_get (&closure->sysroot); if (sysroot != NULL) transaction = rpmostreed_transaction_monitor_ref_active_transaction (sysroot->transaction_monitor); /* XXX Would very much like g_buffered_input_stream_fill_nonblocking(). * Much of this function is a clumsy and inefficient attempt to * achieve the same thing. * * See: https://bugzilla.gnome.org/726797 */ buffered_stream = G_BUFFERED_INPUT_STREAM (closure->data_stream); memory_stream = (GMemoryInputStream *) g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (buffered_stream)); while (local_error == NULL) { gssize n_read; n_read = g_pollable_input_stream_read_nonblocking (pollable_stream, buffer, sizeof (buffer), NULL, &local_error); if (n_read > 0) { /* XXX Gotta use GBytes so the data gets copied. */ g_autoptr(GBytes) bytes = g_bytes_new (buffer, n_read); g_memory_input_stream_add_bytes (memory_stream, bytes); total_bytes_read += n_read; } } if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) goto out; g_clear_error (&local_error); read_another_line: /* Fill the buffered stream with the data we just put in the * memory stream, then peek at the buffer to see if it's safe * to call g_data_input_stream_read_line() without blocking. * * XXX Oye, there's gotta be an easier way to do this... */ /* This should never fail since it's just reading from memory. */ g_buffered_input_stream_fill (buffered_stream, total_bytes_read, NULL, NULL); stream_buffer = g_buffered_input_stream_peek_buffer (buffered_stream, &stream_buffer_size); have_line = (memchr (stream_buffer, '\n', stream_buffer_size) != NULL); if (have_line) { g_autofree char *line = NULL; gsize length; line = g_data_input_stream_read_line (closure->data_stream, &length, NULL, &local_error); if (local_error != NULL) goto out; /* If there's an active transaction, forward the line to the * transaction's owner through the "Message" signal. Otherwise * dump it to the non-redirected standard output stream. */ if (transaction != NULL) { rpmostree_transaction_emit_message (RPMOSTREE_TRANSACTION (transaction), line); } else { /* This is essentially puts(), don't care about errors. */ g_output_stream_write_all (closure->real_stdout, line, length, NULL, NULL, NULL); g_output_stream_write_all (closure->real_stdout, "\n", 1, NULL, NULL, NULL); } goto read_another_line; } out: if (local_error != NULL) { g_warning ("Failed to read stdout pipe: %s", local_error->message); g_clear_error (&local_error); } return G_SOURCE_CONTINUE; }