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:

committed by
Jeffrey Stedfast

parent
ce3ae88564
commit
4e8deb5e4c
@ -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.
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user