1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * gsf-infile-stdio.c: read a directory tree
4 *
5 * Copyright (C) 2004-2006 Novell, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2.1 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 #include <gsf-config.h>
23 #include <gsf/gsf-infile.h>
24 #include <gsf/gsf.h>
25
26 #include <string.h>
27 #include <errno.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <string.h>
34
35 static GObjectClass *parent_class;
36
37 struct _GsfInfileStdio {
38 GsfInfile parent;
39 char *root;
40 GPtrArray *children;
41 };
42
43 typedef GsfInfileClass GsfInfileStdioClass;
44
45 static void
gsf_infile_stdio_finalize(GObject * obj)46 gsf_infile_stdio_finalize (GObject *obj)
47 {
48 GsfInfileStdio *ifs = GSF_INFILE_STDIO (obj);
49
50 g_free (ifs->root);
51 g_ptr_array_free (ifs->children, TRUE);
52 parent_class->finalize (obj);
53 }
54
55 static GsfInput *
gsf_infile_stdio_dup(GsfInput * src_input,G_GNUC_UNUSED GError ** err)56 gsf_infile_stdio_dup (GsfInput *src_input, G_GNUC_UNUSED GError **err)
57 {
58 GsfInfileStdio *src = GSF_INFILE_STDIO (src_input);
59 unsigned ui;
60
61 GsfInfileStdio *dst = g_object_new (GSF_INFILE_STDIO_TYPE, NULL);
62 dst->root = g_strdup (src->root);
63
64 for (ui = 0; ui < src->children->len; ui++) {
65 const char *child = g_ptr_array_index (src->children, ui);
66 g_ptr_array_add (dst->children, g_strdup (child));
67 }
68
69 return GSF_INPUT (dst);
70 }
71
72 static guint8 const *
gsf_infile_stdio_read(G_GNUC_UNUSED GsfInput * input,G_GNUC_UNUSED size_t num_bytes,G_GNUC_UNUSED guint8 * buffer)73 gsf_infile_stdio_read (G_GNUC_UNUSED GsfInput *input, G_GNUC_UNUSED size_t num_bytes,
74 G_GNUC_UNUSED guint8 *buffer)
75 {
76 return NULL;
77 }
78
79 static GsfInput *
open_child(GsfInfileStdio * ifs,char const * name,GError ** err)80 open_child (GsfInfileStdio *ifs, char const *name, GError **err)
81 {
82 GsfInput *child;
83 char *path = g_build_filename (ifs->root, name, NULL);
84
85 if (g_file_test (path, G_FILE_TEST_IS_DIR))
86 child = (GsfInput *) gsf_infile_stdio_new (path, err);
87 else
88 child = gsf_input_stdio_new (path, err);
89 g_free (path);
90
91 return child;
92 }
93
94 static char const *
gsf_infile_stdio_name_by_index(GsfInfile * infile,int target)95 gsf_infile_stdio_name_by_index (GsfInfile *infile, int target)
96 {
97 GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
98 return (unsigned)target < ifs->children->len
99 ? g_ptr_array_index (ifs->children, target)
100 : NULL;
101 }
102
103 static GsfInput *
gsf_infile_stdio_child_by_index(GsfInfile * infile,int target,GError ** err)104 gsf_infile_stdio_child_by_index (GsfInfile *infile, int target, GError **err)
105 {
106 GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
107 const char *name = gsf_infile_stdio_name_by_index (infile, target);
108 return name ? open_child (ifs, name, err) : NULL;
109 }
110
111 static GsfInput *
gsf_infile_stdio_child_by_name(GsfInfile * infile,char const * name,GError ** err)112 gsf_infile_stdio_child_by_name (GsfInfile *infile, char const *name, GError **err)
113 {
114 GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
115 unsigned ui;
116
117 for (ui = 0; ui < ifs->children->len; ui++) {
118 const char *child = g_ptr_array_index (ifs->children, ui);
119 if (!strcmp (child, name))
120 return open_child (ifs, name, err);
121 }
122
123 return NULL;
124 }
125
126 static int
gsf_infile_stdio_num_children(GsfInfile * infile)127 gsf_infile_stdio_num_children (GsfInfile *infile)
128 {
129 GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
130 return ifs->children->len;
131 }
132
133 static void
gsf_infile_stdio_init(GsfInfileStdio * ifs)134 gsf_infile_stdio_init (GsfInfileStdio *ifs)
135 {
136 ifs->root = NULL;
137 ifs->children = g_ptr_array_new_with_free_func (g_free);
138 }
139
140 static void
gsf_infile_stdio_class_init(GObjectClass * gobject_class)141 gsf_infile_stdio_class_init (GObjectClass *gobject_class)
142 {
143 GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
144 GsfInfileClass *infile_class = GSF_INFILE_CLASS (gobject_class);
145
146 parent_class = g_type_class_peek (GSF_INFILE_TYPE);
147
148 gobject_class->finalize = gsf_infile_stdio_finalize;
149 input_class->Dup = gsf_infile_stdio_dup;
150 input_class->Read = gsf_infile_stdio_read;
151 input_class->Seek = NULL;
152 infile_class->num_children = gsf_infile_stdio_num_children;
153 infile_class->name_by_index = gsf_infile_stdio_name_by_index;
154 infile_class->child_by_index = gsf_infile_stdio_child_by_index;
155 infile_class->child_by_name = gsf_infile_stdio_child_by_name;
156 }
157
GSF_CLASS(GsfInfileStdio,gsf_infile_stdio,gsf_infile_stdio_class_init,gsf_infile_stdio_init,GSF_INFILE_TYPE)158 GSF_CLASS (GsfInfileStdio, gsf_infile_stdio,
159 gsf_infile_stdio_class_init, gsf_infile_stdio_init,
160 GSF_INFILE_TYPE)
161
162 /**
163 * gsf_infile_stdio_new:
164 * @root: in locale dependent encoding
165 * @err: optionally %NULL.
166 *
167 * Returns: a new file or %NULL.
168 **/
169 GsfInfile *
170 gsf_infile_stdio_new (char const *root, GError **err)
171 {
172 GsfInfileStdio *ifs;
173 GDir *dir;
174 char const *child;
175
176 dir = g_dir_open (root, 0, err);
177 if (dir == NULL)
178 return NULL;
179
180 ifs = g_object_new (GSF_INFILE_STDIO_TYPE, NULL);
181 ifs->root = g_strdup (root);
182
183 while ((child = g_dir_read_name (dir)))
184 g_ptr_array_add (ifs->children, g_strdup (child));
185
186 g_dir_close (dir);
187
188 gsf_input_set_name_from_filename (GSF_INPUT (ifs), root);
189
190 return GSF_INFILE (ifs);
191 }
192