Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2009 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #include <config.h>
24 : :
25 : : #include <stdio.h>
26 : : #include <locale.h>
27 : : #include <errno.h>
28 : :
29 : : #include <glib.h>
30 : : #include <gio/gio.h>
31 : :
32 : : #ifdef G_OS_UNIX
33 : : #include <unistd.h>
34 : : #endif
35 : :
36 : : #ifdef G_OS_WIN32
37 : : #include <io.h>
38 : : #ifndef STDOUT_FILENO
39 : : #define STDOUT_FILENO 1
40 : : #endif
41 : : #endif
42 : :
43 : : static gchar **locations = NULL;
44 : : static char *from_charset = NULL;
45 : : static char *to_charset = NULL;
46 : : static gboolean decompress = FALSE;
47 : : static gboolean compress = FALSE;
48 : : static gboolean gzip = FALSE;
49 : : static gboolean fallback = FALSE;
50 : :
51 : : static GOptionEntry entries[] = {
52 : : {"decompress", 0, 0, G_OPTION_ARG_NONE, &decompress, "decompress", NULL},
53 : : {"compress", 0, 0, G_OPTION_ARG_NONE, &compress, "compress", NULL},
54 : : {"gzip", 0, 0, G_OPTION_ARG_NONE, &gzip, "use gzip format", NULL},
55 : : {"from-charset", 0, 0, G_OPTION_ARG_STRING, &from_charset, "from charset", NULL},
56 : : {"to-charset", 0, 0, G_OPTION_ARG_STRING, &to_charset, "to charset", NULL},
57 : : {"fallback", 0, 0, G_OPTION_ARG_NONE, &fallback, "use fallback", NULL},
58 : : {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "locations", NULL},
59 : : G_OPTION_ENTRY_NULL
60 : : };
61 : :
62 : : static void
63 : 0 : decompressor_file_info_notify_cb (GZlibDecompressor *decompressor,
64 : : GParamSpec *pspec,
65 : : gpointer data)
66 : : {
67 : : GFileInfo *file_info;
68 : : const gchar *filename;
69 : :
70 : 0 : file_info = g_zlib_decompressor_get_file_info (decompressor);
71 : 0 : if (file_info == NULL)
72 : 0 : return;
73 : :
74 : 0 : filename = g_file_info_get_name (file_info);
75 : 0 : if (filename)
76 : 0 : g_printerr ("Decompressor filename: %s\n", filename);
77 : : }
78 : :
79 : : static void
80 : 0 : cat (GFile * file)
81 : : {
82 : : GInputStream *in;
83 : : char buffer[1024 * 8 + 1];
84 : : char *p;
85 : : gssize res;
86 : : gboolean close_res;
87 : : GError *error;
88 : : GConverter *conv;
89 : 0 : GCharsetConverter *cconv = NULL;
90 : :
91 : 0 : error = NULL;
92 : 0 : in = (GInputStream *) g_file_read (file, NULL, &error);
93 : 0 : if (in == NULL)
94 : : {
95 : : /* Translators: the first %s is the program name, the second one */
96 : : /* is the URI of the file, the third is the error message. */
97 : 0 : g_printerr ("%s: %s: error opening file: %s\n",
98 : 0 : g_get_prgname (), g_file_get_uri (file), error->message);
99 : 0 : g_error_free (error);
100 : 0 : return;
101 : : }
102 : :
103 : 0 : if (decompress)
104 : : {
105 : : GInputStream *old;
106 : 0 : conv = (GConverter *)g_zlib_decompressor_new (gzip?G_ZLIB_COMPRESSOR_FORMAT_GZIP:G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
107 : 0 : old = in;
108 : 0 : in = (GInputStream *) g_converter_input_stream_new (in, conv);
109 : 0 : g_signal_connect (conv, "notify::file-info", G_CALLBACK (decompressor_file_info_notify_cb), NULL);
110 : 0 : g_object_unref (conv);
111 : 0 : g_object_unref (old);
112 : : }
113 : :
114 : 0 : if (from_charset && to_charset)
115 : : {
116 : 0 : cconv = g_charset_converter_new (to_charset, from_charset, &error);
117 : 0 : conv = (GConverter *)cconv;
118 : 0 : if (conv)
119 : : {
120 : : GInputStream *old;
121 : :
122 : 0 : g_charset_converter_set_use_fallback (cconv, fallback);
123 : :
124 : 0 : old = in;
125 : 0 : in = (GInputStream *) g_converter_input_stream_new (in, conv);
126 : 0 : g_object_unref (conv);
127 : 0 : g_object_unref (old);
128 : : }
129 : : else
130 : : {
131 : 0 : g_printerr ("%s: Can't convert between charsets: %s\n",
132 : 0 : g_get_prgname (), error->message);
133 : : }
134 : : }
135 : :
136 : 0 : if (compress)
137 : : {
138 : : GInputStream *old;
139 : : GFileInfo *in_file_info;
140 : :
141 : 0 : in_file_info = g_file_query_info (file,
142 : : G_FILE_ATTRIBUTE_STANDARD_NAME ","
143 : : G_FILE_ATTRIBUTE_TIME_MODIFIED,
144 : : G_FILE_QUERY_INFO_NONE,
145 : : NULL,
146 : : &error);
147 : 0 : if (in_file_info == NULL)
148 : : {
149 : 0 : g_printerr ("%s: %s: error reading file info: %s\n",
150 : 0 : g_get_prgname (), g_file_get_uri (file), error->message);
151 : 0 : g_error_free (error);
152 : 0 : return;
153 : : }
154 : :
155 : 0 : conv = (GConverter *)g_zlib_compressor_new(gzip?G_ZLIB_COMPRESSOR_FORMAT_GZIP:G_ZLIB_COMPRESSOR_FORMAT_ZLIB, -1);
156 : 0 : g_zlib_compressor_set_file_info (G_ZLIB_COMPRESSOR (conv), in_file_info);
157 : 0 : old = in;
158 : 0 : in = (GInputStream *) g_converter_input_stream_new (in, conv);
159 : 0 : g_object_unref (conv);
160 : 0 : g_object_unref (old);
161 : 0 : g_object_unref (in_file_info);
162 : : }
163 : :
164 : : while (1)
165 : : {
166 : 0 : res =
167 : 0 : g_input_stream_read (in, buffer, sizeof (buffer) - 1, NULL, &error);
168 : 0 : if (res > 0)
169 : : {
170 : : gssize written;
171 : :
172 : 0 : p = buffer;
173 : 0 : while (res > 0)
174 : : {
175 : 0 : written = write (STDOUT_FILENO, p, res);
176 : :
177 : 0 : if (written == -1 && errno != EINTR)
178 : : {
179 : : /* Translators: the first %s is the program name, the */
180 : : /* second one is the URI of the file. */
181 : 0 : g_printerr ("%s: %s, error writing to stdout",
182 : : g_get_prgname (), g_file_get_uri (file));
183 : 0 : goto out;
184 : : }
185 : 0 : res -= written;
186 : 0 : p += written;
187 : : }
188 : : }
189 : 0 : else if (res < 0)
190 : : {
191 : 0 : g_printerr ("%s: %s: error reading: %s\n",
192 : : g_get_prgname (), g_file_get_uri (file),
193 : 0 : error->message);
194 : 0 : g_error_free (error);
195 : 0 : error = NULL;
196 : 0 : break;
197 : : }
198 : 0 : else if (res == 0)
199 : 0 : break;
200 : : }
201 : :
202 : 0 : out:
203 : :
204 : 0 : close_res = g_input_stream_close (in, NULL, &error);
205 : 0 : if (!close_res)
206 : : {
207 : 0 : g_printerr ("%s: %s:error closing: %s\n",
208 : 0 : g_get_prgname (), g_file_get_uri (file), error->message);
209 : 0 : g_error_free (error);
210 : : }
211 : :
212 : 0 : if (cconv != NULL && fallback)
213 : : {
214 : 0 : guint num = g_charset_converter_get_num_fallbacks (cconv);
215 : 0 : if (num > 0)
216 : 0 : g_printerr ("Number of fallback errors: %u\n", num);
217 : : }
218 : : }
219 : :
220 : : int
221 : 0 : main (int argc, char *argv[])
222 : : {
223 : 0 : GError *error = NULL;
224 : 0 : GOptionContext *context = NULL;
225 : : GFile *file;
226 : : int i;
227 : :
228 : : context =
229 : 0 : g_option_context_new ("LOCATION... - concatenate LOCATIONS "
230 : : "to standard output.");
231 : :
232 : 0 : g_option_context_set_summary (context, "filter files");
233 : :
234 : 0 : g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
235 : 0 : g_option_context_parse (context, &argc, &argv, &error);
236 : :
237 : 0 : g_option_context_free (context);
238 : :
239 : 0 : if (error != NULL)
240 : : {
241 : 0 : g_printerr ("Error parsing commandline options: %s\n", error->message);
242 : 0 : g_printerr ("\n");
243 : 0 : g_printerr ("Try \"%s --help\" for more information.",
244 : : g_get_prgname ());
245 : 0 : g_printerr ("\n");
246 : 0 : g_error_free(error);
247 : 0 : return 1;
248 : : }
249 : :
250 : 0 : if (!locations)
251 : : {
252 : 0 : g_printerr ("%s: missing locations", g_get_prgname ());
253 : 0 : g_printerr ("\n");
254 : 0 : g_printerr ("Try \"%s --help\" for more information.",
255 : : g_get_prgname ());
256 : 0 : g_printerr ("\n");
257 : 0 : return 1;
258 : : }
259 : :
260 : 0 : i = 0;
261 : :
262 : : do
263 : : {
264 : 0 : file = g_file_new_for_commandline_arg (locations[i]);
265 : 0 : cat (file);
266 : 0 : g_object_unref (file);
267 : : }
268 : 0 : while (locations[++i] != NULL);
269 : :
270 : 0 : return 0;
271 : : }
|