Пример #1
0
static void
gsf_output_stdio_init (GObject *obj)
{
	GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (obj);

	stdio->file = NULL;
	stdio->create_backup_copy = FALSE;
	stdio->keep_open	  = FALSE;
}
Пример #2
0
static void
gsf_output_stdio_finalize (GObject *obj)
{
	GsfOutput	*output = (GsfOutput *)obj;
	GsfOutputStdio	*stdio = GSF_OUTPUT_STDIO (output);

	if (!gsf_output_is_closed (output))
		gsf_output_close (output);

	g_free (stdio->real_filename);
	stdio->real_filename = NULL;
	g_free (stdio->temp_filename);
	stdio->temp_filename = NULL;

	parent_class->finalize (obj);
}
Пример #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));
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}