1 /* mkisofs.c
2 * Copyright (C) 2004, 2005 Sylvain Cresto <scresto@gmail.com>
3 *
4 * This file is part of graveman!
5 *
6 * graveman! is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or
9 * (at your option) any later version.
10 *
11 * graveman! 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 GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with program; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
20 *
21 * URL: http://www.nongnu.org/graveman/
22 *
23 */
24
25 #include "graveman.h"
26
27 /* communication avec mkisofs */
28
29 #define MKISOFS_ESTIMATE "done, estimate finish"
30 #define MKISOFS_ERROR "mkisofs:"
31 #define MKISOFS_IGNORE "-follow-links does not always"
32 #define MKISOFS_OK "Total translation table size"
33 #define MKISOFS_NOSPACE "No space left on device"
34 #define MKISOFS_SUPPORT_ISOV2 "Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2"
35 #define MKISOFS_CHARSET "Known charsets are:"
36
37 /* on verifie si le support iso9660 version 2 est disponnible ou non */
check_mkisofs()38 gboolean check_mkisofs()
39 {
40 gchar *Lmkisofs = conf_get_string("mkisofs");
41 gchar *Lcommandline, *Lerr = NULL;
42 gboolean Lstatus;
43 gint Lexit = 0;
44 if (!Lmkisofs || !*Lmkisofs) return FALSE;
45
46 Lcommandline = g_strdup_printf("%s -help", conf_get_string("mkisofs"));
47 Lstatus = g_spawn_command_line_sync(Lcommandline, NULL, &Lerr, &Lexit, NULL);
48 g_free(Lcommandline);
49
50 Lstatus = (Lstatus == TRUE && Lerr && ((strstr(Lerr, MKISOFS_SUPPORT_ISOV2))));
51 g_free(Lerr);
52
53 return Lstatus;
54 }
55
56 /* recherche les parametres supplementaires a passer a mkisofs */
make_image_getextrapara(Tgrave * Ag,gchar * Aop)57 gchar *make_image_getextrapara(Tgrave *Ag, gchar *Aop)
58 {
59 const gchar *Ldatavoli = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%svoli", Aop)));
60 const gchar *Ldatapubl = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%spubl", Aop)));
61 const gchar *Ldataprep = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%sprep", Aop)));
62 const gchar *Ldatabibl = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%sbibl", Aop)));
63 const gchar *Ldatacopy = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%scopy", Aop)));
64 const gchar *Ldataabst = gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widgetv(Ag, "%sabst", Aop)));
65 gchar *Lreturn, *Linputcharset = NULL;
66 gchar *Lextra = NULL;
67 gchar *Ldevchar = NULL;
68 GtkTextIter Lstart, Lend;
69 GtkTextBuffer *Lbufappi = gtk_text_view_get_buffer (GTK_TEXT_VIEW (sc_grave_get_widgetv(Ag, "%sappi", Aop)));
70 char *Ldataappi, *Ltmpappi;
71 gtk_text_buffer_get_bounds (Lbufappi, &Lstart, &Lend);
72 Ltmpappi = gtk_text_iter_get_text (&Lstart, &Lend);
73 Ldataappi = g_strescape(Ltmpappi, "");
74 g_free(Ltmpappi);
75
76 if (!strcmp(Aop, "data")) { /* data cd */
77 gboolean Lrockridge = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "datarockridge")));
78 gboolean Ljoliet = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "datajoliet")));
79 gchar *Lisolevel = get_combo_value(sc_grave_get_widget(Ag, "dataisolevel"));
80 gchar *Lmediainfo = NULL;
81
82 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "datamulti")))) {
83 gboolean *Luseautoblank = (gboolean *) sc_grave_get_data(Ag, "useautoblank");
84
85 if (*Luseautoblank == FALSE) {
86 Tdriveinfo *Ldevice = matos_get_drive_info(Ag, "dstdatacombo");
87 if (Ldevice) {
88 Ldevchar = DRIVE_DEV(Ldevice);
89 Lmediainfo = cdrecord_get_mediainfo(Ag, Ldevice, NULL);
90 }
91 }
92 }
93
94 Lextra = g_strdup_printf("%s %s -iso-level %s %s%s %s%s", Lrockridge == TRUE ? "-r" : "", Ljoliet ? "-J" : "", Lisolevel,
95 Lmediainfo ? "-C " : "", Lmediainfo ? Lmediainfo : "", Lmediainfo && Ldevchar ? "-M " : "",
96 Lmediainfo && Ldevchar ? Ldevchar : "");
97 g_free(Lmediainfo);
98 g_free(Lisolevel);
99 } else { /* data dvd */
100 Lextra = g_strdup("-r -J");
101 }
102
103 /* charsets a utiliser pour la creation de l'image iso */
104 if ((Lreturn = conf_get_string("inputcharset"))) {
105 Linputcharset = g_strdup_printf("-input-charset %s", Lreturn);
106 }
107 Lreturn = g_strdup_printf("-V \"%s\" -A \"%s\" -publisher \"%s\" -p \"%s\" -biblio \"%s\" -copyright \"%s\" "
108 "-abstract \"%s\" %s %s",
109 _NN(Ldatavoli), _NN(Ldataappi), _NN(Ldatapubl), _NN(Ldataprep), _NN(Ldatabibl), _NN(Ldatacopy),
110 _NN(Ldataabst), Lextra, Linputcharset ? Linputcharset : "");
111 g_free(Linputcharset);
112 g_free(Lextra);
113
114 return Lreturn;
115 }
116
mkisofs_makeimage_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)117 gboolean mkisofs_makeimage_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
118 {
119 GIOStatus Lstatus;
120 Tgrave *Lg = (Tgrave *)Adata;
121 gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
122 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
123 gint *Ltodo = (gint *) sc_grave_get_data(Lg, "todo"); /* nombre de piste a traiter */
124 gint *Ldone = (gint *) sc_grave_get_data(Lg, "done"); /* nombre de piste deja traite */
125 GtkProgressBar *Lprogressbar = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_total"));
126 GtkProgressBar *Lprogressbar2 = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_step"));
127 gchar *Lbuffer = NULL, *f, *Ltxt;
128 gdouble Lpct, Ltava;
129 gchar Lsbuf[100], Lsbuf2[100];
130
131 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
132 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
133 *Lcont = 0;
134 return FALSE;
135 }
136 Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
137 if (!Lbuffer || Lstatus == G_IO_STATUS_ERROR || Lstatus == G_IO_STATUS_AGAIN) return TRUE;
138 _DEB("on recoi => '%s'\n", Lbuffer);
139
140 if ((strstr(Lbuffer, MKISOFS_ESTIMATE)) && Lbuffer[3]=='.') {
141 Lbuffer[3]=0;
142 f=ltrim(Lbuffer);
143
144 /* avancement tache */
145 Lpct = 0.01 * atof(f);
146 gtk_progress_bar_set_fraction(Lprogressbar2, Lpct);
147 g_snprintf(Lsbuf, sizeof(Lsbuf)-1, "%s%%", f);
148 gtk_progress_bar_set_text(Lprogressbar2, Lsbuf);
149 /* avancement total */
150 Ltava = (1.0 / (*Ltodo)) * ((*Ldone)-1+Lpct);
151 gtk_progress_bar_set_fraction(Lprogressbar, Ltava);
152 g_snprintf(Lsbuf2, sizeof(Lsbuf2)-1, "%.0f%%", Ltava*100);
153 gtk_progress_bar_set_text(Lprogressbar, Lsbuf2);
154 } else if ((strstr(Lbuffer, MKISOFS_ERROR)) && (!strstr(Lbuffer, MKISOFS_IGNORE))) {
155 *Lcont = 0;
156
157 if (!strstr(Lbuffer, MKISOFS_NOSPACE)) {
158 Ltxt = _UTF8(Lbuffer);
159 } else {
160 Ltxt = g_strdup(_("Not enough free disk space to create iso image !"));
161 }
162 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_MKISOFS, Ltxt);
163 g_free(Ltxt);
164 return FALSE;
165 } else if (!strncmp(Lbuffer, MKISOFS_OK, strlen(MKISOFS_OK))) {
166 gboolean *Lopstatus = (gboolean *) sc_grave_get_data(Lg, "operationstatus");
167 /* ok tout s'est bien passe ! */
168 gtk_progress_bar_set_fraction(Lprogressbar2, 1);
169 gtk_progress_bar_set_text(Lprogressbar2, "100%");
170 Ltava = (1.0 / (*Ltodo)) * (*Ldone);
171 gtk_progress_bar_set_fraction(Lprogressbar, Ltava);
172 g_snprintf(Lsbuf2, sizeof(Lsbuf2)-1, "%.0f%%", Ltava*100);
173 gtk_progress_bar_set_text(Lprogressbar, Lsbuf2);
174 *Lcont = 0;
175 *Lopstatus = TRUE;
176 }
177
178 return TRUE;
179 }
180
181 /* creation image iso */
make_iso(Tgrave * Ag,GError ** Aerror)182 gboolean make_iso(Tgrave *Ag, GError **Aerror)
183 {
184 gboolean Lstatus = FALSE;
185 gchar **Lcmd;
186 gchar *Lcommandline;
187 GIOChannel *Lcomerr, *Lcom;
188 guint Lcomerrevent, Lcomevent;
189 gint *Lcont = (gint *)sc_grave_get_data(Ag, "cont");
190 gboolean *Labort = (gboolean *) sc_grave_get_data(Ag, "gabort");
191 gchar *Ltmpdir = (gchar *)sc_grave_get_data(Ag, "tmpdir");
192 gchar *Lextrapara = (gchar *)sc_grave_get_data(Ag, "extrapara");
193 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
194 gint *Ldone = (gint *)sc_grave_get_data(Ag, "done"); /* fais */
195 gchar *Liso = (gchar *)sc_grave_get_data(Ag, "iso"); /* image iso */
196 gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Ag, "operationstatus");
197 GtkLabel *Ltitle = GTK_LABEL(sc_grave_get_data(Ag, "gravetitle"));
198 gint g_out, g_err, Lnbrarg;
199
200 *Loperationstatus = FALSE;
201 gtk_label_set_text(Ltitle, _("Writing image..."));
202
203 Lcommandline = g_strdup_printf("%s %s %s -o %s -graft-points -path-list %s/pathlist",
204 conf_get_string("mkisofs"), Lextrapara, conf_get_string("mkisofspara"), Liso, Ltmpdir);
205
206 _DEB("execution [%s]\n", Lcommandline);
207 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
208 _DEB("nbr arg [%d]\n", Lnbrarg);
209 g_free(Lcommandline);
210 if (Lstatus == FALSE) {
211 return FALSE;
212 }
213
214 Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
215 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
216 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
217 g_strfreev(Lcmd);
218
219 if (Lstatus == FALSE) {
220 g_warning("ERROR EXECUTION !\n");
221 return FALSE;
222 }
223
224 Lcom = g_io_channel_unix_new( g_out );
225 g_io_channel_set_encoding (Lcom, NULL, NULL);
226 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
227 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
228 mkisofs_makeimage_callback, Ag);
229
230 Lcomerr = g_io_channel_unix_new( g_err );
231 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
232 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
233 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
234 mkisofs_makeimage_callback, Ag);
235 _DEB("debut !!");
236 while (*Lcont > 0 && *Labort == FALSE) {
237 gtk_main_iteration();
238 }
239 exit_prog(*Lpid, *Labort, Aerror, NULL);
240
241 _DEB("fin !!");
242
243 g_source_remove(Lcomerrevent);
244 g_source_remove(Lcomevent);
245
246 /* fermeture mkisofs */
247 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
248 g_io_channel_unref(Lcomerr);
249 g_io_channel_shutdown(Lcom, FALSE, NULL);
250 g_io_channel_unref(Lcom);
251 g_spawn_close_pid(*Lpid);
252 *Lpid = 0;
253
254 if (*Aerror) {
255 return FALSE;
256 }
257
258 (*Ldone)++;
259 return TRUE;
260 }
261
262 /* recuperation des charsets integr� dans mkisofs */
get_builtin_charset(Tgrave * Ag,GError ** Aerror)263 gboolean get_builtin_charset(Tgrave *Ag, GError **Aerror)
264 {
265 gchar *Lcommandline, *Lout = NULL, *Lerr = NULL;
266 gboolean Lstatus = TRUE;
267 gchar **Lcharsetl;
268 gint Lexit = 0, i;
269 gboolean Lajout = FALSE;
270 gchar *Lmkisofs = conf_get_string("mkisofs");
271
272 if (!Lmkisofs || !*Lmkisofs) return FALSE;
273
274 Lcommandline = g_strdup_printf("%s -input-charset help", Lmkisofs);
275 _DEB("command [%s]", Lcommandline);
276 Lstatus = g_spawn_command_line_sync(Lcommandline, &Lout, &Lerr, &Lexit, Aerror);
277 g_free(Lcommandline);
278
279 if (Lstatus == FALSE || !Lerr) {
280 g_free(Lout);
281 g_free(Lerr);
282 return FALSE;
283 }
284
285 Lcharsetl = g_strsplit(Lerr, "\n", 0);
286 g_slist_free(Gcharsetlist);
287 Gcharsetlist = NULL;
288
289 for (i=0; Lcharsetl[i] && *Lcharsetl[i]; i++) {
290 if (Lajout) {
291 config_append_charset(Lcharsetl[i], (gchar *)charset_code_to_label(Lcharsetl[i]));
292 } else if (!strncmp(Lcharsetl[i], MKISOFS_CHARSET, strlen(MKISOFS_CHARSET))) {
293 Lajout = TRUE;
294 }
295 }
296
297 g_strfreev(Lcharsetl);
298
299 return TRUE;
300 }
301
302
303 /*
304 * vim:et:ts=8:sts=2:sw=2
305 */
306