static VALUE rg_fill(int argc, VALUE *argv, VALUE self) { VALUE count, cancellable; GError *error = NULL; gsize bytes_read; rb_scan_args(argc, argv, "02", &count, &cancellable); bytes_read = g_buffered_input_stream_fill(_SELF(self), NIL_P(count) ? -1 : RVAL2GSSIZE(count), RVAL2GCANCELLABLE(cancellable), &error); if (error != NULL) rbgio_raise_error(error); return GSSIZE2RVAL(bytes_read); }
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; }
static gboolean log_load (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { /* this runs in a separate i/o thread */ LoadJob *job = user_data; LogviewLog *log = job->log; GFile *f = log->priv->file; GFileInfo *info; GInputStream *is; const char *peeked_buffer; const char * parse_data[2]; GSList *days; const char *content_type; GFileType type; GError *err = NULL; GTimeVal timeval; gboolean is_archive, can_read; info = g_file_query_info (f, G_FILE_ATTRIBUTE_ACCESS_CAN_READ "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",", 0, NULL, &err); if (err) { if (err->code == G_IO_ERROR_PERMISSION_DENIED) { /* TODO: PolicyKit integration */ } goto out; } can_read = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ); if (!can_read) { /* TODO: PolicyKit integration */ err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_PERMISSION_DENIED, _("You don't have enough permissions to read the file.")); g_object_unref (info); goto out; } type = g_file_info_get_file_type (info); content_type = g_file_info_get_content_type (info); is_archive = g_content_type_equals (content_type, "application/x-gzip"); if (type != (G_FILE_TYPE_REGULAR || G_FILE_TYPE_SYMBOLIC_LINK) || (!g_content_type_is_a (content_type, "text/plain") && !is_archive)) { err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_A_LOG, _("The file is not a regular file or is not a text file.")); g_object_unref (info); goto out; } log->priv->file_size = g_file_info_get_size (info); g_file_info_get_modification_time (info, &timeval); log->priv->file_time = timeval.tv_sec; log->priv->display_name = g_strdup (g_file_info_get_display_name (info)); g_object_unref (info); /* initialize the stream */ is = G_INPUT_STREAM (g_file_read (f, NULL, &err)); if (err) { if (err->code == G_IO_ERROR_PERMISSION_DENIED) { /* TODO: PolicyKit integration */ } goto out; } if (is_archive) { #ifdef HAVE_ZLIB GZHandle *gz; gboolean res; guchar * buffer; gsize bytes_read; GInputStream *real_is; time_t mtime; /* seconds */ /* this also skips the header from |is| */ res = read_gzip_header (is, &mtime); if (!res) { g_object_unref (is); err = create_zlib_error (); goto out; } log->priv->file_time = mtime; gz = gz_handle_new (f, is); res = gz_handle_init (gz); if (!res) { g_object_unref (is); gz_handle_free (gz); err = create_zlib_error (); goto out; } real_is = g_memory_input_stream_new (); do { buffer = g_malloc (1024); res = gz_handle_read (gz, buffer, 1024, &bytes_read); g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (real_is), buffer, bytes_read, g_free); } while (res == TRUE && bytes_read > 0); if (!res) { gz_handle_free (gz); g_object_unref (real_is); g_object_unref (is); err = create_zlib_error (); goto out; } g_object_unref (is); is = real_is; gz_handle_free (gz); #else /* HAVE_ZLIB */ g_object_unref (is); err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_SUPPORTED, _("This version of System Log does not support GZipped logs.")); goto out; #endif /* HAVE_ZLIB */ } log->priv->stream = g_data_input_stream_new (is); /* sniff into the stream for a timestamped line */ g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (log->priv->stream), (gssize) g_buffered_input_stream_get_buffer_size (G_BUFFERED_INPUT_STREAM (log->priv->stream)), NULL, &err); if (err == NULL) { peeked_buffer = g_buffered_input_stream_peek_buffer (G_BUFFERED_INPUT_STREAM (log->priv->stream), NULL); parse_data[0] = peeked_buffer; parse_data[1] = NULL; if ((days = log_read_dates (parse_data, time (NULL))) != NULL) { log->priv->has_days = TRUE; g_slist_foreach (days, (GFunc) logview_utils_day_free, NULL); g_slist_free (days); } else { log->priv->has_days = FALSE; } } else { log->priv->has_days = FALSE; g_clear_error (&err); } g_object_unref (is); out: if (err) { job->err = err; } g_io_scheduler_job_send_to_mainloop_async (io_job, log_load_done, job, NULL); return FALSE; }
char * g_data_input_stream_read_upto (GDataInputStream *stream, const gchar *stop_chars, gssize stop_chars_len, gsize *length, GCancellable *cancellable, GError **error) { GBufferedInputStream *bstream; gsize checked; gssize found_pos; gssize res; char *data_until; g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); if (stop_chars_len < 0) stop_chars_len = strlen (stop_chars); bstream = G_BUFFERED_INPUT_STREAM (stream); checked = 0; while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1) { if (g_buffered_input_stream_get_available (bstream) == g_buffered_input_stream_get_buffer_size (bstream)) g_buffered_input_stream_set_buffer_size (bstream, 2 * g_buffered_input_stream_get_buffer_size (bstream)); res = g_buffered_input_stream_fill (bstream, -1, cancellable, error); if (res < 0) return NULL; if (res == 0) { /* End of stream */ if (g_buffered_input_stream_get_available (bstream) == 0) { if (length) *length = 0; return NULL; } else { found_pos = checked; break; } } } data_until = g_malloc (found_pos + 1); res = g_input_stream_read (G_INPUT_STREAM (stream), data_until, found_pos, NULL, NULL); if (length) *length = (gsize)found_pos; g_warn_if_fail (res == found_pos); data_until[found_pos] = 0; return data_until; }