Example #1
0
/**
 * gsf_output_close:
 * @output: #GsfOutput
 *
 * Close a stream.
 *
 * Returns: %FALSE on error
 **/
gboolean
gsf_output_close (GsfOutput *output)
{
	gboolean res;

	g_return_val_if_fail (GSF_IS_OUTPUT (output),
		gsf_output_set_error (output, 0, "<internal>"));
	g_return_val_if_fail (!output->is_closed,
		gsf_output_set_error (output, 0, "<internal>"));

	/* The implementation will log any errors, but we can never try to
	 * close multiple times even on failure.
	 */
	res = GET_CLASS (output)->Close (output);
	output->is_closed = TRUE;
	return res;
}
Example #2
0
static inline gboolean
gsf_output_inc_cur_offset (GsfOutput *output, gsf_off_t num_bytes)
{
	output->cur_offset += num_bytes;
	if (output->cur_offset < num_bytes)
		return gsf_output_set_error (output, 0, "Output size overflow.");
	if (output->cur_size < output->cur_offset)
		output->cur_size = output->cur_offset;
	return TRUE;
}
Example #3
0
static gboolean
gsf_output_stdio_seek (GsfOutput *output, gsf_off_t offset, GSeekType whence)
{
	GsfOutputStdio const *stdio = GSF_OUTPUT_STDIO (output);
	int stdio_whence = 0;	/* make compiler shut up */

#ifndef HAVE_FSEEKO
	long loffset;
#else
	off_t loffset;
#endif

	g_return_val_if_fail (stdio->file != NULL,
			      gsf_output_set_error (output, 0, "missing file"));

	loffset = offset;
	if ((gsf_off_t) loffset != offset) { /* Check for overflow */
#ifdef HAVE_FSEEKO
		g_warning ("offset too large for fseeko");
		return gsf_output_set_error (output, 0, "offset too large for fseeko");
#else
		g_warning ("offset too large for fseek");
		return gsf_output_set_error (output, 0, "offset too large for fseek");
#endif
	}
	switch (whence) {
	default : ; /*checked in GsfOutput wrapper */
	case G_SEEK_SET : stdio_whence = SEEK_SET;	break;
	case G_SEEK_CUR : stdio_whence = SEEK_CUR;	break;
	case G_SEEK_END : stdio_whence = SEEK_END;	break;
	}

	errno = 0;
#ifdef HAVE_FSEEKO
	if (0 == fseeko (stdio->file, loffset, stdio_whence))
		return TRUE;
#else
	if (0 == fseek (stdio->file, loffset, stdio_whence))
		return TRUE;
#endif
	return gsf_output_set_error (output, errno, "%s", g_strerror (errno));
}
Example #4
0
static gboolean
close_file_helper (GsfOutputStdio *stdio, gboolean seterr)
{
	gboolean res = (0 == fclose (stdio->file));
	stdio->file = NULL;
	if (!res && seterr)
		gsf_output_set_error (GSF_OUTPUT (stdio), errno,
				      "Failed to close file: %s",
				      g_strerror (errno));
	return res;
}
Example #5
0
static gboolean
gsf_output_stdio_write (GsfOutput *output,
			size_t num_bytes,
			guint8 const *buffer)
{
	GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
	size_t written, remaining;

	g_return_val_if_fail (stdio != NULL, FALSE);
	g_return_val_if_fail (stdio->file != NULL, FALSE);

	remaining = num_bytes;

	while (remaining > 0) {
		written = fwrite (buffer + (num_bytes - remaining), 1,
				  remaining, stdio->file);
		if ((written < remaining) && ferror (stdio->file) != 0)
			return gsf_output_set_error (output, errno, "%s", g_strerror (errno));

		remaining -= written;
	}
	return TRUE;
}
Example #6
0
static void
go_plugin_file_saver_save (GOFileSaver const *fs, GOIOContext *io_context,
			    GoView const *view,
			    GsfOutput *output)
{
	GOPluginFileSaver *pfs = GO_PLUGIN_FILE_SAVER (fs);
	GOPluginServiceFileSaver *service_file_saver = GO_PLUGIN_SERVICE_FILE_SAVER (pfs->service);
	GOErrorInfo *error = NULL;

	g_return_if_fail (GSF_IS_OUTPUT (output));

	go_plugin_service_load (pfs->service, &error);
	if (error != NULL) {
		go_io_error_info_set (io_context, error);
		go_io_error_push (io_context, go_error_info_new_str (
		                        _("Error while loading plugin for saving.")));
		if (!gsf_output_error (output))
			gsf_output_set_error (output, 0, _("Failed to load plugin for saving"));
		return;
	}

	g_return_if_fail (service_file_saver->cbs.plugin_func_file_save != NULL);
	service_file_saver->cbs.plugin_func_file_save (fs, pfs->service, io_context, view, output);
}
Example #7
0
static gboolean
gsf_output_stdio_close (GsfOutput *output)
{
	GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
	gboolean res;
	char *backup_filename = NULL;
	GDateTime *modtime;

	if (stdio->file == NULL)
		return FALSE;

	if (gsf_output_error (output)) {
		res = TRUE;
		if (!stdio->keep_open && !close_file_helper (stdio, FALSE))
			res = FALSE;

		if (!unlink_file_helper (stdio))
			res = FALSE;

		return res;
	}

	if (stdio->keep_open) {
		gboolean res = (0 == fflush (stdio->file));
		if (!res)
			gsf_output_set_error (output, errno,
					      "Failed to flush.");
		stdio->file = NULL;
		return res;
	}

	res = close_file_helper (stdio, TRUE);

	/* short circuit our when dealing with raw FILE */
	if (!stdio->real_filename)
		return res;
	if (!res) {
		unlink_file_helper (stdio);
		return FALSE;
	}

	/* Move the original file to a backup */
	if (stdio->create_backup_copy) {
		gint result;
		backup_filename = g_strconcat (stdio->real_filename, ".bak", NULL);
		result = rename_wrapper (stdio->real_filename, backup_filename);
		if (result != 0) {
			char *utf8name = g_filename_display_name (backup_filename);
			gsf_output_set_error (output, errno,
					      "Could not backup the original as %s.",
					      utf8name);
			g_free (utf8name);
			g_unlink (stdio->temp_filename);
			res = FALSE;
			goto out;
		}
	}

	/* Move the temp file to the original file */
	if (rename_wrapper (stdio->temp_filename, stdio->real_filename) != 0) {
		gint saved_errno = errno;
		if (backup_filename != NULL &&
		    rename_wrapper (backup_filename, stdio->real_filename) != 0)
			saved_errno = errno;
		res = gsf_output_set_error (output,
					    saved_errno,
					    "%s", g_strerror (saved_errno));
		goto out;
	}

	modtime = gsf_output_get_modtime (output);
	if (modtime) {
#ifdef UTIME_AVAILABLE
		struct utimbuf ut;

		ut.actime = time (NULL);
		ut.modtime = g_date_time_to_unix (modtime);
		/* Ignore errors */
		/* utimes() provides better accuracy, but doesn't have 
		   gstdio version.  gio seems to provide access.  */
		(void)utime (stdio->real_filename, &ut);
#endif
	}

	/* Restore permissions.  There is not much error checking we
	 * can do here, I'm afraid.  The final data is saved anyways.
	 * Note the order: mode, uid+gid, gid, uid, mode.
	 */
	g_chmod (stdio->real_filename, stdio->st.st_mode);
#ifdef HAVE_CHOWN
	if (chown_wrapper (stdio->real_filename,
			   stdio->st.st_uid,
			   stdio->st.st_gid)) {
		/* We cannot set both.  Maybe we can set one.  */
		chown_wrapper (stdio->real_filename, -1, stdio->st.st_gid);
		chown_wrapper (stdio->real_filename, stdio->st.st_uid, -1);
	}
	g_chmod (stdio->real_filename, stdio->st.st_mode);
#endif

out:
	g_free (backup_filename);

	return res;
}
Example #8
0
static gboolean
gsf_output_stdio_close (GsfOutput *output)
{
	GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
	gboolean res;
	char *backup_filename = NULL;

	if (stdio->file == NULL)
		return FALSE;

	if (gsf_output_error (output)) {
		res = TRUE;
		if (!stdio->keep_open && !close_file_helper (stdio, FALSE))
			res = FALSE;

		if (!unlink_file_helper (stdio))
			res = FALSE;

		return res;
	}

	if (stdio->keep_open) {
		gboolean res = (0 == fflush (stdio->file));
		if (!res)
			gsf_output_set_error (output, errno,
					      "Failed to flush.");
		stdio->file = NULL;
		return res;
	}

	res = close_file_helper (stdio, TRUE);

	/* short circuit our when dealing with raw FILE */
	if (!stdio->real_filename)
		return res;
	if (!res) {
		unlink_file_helper (stdio);
		return FALSE;
	}

	/* Move the original file to a backup */
	if (stdio->create_backup_copy) {
		gint result;
		backup_filename = g_strconcat (stdio->real_filename, ".bak", NULL);
		result = rename_wrapper (stdio->real_filename, backup_filename);
		if (result != 0) {
			char *utf8name = g_filename_display_name (backup_filename);
			gsf_output_set_error (output, errno,
					      "Could not backup the original as %s.",
					      utf8name);
			g_free (utf8name);
			g_free (backup_filename);
			g_unlink (stdio->temp_filename);
			return FALSE;
		}
	}

	/* Move the temp file to the original file */
	if (rename_wrapper (stdio->temp_filename, stdio->real_filename) != 0) {
		gint saved_errno = errno;
		if (backup_filename != NULL &&
		    rename_wrapper (backup_filename, stdio->real_filename) != 0)
			saved_errno = errno;
		res = gsf_output_set_error (output,
					    saved_errno,
					    "%s", g_strerror (saved_errno));
	} else {
		/* Restore permissions.  There is not much error checking we
		 * can do here, I'm afraid.  The final data is saved anyways.
		 * Note the order: mode, uid+gid, gid, uid, mode.
		 */
		chmod_wrapper (stdio->real_filename, stdio->st.st_mode);
#ifdef HAVE_CHOWN
		if (chown (stdio->real_filename,
			   stdio->st.st_uid,
			   stdio->st.st_gid)) {
			/* We cannot set both.  Maybe we can set one.  */
			chown (stdio->real_filename, -1, stdio->st.st_gid);
			chown (stdio->real_filename, stdio->st.st_uid, -1);
		}
		chmod_wrapper (stdio->real_filename, stdio->st.st_mode);
#endif
	}

	g_free (backup_filename);

	return res;
}