Mercurial > geeqie
comparison src/ui_fileops.c @ 9:d907d608745f
Sync to GQview 1.5.9 release.
########
DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS!
This CVS is never up to date with current development and is provided
solely for reference purposes, please use the latest official release
package when making any changes or translation updates.
########
author | gqview |
---|---|
date | Sat, 26 Feb 2005 00:13:35 +0000 |
parents | |
children | dcc04a6a58bf |
comparison
equal
deleted
inserted
replaced
8:e0d0593d519e | 9:d907d608745f |
---|---|
1 /* | |
2 * (SLIK) SimpLIstic sKin functions | |
3 * (C) 2004 John Ellis | |
4 * | |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 #ifdef HAVE_CONFIG_H | |
13 # include "config.h" | |
14 #endif | |
15 | |
16 #include <pwd.h> | |
17 #include <stdio.h> | |
18 #include <stdlib.h> | |
19 #include <string.h> | |
20 #include <unistd.h> | |
21 #include <sys/param.h> | |
22 #include <dirent.h> | |
23 #include <utime.h> | |
24 | |
25 #include <glib.h> | |
26 #include <gtk/gtk.h> /* for locale warning dialog */ | |
27 | |
28 #include "ui_fileops.h" | |
29 | |
30 #include "ui_utildlg.h" /* for locale warning dialog */ | |
31 | |
32 /* | |
33 *----------------------------------------------------------------------------- | |
34 * generic file information and manipulation routines (public) | |
35 *----------------------------------------------------------------------------- | |
36 */ | |
37 | |
38 /* file sorting method (case) */ | |
39 gint file_sort_case_sensitive = FALSE; | |
40 | |
41 | |
42 void print_term(const gchar *text_utf8) | |
43 { | |
44 gchar *text_l; | |
45 | |
46 text_l = g_locale_from_utf8(text_utf8, -1, NULL, NULL, NULL); | |
47 printf((text_l) ? text_l : text_utf8); | |
48 g_free(text_l); | |
49 } | |
50 | |
51 static void encoding_dialog(const gchar *path); | |
52 | |
53 static gint encoding_dialog_idle(gpointer data) | |
54 { | |
55 gchar *path = data; | |
56 | |
57 encoding_dialog(path); | |
58 g_free(path); | |
59 | |
60 return FALSE; | |
61 } | |
62 | |
63 static gint encoding_dialog_delay(gpointer data) | |
64 { | |
65 g_idle_add(encoding_dialog_idle, data); | |
66 | |
67 return 0; | |
68 } | |
69 | |
70 static void encoding_dialog(const gchar *path) | |
71 { | |
72 static gint warned_user = FALSE; | |
73 GenericDialog *gd; | |
74 GString *string; | |
75 const gchar *lc; | |
76 const gchar *bf; | |
77 | |
78 /* check that gtk is initialized (loop is level > 0) */ | |
79 if (gtk_main_level() == 0) | |
80 { | |
81 /* gtk not initialized */ | |
82 gtk_init_add(encoding_dialog_delay, g_strdup(path)); | |
83 return; | |
84 } | |
85 | |
86 if (warned_user) return; | |
87 warned_user = TRUE; | |
88 | |
89 lc = getenv("LANG"); | |
90 bf = getenv("G_BROKEN_FILENAMES"); | |
91 warned_user = TRUE; | |
92 | |
93 string = g_string_new(""); | |
94 g_string_append(string, "One or more filenames are not encoded with the preferred locale character set.\n"); | |
95 g_string_append_printf(string, "Operations on, and display of these files with %s may not succeed.\n\n", PACKAGE); | |
96 g_string_append(string, "If your filenames are not encoded in utf-8, try setting\n"); | |
97 g_string_append(string, "the environment variable G_BROKEN_FILENAMES=1\n"); | |
98 g_string_append_printf(string, "It appears G_BROKEN_FILENAMES is %s%s\n\n", | |
99 (bf) ? "set to " : "not set.", (bf) ? bf : ""); | |
100 g_string_append_printf(string, "The locale appears to be set to \"%s\"\n(set by the LANG environment variable)\n", (lc) ? lc : "undefined"); | |
101 if (lc && (strstr(lc, "UTF-8") || strstr(lc, "utf-8"))) | |
102 { | |
103 gchar *name; | |
104 name = g_convert(path, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); | |
105 string = g_string_append(string, "\nPreferred encoding appears to be UTF-8, however the file:\n"); | |
106 g_string_append_printf(string, "\"%s\"\n%s encoded in valid UTF-8.\n", | |
107 (name) ? name : "[name not displayable]", | |
108 (g_utf8_validate(path, -1, NULL)) ? "is": "is NOT"); | |
109 g_free(name); | |
110 } | |
111 | |
112 gd = generic_dialog_new("Filename encoding locale mismatch", | |
113 PACKAGE, "locale warning", NULL, TRUE, NULL, NULL); | |
114 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL, NULL, TRUE); | |
115 | |
116 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_WARNING, | |
117 "Filename encoding locale mismatch", string->str); | |
118 | |
119 gtk_widget_show(gd->dialog); | |
120 | |
121 g_string_free(string, TRUE); | |
122 } | |
123 | |
124 gchar *path_to_utf8(const gchar *path) | |
125 { | |
126 gchar *utf8; | |
127 GError *error = NULL; | |
128 | |
129 if (!path) return NULL; | |
130 | |
131 utf8 = g_filename_to_utf8(path, -1, NULL, NULL, &error); | |
132 if (error) | |
133 { | |
134 printf("Unable to convert filename to UTF-8:\n%s\n%s\n", path, error->message); | |
135 g_error_free(error); | |
136 encoding_dialog(path); | |
137 } | |
138 if (!utf8) | |
139 { | |
140 /* just let it through, but bad things may happen */ | |
141 utf8 = g_strdup(path); | |
142 } | |
143 | |
144 return utf8; | |
145 } | |
146 | |
147 gchar *path_from_utf8(const gchar *utf8) | |
148 { | |
149 gchar *path; | |
150 GError *error = NULL; | |
151 | |
152 if (!utf8) return NULL; | |
153 | |
154 path = g_filename_from_utf8(utf8, -1, NULL, NULL, &error); | |
155 if (error) | |
156 { | |
157 printf("Unable to convert filename to locale from UTF-8:\n%s\n%s\n", utf8, error->message); | |
158 g_error_free(error); | |
159 } | |
160 if (!path) | |
161 { | |
162 /* if invalid UTF-8, text probaby still in original form, so just copy it */ | |
163 path = g_strdup(utf8); | |
164 } | |
165 | |
166 return path; | |
167 } | |
168 | |
169 /* first we try the HOME environment var, if that doesn't work, we try getpwuid(). */ | |
170 const gchar *homedir(void) | |
171 { | |
172 static gchar *home = NULL; | |
173 | |
174 if (!home) | |
175 { | |
176 home = path_to_utf8(getenv("HOME")); | |
177 } | |
178 if (!home) | |
179 { | |
180 struct passwd *pw = getpwuid(getuid()); | |
181 if (pw) home = path_to_utf8(pw->pw_dir); | |
182 } | |
183 | |
184 return home; | |
185 } | |
186 | |
187 gint stat_utf8(const gchar *s, struct stat *st) | |
188 { | |
189 gchar *sl; | |
190 gint ret; | |
191 | |
192 if (!s) return FALSE; | |
193 sl = path_from_utf8(s); | |
194 ret = (stat(sl, st) == 0); | |
195 g_free(sl); | |
196 | |
197 return ret; | |
198 } | |
199 | |
200 gint isname(const gchar *s) | |
201 { | |
202 struct stat st; | |
203 | |
204 return stat_utf8(s, &st); | |
205 } | |
206 | |
207 gint isfile(const gchar *s) | |
208 { | |
209 struct stat st; | |
210 | |
211 return (stat_utf8(s, &st) && S_ISREG(st.st_mode)); | |
212 } | |
213 | |
214 gint isdir(const gchar *s) | |
215 { | |
216 struct stat st; | |
217 | |
218 return (stat_utf8(s ,&st) && S_ISDIR(st.st_mode)); | |
219 } | |
220 | |
221 gint64 filesize(const gchar *s) | |
222 { | |
223 struct stat st; | |
224 | |
225 if (!stat_utf8(s, &st)) return 0; | |
226 return (gint)st.st_size; | |
227 } | |
228 | |
229 time_t filetime(const gchar *s) | |
230 { | |
231 struct stat st; | |
232 | |
233 if (!stat_utf8(s, &st)) return 0; | |
234 return st.st_mtime; | |
235 } | |
236 | |
237 gint filetime_set(const gchar *s, time_t tval) | |
238 { | |
239 gint ret = FALSE; | |
240 | |
241 if (tval > 0) | |
242 { | |
243 struct utimbuf ut; | |
244 gchar *sl; | |
245 | |
246 ut.actime = ut.modtime = tval; | |
247 | |
248 sl = path_from_utf8(s); | |
249 ret = (utime(sl, &ut) == 0); | |
250 g_free(sl); | |
251 } | |
252 | |
253 return ret; | |
254 } | |
255 | |
256 gint access_file(const gchar *s, int mode) | |
257 { | |
258 gchar *sl; | |
259 gint ret; | |
260 | |
261 if (!s) return FALSE; | |
262 | |
263 sl = path_from_utf8(s); | |
264 ret = (access(sl, mode) == 0); | |
265 g_free(sl); | |
266 | |
267 return ret; | |
268 } | |
269 | |
270 gint unlink_file(const gchar *s) | |
271 { | |
272 gchar *sl; | |
273 gint ret; | |
274 | |
275 if (!s) return FALSE; | |
276 | |
277 sl = path_from_utf8(s); | |
278 ret = (unlink(sl) == 0); | |
279 g_free(sl); | |
280 | |
281 return ret; | |
282 } | |
283 | |
284 gint symlink_utf8(const gchar *source, const gchar *target) | |
285 { | |
286 gchar *sl; | |
287 gchar *tl; | |
288 gint ret; | |
289 | |
290 if (!source || !target) return FALSE; | |
291 | |
292 sl = path_from_utf8(source); | |
293 tl = path_from_utf8(target); | |
294 | |
295 ret = (symlink(sl, tl) == 0); | |
296 | |
297 g_free(sl); | |
298 g_free(tl); | |
299 | |
300 return ret; | |
301 } | |
302 | |
303 gint mkdir_utf8(const gchar *s, int mode) | |
304 { | |
305 gchar *sl; | |
306 gint ret; | |
307 | |
308 if (!s) return FALSE; | |
309 | |
310 sl = path_from_utf8(s); | |
311 ret = (mkdir(sl, mode) == 0); | |
312 g_free(sl); | |
313 return ret; | |
314 } | |
315 | |
316 gint rmdir_utf8(const gchar *s) | |
317 { | |
318 gchar *sl; | |
319 gint ret; | |
320 | |
321 if (!s) return FALSE; | |
322 | |
323 sl = path_from_utf8(s); | |
324 ret = (rmdir(sl) == 0); | |
325 g_free(sl); | |
326 | |
327 return ret; | |
328 } | |
329 | |
330 gint copy_file_attributes(const gchar *s, const gchar *t, gint perms, gint mtime) | |
331 { | |
332 struct stat st; | |
333 gchar *sl, *tl; | |
334 gint ret = FALSE; | |
335 | |
336 if (!s || !t) return FALSE; | |
337 | |
338 sl = path_from_utf8(s); | |
339 tl = path_from_utf8(t); | |
340 | |
341 if (stat(sl, &st) == 0) | |
342 { | |
343 struct utimbuf tb; | |
344 | |
345 ret = TRUE; | |
346 | |
347 /* set the dest file attributes to that of source (ignoring errors) */ | |
348 | |
349 if (perms && chown(tl, st.st_uid, st.st_gid) < 0) ret = FALSE; | |
350 if (perms && chmod(tl, st.st_mode) < 0) ret = FALSE; | |
351 | |
352 tb.actime = st.st_atime; | |
353 tb.modtime = st.st_mtime; | |
354 if (mtime && utime(tl, &tb) < 0) ret = FALSE; | |
355 } | |
356 | |
357 g_free(sl); | |
358 g_free(tl); | |
359 | |
360 return ret; | |
361 } | |
362 | |
363 /* paths are in filesystem encoding */ | |
364 static gint hard_linked(const gchar *a, const gchar *b) | |
365 { | |
366 struct stat sta; | |
367 struct stat stb; | |
368 | |
369 if (stat(a, &sta) != 0 || stat(b, &stb) != 0) return FALSE; | |
370 | |
371 return (sta.st_dev == stb.st_dev && | |
372 sta.st_ino == stb.st_ino); | |
373 } | |
374 | |
375 gint copy_file(const gchar *s, const gchar *t) | |
376 { | |
377 FILE *fi = NULL; | |
378 FILE *fo = NULL; | |
379 gchar *sl, *tl; | |
380 gchar buf[4096]; | |
381 gint b; | |
382 | |
383 sl = path_from_utf8(s); | |
384 tl = path_from_utf8(t); | |
385 | |
386 if (hard_linked(sl, tl)) | |
387 { | |
388 g_free(sl); | |
389 g_free(tl); | |
390 return TRUE; | |
391 } | |
392 | |
393 fi = fopen(sl, "rb"); | |
394 if (fi) | |
395 { | |
396 fo = fopen(tl, "wb"); | |
397 if (!fo) | |
398 { | |
399 fclose(fi); | |
400 fi = NULL; | |
401 } | |
402 } | |
403 | |
404 g_free(sl); | |
405 g_free(tl); | |
406 | |
407 if (!fi || !fo) return FALSE; | |
408 | |
409 while((b = fread(buf, sizeof(char), 4096, fi)) && b != 0) | |
410 { | |
411 if (fwrite(buf, sizeof(char), b, fo) != b) | |
412 { | |
413 fclose(fi); | |
414 fclose(fo); | |
415 return FALSE; | |
416 } | |
417 } | |
418 | |
419 fclose(fi); | |
420 fclose(fo); | |
421 | |
422 copy_file_attributes(s, t, TRUE, TRUE); | |
423 | |
424 return TRUE; | |
425 } | |
426 | |
427 gint move_file(const gchar *s, const gchar *t) | |
428 { | |
429 gchar *sl, *tl; | |
430 gint ret = TRUE; | |
431 | |
432 if (!s || !t) return FALSE; | |
433 | |
434 sl = path_from_utf8(s); | |
435 tl = path_from_utf8(t); | |
436 if (rename(sl, tl) < 0) | |
437 { | |
438 /* this may have failed because moving a file across filesystems | |
439 was attempted, so try copy and delete instead */ | |
440 if (copy_file(s, t)) | |
441 { | |
442 if (unlink(sl) < 0) | |
443 { | |
444 /* err, now we can't delete the source file so return FALSE */ | |
445 ret = FALSE; | |
446 } | |
447 } | |
448 else | |
449 { | |
450 ret = FALSE; | |
451 } | |
452 } | |
453 g_free(sl); | |
454 g_free(tl); | |
455 | |
456 return ret; | |
457 } | |
458 | |
459 gint rename_file(const gchar *s, const gchar *t) | |
460 { | |
461 gchar *sl, *tl; | |
462 gint ret; | |
463 | |
464 if (!s || !t) return FALSE; | |
465 | |
466 sl = path_from_utf8(s); | |
467 tl = path_from_utf8(t); | |
468 ret = (rename(sl, tl) == 0); | |
469 g_free(sl); | |
470 g_free(tl); | |
471 | |
472 return ret; | |
473 } | |
474 | |
475 gchar *get_current_dir(void) | |
476 { | |
477 gchar *pathl; | |
478 gchar *path8; | |
479 | |
480 pathl = g_get_current_dir(); | |
481 path8 = path_to_utf8(pathl); | |
482 g_free(pathl); | |
483 | |
484 return path8; | |
485 } | |
486 | |
487 gint path_list(const gchar *path, GList **files, GList **dirs) | |
488 { | |
489 DIR *dp; | |
490 struct dirent *dir; | |
491 struct stat ent_sbuf; | |
492 GList *f_list = NULL; | |
493 GList *d_list = NULL; | |
494 gchar *pathl; | |
495 | |
496 if (!path) return FALSE; | |
497 | |
498 pathl = path_from_utf8(path); | |
499 dp = opendir(pathl); | |
500 if (!dp) | |
501 { | |
502 /* dir not found */ | |
503 g_free(pathl); | |
504 return FALSE; | |
505 } | |
506 | |
507 /* root dir fix */ | |
508 if (pathl[0] == '/' && pathl[1] == '\0') | |
509 { | |
510 g_free(pathl); | |
511 pathl = g_strdup(""); | |
512 } | |
513 | |
514 while ((dir = readdir(dp)) != NULL) | |
515 { | |
516 /* skip removed files */ | |
517 if (dir->d_ino > 0) | |
518 { | |
519 gchar *name = dir->d_name; | |
520 gchar *filepath = g_strconcat(pathl, "/", name, NULL); | |
521 if (stat(filepath, &ent_sbuf) >= 0) | |
522 { | |
523 gchar *path8; | |
524 gchar *name8; | |
525 | |
526 name8 = path_to_utf8(name); | |
527 path8 = g_strconcat(path, "/", name8, NULL); | |
528 g_free(name8); | |
529 | |
530 if (dirs && S_ISDIR(ent_sbuf.st_mode) && | |
531 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) ) | |
532 { | |
533 d_list = g_list_prepend(d_list, path8); | |
534 path8 = NULL; | |
535 } | |
536 else if (files && S_ISREG(ent_sbuf.st_mode)) | |
537 { | |
538 f_list = g_list_prepend(f_list, path8); | |
539 path8 = NULL; | |
540 } | |
541 g_free(path8); | |
542 } | |
543 g_free(filepath); | |
544 } | |
545 } | |
546 closedir(dp); | |
547 | |
548 g_free(pathl); | |
549 | |
550 if (dirs) *dirs = g_list_reverse(d_list); | |
551 if (files) *files = g_list_reverse(f_list); | |
552 | |
553 return TRUE; | |
554 } | |
555 | |
556 void path_list_free(GList *list) | |
557 { | |
558 g_list_foreach(list, (GFunc)g_free, NULL); | |
559 g_list_free(list); | |
560 } | |
561 | |
562 GList *path_list_copy(GList *list) | |
563 { | |
564 GList *new_list = NULL; | |
565 GList *work; | |
566 | |
567 work = list; | |
568 while (work) | |
569 { | |
570 gchar *path; | |
571 | |
572 path = work->data; | |
573 work = work->next; | |
574 | |
575 new_list = g_list_prepend(new_list, g_strdup(path)); | |
576 } | |
577 | |
578 return g_list_reverse(new_list); | |
579 } | |
580 | |
581 long checksum_simple(const gchar *path) | |
582 { | |
583 gchar *path8; | |
584 FILE *f; | |
585 long sum = 0; | |
586 gint c; | |
587 | |
588 path8 = path_from_utf8(path); | |
589 f = fopen(path8, "r"); | |
590 g_free(path8); | |
591 if (!f) return -1; | |
592 | |
593 while((c = fgetc(f)) != EOF) | |
594 { | |
595 sum += c; | |
596 } | |
597 | |
598 fclose(f); | |
599 | |
600 return sum; | |
601 } | |
602 | |
603 gchar *unique_filename(const gchar *path, const gchar *ext, const gchar *divider, gint pad) | |
604 { | |
605 gchar *unique; | |
606 gint n = 1; | |
607 | |
608 if (!ext) ext = ""; | |
609 if (!divider) divider = ""; | |
610 | |
611 unique = g_strconcat(path, ext, NULL); | |
612 while (isname(unique)) | |
613 { | |
614 g_free(unique); | |
615 if (pad) | |
616 { | |
617 unique = g_strdup_printf("%s%s%03d%s", path, divider, n, ext); | |
618 } | |
619 else | |
620 { | |
621 unique = g_strdup_printf("%s%s%d%s", path, divider, n, ext); | |
622 } | |
623 n++; | |
624 if (n > 999) | |
625 { | |
626 /* well, we tried */ | |
627 g_free(unique); | |
628 return NULL; | |
629 } | |
630 } | |
631 | |
632 return unique; | |
633 } | |
634 | |
635 gchar *unique_filename_simple(const gchar *path) | |
636 { | |
637 gchar *unique; | |
638 const gchar *name; | |
639 const gchar *ext; | |
640 | |
641 if (!path) return NULL; | |
642 | |
643 name = filename_from_path(path); | |
644 if (!name) return NULL; | |
645 | |
646 ext = extension_from_path(name); | |
647 | |
648 if (!ext) | |
649 { | |
650 unique = unique_filename(path, NULL, "_", TRUE); | |
651 } | |
652 else | |
653 { | |
654 gchar *base; | |
655 | |
656 base = remove_extension_from_path(path); | |
657 unique = unique_filename(base, ext, "_", TRUE); | |
658 g_free(base); | |
659 } | |
660 | |
661 return unique; | |
662 } | |
663 | |
664 const gchar *filename_from_path(const gchar *path) | |
665 { | |
666 const gchar *base; | |
667 | |
668 if (!path) return NULL; | |
669 | |
670 base = strrchr(path, '/'); | |
671 if (base) return base + 1; | |
672 | |
673 return path; | |
674 } | |
675 | |
676 gchar *remove_level_from_path(const gchar *path) | |
677 { | |
678 gchar *new_path; | |
679 const gchar *ptr = path; | |
680 gint p; | |
681 | |
682 if (!path) return NULL; | |
683 | |
684 p = strlen(path) - 1; | |
685 if (p < 0) return NULL; | |
686 while(ptr[p] != '/' && p > 0) p--; | |
687 if (p == 0 && ptr[p] == '/') p++; | |
688 new_path = g_strndup(path, (guint)p); | |
689 return new_path; | |
690 } | |
691 | |
692 gchar *concat_dir_and_file(const gchar *base, const gchar *name) | |
693 { | |
694 if (!base || !name) return NULL; | |
695 | |
696 if (strcmp(base, "/") == 0) return g_strconcat(base, name, NULL); | |
697 | |
698 return g_strconcat(base, "/", name, NULL); | |
699 } | |
700 | |
701 const gchar *extension_from_path(const gchar *path) | |
702 { | |
703 if (!path) return NULL; | |
704 return strrchr(path, '.'); | |
705 } | |
706 | |
707 gint file_extension_match(const gchar *path, const gchar *ext) | |
708 { | |
709 gint p; | |
710 gint e; | |
711 | |
712 if (!path) return FALSE; | |
713 if (!ext) return TRUE; | |
714 | |
715 p = strlen(path); | |
716 e = strlen(ext); | |
717 | |
718 return (p > e && strncasecmp(path + p - e, ext, e) == 0); | |
719 } | |
720 | |
721 gchar *remove_extension_from_path(const gchar *path) | |
722 { | |
723 gchar *new_path; | |
724 const gchar *ptr = path; | |
725 gint p; | |
726 | |
727 if (!path) return NULL; | |
728 if (strlen(path) < 2) return g_strdup(path); | |
729 | |
730 p = strlen(path) - 1; | |
731 while(ptr[p] != '.' && p > 0) p--; | |
732 if (p == 0) p = strlen(path) - 1; | |
733 new_path = g_strndup(path, (guint)p); | |
734 return new_path; | |
735 } | |
736 | |
737 void parse_out_relatives(gchar *path) | |
738 { | |
739 gint s, t; | |
740 | |
741 if (!path) return; | |
742 | |
743 s = t = 0; | |
744 | |
745 while (path[s] != '\0') | |
746 { | |
747 if (path[s] == '/' && path[s+1] == '.' && (path[s+2] == '/' || path[s+2] == '\0') ) | |
748 { | |
749 s += 2; | |
750 } | |
751 else if (path[s] == '/' && path[s+1] == '.' && path[s+2] == '.' && (path[s+3] == '/' || path[s+3] == '\0') ) | |
752 { | |
753 s += 3; | |
754 if (t > 0) t--; | |
755 while (path[t] != '/' && t > 0) t--; | |
756 } | |
757 else | |
758 { | |
759 if (s != t) path[t] = path[s]; | |
760 t++; | |
761 s++; | |
762 } | |
763 } | |
764 if (t == 0 && path[t] == '/') t++; | |
765 if (t > 1 && path[t-1] == '/') t--; | |
766 path[t] = '\0'; | |
767 } | |
768 | |
769 gint file_in_path(const gchar *name) | |
770 { | |
771 gchar *path; | |
772 gchar *namel; | |
773 gint p, l; | |
774 gint ret = FALSE; | |
775 | |
776 if (!name) return FALSE; | |
777 path = g_strdup(getenv("PATH")); | |
778 if (!path) return FALSE; | |
779 namel = path_from_utf8(name); | |
780 | |
781 p = 0; | |
782 l = strlen(path); | |
783 while (p < l && !ret) | |
784 { | |
785 gchar *f; | |
786 gint e = p; | |
787 while (path[e] != ':' && path[e] != '\0') e++; | |
788 path[e] = '\0'; | |
789 e++; | |
790 f = g_strconcat(path + p, "/", namel, NULL); | |
791 if (isfile(f)) ret = TRUE; | |
792 g_free(f); | |
793 p = e; | |
794 } | |
795 g_free(namel); | |
796 g_free(path); | |
797 | |
798 return ret; | |
799 } | |
800 |