1 /*
2 * Copyright (C) 2002 2003 2004 2005 2006 2011, Magnus Hjorth
3 *
4 * This file is part of mhWaveEdit.
5 *
6 * mhWaveEdit 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 of the License, or
9 * (at your option) any later version.
10 *
11 * mhWaveEdit 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 General Public License
17 * along with mhWaveEdit; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include "um.h"
31 #include "gtkfiles.h"
32 #include "main.h"
33 #include "mainloop.h"
34 #include "inifile.h"
35 #include "gettext.h"
36
37 gboolean report_write_errors = TRUE;
38
39 static int highest_fd = 2;
40
xopen(char * filename,int flags,int mode)41 int xopen(char *filename, int flags, int mode)
42 {
43 int fd;
44 gchar *c;
45 fd = open(filename,flags,mode);
46 if (fd == -1) {
47 if (report_write_errors || mode==EFILE_READ) {
48 c = g_strdup_printf(_("Could not open %s: %s"),filename,
49 strerror(errno));
50 user_error(c);
51 g_free(c);
52 } else if (errno != ENOSPC) {
53 c = g_strdup_printf(_("Warning: Unexpected error: %s"),
54 filename);
55 user_perror(c);
56 g_free(c);
57 }
58 }
59 if (fd > highest_fd) highest_fd = fd;
60 return fd;
61 }
62
63
e_fopen(char * filename,int mode)64 EFILE *e_fopen(char *filename, int mode)
65 {
66 int fd,flag;
67 switch (mode) {
68 case EFILE_READ: flag = O_RDONLY; break;
69 case EFILE_WRITE: flag = O_WRONLY | O_CREAT | O_TRUNC; break;
70 case EFILE_APPEND: flag = O_WRONLY | O_CREAT | O_APPEND; break;
71 default: g_assert_not_reached(); return NULL;
72 }
73 fd = xopen(filename,flag,0666);
74 if (fd == -1) return NULL;
75 return e_fopen_fd(fd,filename);
76 }
77
e_fopen_fd(int fd,gchar * virtual_filename)78 EFILE *e_fopen_fd(int fd, gchar *virtual_filename)
79 {
80 EFILE *e;
81 e = g_malloc(sizeof(*e));
82 e->fd = fd;
83 e->filename = g_strdup(virtual_filename);
84 return e;
85 }
86
close_all_files(void)87 void close_all_files(void)
88 {
89 close_all_files_except(NULL,0);
90 }
91
close_all_files_except(int * fds,int count)92 void close_all_files_except(int *fds, int count)
93 {
94 /* We close one file higher than highest_fd because of some sound
95 drivers keep a file handle that wasn't opened through us. */
96 int i,j;
97 for (i=3; i<=highest_fd+1; i++) {
98 for (j=0; j<count; j++)
99 if (i == fds[j]) break;
100 if (j==count && close(i) == -1 && errno != EBADF)
101 console_perror("close_all_files");
102 }
103 }
104
e_fclose(EFILE * f)105 gboolean e_fclose(EFILE *f)
106 {
107 gchar *c;
108 gboolean b=FALSE;
109 if (close(f->fd) != 0) {
110 c = g_strdup_printf(_("Error closing %s: %s"), f->filename, strerror(errno));
111 user_error(c);
112 g_free(c);
113 b = TRUE;
114 }
115 g_free(f->filename);
116 g_free(f);
117 return b;
118 }
119
e_fclose_remove(EFILE * f)120 gboolean e_fclose_remove(EFILE *f)
121 {
122 gchar *c;
123 gboolean b=FALSE;
124 if (close(f->fd) != 0) {
125 c = g_strdup_printf(_("Error closing %s: %s"), f->filename, strerror(errno));
126 user_error(c);
127 g_free(c);
128 b=TRUE;
129 }
130 if (xunlink(f->filename)) b=TRUE;
131 g_free(f->filename);
132 g_free(f);
133 return b;
134 }
135
e_fseek(EFILE * stream,off_t offset,int whence)136 gboolean e_fseek(EFILE *stream, off_t offset, int whence)
137 {
138 char *c;
139 if (lseek(stream->fd,offset,whence) == (off_t)-1) {
140 c = g_strdup_printf(_("Could not seek in %s: %s"),stream->filename,
141 strerror(errno));
142 user_error(c);
143 g_free(c);
144 return TRUE;
145 }
146 return FALSE;
147 }
148
e_fread_upto(void * data,size_t size,EFILE * stream)149 gint e_fread_upto(void *data, size_t size, EFILE *stream)
150 {
151 char *c;
152 gint r = 0;
153 ssize_t i;
154 while (size > 0) {
155 i = read(stream->fd, (void *)(((char *)data)+r), size);
156 if (i == 0) return r;
157 if (i < 0) {
158 if (errno == EINTR) continue;
159 c = g_strdup_printf(_("Could not read from %s: %s"),
160 stream->filename,strerror(errno));
161 user_error(c);
162 g_free(c);
163 return -1;
164 }
165 r += i;
166 size -= i;
167 }
168 return r;
169 }
170
e_fread(void * data,size_t size,EFILE * stream)171 gboolean e_fread(void *data, size_t size, EFILE *stream)
172 {
173 gint i;
174 gchar *c;
175 i = e_fread_upto(data,size,stream);
176 if (i < size) {
177 if (i >= 0) {
178 c = g_strdup_printf(_("Unexpected end of file reading from %s"),
179 stream->filename);
180 user_error(c);
181 g_free(c);
182 }
183 return TRUE;
184 }
185 return FALSE;
186 }
187
e_fwrite(void * data,size_t size,EFILE * stream)188 gboolean e_fwrite(void *data, size_t size, EFILE *stream)
189 {
190 char *c;
191 gint w = 0;
192 ssize_t i;
193 while (size > 0) {
194 i = write(stream->fd, (void *)(((char *)data)+w), size);
195 if (i == 0) {
196 c = g_strdup_printf(_("Unable to write data to %s"),
197 stream->filename);
198 user_error(c);
199 g_free(c);
200 return TRUE;
201 }
202 if (i < 0) {
203 if (errno == EINTR) continue;
204 c = g_strdup_printf(_("Could not read from %s: %s"),
205 stream->filename,strerror(errno));
206 user_error(c);
207 g_free(c);
208 return TRUE;
209 }
210 w += i;
211 size -= i;
212 }
213 return FALSE;
214 }
215
e_fwrite0(size_t size,EFILE * stream)216 gboolean e_fwrite0(size_t size, EFILE *stream)
217 {
218 char buf[4096];
219 size_t s;
220 memset(buf,0,sizeof(buf));
221 while (size>0) {
222 s = MIN(size,sizeof(buf));
223 if (e_fwrite(buf,s,stream)) return TRUE;
224 size -= s;
225 }
226 return FALSE;
227 }
228
e_fread_bswap(void * data,size_t size,EFILE * stream)229 gboolean e_fread_bswap(void *data, size_t size, EFILE *stream)
230 {
231 size_t i;
232 gchar c;
233 if (e_fread(data,size,stream)) return TRUE;
234 i=0;
235 size--;
236 while (i<size) {
237 c = ((gchar *)data)[i];
238 ((gchar *)data)[i] = ((gchar *)data)[size];
239 ((gchar *)data)[size] = c;
240 i++;
241 size--;
242 }
243 return FALSE;
244 }
245
e_fwrite_bswap(void * data,size_t size,EFILE * stream)246 gboolean e_fwrite_bswap(void *data, size_t size, EFILE *stream)
247 {
248 static gchar *buf = NULL;
249 static size_t bufsize = 0;
250 size_t i;
251 if (size>bufsize) { buf=g_realloc(buf,size); bufsize=size; }
252 for (i=0; i<size; i++) buf[i]=((gchar *)data)[size-(1+i)];
253 return e_fwrite(buf,size,stream);
254 }
255
e_ftell(EFILE * stream)256 off_t e_ftell(EFILE *stream)
257 {
258 off_t l;
259 char *c;
260 l = lseek(stream->fd, 0, SEEK_CUR);
261 if (l == -1) {
262 c = g_strdup_printf(_("Could not get file position in %s: %s"),
263 stream->filename, strerror(errno));
264 user_error(c);
265 g_free(c);
266 }
267 return l;
268 }
269
is_same_file(char * filename1,char * filename2)270 gboolean is_same_file(char *filename1, char *filename2)
271 {
272 struct stat s1, s2;
273
274 if (!strcmp(filename1,filename2)) return TRUE;
275 if (stat(filename1,&s1)) {
276 if (errno == ENOENT) return FALSE;
277 else return TRUE;
278 }
279 if (stat(filename2,&s2)) {
280 if (errno == ENOENT) return FALSE;
281 else return TRUE;
282 }
283 return (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino);
284 }
285
286 /* Removes double slashes */
cleanup_filename(gchar * fn)287 static void cleanup_filename(gchar *fn)
288 {
289 gchar *c;
290 while (1) {
291 c = strstr(fn,"//");
292 if (c == NULL) return;
293 while (*c != 0) { c[0]=c[1]; c++; }
294 }
295 }
296
297 #if (GTK_MAJOR_VERSION < 2) || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || defined(DISABLE_FILECHOOSER)
298
299 /* Use the GtkFileSelection */
300
301 static gchar *get_filename_result;
302 static gboolean get_filename_quitflag;
303 static gboolean get_filename_savemode;
304 static GtkFileSelection *get_filename_fs;
305
get_filename_callback(GtkButton * button,gpointer user_data)306 static void get_filename_callback(GtkButton *button, gpointer user_data)
307 {
308 GtkFileSelection *fs = GTK_FILE_SELECTION(user_data);
309 gchar *c;
310 if (button==GTK_BUTTON(fs->ok_button)) {
311 if (get_filename_savemode &&
312 file_exists((gchar *)gtk_file_selection_get_filename(fs))) {
313 if (user_message(_("File already exists. Overwrite?"),
314 UM_YESNOCANCEL) != MR_YES) {
315 gtk_signal_emit_stop_by_name(GTK_OBJECT(button),"clicked");
316 return;
317 }
318 } else if (!get_filename_savemode &&
319 !file_exists((gchar *)
320 gtk_file_selection_get_filename(fs))) {
321 user_error(_("No file with that name!"));
322 gtk_signal_emit_stop_by_name(GTK_OBJECT(button),"clicked");
323 return;
324 }
325 if (get_filename_result) free(get_filename_result);
326 get_filename_result = g_strdup(gtk_file_selection_get_filename(fs));
327 if (inifile_get_gboolean("useGeometry",FALSE)) {
328 c = get_geom(GTK_WINDOW(fs));
329 inifile_set("fileGeometry",c);
330 g_free(c);
331 }
332 }
333 }
334
get_filename_destroy(void)335 static void get_filename_destroy(void)
336 {
337 get_filename_quitflag = TRUE;
338 }
339
get_filename_internal_get_name(void)340 static gchar *get_filename_internal_get_name(void)
341 {
342 return g_strdup(gtk_file_selection_get_filename(get_filename_fs));
343 }
344
get_filename_internal_set_name(gchar * new_name)345 static void get_filename_internal_set_name(gchar *new_name)
346 {
347 gtk_file_selection_set_filename(get_filename_fs,new_name);
348 }
349
get_filename(gchar * current_name,gchar * filemask,gchar * title_text,gboolean savemode,GtkWidget * custom_widget)350 gchar *get_filename(gchar *current_name, gchar *filemask, gchar *title_text,
351 gboolean savemode, GtkWidget *custom_widget)
352 {
353 GtkFileSelection *f;
354 GtkAllocation all;
355 gchar *c;
356
357 get_filename_result=NULL;
358 get_filename_savemode = savemode;
359 f=GTK_FILE_SELECTION(gtk_file_selection_new(title_text));
360 get_filename_fs = f;
361 if (custom_widget != NULL)
362 gtk_box_pack_end(GTK_BOX(GTK_FILE_SELECTION(f)->main_vbox),
363 custom_widget, FALSE, FALSE, 0);
364 c = inifile_get("fileGeometry",NULL);
365 if (c!=NULL && inifile_get_gboolean("useGeometry",FALSE) &&
366 !parse_geom(c,&all)) {
367 gtk_window_set_default_size(GTK_WINDOW(f),all.width,all.height);
368 gtk_widget_set_uposition(GTK_WIDGET(f),all.x,all.y);
369 } else
370 gtk_window_set_position(GTK_WINDOW(f),GTK_WIN_POS_CENTER);
371 if (current_name) gtk_file_selection_set_filename(f,current_name);
372 if (filemask) gtk_file_selection_complete(f,filemask);
373 gtk_signal_connect(GTK_OBJECT(f),"destroy",
374 GTK_SIGNAL_FUNC(get_filename_destroy),NULL);
375 gtk_signal_connect(GTK_OBJECT(f->ok_button),"clicked",
376 GTK_SIGNAL_FUNC(get_filename_callback),f);
377 gtk_signal_connect(GTK_OBJECT(f->cancel_button),"clicked",
378 GTK_SIGNAL_FUNC(get_filename_callback),f);
379 gtk_signal_connect_object(GTK_OBJECT(f->ok_button),"clicked",
380 GTK_SIGNAL_FUNC(gtk_widget_destroy),
381 GTK_OBJECT(f));
382 gtk_signal_connect_object(GTK_OBJECT(f->cancel_button),"clicked",
383 GTK_SIGNAL_FUNC(gtk_widget_destroy),
384 GTK_OBJECT(f));
385 gtk_window_set_modal(GTK_WINDOW(f),TRUE);
386 gtk_widget_show(GTK_WIDGET(f));
387
388 /* gtk_window_maximize(GTK_WINDOW(f)); */
389
390
391 get_filename_quitflag=FALSE;
392 while (!get_filename_quitflag) mainloop();
393 if (get_filename_result != NULL)
394 cleanup_filename(get_filename_result);
395 return get_filename_result;
396 }
397
get_directory_callback(GtkButton * button,gpointer user_data)398 static void get_directory_callback(GtkButton *button, gpointer user_data)
399 {
400 GtkFileSelection *fs = GTK_FILE_SELECTION(user_data);
401 gchar *c;
402 get_filename_result = g_strdup(gtk_file_selection_get_filename(fs));
403 c = strchr(get_filename_result,0);
404 c--;
405 while (c>get_filename_result && *c=='/') {
406 *c = 0;
407 c--;
408 }
409 if (inifile_get_gboolean("useGeometry",FALSE)) {
410 c = get_geom(GTK_WINDOW(fs));
411 inifile_set("dirGeometry",c);
412 g_free(c);
413 }
414 }
415
get_directory(gchar * current_name,gchar * title_text)416 gchar *get_directory(gchar *current_name, gchar *title_text)
417 {
418 GtkFileSelection *f;
419 gchar *c;
420 GtkAllocation all;
421
422 f = GTK_FILE_SELECTION(gtk_file_selection_new(title_text));
423 c = inifile_get("dirGeometry",NULL);
424 if (c!=NULL && inifile_get_gboolean("useGeometry",FALSE) &&
425 !parse_geom(c,&all)) {
426 gtk_window_set_default_size(GTK_WINDOW(f),all.width,all.height);
427 gtk_widget_set_uposition(GTK_WIDGET(f),all.x,all.y);
428 } else
429 gtk_window_set_position(GTK_WINDOW(f),GTK_WIN_POS_CENTER);
430 if (current_name) gtk_file_selection_set_filename(f,current_name);
431 gtk_signal_connect(GTK_OBJECT(f),"destroy",
432 GTK_SIGNAL_FUNC(get_filename_destroy),NULL);
433 gtk_signal_connect(GTK_OBJECT(f->ok_button),"clicked",
434 GTK_SIGNAL_FUNC(get_directory_callback),f);
435 gtk_signal_connect(GTK_OBJECT(f->cancel_button),"clicked",
436 GTK_SIGNAL_FUNC(get_directory_callback),f);
437 gtk_signal_connect_object(GTK_OBJECT(f->ok_button),"clicked",
438 GTK_SIGNAL_FUNC(gtk_widget_destroy),
439 GTK_OBJECT(f));
440 gtk_signal_connect_object(GTK_OBJECT(f->cancel_button),"clicked",
441 GTK_SIGNAL_FUNC(gtk_widget_destroy),
442 GTK_OBJECT(f));
443 gtk_window_set_modal(GTK_WINDOW(f),TRUE);
444 gtk_widget_set_sensitive(GTK_WIDGET(f->file_list),FALSE);
445 gtk_widget_show(GTK_WIDGET(f));
446
447 get_filename_quitflag=FALSE;
448 while (!get_filename_quitflag) mainloop();
449 if (get_filename_result != NULL) cleanup_filename(get_filename_result);
450 return get_filename_result;
451
452 }
453
454 #else
455
456 /* Use the GtkFileChooserDialog */
457
458 static GtkFileChooser *get_filename_fc;
459
460 struct response {
461 gboolean savemode;
462 gboolean responded;
463 gint r;
464 };
465
response(GtkDialog * dialog,gint arg1,gpointer user_data)466 static void response(GtkDialog *dialog, gint arg1, gpointer user_data)
467 {
468 struct response *sr = (struct response *)user_data;
469 gchar *c;
470 if (sr->savemode && arg1 == GTK_RESPONSE_ACCEPT) {
471 c = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
472 if (c != NULL && file_exists(c)) {
473 if (user_message(_("File already exists. Overwrite?"),
474 UM_YESNOCANCEL) != MR_YES)
475 return;
476 }
477 }
478 sr->responded = TRUE;
479 sr->r = arg1;
480 }
481
get_filename_internal_get_name(void)482 static gchar *get_filename_internal_get_name(void)
483 {
484 gchar *c;
485 c = gtk_file_chooser_get_filename(get_filename_fc);
486 if (c == NULL) return g_strdup("");
487 return c;
488 }
489
get_filename_internal_set_name(gchar * new_name)490 static void get_filename_internal_set_name(gchar *new_name)
491 {
492 gchar *c,*d;
493 c = g_filename_to_utf8(new_name,-1,NULL,NULL,NULL);
494 gtk_file_chooser_set_filename(get_filename_fc,c);
495 d = strrchr(c,'/');
496 if (d != NULL && d[1] != 0)
497 gtk_file_chooser_set_current_name(get_filename_fc,d+1);
498 g_free(c);
499 }
500
get_filename_main(gchar * current_name,gchar * title_text,gboolean savemode,GtkFileChooserAction action,gchar * geom_setting,GtkWidget * custom_widget)501 static gchar *get_filename_main(gchar *current_name, gchar *title_text,
502 gboolean savemode,
503 GtkFileChooserAction action,
504 gchar *geom_setting, GtkWidget *custom_widget)
505 {
506 GtkWidget *w;
507 GtkFileChooser *fc;
508 gchar *c,*d;
509 GtkAllocation all;
510 struct response sr = { savemode, FALSE, 0 };
511 if (current_name != NULL)
512 c = g_filename_to_utf8(current_name,-1,NULL,NULL,NULL);
513 else
514 c = NULL;
515 w = gtk_file_chooser_dialog_new(title_text,NULL,
516 action,
517 savemode?GTK_STOCK_SAVE_AS:GTK_STOCK_OPEN,
518 GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,
519 GTK_RESPONSE_CANCEL,NULL);
520 fc = GTK_FILE_CHOOSER(w);
521 get_filename_fc = fc;
522 if (custom_widget != NULL)
523 gtk_file_chooser_set_extra_widget(fc, custom_widget);
524
525 d = inifile_get(geom_setting,NULL);
526 if (d!=NULL && !savemode && inifile_get_gboolean("useGeometry",FALSE) &&
527 !parse_geom(d,&all)) {
528 gtk_window_set_default_size(GTK_WINDOW(w),all.width,all.height);
529 gtk_widget_set_uposition(GTK_WIDGET(w),all.x,all.y);
530 } else
531 gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER);
532 gtk_window_set_modal(GTK_WINDOW(w),TRUE);
533
534 if (c != NULL) {
535 if (c[0] == '/' &&
536 (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
537 file_is_directory(c))) {
538 gtk_file_chooser_set_current_folder(fc,c);
539 } else {
540 gtk_file_chooser_set_filename(fc,c);
541 if (savemode) {
542 d = strrchr(c,'/');
543 if (d != NULL && d[1] != 0)
544 gtk_file_chooser_set_current_name(fc,d+1);
545 }
546 g_free(c);
547 }
548 }
549 gtk_signal_connect(GTK_OBJECT(fc),"response",GTK_SIGNAL_FUNC(response),
550 &sr);
551 gtk_widget_show(w);
552 while (!sr.responded) mainloop();
553 c = NULL;
554 if (sr.r == GTK_RESPONSE_ACCEPT)
555 c = gtk_file_chooser_get_filename(fc);
556 if (sr.r != GTK_RESPONSE_DELETE_EVENT) {
557 if (!savemode && inifile_get_gboolean("useGeometry",FALSE)) {
558 d = get_geom(GTK_WINDOW(w));
559 inifile_set(geom_setting,d);
560 g_free(d);
561 }
562 gtk_widget_destroy(w);
563 }
564 if (c != NULL) cleanup_filename(c);
565 return c;
566 }
567
get_filename(gchar * current_name,gchar * filemask,gchar * title_text,gboolean savemode,GtkWidget * custom_widget)568 gchar *get_filename(gchar *current_name, gchar *filemask, gchar *title_text,
569 gboolean savemode, GtkWidget *custom_widget)
570 {
571 return get_filename_main(current_name,title_text,savemode,
572 savemode?GTK_FILE_CHOOSER_ACTION_SAVE:
573 GTK_FILE_CHOOSER_ACTION_OPEN,"fileGeometry",
574 custom_widget);
575 }
576
get_directory(gchar * current_name,gchar * title_text)577 gchar *get_directory(gchar *current_name, gchar *title_text)
578 {
579 return get_filename_main(current_name,title_text,FALSE,
580 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
581 "dirGeometry",NULL);
582 }
583
584 #endif
585
get_filename_modify_extension(gchar * new_extension)586 void get_filename_modify_extension(gchar *new_extension)
587 {
588 gchar *c,*d,*e,*f;
589 c = get_filename_internal_get_name();
590 d = strrchr(c,'.');
591 e = strrchr(c,'/');
592 if (d != NULL && (e == NULL || e < d))
593 *d = 0;
594 if (c[0] != 0 && (e == NULL || e[1] != 0)) {
595 /* printf("%s\n",c); */
596 f = g_strdup_printf("%s%s",c,new_extension);
597 get_filename_internal_set_name(f);
598 g_free(f);
599 }
600 g_free(c);
601 }
602
e_copydata(EFILE * from,EFILE * to,off_t bytes)603 gboolean e_copydata(EFILE *from, EFILE *to, off_t bytes)
604 {
605 off_t count;
606 size_t rest;
607 guint8 buf[4096];
608 count = bytes / sizeof(buf);
609 rest = bytes % sizeof(buf);
610 for (; count>0; count--)
611 if (e_fread(buf,sizeof(buf),from) ||
612 e_fwrite(buf,sizeof(buf),to)) return TRUE;
613 if (rest>0)
614 return (e_fread(buf,rest,from) ||
615 e_fwrite(buf,rest,to));
616 else
617 return FALSE;
618 }
619
errdlg_filesize(gchar * filename)620 off_t errdlg_filesize(gchar *filename)
621 {
622 EFILE *f;
623 off_t r;
624
625 f = e_fopen(filename,EFILE_READ);
626 if (f == NULL) return -1;
627 if (e_fseek(f,0,SEEK_END)) { e_fclose(f); return -1; }
628 r = e_ftell(f);
629 e_fclose(f);
630 return r;
631 }
632
errdlg_copyfile(gchar * from,gchar * to)633 gboolean errdlg_copyfile(gchar *from, gchar *to)
634 {
635 off_t l;
636 EFILE *in, *out;
637 gboolean b;
638 l = errdlg_filesize ( from );
639 if ( l == -1 ) return TRUE;
640 in = e_fopen(from,EFILE_READ);
641 if (!in) return TRUE;
642 out = e_fopen(to,EFILE_WRITE);
643 if (!out) { e_fclose(in); return TRUE; }
644 b = e_copydata(in,out,l);
645 e_fclose(in);
646 if (b) e_fclose_remove(out);
647 else e_fclose(out);
648 return b;
649 }
650
file_exists(char * filename)651 gboolean file_exists(char *filename)
652 {
653 int i;
654 struct stat ss;
655 i = stat(filename,&ss);
656 if (i && errno==ENOENT) return FALSE;
657 return TRUE;
658 }
659
program_exists(char * progname)660 gboolean program_exists(char *progname)
661 {
662 gchar *c,*d,*e;
663 c = getenv("PATH");
664 if (c == NULL) c="/bin:/usr/bin";
665 c = g_strdup(c);
666 for (d=strtok(c,":"); d!=NULL; d=strtok(NULL,":")) {
667 e = g_strdup_printf("%s/%s",d,progname);
668 if (file_exists(e)) {
669 g_free(e);
670 g_free(c);
671 return TRUE;
672 }
673 g_free(e);
674 }
675 g_free(c);
676 return FALSE;
677 }
678
file_is_normal(char * filename)679 gboolean file_is_normal(char *filename)
680 {
681 struct stat s;
682 int i;
683 i = stat(filename,&s);
684 return (i==0 && S_ISREG(s.st_mode));
685 }
686
file_is_directory(char * filename)687 gboolean file_is_directory(char *filename)
688 {
689 struct stat s;
690 int i;
691 i = stat(filename,&s);
692 return (i==0 && S_ISDIR(s.st_mode));
693 }
694
e_fgetc(EFILE * stream)695 static int e_fgetc(EFILE *stream)
696 {
697 unsigned char c;
698 ssize_t i;
699 gchar *m;
700 while (1) {
701 i = read(stream->fd,&c,1);
702 if (i == 0) return -1;
703 if (i == -1) {
704 if (errno == EINTR) continue;
705 m = g_strdup_printf(_("Error reading from %s: %s"),
706 stream->filename,strerror(errno));
707 user_error(m);
708 g_free(m);
709 return -1;
710 }
711 return (int)c;
712 }
713 }
714
e_readline(gchar ** line,size_t * size,EFILE * stream)715 long int e_readline(gchar **line, size_t *size, EFILE *stream)
716 {
717 size_t s = 0;
718 int c;
719 while (1) {
720 if (s == *size) {
721 *size = *size ? *size * 2 : 32;
722 *line = g_realloc(*line, *size);
723 }
724 c = e_fgetc(stream);
725 if (c==EOF || (c=='\n' && s>0)) { (*line)[s]=0; return s; }
726 if (c=='\n') return e_readline(line,size,stream);
727 (*line)[s] = (gchar)c;
728 s++;
729 }
730 }
731
xunlink(gchar * filename)732 gboolean xunlink(gchar *filename)
733 {
734 gchar *c;
735
736 if (unlink(filename) == -1 && errno != ENOENT) {
737 c = g_strdup_printf(_("Could not remove '%s': %s"),filename,
738 strerror(errno));
739 user_error(c);
740 g_free(c);
741 return TRUE;
742 }
743 return FALSE;
744 }
745
xrename(gchar * oldname,gchar * newname,gboolean allow_copy)746 gint xrename(gchar *oldname, gchar *newname, gboolean allow_copy)
747 {
748 gchar *c;
749
750 g_assert(strcmp(oldname,newname) != 0);
751
752 if (rename(oldname,newname) == 0) return 0;
753 if (errno == EXDEV) {
754 if (allow_copy) return errdlg_copyfile(oldname,newname)?1:0;
755 else return 2;
756 } else {
757 c = g_strdup_printf(_("Error creating link to '%s': %s"),oldname,
758 strerror(errno));
759 user_error(c);
760 g_free(c);
761 return 1;
762 }
763 }
764
make_filename_rooted(gchar * name)765 gchar *make_filename_rooted(gchar *name)
766 {
767 gchar *c,*d;
768 if (name[0] == '/' || name[0] == 0) return g_strdup(name);
769 c = g_get_current_dir();
770 d = g_strdup_printf("%s/%s",c,name);
771 g_free(c);
772 cleanup_filename(d);
773 return d;
774 }
775
fd_canwrite(int fd)776 gboolean fd_canwrite(int fd)
777 {
778 fd_set set;
779 struct timeval tv = {};
780 int i;
781 FD_ZERO(&set);
782 FD_SET(fd,&set);
783 i = select(fd+1,NULL,&set,NULL,&tv);
784 if (i == 0) return FALSE;
785 else return TRUE;
786 }
787
fd_canread(int fd)788 gboolean fd_canread(int fd)
789 {
790 fd_set set;
791 struct timeval tv = {};
792 int i;
793 FD_ZERO(&set);
794 FD_SET(fd,&set);
795 i = select(fd+1,&set,NULL,NULL,&tv);
796 if (i == 0) return FALSE;
797 else return TRUE;
798 }
799
e_fread_u16_xe(guint16 * data,EFILE * stream,gboolean be)800 gboolean e_fread_u16_xe(guint16 *data, EFILE *stream, gboolean be)
801 {
802 unsigned char buf[2];
803 guint16 i;
804 if (e_fread(buf,2,stream)) return TRUE;
805 if (be) {
806 i=buf[0];
807 i<<=8; i|=buf[1];
808 } else {
809 i=buf[1];
810 i<<=8; i|=buf[0];
811 }
812 *data = i;
813 return FALSE;
814 }
815
e_fread_u32_xe(guint32 * data,EFILE * stream,gboolean be)816 gboolean e_fread_u32_xe(guint32 *data, EFILE *stream, gboolean be)
817 {
818 unsigned char buf[4];
819 guint32 i;
820 if (e_fread(buf,4,stream)) return TRUE;
821 if (be) {
822 i=buf[0];
823 i<<=8; i|=buf[1];
824 i<<=8; i|=buf[2];
825 i<<=8; i|=buf[3];
826 } else {
827 i=buf[3];
828 i<<=8; i|=buf[2];
829 i<<=8; i|=buf[1];
830 i<<=8; i|=buf[0];
831 }
832 *data = i;
833 return FALSE;
834 }
835