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>
|
2002-08-02 Not Zed <NotZed@Ximian.com>
|
||||||
|
|
||||||
* filter.glade: Added a datespec editor window.
|
* 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.
|
* Copyright (C) 2000 Ximian Inc.
|
||||||
*
|
*
|
||||||
@ -18,6 +19,7 @@
|
|||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
@ -26,8 +28,13 @@
|
|||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.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 <gtk/gtksignal.h>
|
||||||
#include <libgnomeui/gnome-dialog.h>
|
#include <libgnomeui/gnome-dialog.h>
|
||||||
#include <libgnomeui/gnome-stock.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);
|
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
|
static int
|
||||||
save (RuleContext *f, const char *user)
|
save (RuleContext *f, const char *user)
|
||||||
{
|
{
|
||||||
@ -411,7 +716,7 @@ save (RuleContext *f, const char *user)
|
|||||||
sprintf(usersav, ".#%s", user);
|
sprintf(usersav, ".#%s", user);
|
||||||
sprintf(userbak, "%s~", user);
|
sprintf(userbak, "%s~", user);
|
||||||
printf("saving rules to '%s' then backup '%s'\n", usersav, userbak);
|
printf("saving rules to '%s' then backup '%s'\n", usersav, userbak);
|
||||||
ret = xmlSaveFile(usersav, doc);
|
ret = xml_doc_save (doc, usersav);
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
rename(user, userbak);
|
rename(user, userbak);
|
||||||
ret = rename(usersav, user);
|
ret = rename(usersav, user);
|
||||||
|
Reference in New Issue
Block a user