コード例 #1
0
ファイル: gvfsfileinfo.c プロジェクト: Amerekanets/gvfs
GFileInfo *
gvfs_file_info_demarshal (char      *data,
			  gsize      size)
{
  guint32 num_attrs, i;
  GInputStream *memstream;
  GDataInputStream *in;
  GFileInfo *info;
  char *attr, *str, **strv;
  GFileAttributeType type;
  GFileAttributeStatus status;
  GObject *obj;
  int objtype;

  memstream = g_memory_input_stream_new_from_data (data, size, NULL);
  in = g_data_input_stream_new (memstream);
  g_object_unref (memstream);

  info = g_file_info_new ();
  num_attrs = g_data_input_stream_read_uint32 (in, NULL, NULL);

  for (i = 0; i < num_attrs; i++)
    {
      attr = read_string (in);
      type = g_data_input_stream_read_byte (in, NULL, NULL);
      status = g_data_input_stream_read_byte (in, NULL, NULL);

      switch (type)
	{
	case G_FILE_ATTRIBUTE_TYPE_STRING:
	  str = read_string (in);
	  g_file_info_set_attribute_string (info, attr, str);
	  g_free (str);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
	  str = read_string (in);
	  g_file_info_set_attribute_byte_string (info, attr, str);
	  g_free (str);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_STRINGV:
	  strv = read_stringv (in);
	  g_file_info_set_attribute_stringv (info, attr, strv);
	  g_strfreev (strv);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
	  g_file_info_set_attribute_boolean (info, attr,
					     g_data_input_stream_read_byte (in,
									    NULL,
									    NULL));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_UINT32:
	  g_file_info_set_attribute_uint32 (info, attr,
					    g_data_input_stream_read_uint32 (in,
									     NULL,
									     NULL));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INT32:
	  g_file_info_set_attribute_int32 (info, attr,
					   g_data_input_stream_read_int32 (in,
									   NULL,
									   NULL));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_UINT64:
	  g_file_info_set_attribute_uint64 (info, attr,
					    g_data_input_stream_read_uint64 (in,
									     NULL,
									     NULL));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INT64:
	  g_file_info_set_attribute_int64 (info, attr,
					   g_data_input_stream_read_int64 (in,
									   NULL,
									   NULL));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
	  objtype = g_data_input_stream_read_byte (in, NULL, NULL);
	  obj = NULL;

	  if (objtype == 1)
	    {
	      char *icon_str;

	      icon_str = read_string (in);
	      obj = (GObject *)g_icon_new_for_string  (icon_str, NULL);
	      g_free (icon_str);
	    }
	  else
	    {
	      g_warning ("Unsupported GFileInfo object type %d\n", objtype);
	      g_free (attr);
	      goto out;
	    }
	  g_file_info_set_attribute_object (info, attr, obj);
	  if (obj)
	    g_object_unref (obj);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INVALID:
	  break;
	default:
	  g_warning ("Unsupported GFileInfo attribute type %d\n", type);
	  g_free (attr);
	  goto out;
	  break;
	}
      g_file_info_set_attribute_status (info, attr, status);
      g_free (attr);
    }
  
 out:
  g_object_unref (in);
  return info;
}
コード例 #2
0
ファイル: tracker-extract-pdf.c プロジェクト: UIKit0/tracker
static gchar *
extract_content_parent_process (PopplerDocument *document,
                                int              fd[2],
                                pid_t            child_pid)
{
	GInputStream *input_stream;
	GDataInputStream *datain_stream;
	GString *content = NULL;
	GError *error = NULL;
	GTimer *timer = NULL;
	gsize bytes_expected = -1;
	gboolean timed_out = FALSE;
	gboolean finished = FALSE;
	struct timeval timeout;
	fd_set rfds;

	/* This is the parent process waiting for the content extractor to
	 * finish in time. */

	g_debug ("Parent: Content extraction now starting in child process (pid = %d)", child_pid);

	/* Set up gio streams */
	input_stream = g_unix_input_stream_new (fd[0], FALSE);
	datain_stream = g_data_input_stream_new (input_stream);

	/* Watch FD to see when it has input. */
	FD_ZERO(&rfds);
	FD_SET(fd[0], &rfds);

	/* We give the content extractor 10 seconds to do its job */
	timeout.tv_sec = EXTRACTION_PROCESS_TIMEOUT;
	timeout.tv_usec = 0;

	/* We also use our own timer because timeouts in select()
	 * can be inconsistent across UNIX platforms. Some update the
	 * timeout and some don't.
	 */
	timer = g_timer_new ();

	/* So, this is fairly simple, what we're doing here is using
	 * select() to know when the child process has written some or
	 * all the data and we then avoid the child blocking by
	 * reading from that stream. We couple with this with a
	 * timeout of 10 seconds so if we receive nothing then we know
	 * we can kill the process because it is taking too long.
	 *
	 * We use waitpid() to know if the process quit because it has
	 * finished or if it is still processing data and needs to be
	 * killed.
	 */
	while (!finished) {
		int retval;

		/* 1a. Wait for data on the FD and limit by timeout */
		retval = select (fd[0] + 1,  &rfds, NULL, NULL, &timeout);

		/* 2. Did we error? Have data? or just timeout? */
		if (retval == -1) {
			perror ("select()");
			finished = TRUE;
		} else if (retval == 1) {
			gsize bytes_remaining = bytes_expected;
			gboolean read_finished = FALSE;

			if (g_timer_elapsed (timer, NULL) >= EXTRACTION_PROCESS_TIMEOUT) {
				finished = TRUE;
				timed_out = TRUE;
				continue;
			}

			/* 3. Start reading data */
			if (bytes_expected == -1) {
				/* We only need to read the size once before the data! */
				bytes_expected = (gsize) g_data_input_stream_read_int64 (datain_stream,
				                                                         NULL,
				                                                         &error);
				if (error) {
					g_warning ("Call to g_data_input_stream_read_int64() failed, %s",
					           error->message);
					g_error_free (error);
					finished = TRUE;
					continue;
				}

				g_debug ("Parent: Expected bytes to read is %" G_GSSIZE_FORMAT "", bytes_expected);
				bytes_remaining = bytes_expected;
				content = g_string_new ("");
			}

			/* 4. Read until done from stream and concatenate data */
			while (!read_finished) {
				gchar buf[BUFFER_SIZE];
				gsize bytes_read;

				memset (buf, 0, BUFFER_SIZE);
				bytes_read = g_input_stream_read (G_INPUT_STREAM (datain_stream),
				                                  buf,
				                                  MIN (BUFFER_SIZE, bytes_remaining),
				                                  NULL,
				                                  &error);

				g_debug ("Parent:   Bytes read is %" G_GSSIZE_FORMAT ","
				         "bytes remaining is %" G_GSSIZE_FORMAT "",
				         bytes_read,
				         MAX (bytes_remaining - bytes_read, 0));

				if (bytes_read == -1 || error) {
					g_warning ("Call to g_input_stream_read() failed, %s",
					           error ? error->message : "no error given");
					g_clear_error (&error);
					read_finished = TRUE;
					finished = TRUE;
				} else {
					content = g_string_append (content, buf);

					bytes_remaining -= bytes_read;
					bytes_remaining  = MAX (bytes_remaining, 0);

					if (bytes_read == 0) {
						/* We finished reading */
						g_debug ("Parent:   Finished reading all bytes");
						read_finished = TRUE;
					}

					/* Are we finished reading everything */
					if (bytes_remaining < 1) {
						finished = TRUE;
					}
				}
			}
		} else {
			/* 3. We must have timed out with no data in select() */
			finished = TRUE;
			timed_out = TRUE;
			g_debug ("Parent: Must have timed out with no data in select()");
		}
	}

	if (timed_out) {
		g_debug ("Parent: Child process took too long. We waited %d seconds, so we're going to kill it!",
		         EXTRACTION_PROCESS_TIMEOUT);
		kill (child_pid, SIGKILL);
	} else {
		g_debug ("Parent: Data received in %2.2f seconds (timeout is %d seconds)",
		         g_timer_elapsed (timer, NULL),
		         EXTRACTION_PROCESS_TIMEOUT);
	}

	g_timer_destroy (timer);

	g_object_unref (datain_stream);
	g_object_unref (input_stream);

	close (fd[0]);

	return content ? g_string_free (content, FALSE) : NULL;
}