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