Translation updates.
[gliv.git] / src / decompression.c
blob81e4c577a897f27ee56931909cb8c8d31852e90f
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /************************************************
22 * Files decompression (images and collections) *
23 ************************************************/
25 #include <unistd.h> /* read(), pipe(), fork(), execlp() ... */
26 #include <sys/types.h> /* pid_t */
27 #include <signal.h> /* kill(), SIGTERM */
28 #include <stdio.h> /* perror() */
29 #include <sys/wait.h> /* waitpid() */
30 #include <errno.h> /* errno */
32 #include "gliv.h"
33 #include "decompression.h"
34 #include "collection.h"
35 #include "loading.h"
37 typedef struct {
38 gchar *ext;
39 gchar *cmd;
40 } decompressor;
42 /* Read from the child process. */
43 static GdkPixbuf *read_image(gint fd, GError ** error)
45 guchar buf[4096];
46 GdkPixbuf *pixbuf;
47 GdkPixbufLoader *loader;
48 gsize size;
50 loader = gdk_pixbuf_loader_new();
52 while ((size = read(fd, buf, sizeof(buf))) > 0 || (errno == EINTR)) {
53 if (size > 0 &&
54 gdk_pixbuf_loader_write(loader, buf, size, error) == FALSE)
55 return NULL;
58 if (gdk_pixbuf_loader_close(loader, error) == FALSE)
59 return NULL;
61 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
62 if (pixbuf != NULL)
63 gdk_pixbuf_ref(pixbuf);
65 g_object_unref(loader);
66 return pixbuf;
69 /* Exec: "%cmd -c %filename" to send the output to stdout, the parent. */
70 static void decomp_file(const gchar * cmd, const gchar * filename, gint fd)
72 if (dup2(fd, STDOUT_FILENO) < 0) {
73 perror("dup2");
74 return;
77 if (execlp(cmd, cmd, "-c", filename, NULL) < 0) {
78 perror("execlp");
79 return;
83 static gboolean init_decompression(const gchar * filename, gint * fd,
84 pid_t * pid_ptr)
86 /* *INDENT-OFF* */
87 static decompressor all_decomp[] = {
88 { "bz2", "bunzip2" },
89 { "gz", "gunzip" },
90 { "z", "uncompress" },
91 { NULL, NULL }
93 /* *INDENT-ON* */
95 gint filedes[2];
96 pid_t pid;
97 decompressor *decomp;
98 const gchar *ext;
100 /* Find the appropriate decompressor. */
101 ext = get_extension(filename);
102 if (ext == NULL)
103 return FALSE;
105 for (decomp = all_decomp; decomp->ext != NULL; decomp++)
106 if (!g_ascii_strcasecmp(decomp->ext, ext))
107 break;
109 if (decomp->ext == NULL)
110 /* Decompressor not found. */
111 return FALSE;
113 if (pipe(filedes) < 0) {
114 perror("pipe");
115 return FALSE;
118 pid = fork();
119 if (pid < 0) {
120 perror("fork");
121 return FALSE;
124 if (pid == 0) {
125 /* Child */
126 close(filedes[0]);
127 decomp_file(decomp->cmd, filename, filedes[1]);
128 return FALSE;
131 /* Parent */
132 close(filedes[1]);
133 *fd = filedes[0];
134 *pid_ptr = pid;
135 return TRUE;
138 GdkPixbuf *load_compressed_pixbuf(const gchar * filename, GError ** error)
140 gint fd;
141 pid_t pid;
142 GdkPixbuf *pixbuf;
144 if (init_decompression(filename, &fd, &pid) == FALSE)
145 return NULL;
147 pixbuf = read_image(fd, error);
148 close(fd);
149 waitpid(pid, NULL, 0);
151 return pixbuf;
154 gint load_compressed_collection(const gchar * filename, gboolean reverse)
156 gint fd;
157 pid_t pid;
158 gint nb_inserted;
159 FILE *file;
161 if (init_decompression(filename, &fd, &pid) == FALSE)
162 return 0;
164 file = fdopen(fd, "r");
165 if (file == NULL) {
166 perror(filename);
167 kill(pid, SIGTERM);
168 nb_inserted = 0;
169 } else
170 nb_inserted = load_dot_gliv_from_file(file, reverse);
172 fclose(file);
173 waitpid(pid, NULL, 0);
175 return nb_inserted;