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