New internal function to replace xmlSaveFile. Does proper error checking

2002-08-05  Jeffrey Stedfast  <fejj@ximian.com>

	* rule-context.c (xml_doc_save): New internal function to replace
	xmlSaveFile. Does proper error checking and so forth to ensure
	that the resulting file does not ever get truncated.
	(save): Cal xml_doc_save rather than xmlSaveFile. Fixes bug
	#25980.

svn path=/trunk/; revision=17703
This commit is contained in:
Jeffrey Stedfast
2002-08-05 23:37:08 +00:00
committed by Jeffrey Stedfast
parent ce3ae88564
commit 4e8deb5e4c
2 changed files with 317 additions and 4 deletions

View File

@ -1,3 +1,11 @@
2002-08-05 Jeffrey Stedfast <fejj@ximian.com>
* rule-context.c (xml_doc_save): New internal function to replace
xmlSaveFile. Does proper error checking and so forth to ensure
that the resulting file does not ever get truncated.
(save): Cal xml_doc_save rather than xmlSaveFile. Fixes bug
#25980.
2002-08-02 Not Zed <NotZed@Ximian.com>
* filter.glade: Added a datespec editor window.

View File

@ -1,3 +1,4 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2000 Ximian Inc.
*
@ -18,6 +19,7 @@
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -26,8 +28,13 @@
#include <alloca.h>
#endif
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <gtk/gtksignal.h>
#include <libgnomeui/gnome-dialog.h>
#include <libgnomeui/gnome-stock.h>
@ -374,6 +381,304 @@ rule_context_save (RuleContext *f, const char *user)
return ((RuleContextClass *) ((GtkObject *) f)->klass)->save(f, user);
}
static void xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format);
static void
xmlAttrDump (xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur)
{
xmlChar *value;
if (cur == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlAttrDump : property == NULL\n");
#endif
return;
}
xmlBufferWriteChar (buf, " ");
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlBufferWriteCHAR (buf, cur->ns->prefix);
xmlBufferWriteChar (buf, ":");
}
xmlBufferWriteCHAR (buf, cur->name);
value = xmlNodeListGetString (doc, cur->val, 0);
if (value) {
xmlBufferWriteChar (buf, "=");
xmlBufferWriteQuotedString (buf, value);
xmlFree (value);
} else {
xmlBufferWriteChar (buf, "=\"\"");
}
}
static void
xmlAttrListDump (xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur)
{
if (cur == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlAttrListDump : property == NULL\n");
#endif
return;
}
while (cur != NULL) {
xmlAttrDump (buf, doc, cur);
cur = cur->next;
}
}
static void
xmlNodeListDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format)
{
int i;
if (cur == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlNodeListDump : node == NULL\n");
#endif
return;
}
while (cur != NULL) {
if ((format) && (xmlIndentTreeOutput) &&
(cur->type == XML_ELEMENT_NODE))
for (i = 0; i < level; i++)
xmlBufferWriteChar (buf, " ");
xmlNodeDump (buf, doc, cur, level, format);
if (format) {
xmlBufferWriteChar (buf, "\n");
}
cur = cur->next;
}
}
static void
xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format)
{
int i;
xmlNodePtr tmp;
if (cur == NULL) {
#ifdef DEBUG_TREE
fprintf(stderr, "xmlNodeDump : node == NULL\n");
#endif
return;
}
if (cur->type == XML_TEXT_NODE) {
if (cur->content != NULL) {
xmlChar *buffer;
#ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeEntitiesReentrant (doc, cur->content);
#else
buffer = xmlEncodeEntitiesReentrant (doc, xmlBufferContent (cur->content));
#endif
if (buffer != NULL) {
xmlBufferWriteCHAR (buf, buffer);
xmlFree (buffer);
}
}
return;
}
if (cur->type == XML_PI_NODE) {
if (cur->content != NULL) {
xmlBufferWriteChar (buf, "<?");
xmlBufferWriteCHAR (buf, cur->name);
if (cur->content != NULL) {
xmlBufferWriteChar (buf, " ");
#ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR (buf, cur->content);
#else
xmlBufferWriteCHAR (buf, xmlBufferContent (cur->content));
#endif
}
xmlBufferWriteChar (buf, "?>");
}
return;
}
if (cur->type == XML_COMMENT_NODE) {
if (cur->content != NULL) {
xmlBufferWriteChar (buf, "<!--");
#ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR (buf, cur->content);
#else
xmlBufferWriteCHAR (buf, xmlBufferContent (cur->content));
#endif
xmlBufferWriteChar (buf, "-->");
}
return;
}
if (cur->type == XML_ENTITY_REF_NODE) {
xmlBufferWriteChar (buf, "&");
xmlBufferWriteCHAR (buf, cur->name);
xmlBufferWriteChar (buf, ";");
return;
}
if (cur->type == XML_CDATA_SECTION_NODE) {
xmlBufferWriteChar (buf, "<![CDATA[");
if (cur->content != NULL)
#ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR (buf, cur->content);
#else
xmlBufferWriteCHAR (buf, xmlBufferContent(cur->content));
#endif
xmlBufferWriteChar (buf, "]]>");
return;
}
if (format == 1) {
tmp = cur->childs;
while (tmp != NULL) {
if ((tmp->type == XML_TEXT_NODE) ||
(tmp->type == XML_ENTITY_REF_NODE)) {
format = 0;
break;
}
tmp = tmp->next;
}
}
xmlBufferWriteChar (buf, "<");
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlBufferWriteCHAR (buf, cur->ns->prefix);
xmlBufferWriteChar (buf, ":");
}
xmlBufferWriteCHAR (buf, cur->name);
if (cur->properties != NULL)
xmlAttrListDump (buf, doc, cur->properties);
if ((cur->content == NULL) && (cur->childs == NULL) &&
(!xmlSaveNoEmptyTags)) {
xmlBufferWriteChar (buf, "/>");
return;
}
xmlBufferWriteChar (buf, ">");
if (cur->content != NULL) {
xmlChar *buffer;
#ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeEntitiesReentrant (doc, cur->content);
#else
buffer = xmlEncodeEntitiesReentrant (doc, xmlBufferContent (cur->content));
#endif
if (buffer != NULL) {
xmlBufferWriteCHAR (buf, buffer);
xmlFree (buffer);
}
}
if (cur->childs != NULL) {
if (format)
xmlBufferWriteChar (buf, "\n");
xmlNodeListDump (buf, doc, cur->childs, (level >= 0 ? level + 1 : -1), format);
if ((xmlIndentTreeOutput) && (format))
for (i = 0; i < level; i++)
xmlBufferWriteChar (buf, " ");
}
xmlBufferWriteChar (buf, "</");
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlBufferWriteCHAR (buf, cur->ns->prefix);
xmlBufferWriteChar (buf, ":");
}
xmlBufferWriteCHAR (buf, cur->name);
xmlBufferWriteChar (buf, ">");
}
static void
xmlDocContentDump (xmlBufferPtr buf, xmlDocPtr cur)
{
xmlBufferWriteChar (buf, "<?xml version=");
if (cur->version != NULL)
xmlBufferWriteQuotedString (buf, cur->version);
else
xmlBufferWriteChar (buf, "\"1.0\"");
if ((cur->encoding != NULL) &&
(strcasecmp (cur->encoding, "UTF-8") != 0)) {
xmlBufferWriteChar (buf, " encoding=");
xmlBufferWriteQuotedString (buf, cur->encoding);
}
switch (cur->standalone) {
case 1:
xmlBufferWriteChar (buf, " standalone=\"yes\"");
break;
}
xmlBufferWriteChar (buf, "?>\n");
if (cur->root != NULL) {
xmlNodePtr child = cur->root;
while (child != NULL) {
xmlNodeDump (buf, cur, child, 0, 1);
xmlBufferWriteChar (buf, "\n");
child = child->next;
}
}
}
static int
xml_doc_save (xmlDocPtr doc, const char *filename)
{
size_t n, written = 0;
xmlBufferPtr buf;
int errnosave;
ssize_t w;
int fd;
fd = open (filename, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd == -1)
return -1;
if (!(buf = xmlBufferCreate ())) {
close (fd);
unlink (filename);
errno = ENOMEM;
return -1;
}
xmlDocContentDump (buf, doc);
n = buf->use;
do {
do {
w = write (fd, buf->content + written, n - written);
} while (w == -1 && errno == EINTR);
if (w > 0)
written += w;
} while (w != -1 && written < n);
xmlBufferFree (buf);
if (written < n || fsync (fd) == -1) {
errnosave = errno;
close (fd);
unlink (filename);
errno = errnosave;
return -1;
}
close (fd);
return 0;
}
static int
save (RuleContext *f, const char *user)
{
@ -384,7 +689,7 @@ save (RuleContext *f, const char *user)
struct _rule_set_map *map;
char *usersav, *userbak, *slash;
int ret;
doc = xmlNewDoc ("1.0");
root = xmlNewDocNode (doc, NULL, "filteroptions", NULL);
xmlDocSetRootElement (doc, root);
@ -401,7 +706,7 @@ save (RuleContext *f, const char *user)
}
l = g_list_next (l);
}
usersav = alloca(strlen(user)+5);
userbak = alloca(strlen(user)+5);
slash = strrchr(user, '/');
@ -411,7 +716,7 @@ save (RuleContext *f, const char *user)
sprintf(usersav, ".#%s", user);
sprintf(userbak, "%s~", user);
printf("saving rules to '%s' then backup '%s'\n", usersav, userbak);
ret = xmlSaveFile(usersav, doc);
ret = xml_doc_save (doc, usersav);
if (ret != -1) {
rename(user, userbak);
ret = rename(usersav, user);