1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2
3 /*
4 * GImageView
5 * Copyright (C) 2001 Takuro Ashie
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program 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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * $Id: gfileutil.c,v 1.43 2004/09/21 08:44:31 makeinu Exp $
22 */
23
24 #include <gtk/gtk.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <utime.h>
32
33 #include "charset.h"
34 #include "fileutil.h"
35 #include "fr-archive.h"
36 #include "gfileutil.h"
37 #include "gimv_comment.h"
38 #include "gimv_image.h"
39 #include "gimv_thumb.h"
40 #include "gimv_thumb_cache.h"
41 #include "gtkutils.h"
42 #include "intl.h"
43 #include "prefs.h"
44
45 #ifndef BUF_SIZE
46 #define BUF_SIZE 4096
47 #endif
48
49 #ifndef MAX_PATH_LEN
50 #define MAX_PATH_LEN 1024
51 #endif
52
53
54 gchar *
add_slash(const gchar * path)55 add_slash (const gchar *path)
56 {
57 g_return_val_if_fail (path, NULL);
58
59 if (!*path) return g_strdup ("/");
60
61 if (path [strlen (path) - 1] == '/')
62 return g_strdup (path);
63 else
64 return g_strconcat (path, "/", NULL);
65 }
66
67
68 gchar *
remove_slash(const gchar * path)69 remove_slash (const gchar *path)
70 {
71 g_return_val_if_fail (path, NULL);
72 g_return_val_if_fail (*path, g_strdup (path));
73
74 if (path[strlen (path) - 1] == '/')
75 return g_dirname (path);
76 else
77 return g_strdup (path);
78 }
79
80
81 gboolean getting_dir = FALSE;
82 gboolean stop_getting_dir = FALSE;
83 static gchar* tmpdir = NULL;
84
85
86 gchar *
get_temp_dir_name(void)87 get_temp_dir_name (void)
88 {
89 if (tmpdir) return tmpdir;
90
91 tmpdir = g_strdup_printf ("%s%s.%d",
92 g_get_tmp_dir (),
93 "/gimv",
94 getpid ());
95 return tmpdir;
96 }
97
98
99 void
remove_dir(const gchar * dirname)100 remove_dir (const gchar *dirname)
101 {
102 GList *node, *list;
103
104 if (!isdir(dirname)) return;
105
106 list = get_dir_all (dirname);
107
108 for (node = list; node; node = g_list_next (node))
109 remove (node->data);
110
111 if (list) {
112 remove (dirname);
113 g_list_foreach (list, (GFunc) g_free, NULL);
114 g_list_free (list);
115 }
116 }
117
118
119 void
remove_temp_dir(void)120 remove_temp_dir (void)
121 {
122 if (!tmpdir) return;
123
124 remove_dir (tmpdir);
125
126 g_free (tmpdir);
127 tmpdir = NULL;
128 }
129
130
131 /*
132 * get_dir:
133 * @ Get image files in specified directory.
134 *
135 * dirname : Directory to scan.
136 * files : Pointer to OpenFiles struct for store directory list.
137 */
138 void
get_dir(const gchar * dirname,GetDirFlags flags,GList ** filelist_ret,GList ** dirlist_ret)139 get_dir (const gchar *dirname, GetDirFlags flags,
140 GList **filelist_ret, GList **dirlist_ret)
141 {
142 DIR *dp;
143 struct dirent *entry;
144 gchar buf[MAX_PATH_LEN], *path;
145 GList *filelist = NULL, *dirlist = NULL, *list;
146
147 g_return_if_fail (dirname && *dirname);
148
149 getting_dir = TRUE;
150
151 if (flags & GETDIR_DISP_STDERR)
152 fprintf (stderr, _("scandir = %s\n"), dirname);
153 else if (flags & GETDIR_DISP_STDOUT)
154 fprintf (stdout, _("scandir = %s\n"), dirname);
155
156 if ((dp = opendir (dirname))) {
157 while ((entry = readdir (dp))) {
158 if (flags & GETDIR_ENABLE_CANCEL) {
159 while (gtk_events_pending()) gtk_main_iteration();
160 if (stop_getting_dir) break;
161 }
162
163 /* ignore dot file */
164 if (!(flags & GETDIR_READ_DOT) && entry->d_name[0] == '.')
165 continue;
166
167 /* get full path */
168 if (dirname [strlen (dirname) - 1] == '/')
169 g_snprintf (buf, MAX_PATH_LEN, "%s%s", dirname, entry->d_name);
170 else
171 g_snprintf (buf, MAX_PATH_LEN, "%s/%s", dirname, entry->d_name);
172
173 /* if path is file */
174 if (!isdir (buf) || (!(flags & GETDIR_FOLLOW_SYMLINK) && islink (buf))) {
175 if (!filelist_ret) continue;
176
177 if (!(flags & GETDIR_DETECT_EXT)
178 || gimv_image_detect_type_by_ext (buf)
179 || ((flags & GETDIR_GET_ARCHIVE)
180 && fr_archive_utils_get_file_name_ext (buf)))
181 {
182 path = g_strdup (buf);
183
184 if (flags & GETDIR_DISP_STDERR)
185 fprintf (stderr, _("filename = %s\n"), path);
186 else if (flags & GETDIR_DISP_STDOUT)
187 fprintf (stdout, _("filename = %s\n"), path);
188
189 filelist = g_list_append (filelist, path);
190 }
191
192 /* if path is dir */
193 } else if (isdir(buf)) {
194 if (dirlist_ret && strcmp(entry->d_name, ".")
195 && strcmp(entry->d_name, ".."))
196 {
197 path = g_strdup (buf);
198
199 if (flags & GETDIR_DISP_STDERR)
200 fprintf (stderr, _("dirname = %s\n"), path);
201 else if (flags & GETDIR_DISP_STDOUT)
202 fprintf (stdout, _("dirname = %s\n"), path);
203
204 dirlist = g_list_append (dirlist, path);
205 }
206 }
207 }
208 closedir (dp);
209 if (filelist)
210 filelist = g_list_sort (filelist, gtkutil_comp_spel);
211 if (dirlist)
212 dirlist = g_list_sort (dirlist, gtkutil_comp_spel);
213 } else {
214 g_warning ("cannot open directory: %s", dirname);
215 }
216
217 /* recursive get */
218 if (flags & GETDIR_RECURSIVE) {
219 GList *tmplist = g_list_copy (dirlist);
220 gint tmp_flags = flags | GETDIR_RECURSIVE_IS_BRANCH;
221
222 list = tmplist;
223 while (list) {
224 GList *tmp_filelist = NULL, *tmp_dirlist = NULL;
225 if (flags & GETDIR_ENABLE_CANCEL) {
226 while (gtk_events_pending()) gtk_main_iteration();
227 if (stop_getting_dir) break;
228 }
229 get_dir ((const gchar *) list->data, tmp_flags,
230 &tmp_filelist, &tmp_dirlist);
231 filelist = g_list_concat (filelist, tmp_filelist);
232 dirlist = g_list_concat (dirlist, tmp_dirlist);
233 list = g_list_next (list);
234 }
235 g_list_free (tmplist);
236 }
237
238 /* return value */
239 if (filelist_ret)
240 *filelist_ret = filelist;
241 if (dirlist_ret)
242 *dirlist_ret = dirlist;
243
244 if (!(flags & GETDIR_RECURSIVE_IS_BRANCH)) {
245 getting_dir = FALSE;
246 stop_getting_dir = FALSE;
247 }
248 }
249
250
251 void
get_dir_stop(void)252 get_dir_stop (void)
253 {
254 if (getting_dir)
255 stop_getting_dir = TRUE;
256 }
257
258
259 /*
260 * get_dir_all:
261 * @
262 *
263 * dirname :
264 * Return :
265 */
266 GList *
get_dir_all(const gchar * dirname)267 get_dir_all (const gchar *dirname)
268 {
269 GList *filelist, *dirlist, *sub_dirlist, *node;
270 gchar *sub_dirname;
271
272 get_dir (dirname, GETDIR_READ_DOT, &filelist, &dirlist);
273
274 if (dirlist) {
275 node = dirlist;
276 while (node) {
277 sub_dirname = node->data;
278 sub_dirlist = get_dir_all (sub_dirname);
279 if (sub_dirlist)
280 filelist = g_list_concat (sub_dirlist, filelist);
281 node = g_list_next (node);
282 }
283 filelist = g_list_concat (filelist, dirlist);
284 }
285 return filelist;
286 }
287
288
289 /*
290 * get_dir_all_file:
291 * @
292 *
293 * dirname :
294 * Return :
295 */
296 static GList *
get_dir_all_file(const gchar * dirname)297 get_dir_all_file (const gchar *dirname)
298 {
299 GList *filelist, *dirlist, *sub_dirlist, *node;
300 gchar *sub_dirname;
301
302 get_dir (dirname, GETDIR_READ_DOT, &filelist, &dirlist);
303
304 if (dirlist) {
305 node = dirlist;
306 while (node) {
307 sub_dirname = node->data;
308 sub_dirlist = get_dir_all_file (sub_dirname);
309 if (sub_dirlist)
310 filelist = g_list_concat (sub_dirlist, filelist);
311 node = g_list_next (node);
312 }
313 }
314 return filelist;
315 }
316
317
318 /*
319 * merge from misc/misc.c in Text maid (Copyright(C) Kazuki Iwamoto).
320 */
321 gchar *
relpath2abs(const gchar * path)322 relpath2abs (const gchar *path)
323 {
324 gchar *dir, *dest;
325 gint i,j,len;
326
327 g_return_val_if_fail (path && *path, NULL);
328
329 if (path[0] != '/') {
330 dir = g_get_current_dir ();
331 dest = g_strjoin ("/", dir, path, NULL);
332 g_free (dir);
333 } else {
334 dest = g_strdup (path);
335 }
336
337 len = strlen (dest) + 1;
338 i = 0;
339 while (i < len - 2) {
340 if (dest[i] == '/' && dest[i + 1] == '.'
341 && (dest[i + 2] == '/' || dest[i + 2] == '\0'))
342 {
343 len -= 2;
344 memmove (dest + i, dest + i + 2, len - i);
345 }
346
347 i++;
348 }
349
350 i = 0;
351 while (i < len - 3) {
352 if (dest[i] == '/' && dest[i + 1] == '.' && dest[i + 2] == '.'
353 && (dest[i + 3] == '/' || dest[i + 3] == '\0'))
354 {
355 len -= 3;
356 memmove (dest + i, dest + i + 3, len - i);
357 for (j = i - 1; j >= 0; j--) {
358 if (dest[j] == '/')
359 break;
360 }
361 if (j >= 0) {
362 memmove (dest + j, dest + i, len - i);
363 len -= i - j;
364 i = j;
365 }
366 }
367
368 i++;
369 }
370
371 return dest;
372 }
373
374
375 gchar *
link2abs(const gchar * path)376 link2abs (const gchar *path)
377 {
378 gchar *retval = NULL, **dirs, buf[MAX_PATH_LEN], *tmpstr;
379 gint i, num;
380
381 g_return_val_if_fail (path && *path, NULL);
382 g_return_val_if_fail (path[0] == '/', g_strdup (path));
383
384 if (!strcmp (path, "/")) return g_strdup (path);
385
386 dirs = g_strsplit (path, "/", -1);
387 g_return_val_if_fail (dirs, g_strdup (path));
388
389 retval = g_strdup("");
390 for (i = 0; dirs[i]; i++) {
391 gchar *endchr;
392
393 if (!*dirs[i]) continue;
394
395 tmpstr = g_strconcat (retval, "/", dirs[i], NULL);
396 g_free (retval);
397 retval = tmpstr;
398
399 num = readlink (retval, buf, MAX_PATH_LEN);
400 if (num < 1) continue;
401
402 buf[num] = '\0';
403 if (buf[0] == '/') {
404 g_free (retval);
405 retval = g_strdup (buf);
406 } else {
407 endchr = strrchr (retval, '/');
408 if (!endchr) {
409 g_free (retval);
410 retval = g_strdup (path);
411 break;
412 }
413 *endchr = '\0';
414 /* FIXME: what about link to link? */
415 tmpstr = g_strconcat (retval, "/", buf, NULL);
416 g_free (retval);
417 retval = tmpstr;
418 }
419 }
420
421 g_strfreev (dirs);
422
423 if (!retval) {
424 g_warning ("invalid link: %s\n", path);
425 } else {
426 tmpstr = relpath2abs (retval);
427 g_free (retval);
428 retval = tmpstr;
429 }
430
431 return retval;
432 }
433
434
435 static gboolean
move_file_check_path(const gchar * from_path,struct stat * from_st,const gchar * dir,gboolean show_error,GtkWindow * window)436 move_file_check_path (const gchar *from_path,
437 struct stat *from_st,
438 const gchar *dir,
439 gboolean show_error,
440 GtkWindow *window)
441 {
442 gchar *from_dir, error_message[BUF_SIZE];
443 gchar *from_path_internal, *dir_internal;
444 gboolean retval = FALSE;
445
446 from_path_internal = charset_to_internal (from_path,
447 conf.charset_filename,
448 conf.charset_auto_detect_fn,
449 conf.charset_filename_mode);
450 dir_internal = charset_to_internal (dir,
451 conf.charset_filename,
452 conf.charset_auto_detect_fn,
453 conf.charset_filename_mode);
454
455 /********************
456 * check source file
457 ********************/
458 if (lstat (from_path, from_st)) {
459 if (show_error) {
460 g_snprintf (error_message, BUF_SIZE,
461 _("Can't find source file :\n%s"),
462 from_path_internal);
463 gtkutil_message_dialog (_("Error!!"), error_message, window);
464 }
465 goto ERROR;
466 }
467
468 /*****************
469 * check dest dir
470 *****************/
471 if (!iswritable (dir)) {
472 if (show_error) {
473 g_snprintf (error_message, BUF_SIZE,
474 _("Can't move file : %s\n"
475 "Permission denied: %s\n"),
476 from_path_internal, dir_internal);
477 gtkutil_message_dialog (_("Error!!"), error_message, window);
478 }
479 goto ERROR;
480 }
481
482 /*******************
483 * check source dir
484 *******************/
485 from_dir = g_dirname (from_path);
486 if (!iswritable (from_dir)) {
487 if (show_error) {
488 gchar *from_dir_internal;
489
490 from_dir_internal = charset_to_internal (from_dir,
491 conf.charset_filename,
492 conf.charset_auto_detect_fn,
493 conf.charset_filename_mode);
494
495 g_snprintf (error_message, BUF_SIZE,
496 _("Can't move file : %s\n"
497 "Permission denied: %s\n"),
498 from_path_internal, from_dir_internal);
499 gtkutil_message_dialog (_("Error!!"), error_message, window);
500
501 g_free (from_dir_internal);
502 }
503 g_free (from_dir);
504 goto ERROR;
505 }
506 g_free (from_dir);
507
508 retval = TRUE;
509
510 ERROR:
511 g_free (from_path_internal);
512 g_free (dir_internal);
513 return retval;
514 }
515
516
517 static gboolean
move_file_check_over_write(const gchar * from_path,struct stat * from_st,const gchar * to_path,struct stat * to_st,gchar * new_path,gint new_path_len,ConfirmType * action,gboolean show_error,GtkWindow * window)518 move_file_check_over_write (const gchar *from_path,
519 struct stat *from_st,
520 const gchar *to_path,
521 struct stat *to_st,
522 gchar *new_path, gint new_path_len,
523 ConfirmType *action,
524 gboolean show_error,
525 GtkWindow *window)
526 {
527 gchar error_message[BUF_SIZE], *to_path_internal;
528 gint exist;
529 gboolean retval = FALSE;
530
531 if (new_path)
532 new_path[0] = '\0';
533
534 to_path_internal = charset_to_internal (to_path,
535 conf.charset_filename,
536 conf.charset_auto_detect_fn,
537 conf.charset_filename_mode);
538
539 exist = !lstat(to_path, to_st);
540 if (exist && (!strcmp (from_path, to_path)
541 || from_st->st_ino == to_st->st_ino))
542 {
543 if (show_error) {
544 g_snprintf (error_message, BUF_SIZE,
545 _("Same file :\n%s"), to_path_internal);
546 gtkutil_message_dialog (_("Error!!"), error_message, window);
547 }
548 goto ERROR;
549
550 } else if (exist && *action == CONFIRM_ASK) {
551 if (isdir (from_path)) {
552 g_snprintf (error_message, BUF_SIZE,
553 _("File exist : %s"), to_path_internal);
554 gtkutil_message_dialog (_("ERROR!!"), error_message, window);
555
556 } else {
557 g_snprintf (error_message, BUF_SIZE,
558 _("The file exists : %s\n"
559 "Overwrite?"),
560 to_path_internal);
561 *action = gtkutil_overwrite_confirm_dialog (_("File exist!!"), error_message,
562 to_path, from_path,
563 new_path, MAX_PATH_LEN,
564 ConfirmDialogMultipleFlag,
565 window);
566 }
567 }
568
569 if (new_path && *new_path) {
570 retval = TRUE;
571 } else {
572 switch (*action) {
573 case CONFIRM_YES:
574 case CONFIRM_YES_TO_ALL:
575 retval = TRUE;
576 break;
577 case CONFIRM_NO:
578 case CONFIRM_CANCEL:
579 retval = FALSE;
580 break;
581 case CONFIRM_NO_TO_ALL:
582 if (exist)
583 retval = FALSE;
584 else
585 retval = TRUE;
586 break;
587 default:
588 if (!exist)
589 retval = TRUE;
590 else
591 retval = FALSE;
592 break;
593 }
594 }
595
596 ERROR:
597 g_free (to_path_internal);
598 return retval;
599 }
600
601
602 /*
603 * move_file:
604 * @
605 *
606 * from_path :
607 * dir :
608 * action :
609 * show_error :
610 * Return : TRUE if success to move file.
611 */
612 gboolean
move_file(const gchar * from_path,const gchar * dir,ConfirmType * action,gboolean show_error,GtkWindow * window)613 move_file (const gchar *from_path, const gchar *dir,
614 ConfirmType *action, gboolean show_error,
615 GtkWindow *window)
616 {
617 gchar *to_path, error_message[BUF_SIZE];
618 struct stat from_st, to_st, todir_st;
619 struct utimbuf ut;
620 gboolean move_file = FALSE, move_faild = FALSE, copy_success = FALSE, retval;
621 gchar *from_path_internal, *to_path_internal, new_path[MAX_PATH_LEN];
622
623 new_path[0] = '\0';
624
625 g_return_val_if_fail (action, FALSE);
626
627 retval = move_file_check_path (from_path, &from_st, dir, show_error, window);
628 if (!retval) return FALSE;
629
630 /* set dest path */
631 to_path = g_strconcat (dir, g_basename (from_path), NULL);
632
633 move_file = move_file_check_over_write (from_path, &from_st,
634 to_path, &to_st,
635 new_path, MAX_PATH_LEN,
636 action, show_error,
637 window);
638 if (!move_file) {
639 retval = FALSE;
640 goto ERROR0;
641 }
642
643 from_path_internal = charset_to_internal (from_path,
644 conf.charset_filename,
645 conf.charset_auto_detect_fn,
646 conf.charset_filename_mode);
647 if (*new_path) {
648 g_free (to_path);
649 to_path = g_strdup (new_path);
650 }
651 to_path_internal = charset_to_internal (to_path,
652 conf.charset_filename,
653 conf.charset_auto_detect_fn,
654 conf.charset_filename_mode);
655
656 /**************
657 * move file!!
658 **************/
659 stat (dir, &todir_st);
660 if (from_st.st_dev != todir_st.st_dev) {
661 copy_success = copy_file_to_file (from_path, to_path, action, show_error,
662 window);
663 if (copy_success) {
664 /* reset new file's time info */
665 ut.actime = from_st.st_atime;
666 ut.modtime = from_st.st_mtime;
667 utime(to_path, &ut);
668
669 /* remove old file */
670 if (remove (from_path) < 0) { /* faild to remove file */
671 if (show_error) {
672 g_snprintf (error_message, BUF_SIZE,
673 _("Faild to remove file :\n"
674 "%s"),
675 from_path_internal);
676 gtkutil_message_dialog (_("Error!!"), error_message, window);
677 }
678 retval = FALSE;
679 goto ERROR1;
680 }
681 } else {
682 move_faild = TRUE;
683 }
684 } else {
685 move_faild = rename (from_path, to_path);
686 }
687
688 /************************
689 * if faild to move file
690 ************************/
691 if (move_faild) {
692 if (show_error) {
693 g_snprintf (error_message, BUF_SIZE,
694 _("Faild to move file :\n"
695 "From : %s\n"
696 "To : %s"),
697 from_path_internal, to_path_internal);
698 gtkutil_message_dialog (_("Error!!"), error_message, window);
699 }
700 retval = FALSE;
701 }
702
703 ERROR1:
704 g_free (from_path_internal);
705 g_free (to_path_internal);
706 ERROR0:
707 g_free (to_path);
708 return retval;
709 }
710
711
712 static gboolean
copy_dir_check_source(const gchar * from_dir,gboolean show_error,GtkWindow * window)713 copy_dir_check_source (const gchar *from_dir, gboolean show_error,
714 GtkWindow *window)
715 {
716 gchar error_message[BUF_SIZE], *from_dir_internal;
717 gboolean retval = TRUE;
718
719 from_dir_internal = charset_to_internal (from_dir,
720 conf.charset_filename,
721 conf.charset_auto_detect_fn,
722 conf.charset_filename_mode);
723
724 if (islink (from_dir)) { /* check path is link or not */
725 if (show_error) {
726 g_snprintf (error_message, BUF_SIZE,
727 _("%s is link!!.\n"),
728 from_dir_internal);
729 gtkutil_message_dialog (_("Error!!"), error_message, window);
730 }
731 retval = FALSE;
732 goto ERROR;
733 }
734
735 if (!file_exists (from_dir)) { /* check path exists or not */
736 if (show_error) {
737 g_snprintf (error_message, BUF_SIZE,
738 _("Can't find source file :\n%s"),
739 from_dir_internal);
740 gtkutil_message_dialog (_("Error!!"), error_message, window);
741 }
742 retval = FALSE;
743 goto ERROR;
744 }
745
746 if (!isdir (from_dir)) { /* check path is directory or not */
747 if (show_error) {
748 g_snprintf (error_message, BUF_SIZE,
749 _("%s is not directory!!.\n"),
750 from_dir_internal);
751 gtkutil_message_dialog (_("Error!!"), error_message, window);
752 }
753 retval = FALSE;
754 goto ERROR;
755 }
756
757 ERROR:
758 g_free (from_dir_internal);
759 return TRUE;
760 }
761
762
763 static gboolean
copy_dir_check_dest(const gchar * from_path,const gchar * dirname,const gchar * to_dir,gboolean show_error,GtkWindow * window)764 copy_dir_check_dest (const gchar *from_path, const gchar *dirname,
765 const gchar *to_dir, gboolean show_error,
766 GtkWindow *window)
767 {
768 gchar error_message[BUF_SIZE];
769 gchar *from_path_internal, *dirname_internal, *to_dir_internal;
770 gboolean retval = TRUE;
771
772 from_path_internal = charset_to_internal (from_path,
773 conf.charset_filename,
774 conf.charset_auto_detect_fn,
775 conf.charset_filename_mode);
776 dirname_internal = charset_to_internal (dirname,
777 conf.charset_filename,
778 conf.charset_auto_detect_fn,
779 conf.charset_filename_mode);
780 to_dir_internal = charset_to_internal (to_dir,
781 conf.charset_filename,
782 conf.charset_auto_detect_fn,
783 conf.charset_filename_mode);
784
785 if (!iswritable (dirname)) { /* check permission */
786 if (show_error) {
787 g_snprintf (error_message, BUF_SIZE,
788 _("Can't copy directory : %s\n"
789 "Permission denied: %s\n"),
790 from_path_internal,
791 dirname_internal);
792 gtkutil_message_dialog (_("Error!!"), error_message, window);
793 }
794 retval = FALSE;
795 goto ERROR;
796 }
797
798 if (file_exists (to_dir)) { /* check dest path */
799 if (show_error) {
800 g_snprintf (error_message, BUF_SIZE,
801 _("File exists!! : %s\n"),
802 to_dir_internal);
803 gtkutil_message_dialog (_("Error!!"), error_message, window);
804 }
805 retval = FALSE;
806 goto ERROR;
807 }
808
809 ERROR:
810 g_free (from_path_internal);
811 g_free (dirname_internal);
812 g_free (to_dir_internal);
813
814 return retval;
815 }
816
817
818 /*
819 * copy_dir:
820 * @
821 *
822 * from_path :
823 * dir :
824 * action :
825 * show_error :
826 * Return : TRUE if success to copy directory.
827 */
828 static gboolean
copy_dir(const gchar * from_path,const gchar * dir,ConfirmType * action,gboolean show_error,GtkWindow * window)829 copy_dir (const gchar *from_path, const gchar *dir,
830 ConfirmType *action, gboolean show_error,
831 GtkWindow *window)
832 {
833 GtkWidget *progress_win;
834 gchar message[BUF_SIZE];
835 GList *filelist, *node;
836 gchar *from_dir, *to_dir, *to_path, *dirname;
837 ConfirmType confirm;
838 gboolean result, cancel = FALSE;
839 gfloat progress;
840 gint pos, length;
841
842 from_dir = g_strdup (from_path);
843 if (from_dir[strlen (from_dir) - 1] == '/')
844 from_dir[strlen (from_dir) - 1] = '\0';
845
846 dirname = g_strdup (dir);
847 if (dirname[strlen (dirname) - 1] == '/')
848 dirname[strlen (dirname) - 1] = '\0';
849
850 to_dir = g_strconcat (dirname, "/", g_basename (from_dir), NULL);
851
852 /*******************
853 * check source dir
854 *******************/
855 result = copy_dir_check_source (from_dir, show_error, window);
856 if (!result) goto ERROR;
857
858 /*****************
859 * check dest dir
860 *****************/
861 result = copy_dir_check_dest (from_path, dirname, to_dir, show_error, window);
862 g_free (dirname);
863 if (!result) goto ERROR;
864
865
866 /****************
867 * do copy files
868 ****************/
869 filelist = node = get_dir_all_file (from_path);
870 confirm = CONFIRM_YES_TO_ALL;
871
872 progress_win = gtkutil_create_progress_window (_("Copy directory"), "...",
873 &cancel, 300, -1, window);
874 gtk_grab_add (progress_win);
875 length = g_list_length (filelist);
876
877 while (node) {
878 guint len;
879 gchar *filename = node->data;
880 gchar *tmpstr;
881
882 while (gtk_events_pending()) gtk_main_iteration();
883
884 pos = g_list_position (filelist, node);
885 progress = (gfloat) pos / (gfloat) length;
886
887 { /********** convert charset **********/
888 gchar *filename_internal;
889
890 filename_internal = charset_to_internal (filename,
891 conf.charset_filename,
892 conf.charset_auto_detect_fn,
893 conf.charset_filename_mode);
894
895 g_snprintf (message, BUF_SIZE, _("Copying %s ..."),
896 filename_internal);
897
898 g_free (filename_internal);
899 }
900
901 gtkutil_progress_window_update (progress_win, _("Copying directory"),
902 message, NULL, progress);
903
904 len = strlen (from_path);
905
906 if (strlen (filename) > len) {
907 tmpstr = filename + len;
908 if (tmpstr[0] == '/') tmpstr++;
909 to_path = g_strconcat (to_dir, "/", tmpstr, NULL);
910
911 /* realy do copy :-) */
912 mkdirs (to_path);
913 copy_file_to_file (filename, to_path, &confirm, show_error, window);
914
915 g_free (to_path);
916 }
917
918 node = g_list_next (node);
919 }
920
921 gtk_grab_remove (progress_win);
922 gtk_widget_destroy (progress_win);
923
924 g_list_foreach (filelist, (GFunc) g_free, NULL);
925 g_list_free (filelist);
926
927 g_free (from_dir);
928 g_free (to_dir);
929
930 return TRUE;
931
932 ERROR:
933 g_free (from_dir);
934 g_free (to_dir);
935 return FALSE;
936 }
937
938
939 /*
940 * copy_file_to_file:
941 * @
942 *
943 * from_path :
944 * to_path :
945 * action :
946 * show_error :
947 * Return : TRUE if success to copy file.
948 */
949 gboolean
copy_file_to_file(const gchar * from_path,const gchar * to_path,ConfirmType * action,gboolean show_error,GtkWindow * window)950 copy_file_to_file (const gchar *from_path, const gchar *to_path,
951 ConfirmType *action, gboolean show_error,
952 GtkWindow *window)
953 {
954 gint b;
955 gchar buf[BUFSIZ], *from_path_internal, *to_path_internal;
956 gchar error_message[BUF_SIZE];
957 FILE *from, *to;
958 struct stat from_st, to_st;
959 gint exist;
960 gchar new_path[MAX_PATH_LEN];
961
962 new_path[0] = '\0';
963
964 g_return_val_if_fail (action, FALSE);
965
966 /********************
967 * check source file
968 ********************/
969 if (isdir (from_path)) {
970 return copy_dir (from_path, to_path, action, show_error, window);
971 }
972
973 from_path_internal = charset_to_internal (from_path,
974 conf.charset_filename,
975 conf.charset_auto_detect_fn,
976 conf.charset_filename_mode);
977 to_path_internal = charset_to_internal (to_path,
978 conf.charset_filename,
979 conf.charset_auto_detect_fn,
980 conf.charset_filename_mode);
981
982 if (lstat (from_path, &from_st)) {
983 if (show_error) {
984 g_snprintf (error_message, BUF_SIZE,
985 _("Can't find source file :\n%s"),
986 from_path_internal);
987 gtkutil_message_dialog (_("Error!!"), error_message, window);
988 }
989 goto ERROR;
990 }
991
992 /******************
993 * check dest file
994 ******************/
995 exist = !lstat(to_path, &to_st);
996 if (exist && (!strcmp (from_path, to_path)
997 || from_st.st_ino == to_st.st_ino))
998 {
999 if (show_error) {
1000 g_snprintf (error_message, BUF_SIZE,
1001 _("Same file :\n%s"),
1002 to_path_internal);
1003 gtkutil_message_dialog (_("Error!!"), error_message, window);
1004 }
1005 goto ERROR;
1006
1007 } else if (exist && *action == CONFIRM_ASK) {
1008 g_snprintf (error_message, BUF_SIZE,
1009 _("The file exists : %s\n"
1010 "Overwrite?"),
1011 to_path_internal);
1012 *action = gtkutil_overwrite_confirm_dialog (_("File exist!!"), error_message,
1013 to_path, from_path,
1014 new_path, MAX_PATH_LEN,
1015 ConfirmDialogMultipleFlag,
1016 window);
1017 }
1018
1019 if (*new_path) {
1020 g_free (to_path_internal);
1021 to_path = new_path;
1022 to_path_internal = charset_to_internal (to_path,
1023 conf.charset_filename,
1024 conf.charset_auto_detect_fn,
1025 conf.charset_filename_mode);
1026 } else {
1027 switch (*action) {
1028 case CONFIRM_YES:
1029 case CONFIRM_YES_TO_ALL:
1030 break;
1031 case CONFIRM_NO:
1032 case CONFIRM_CANCEL:
1033 goto ERROR;
1034 break;
1035 case CONFIRM_NO_TO_ALL:
1036 if (exist)
1037 goto ERROR;
1038 break;
1039 default:
1040 if (exist)
1041 goto ERROR;
1042 break;
1043 }
1044 }
1045
1046 /**********
1047 * do copy
1048 **********/
1049 from = fopen (from_path, "rb");
1050 if (!from) {
1051 if (show_error) {
1052 g_snprintf (error_message, BUF_SIZE,
1053 _("Can't open file for read :\n%s"),
1054 to_path_internal);
1055 gtkutil_message_dialog (_("Error!!"), error_message, window);
1056 }
1057 goto ERROR;
1058 }
1059
1060 to = fopen (to_path, "wb");
1061 if (!to) {
1062 fclose (from);
1063 if (show_error) {
1064 g_snprintf (error_message, BUF_SIZE,
1065 _("Can't open file for write :\n%s"),
1066 to_path_internal);
1067 gtkutil_message_dialog (_("Error!!"), error_message, window);
1068 }
1069 goto ERROR;
1070 }
1071
1072 while ((b = fread (buf, sizeof (char), BUFSIZ, from)) > 0) {
1073 fwrite (buf, sizeof (char), b, to);
1074 if (ferror (to)) {
1075 fclose (from);
1076 fclose (to);
1077
1078 if (show_error) {
1079 g_snprintf (error_message, BUF_SIZE,
1080 _("An error occured while copying file :\n%s"),
1081 to_path_internal);
1082 gtkutil_message_dialog (_("Error!!"), error_message, window);
1083 }
1084 goto ERROR;
1085 }
1086 }
1087
1088 fclose (from);
1089 fclose (to);
1090
1091 g_free (to_path_internal);
1092 g_free (from_path_internal);
1093 return TRUE;
1094
1095 ERROR:
1096 g_free (to_path_internal);
1097 g_free (from_path_internal);
1098 return FALSE;
1099 }
1100
1101
1102 /*
1103 * copy_file:
1104 * @
1105 *
1106 * from_path :
1107 * dir :
1108 * action :
1109 * show_error :
1110 * Return : TRUE if success to copy file.
1111 */
1112 gboolean
copy_file(const gchar * from_path,const gchar * dir,ConfirmType * action,gboolean show_error,GtkWindow * window)1113 copy_file (const gchar *from_path, const gchar *dir,
1114 ConfirmType *action, gboolean show_error,
1115 GtkWindow *window)
1116 {
1117 gchar *to_path;
1118 gboolean retval;
1119 gchar error_message[BUF_SIZE];
1120
1121 g_return_val_if_fail (action, FALSE);
1122
1123 /* check source file is directory or not */
1124 if (isdir (from_path)) {
1125 return copy_dir (from_path, dir, action, show_error, window);
1126 }
1127
1128 /*****************
1129 * check dest dir
1130 *****************/
1131 if (!iswritable (dir)) {
1132 if (show_error) {
1133 gchar *from_path_internal, *dir_internal;
1134
1135 from_path_internal = charset_to_internal (from_path,
1136 conf.charset_filename,
1137 conf.charset_auto_detect_fn,
1138 conf.charset_filename_mode);
1139 dir_internal = charset_to_internal (dir,
1140 conf.charset_filename,
1141 conf.charset_auto_detect_fn,
1142 conf.charset_filename_mode);
1143 g_snprintf (error_message, BUF_SIZE,
1144 _("Can't copy file : %s\n"
1145 "Permission denied: %s\n"),
1146 from_path_internal, dir_internal);
1147
1148 gtkutil_message_dialog (_("Error!!"), error_message, window);
1149
1150 g_free (from_path_internal);
1151 g_free (dir_internal);
1152 }
1153 return FALSE;
1154 }
1155
1156 to_path = g_strconcat (dir, g_basename (from_path), NULL);
1157 retval = copy_file_to_file (from_path, to_path, action, show_error, window);
1158 g_free (to_path);
1159
1160 return retval;
1161 }
1162
1163
1164 /*
1165 * link_file:
1166 * @
1167 *
1168 * from_path :
1169 * dir :
1170 * action :
1171 * show_error :
1172 * Return : TRUE if success to link file.
1173 */
1174 gboolean
link_file(const gchar * from_path,const gchar * dir,gboolean show_error,GtkWindow * window)1175 link_file (const gchar *from_path, const gchar *dir,
1176 gboolean show_error, GtkWindow *window)
1177 {
1178 gchar *to_path, *to_path_internal, *from_path_internal, *dir_internal;
1179 struct stat from_st, to_st;
1180 gboolean link_faild;
1181 gchar error_message[BUF_SIZE];
1182
1183 from_path_internal = charset_to_internal (from_path,
1184 conf.charset_filename,
1185 conf.charset_auto_detect_fn,
1186 conf.charset_filename_mode);
1187 dir_internal = charset_to_internal (dir,
1188 conf.charset_filename,
1189 conf.charset_auto_detect_fn,
1190 conf.charset_filename_mode);
1191
1192 /********************
1193 * check source file
1194 ********************/
1195 if (lstat (from_path, &from_st)) {
1196 if (show_error) {
1197 g_snprintf (error_message, BUF_SIZE,
1198 _("Can't find source file :\n%s"),
1199 from_path_internal);
1200 gtkutil_message_dialog (_("Error!!"), error_message, window);
1201 }
1202 goto ERROR0;
1203 }
1204
1205 /*****************
1206 * check dest dir
1207 *****************/
1208 if (!iswritable (dir)) {
1209 if (show_error) {
1210 g_snprintf (error_message, BUF_SIZE,
1211 _("Can't create link : %s\n"
1212 "Permission denied: %s\n"),
1213 from_path_internal, dir_internal);
1214 gtkutil_message_dialog (_("Error!!"), error_message, window);
1215 }
1216 goto ERROR0;
1217 }
1218
1219 to_path = g_strconcat(dir_internal, g_basename(from_path), NULL);
1220 to_path_internal = charset_to_internal (to_path,
1221 conf.charset_filename,
1222 conf.charset_auto_detect_fn,
1223 conf.charset_filename_mode);
1224
1225 /******************
1226 * check dest path
1227 ******************/
1228 if (!lstat (to_path, &to_st)) {
1229 if (show_error) {
1230 g_snprintf (error_message, BUF_SIZE,
1231 _("File exist : %s"),
1232 to_path_internal);
1233 gtkutil_message_dialog (_("Error!!"), error_message, window);
1234 }
1235 goto ERROR1;
1236 }
1237
1238 link_faild = symlink(from_path, to_path);
1239
1240 if (link_faild) {
1241 if (show_error) {
1242 g_snprintf (error_message, BUF_SIZE,
1243 _("Faild to create link :\n"
1244 "From : %s\n"
1245 "To : %s"),
1246 from_path_internal, to_path_internal);
1247 gtkutil_message_dialog (_("Error!!"), error_message, window);
1248 }
1249 goto ERROR1;
1250 }
1251
1252 g_free (to_path);
1253 g_free (to_path_internal);
1254 g_free (from_path_internal);
1255 g_free (dir_internal);
1256 return TRUE;
1257
1258 ERROR1:
1259 g_free (to_path);
1260 g_free (to_path_internal);
1261 ERROR0:
1262 g_free (from_path_internal);
1263 g_free (dir_internal);
1264 return FALSE;
1265 }
1266
1267
1268
1269 static gchar *
get_dest_cache_dir(const gchar * src_file,const gchar * dest_dir,const gchar * cache_type)1270 get_dest_cache_dir (const gchar *src_file,
1271 const gchar *dest_dir,
1272 const gchar *cache_type)
1273 {
1274 gchar *dest_file, *dest_cache_dir;
1275
1276 if (!src_file || !dest_dir || !cache_type) return NULL;
1277
1278 dest_file = g_strconcat (dest_dir, g_basename (src_file), NULL);
1279 dest_cache_dir = gimv_thumb_cache_get_path (dest_file, cache_type);
1280
1281 if (dest_cache_dir) {
1282 gchar *endchr;
1283
1284 endchr = strrchr (dest_cache_dir, '/');
1285 if (endchr) {
1286 *(endchr + 1) = '\0';
1287 mkdirs (dest_cache_dir);
1288 } else {
1289 g_free (dest_cache_dir);
1290 dest_cache_dir = NULL;
1291 }
1292 }
1293 g_free (dest_file);
1294
1295 return dest_cache_dir;
1296 }
1297
1298
1299 static gchar *
get_dest_comment_dir(const gchar * src_file,const gchar * dest_dir)1300 get_dest_comment_dir (const gchar *src_file,
1301 const gchar *dest_dir)
1302 {
1303 gchar *dest_file, *dest_comment_dir;
1304
1305 if (!src_file || !dest_dir) return NULL;
1306
1307 dest_file = g_strconcat (dest_dir, g_basename (src_file), NULL);
1308 dest_comment_dir = gimv_comment_get_path (dest_file);
1309
1310 if (dest_comment_dir) {
1311 gchar *endchr;
1312
1313 endchr = strrchr (dest_comment_dir, '/');
1314 if (endchr) {
1315 *(endchr + 1) = '\0';
1316 mkdirs (dest_comment_dir);
1317 } else {
1318 g_free (dest_comment_dir);
1319 dest_comment_dir = NULL;
1320 }
1321 }
1322 g_free (dest_file);
1323
1324 return dest_comment_dir;
1325 }
1326
1327
1328 static gboolean
do_file_operate(const gchar * src_file,const gchar * dest_dir,ConfirmType * over_write,FileOperateType action,GtkWidget * progress_win,gfloat progress,GtkWindow * window)1329 do_file_operate (const gchar *src_file,
1330 const gchar *dest_dir,
1331 ConfirmType *over_write,
1332 FileOperateType action,
1333 GtkWidget *progress_win,
1334 gfloat progress,
1335 GtkWindow *window)
1336 {
1337 gchar *src_cache, *dest_cache_dir;
1338 gchar *src_comment, *dest_comment_dir;
1339 gchar *cache_type;
1340 gchar *src_file_internal;
1341 struct stat src_st, dest_st;
1342 ConfirmType cache_over_write = CONFIRM_YES_TO_ALL;
1343 gboolean success = TRUE, delete_src = FALSE, result;
1344 gchar message[BUF_SIZE];
1345
1346 /* FIXME!! */ /* get cache file & dir */
1347 src_cache = gimv_thumb_find_thumbcache (src_file, &cache_type);
1348 dest_cache_dir = get_dest_cache_dir (src_file, dest_dir, cache_type);
1349 src_comment = gimv_comment_find_file (src_file);
1350 dest_comment_dir = get_dest_comment_dir (src_file, dest_dir);
1351
1352 /* if move to different file system, change to copy */
1353 lstat (src_file, &src_st);
1354 lstat (dest_dir, &dest_st);
1355 if (src_st.st_dev != dest_st.st_dev && action == FILE_MOVE ) {
1356 action = FILE_COPY;
1357 delete_src = TRUE;
1358 }
1359
1360 src_file_internal = charset_to_internal (src_file,
1361 conf.charset_filename,
1362 conf.charset_auto_detect_fn,
1363 conf.charset_filename_mode);
1364
1365 switch (action) {
1366 case FILE_MOVE:
1367 g_snprintf (message, BUF_SIZE,
1368 _("Moving %s ..."), src_file_internal);
1369 gtkutil_progress_window_update (progress_win, _("Moving files"),
1370 message, NULL, progress);
1371 result = move_file (src_file, dest_dir, over_write, TRUE, window);
1372
1373 if (!result)
1374 success = FALSE;
1375
1376 /* FIXME!! */ /* move cache file */
1377 if (result && src_cache && dest_cache_dir)
1378 move_file (src_cache, dest_cache_dir, &cache_over_write, FALSE, window);
1379 if (result && src_comment && dest_comment_dir)
1380 move_file (src_comment, dest_comment_dir, &cache_over_write, FALSE, window);
1381
1382 break;
1383
1384 case FILE_COPY:
1385 {
1386 gboolean delete_src_cache = FALSE, delete_src_comment = FALSE;
1387
1388 g_snprintf (message, BUF_SIZE,
1389 _("Copying %s ..."), src_file_internal);
1390 gtkutil_progress_window_update (progress_win, _("Copying files"),
1391 message, NULL, progress);
1392 result = copy_file (src_file, dest_dir, over_write, TRUE, window);
1393
1394 if (!result)
1395 success = FALSE;
1396
1397 /* FIXME!! */ /* copy cache file */
1398 if (result && src_cache && dest_cache_dir) {
1399 if (copy_file (src_cache, dest_cache_dir, &cache_over_write, FALSE, window))
1400 delete_src_cache = TRUE;
1401 }
1402 if (result && src_comment && dest_comment_dir) {
1403 if (copy_file (src_comment, dest_comment_dir, &cache_over_write, FALSE, window))
1404 delete_src_comment = TRUE;
1405 }
1406
1407 /* FIXME: delete src? */
1408 if (result && delete_src) {
1409 GList *delete_file_list = NULL;
1410 delete_file_list = g_list_append (delete_file_list, (gpointer) src_file);
1411 if (delete_src_cache)
1412 delete_file_list = g_list_append (delete_file_list, src_cache);
1413 if (delete_src_comment)
1414 delete_file_list = g_list_append (delete_file_list, src_comment);
1415 if (delete_file_list)
1416 delete_files (delete_file_list, CONFIRM_YES, window);
1417 g_list_free (delete_file_list);
1418 }
1419
1420 break;
1421 }
1422 case FILE_LINK:
1423 g_snprintf (message, BUF_SIZE,
1424 _("Creating Link %s ..."), src_file_internal);
1425 gtkutil_progress_window_update (progress_win, _("Creating Links"),
1426 message, NULL, progress);
1427 result = link_file (src_file, dest_dir, TRUE, window);
1428
1429 if (!result)
1430 success = FALSE;
1431
1432 /* FIXME!! */ /* link cache file */
1433 if (result && src_cache && dest_cache_dir)
1434 link_file (src_cache, dest_cache_dir, FALSE, window);
1435 if (result && src_comment && dest_comment_dir)
1436 link_file (src_comment, dest_comment_dir, FALSE, window);
1437
1438 break;
1439
1440 default:
1441 success = FALSE;
1442 break;
1443 }
1444
1445 g_free (src_file_internal);
1446
1447 /* FIXME!! */
1448 g_free (src_cache);
1449 g_free (dest_cache_dir);
1450 g_free (src_comment);
1451 g_free (dest_comment_dir);
1452
1453 return success;
1454 }
1455
1456
1457 gboolean
files2dir(GList * filelist,const gchar * dir,FileOperateType action,GtkWindow * window)1458 files2dir (GList *filelist, const gchar *dir, FileOperateType action, GtkWindow *window)
1459 {
1460 GtkWidget *progress_win;
1461 GList *node;
1462 ConfirmType over_write = CONFIRM_ASK;
1463 gboolean success = TRUE, cancel = FALSE, result;
1464 gchar message[BUF_SIZE], *src_file, *dest_dir, *dir_internal;
1465 gint length, pos;
1466 gfloat progress;
1467
1468 g_return_val_if_fail (filelist, FALSE);
1469 g_return_val_if_fail (dir, FALSE);
1470
1471 dir_internal = charset_to_internal (dir,
1472 conf.charset_filename,
1473 conf.charset_auto_detect_fn,
1474 conf.charset_filename_mode);
1475
1476 /*****************
1477 * check dest dir
1478 *****************/
1479 if (!file_exists (dir)) {
1480 g_snprintf (message, BUF_SIZE,
1481 _("Directory doesn't exist!!: %s"),
1482 dir_internal);
1483 gtkutil_message_dialog (_("Error!!"), message, window);
1484 goto ERROR;
1485 }
1486 if (!iswritable (dir)) {
1487 g_snprintf (message, BUF_SIZE,
1488 _("Permission denied!!: %s"),
1489 dir_internal);
1490 gtkutil_message_dialog (_("Error!!"), message, window);
1491 goto ERROR;
1492 }
1493
1494 /* add "/" character */
1495 if (dir[strlen(dir) - 1] == '/')
1496 dest_dir = g_strdup (dir);
1497 else
1498 dest_dir = g_strconcat (dir, "/", NULL);
1499
1500 /* create progress window */
1501 progress_win = gtkutil_create_progress_window ("File Operation", "...",
1502 &cancel, 300, -1, window);
1503 gtk_grab_add (progress_win);
1504
1505 /* do file operation */
1506 length = g_list_length (filelist);
1507 for (node = filelist; node; node = g_list_next (node)) {
1508 src_file = node->data;
1509
1510 while (gtk_events_pending()) gtk_main_iteration();
1511
1512 pos = g_list_position (filelist, node);
1513 progress = (gfloat) pos / (gfloat) length;
1514
1515 result = do_file_operate (src_file, dest_dir, &over_write, action,
1516 progress_win, progress, window);
1517 if (!result)
1518 success = FALSE;
1519
1520 /* cancel */
1521 if (cancel || (over_write == CONFIRM_CANCEL)) break;
1522
1523 /* reset to CONFIRM_ASK mode */
1524 if (over_write != CONFIRM_YES_TO_ALL && over_write != CONFIRM_NO_TO_ALL) {
1525 over_write = CONFIRM_ASK;
1526 }
1527 }
1528
1529 gtk_grab_remove (progress_win);
1530 gtk_widget_destroy (progress_win);
1531
1532 g_free (dest_dir);
1533 g_free (dir_internal);
1534
1535 return success;
1536
1537 ERROR:
1538 g_free (dir_internal);
1539 return FALSE;
1540 }
1541
1542
1543 gboolean
files2dir_with_dialog(GList * filelist,gchar ** default_dir,FileOperateType action,GtkWindow * window)1544 files2dir_with_dialog (GList *filelist, gchar **default_dir, FileOperateType action,
1545 GtkWindow *window)
1546 {
1547 gchar *dir;
1548 gboolean retval = FALSE;
1549 gchar *title, *label, *tmpstr;
1550
1551 g_return_val_if_fail (filelist, FALSE);
1552 g_return_val_if_fail (default_dir, FALSE);
1553
1554 if (!*default_dir)
1555 *default_dir = g_strdup (g_getenv("HOME"));
1556
1557 switch (action) {
1558 case FILE_MOVE:
1559 title = _("Move files to...");
1560 label = _("Move files to: ");
1561 break;
1562 case FILE_COPY:
1563 title = _("Copy files to...");
1564 label = _("Copy files to: ");
1565 break;
1566 case FILE_LINK:
1567 title = _("Link files to...");
1568 label = _("Link files to: ");
1569 break;
1570 default:
1571 dir = *default_dir;
1572 goto FUNC_END;
1573 break;
1574 }
1575
1576 tmpstr = charset_to_internal (*default_dir,
1577 conf.charset_filename,
1578 conf.charset_auto_detect_fn,
1579 conf.charset_filename_mode);
1580 dir = gtkutil_modal_file_dialog (title, tmpstr, MODAL_FILE_DIALOG_DIR_ONLY, window);
1581 g_free (tmpstr);
1582 tmpstr = NULL;
1583
1584 if (dir) {
1585 if (dir[strlen(dir) - 1] != '/') {
1586 tmpstr = dir;
1587 dir = g_strconcat (dir, "/", NULL);
1588 g_free (tmpstr);
1589 }
1590
1591 tmpstr = dir;
1592 dir = charset_internal_to_locale (dir);
1593 g_free (tmpstr);
1594
1595 retval = files2dir (filelist, dir, action, window);
1596 }
1597
1598 FUNC_END:
1599 if (*default_dir != dir)
1600 g_free (*default_dir);
1601 *default_dir = dir;
1602
1603 return retval;
1604 }
1605
1606
1607 gboolean
delete_dir(const gchar * path,GtkWindow * window)1608 delete_dir (const gchar *path, GtkWindow *window)
1609 {
1610 gboolean exist, cancel, not_empty = FALSE;
1611 struct stat st;
1612 gchar message[BUF_SIZE], *path_internal;
1613 GList *filelist, *listnode;
1614 gint length, pos;
1615 gfloat progress;
1616 GtkWidget *progress_win;
1617 ConfirmType action;
1618
1619 g_return_val_if_fail (path && *path, FALSE);
1620
1621 path_internal = charset_to_internal (path,
1622 conf.charset_filename,
1623 conf.charset_auto_detect_fn,
1624 conf.charset_filename_mode);
1625
1626 /* check direcotry exist or not */
1627 exist = !lstat (path, &st);
1628 if (!exist) {
1629 g_snprintf (message, BUF_SIZE,
1630 _("Directory not exist : %s"), path_internal);
1631 gtkutil_message_dialog (_("Error!!"), message, window);
1632 goto ERROR;
1633 }
1634
1635 /* check path is link or not */
1636 if (islink (path)) {
1637 g_snprintf (message, BUF_SIZE,
1638 _("%s is symbolic link.\n"
1639 "Remove link ?"), path_internal);
1640 action = gtkutil_confirm_dialog (_("Confirm Deleting Directory"),
1641 message, 0, window);
1642 if (action == CONFIRM_YES) {
1643 remove (path);
1644 }
1645 goto SUCCESS;
1646 }
1647
1648 /* confirm */
1649 g_snprintf (message, BUF_SIZE,
1650 _("Delete %s\n"
1651 "OK?"), path_internal);
1652 action = gtkutil_confirm_dialog (_("Confirm Deleting Directory"),
1653 message, 0, window);
1654 if (action != CONFIRM_YES) goto ERROR;
1655
1656 /* remove sub directories recursively */
1657 filelist = get_dir_all (path);
1658 if (filelist) {
1659 g_snprintf (message, BUF_SIZE,
1660 _("%s is not empty\n"
1661 "Delete all files under %s ?"),
1662 path_internal, path_internal);
1663 action = gtkutil_confirm_dialog (_("Confirm Deleting Directory"),
1664 message, 0, window);
1665 if (action != CONFIRM_YES) goto ERROR;
1666
1667 /* create progress bar */
1668 progress_win = gtkutil_create_progress_window ("Delete File", "Deleting Files",
1669 &cancel, 300, -1, window);
1670 gtk_grab_add (progress_win);
1671
1672 length = g_list_length (filelist);
1673 listnode = filelist;
1674
1675 while (listnode) {
1676
1677 /* update progress */
1678 pos = g_list_position (filelist, listnode);
1679 if ((pos % 50) == 0) {
1680 while (gtk_events_pending()) gtk_main_iteration();
1681
1682 pos = g_list_position (filelist, listnode);
1683 progress = (gfloat) pos / (gfloat) length;
1684
1685 { /********** convert charset **********/
1686 gchar *tmpstr;
1687 tmpstr = charset_to_internal (listnode->data,
1688 conf.charset_filename,
1689 conf.charset_auto_detect_fn,
1690 conf.charset_filename_mode);
1691 g_snprintf (message, BUF_SIZE,
1692 _("Deleting %s ..."),
1693 tmpstr);
1694 g_free (tmpstr);
1695 }
1696
1697 gtkutil_progress_window_update (progress_win, NULL,
1698 message, NULL, progress);
1699 }
1700
1701 /* remove a file */
1702 if (remove ((gchar *) listnode->data) < 0)
1703 not_empty = TRUE;
1704 listnode = g_list_next (listnode);
1705
1706 /* cancel */
1707 if (cancel) break;
1708 }
1709 gtk_grab_remove (progress_win);
1710 gtk_widget_destroy (progress_win);
1711
1712 g_list_foreach (filelist, (GFunc) g_free, NULL);
1713 g_list_free (filelist);
1714 }
1715
1716 /* remove the directory */
1717 if (not_empty) {
1718 g_snprintf (message, BUF_SIZE,
1719 _("Faild to remove directory :\n"
1720 "%s is not empty."), path_internal);
1721 gtkutil_message_dialog (_("Error!!"), message, window);
1722 } else if (remove (path) < 0) {
1723 g_snprintf (message, BUF_SIZE,
1724 _("Faild to remove directory : %s"), path_internal);
1725 gtkutil_message_dialog (_("Error!!"), message, window);
1726 }
1727
1728 SUCCESS:
1729 g_free (path_internal);
1730 return TRUE;
1731
1732 ERROR:
1733 g_free (path_internal);
1734 return FALSE;
1735 }
1736
1737
1738 gboolean
delete_files(GList * filelist,ConfirmType confirm,GtkWindow * window)1739 delete_files (GList *filelist, ConfirmType confirm, GtkWindow *window)
1740 {
1741 GtkWidget *progress_win = NULL;
1742 GList *node;
1743 gboolean cancel = FALSE, dialog = FALSE;
1744 gint pos, length;
1745 gfloat progress;
1746 gchar message[BUF_SIZE], *dirname;
1747
1748 g_return_val_if_fail (filelist, FALSE);
1749
1750 length = g_list_length (filelist);
1751
1752 if (confirm == CONFIRM_ASK)
1753 dialog = TRUE;
1754
1755 if (dialog) {
1756 g_snprintf (message, BUF_SIZE,
1757 _("Delete these %d files.\n"
1758 "OK?"),
1759 length);
1760 confirm = gtkutil_confirm_dialog (_("Confirm Deleting Files"),
1761 message, 0, window);
1762 }
1763
1764 if (!(confirm == CONFIRM_YES || confirm == CONFIRM_YES_TO_ALL)) {
1765 return FALSE;
1766 }
1767
1768 if (dialog) {
1769 progress_win = gtkutil_create_progress_window (_("Delete File"),
1770 _("Deleting Files"),
1771 &cancel, 300, -1, window);
1772 gtk_grab_add (progress_win);
1773 }
1774
1775 node = filelist;
1776 while (node) {
1777 gchar *filename = node->data, *filename_internal, *dirname_internal;
1778
1779 node = g_list_next (node);
1780 if (!filename || !*filename) continue;
1781
1782 filename_internal = charset_to_internal (filename,
1783 conf.charset_filename,
1784 conf.charset_auto_detect_fn,
1785 conf.charset_filename_mode);
1786
1787 while (gtk_events_pending()) gtk_main_iteration();
1788
1789 pos = g_list_position (filelist, node);
1790 progress = (gfloat) pos / (gfloat) length;
1791
1792 if (dialog && progress_win) {
1793 g_snprintf (message, BUF_SIZE, _("Deleting %s ..."),
1794 filename_internal);
1795 gtkutil_progress_window_update (progress_win, NULL,
1796 message, NULL, progress);
1797 }
1798
1799 dirname = g_dirname (filename);
1800 dirname_internal = charset_to_internal (dirname,
1801 conf.charset_filename,
1802 conf.charset_auto_detect_fn,
1803 conf.charset_filename_mode);
1804
1805 if (!iswritable (dirname)) {
1806 g_snprintf (message, BUF_SIZE,
1807 _("Permission denied : %s"), dirname_internal);
1808 gtkutil_message_dialog (_("Error!!"), message, window);
1809
1810 } else { /* remove file!! */
1811 gboolean success;
1812 gint ret;
1813
1814 if (isdir (filename)) {
1815 success = delete_dir (filename, window);
1816 } else {
1817 ret = remove (filename);
1818 if (ret < 0)
1819 success = FALSE;
1820 else
1821 success = TRUE;
1822 }
1823
1824 if (!success) {
1825 g_snprintf (message, BUF_SIZE,
1826 _("Faild to delete file :\n%s"),
1827 filename_internal);
1828 gtkutil_message_dialog (_("Error!!"), message, window);
1829 }
1830 }
1831
1832 g_free (dirname);
1833 g_free (dirname_internal);
1834 g_free (filename_internal);
1835 dirname = NULL;
1836 dirname_internal = NULL;
1837 filename_internal = NULL;
1838
1839 /* cancel */
1840 if (cancel) break;
1841 }
1842
1843 if (dialog && progress_win) {
1844 gtk_grab_remove (progress_win);
1845 gtk_widget_destroy (progress_win);
1846 }
1847
1848 return TRUE;
1849 }
1850
1851 gboolean
make_dir_dialog(const gchar * parent_dir,GtkWindow * window)1852 make_dir_dialog (const gchar *parent_dir, GtkWindow *window)
1853 {
1854 gchar *dirname, *path, *parent_path, *tmpstr;
1855 gboolean success = FALSE, exist;
1856 struct stat st;
1857 gchar error_message[BUF_SIZE];
1858
1859 g_return_val_if_fail (parent_dir && *parent_dir, FALSE);
1860
1861 parent_path = add_slash (parent_dir);
1862
1863 if (!iswritable (parent_path)) {
1864 g_snprintf (error_message, BUF_SIZE,
1865 _("Permission denied : %s"), parent_path);
1866 gtkutil_message_dialog (_("Error!!"), error_message, window);
1867 goto ERROR0;
1868 }
1869
1870 dirname = gtkutil_popup_textentry (_("Make directory"),
1871 _("New directory name: "),
1872 NULL, NULL, -1, 0, window);
1873 if (!dirname) goto ERROR0;
1874
1875 tmpstr = charset_internal_to_locale (dirname);
1876 g_free (dirname);
1877 dirname = tmpstr;
1878 path = g_strconcat (parent_path, dirname, NULL);
1879
1880 exist = !lstat (path, &st);
1881 if (exist) {
1882 if (isdir (path))
1883 g_snprintf (error_message, BUF_SIZE,
1884 _("Directory exist : %s"), path);
1885 else
1886 g_snprintf (error_message, BUF_SIZE,
1887 _("File exist : %s"), path);
1888 gtkutil_message_dialog (_("Error!!"), error_message, window);
1889 g_free (path);
1890 goto ERROR1;
1891 }
1892
1893 success = makedir (path);
1894 if (!success) {
1895 g_snprintf (error_message, BUF_SIZE,
1896 _("Faild to create directory : %s"), path);
1897 gtkutil_message_dialog (_("Error!!"), error_message, window);
1898 }
1899
1900 ERROR1:
1901 g_free (path);
1902 ERROR0:
1903 g_free (parent_path);
1904
1905 return success;
1906 }
1907
1908
1909 gboolean
rename_dir_dialog(const gchar * dir,GtkWindow * window)1910 rename_dir_dialog (const gchar *dir, GtkWindow *window)
1911 {
1912 gboolean exist, success = FALSE;
1913 struct stat st;
1914 gchar message[BUF_SIZE];
1915 gchar *path, *parent_dir, *dirname, *src_path, *src_file_internal;
1916 gchar *dest_path, *tmpstr;
1917
1918 g_return_val_if_fail (dir && *dir, FALSE);
1919
1920 path = add_slash (dir);
1921
1922 /* check direcotry */
1923 exist = !lstat (path, &st);
1924 if (!exist) {
1925 g_snprintf (message, BUF_SIZE,
1926 _("Directory not exist :%s"), path);
1927 gtkutil_message_dialog (_("Error!!"), message, window);
1928 goto ERROR0;
1929 }
1930
1931 src_path = remove_slash (path);
1932 parent_dir = g_dirname (src_path);
1933
1934 /* popup rename directory dialog */
1935 src_file_internal = charset_locale_to_internal (g_basename (src_path));
1936 dirname = gtkutil_popup_textentry (_("Rename directory"),
1937 _("New directory name: "),
1938 src_file_internal,
1939 NULL, -1, 0, window);
1940 g_free (src_file_internal);
1941 if (!dirname) goto ERROR1;
1942
1943 tmpstr = charset_internal_to_locale (dirname);
1944 g_free (dirname);
1945 dirname = tmpstr;
1946
1947 dest_path = g_strconcat (parent_dir, "/", dirname, NULL);
1948
1949 if (rename (src_path, dest_path) < 0) {
1950 g_snprintf (message, BUF_SIZE,
1951 _("Faild to rename directory : %s"), src_path);
1952 gtkutil_message_dialog (_("Error!!"), message, window);
1953 } else {
1954 success = TRUE;
1955 }
1956
1957 g_free (dirname);
1958 g_free (dest_path);
1959 ERROR1:
1960 g_free (src_path);
1961 g_free (parent_dir);
1962 ERROR0:
1963 g_free (path);
1964
1965 return success;
1966 }
1967