YAZ  5.23.1
xml_include.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/tpath.h>
20 #include <yaz/log.h>
21 #include <yaz/xml_include.h>
22 
23 #if YAZ_HAVE_XML2
24 
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27 
29  const char *confdir;
30  unsigned glob_flags;
31 };
32 
34 
35 static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
36 
37 static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
38 {
39  if (config->confdir && *config->confdir > 0 &&
40  !yaz_is_abspath(src))
41  {
42  wrbuf_printf(w, "%s/%s", config->confdir, src);
43  }
44  else
45  wrbuf_puts(w, src);
46 }
47 
48 static int config_include_one(yaz_xml_include_t config, xmlNode **sib,
49  const char *path)
50 {
51  struct stat st;
52  if (stat(path, &st) < 0)
53  {
54  yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path);
55  return -1;
56  }
57  else
58  {
59  if ((st.st_mode & S_IFMT) == S_IFREG)
60  {
61  xmlDoc *doc = xmlParseFile(path);
62  if (doc)
63  {
64  xmlNodePtr t = xmlDocGetRootElement(doc);
65  int ret = process_config_includes(config, t);
66  *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1));
67  xmlFreeDoc(doc);
68  if (ret)
69  return -1;
70  }
71  else
72  {
73  yaz_log(YLOG_FATAL, "Could not parse %s", path);
74  return -1;
75  }
76  }
77  }
78  return 0;
79 }
80 
81 static int config_include_src(yaz_xml_include_t config, xmlNode **np,
82  const char *src)
83 {
84  int ret = 0; /* return code. OK so far */
85  WRBUF w = wrbuf_alloc();
86  xmlNodePtr sib; /* our sibling that we append */
87  xmlNodePtr c; /* tmp node */
88 
89  wrbuf_printf(w, " begin include src=\"%s\" ", src);
90 
91  /* replace include element with a 'begin' comment */
92  sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
93  xmlReplaceNode(*np, sib);
94 
95  xmlFreeNode(*np);
96 
97  wrbuf_rewind(w);
98  conf_dir_path(config, w, src);
99  {
100  int glob_ret;
102 
103  glob_ret = yaz_file_glob2(wrbuf_cstr(w), &glob_res, config->glob_flags);
104  if (glob_ret == 0)
105  {
106  size_t i;
107  const char *path;
108  for (i = 0; (path = yaz_file_glob_get_file(glob_res, i)); i++)
109  ret = config_include_one(config, &sib, path);
110  yaz_file_globfree(&glob_res);
111  }
112  }
113  wrbuf_rewind(w);
114  wrbuf_printf(w, " end include src=\"%s\" ", src);
115  c = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
116  sib = xmlAddNextSibling(sib, c);
117 
118  *np = sib;
119  wrbuf_destroy(w);
120  return ret;
121 }
122 
123 static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
124 {
125  for (n = n->children; n; n = n->next)
126  {
127  if (n->type == XML_ELEMENT_NODE)
128  {
129  if (!strcmp((const char *) n->name, "include"))
130  {
131  xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
132  if (src)
133  {
134  /* src must be preserved, because n is destroyed */
135  int ret = config_include_src(config, &n,
136  (const char *) src);
137  xmlFree(src);
138  if (ret)
139  return ret;
140 
141  }
142  }
143  else
144  {
145  if (process_config_includes(config, n))
146  return -1;
147  }
148  }
149  }
150  return 0;
151 }
152 
153 int yaz_xml_include_glob(xmlNode *n, const char *base_path,
154  unsigned glob_flags)
155 {
156  struct yaz_xml_include_s s;
157 
158  s.confdir = base_path;
160  return process_config_includes(&s, n);
161 }
162 
163 int yaz_xml_include_simple(xmlNode *n, const char *base_path)
164 {
165  return yaz_xml_include_glob(n, base_path, 0);
166 }
167 
168 
169 /* YAZ_HAVE_XML2 */
170 #endif
171 
172 /*
173  * Local variables:
174  * c-basic-offset: 4
175  * c-file-style: "Stroustrup"
176  * indent-tabs-mode: nil
177  * End:
178  * vim: shiftwidth=4 tabstop=8 expandtab
179  */
180 
int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags)
perform glob (with flags)
Definition: file_glob.c:146
Header for WRBUF (growing buffer)
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition: wrbuf.c:281
int yaz_xml_include_glob(xmlNode *n, const char *base_path, unsigned glob_flags)
substitute include nodes in a tree
Definition: xml_include.c:153
static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
Definition: xml_include.c:123
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition: wrbuf.c:89
struct yaz_xml_include_s * yaz_xml_include_t
Definition: xml_include.c:33
string buffer
Definition: wrbuf.h:42
#define YLOG_FATAL
log level: fatal
Definition: log.h:42
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition: wrbuf.c:47
static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
Definition: xml_include.c:37
int yaz_xml_include_simple(xmlNode *n, const char *base_path)
substitute include nodes in a tree
Definition: xml_include.c:163
File Path utilities.
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition: wrbuf.c:178
#define YLOG_ERRNO
log level: append system error message
Definition: log.h:50
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition: wrbuf.c:38
static int config_include_src(yaz_xml_include_t config, xmlNode **np, const char *src)
Definition: xml_include.c:81
XML Include (not to be confused with W3C XInclude)
int yaz_is_abspath(const char *p)
checks whether path is absolute
Definition: tpath.c:127
unsigned glob_flags
Definition: xml_include.c:30
void yaz_log(int level, const char *fmt,...)
Writes log message.
Definition: log.c:485
const char * confdir
Definition: xml_include.c:29
void yaz_file_globfree(yaz_glob_res_t *res)
release glob result
Definition: file_glob.c:163
const char * yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
return resulting matching file
Definition: file_glob.c:173
Logging utility.
static int config_include_one(yaz_xml_include_t config, xmlNode **sib, const char *path)
Definition: xml_include.c:48
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition: wrbuf.c:25