Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / libedataserver / e-xml-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* 
3  * Copyright (C) 2005 Novell, Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU Lesser General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25
26 #ifndef O_BINARY
27 #define O_BINARY 0
28 #endif
29
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32
33 #include <glib.h>
34 #include <glib/gstdio.h>
35
36 #include "e-xml-utils.h"
37
38 #ifdef G_OS_WIN32
39 #define fsync(fd) 0
40 #endif
41
42 xmlDocPtr
43 e_xml_parse_file (const char *filename)
44 {
45         xmlDocPtr result = NULL;
46
47         GMappedFile *mapped_file;
48
49         mapped_file = g_mapped_file_new (filename, FALSE, NULL);
50         if (mapped_file) {
51                 result = xmlParseMemory (g_mapped_file_get_contents (mapped_file),
52                                          g_mapped_file_get_length (mapped_file));
53                 g_mapped_file_free (mapped_file);
54         }
55         return result;
56 }
57
58 int
59 e_xml_save_file (const char *filename, xmlDocPtr doc)
60 {
61         char *filesave;
62         xmlChar *xmlbuf;
63         size_t n, written = 0;
64         int ret, fd, size;
65         int errnosave;
66         ssize_t w;
67         gchar *dirname = g_path_get_dirname (filename);
68         gchar *basename = g_path_get_basename (filename);
69         gchar *savebasename = g_strconcat (".#", basename, NULL);
70
71         g_free (basename);
72         filesave = g_build_filename (dirname, savebasename, NULL);
73         g_free (savebasename);
74         g_free (dirname);
75         
76         fd = g_open (filesave, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
77         if (fd == -1) {
78                 g_free (filesave);
79                 return -1;
80         }
81         
82         xmlDocDumpFormatMemory (doc, &xmlbuf, &size, TRUE);
83         if (size <= 0) {
84                 close (fd);
85                 g_unlink (filesave);
86                 g_free (filesave);
87                 errno = ENOMEM;
88                 return -1;
89         }
90         
91         n = (size_t) size;
92         do {
93                 do {
94                         w = write (fd, xmlbuf + written, n - written);
95                 } while (w == -1 && errno == EINTR);
96                 
97                 if (w > 0)
98                         written += w;
99         } while (w != -1 && written < n);
100         
101         xmlFree (xmlbuf);
102         
103         if (written < n || fsync (fd) == -1) {
104                 errnosave = errno;
105                 close (fd);
106                 g_unlink (filesave);
107                 g_free (filesave);
108                 errno = errnosave;
109                 return -1;
110         }
111
112         while ((ret = close (fd)) == -1 && errno == EINTR)
113                 ;
114         
115         if (ret == -1) {
116                 g_free (filesave);
117                 return -1;
118         }
119         
120         if (g_rename (filesave, filename) == -1) {
121                 errnosave = errno;
122                 g_unlink (filesave);
123                 g_free (filesave);
124                 errno = errnosave;
125                 return -1;
126         }
127         g_free (filesave);
128         
129         return 0;
130 }
131
132 xmlNode *
133 e_xml_get_child_by_name (const xmlNode *parent, const xmlChar *child_name)
134 {
135         xmlNode *child;
136
137         g_return_val_if_fail (parent != NULL, NULL);
138         g_return_val_if_fail (child_name != NULL, NULL);
139         
140         for (child = parent->xmlChildrenNode; child != NULL; child = child->next) {
141                 if (xmlStrcmp (child->name, child_name) == 0) {
142                         return child;
143                 }
144         }
145         return NULL;
146 }
147
148