4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2005, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
21 /* choices.c - code for handling loading and saving of user choices */
27 #include <sys/param.h>
33 #include "gui_support.h"
37 static gboolean saving_disabled
= TRUE
;
38 static gchar
**dir_list
= NULL
;
39 static gchar
**xdg_dir_list
= NULL
;
40 static int xdg_dir_count
= 0 ;
42 static struct migration
{
47 {"ROX-Filer", SITE
, TRUE
},
48 {"SendTo", SITE
, TRUE
},
49 {"Templates", SITE
, TRUE
},
50 {"MIME-types", SITE
, TRUE
},
51 {"MIME-icons", SITE
, TRUE
},
52 {"MIME-thumb", SITE
, TRUE
},
57 /* Static prototypes */
58 static gboolean
exists(char *path
);
59 static void migrate_choices(void);
61 /****************************************************************
62 * EXTERNAL INTERFACE *
63 ****************************************************************/
66 /* Reads in CHOICESPATH and constructs the directory list table.
67 * You must call this before using any other choices_* functions.
69 * If CHOICESPATH does not exist then a suitable default is used.
71 void choices_init(void)
78 g_return_if_fail(dir_list
== NULL
);
80 /* Initialize old system */
81 choices
= getenv("CHOICESPATH");
85 if (*choices
!= ':' && *choices
!= '\0')
86 saving_disabled
= FALSE
;
88 while (*choices
== ':')
93 dir_list
= g_new(char *, 1);
97 dir_list
= g_strsplit(choices
, ":", 0);
101 saving_disabled
= FALSE
;
103 dir_list
= g_new(gchar
*, 4);
104 dir_list
[0] = g_build_filename(g_get_home_dir(), "Choices",
106 dir_list
[1] = g_strdup("/usr/local/share/Choices");
107 dir_list
[2] = g_strdup("/usr/share/Choices");
111 /* Initialize new system */
112 env
= getenv("XDG_CONFIG_DIRS");
115 dirs
= g_strsplit(env
, ":", 0);
116 g_return_if_fail(dirs
!= NULL
);
117 for (n
= 0; dirs
[n
]; n
++)
119 for (i
= n
; i
> 0; i
--)
120 dirs
[i
] = dirs
[i
- 1];
121 env
= getenv("XDG_CONFIG_HOME");
123 dirs
[0] = g_strdup(env
);
125 dirs
[0] = g_build_filename(g_get_home_dir(), ".config", NULL
);
128 xdg_dir_count
= n
+ 1;
132 gchar
**cdir
= dir_list
;
134 for(i
=0; i
<xdg_dir_count
; i
++)
135 g_print("[ XDG dir '%s' ]\n", xdg_dir_list
[i
]);
139 g_print("[ choices dir '%s' ]\n", *cdir
);
143 g_print("[ saving is %s ]\n", saving_disabled
? "disabled"
150 /* If our XDG choices directory does not yet exist, offer to move the
153 void choices_migrate(void)
157 /* Attempt migration */
158 newpath
=choices_find_xdg_path_save(".", PROJECT
, SITE
, FALSE
);
159 if(!exists(newpath
) && !saving_disabled
)
164 void choices_free_list(GPtrArray
*list
)
168 g_return_if_fail(list
!= NULL
);
170 for (i
= 0; i
< list
->len
; i
++)
171 g_free(g_ptr_array_index(list
, i
));
173 g_ptr_array_free(list
, TRUE
);
176 /* Get the pathname of a choices file to load. Eg:
178 * choices_find_path_load("menus", "ROX-Filer")
179 * -> "/usr/local/share/Choices/ROX-Filer/menus".
181 * The return values may be NULL - use built-in defaults.
182 * g_free() the result.
184 static gchar
*choices_find_path_load(const char *leaf
, const char *dir
)
186 gchar
**cdir
= dir_list
;
188 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
190 for (; *cdir
; cdir
++)
194 path
= g_build_filename(*cdir
, dir
, leaf
, NULL
);
205 /* Get the pathname of a choices file to load, using the XDG paths. Eg:
207 * choices_find_xdg_path_load("menus", "ROX-Filer", "rox.sourceforge.net")
208 * -> "/etc/xdg/rox.sourceforge.net/ROX-Filer/menus".
210 * Falls back on choices_find_path_load(leaf, dir) if it fails
211 * The return values may be NULL - use built-in defaults.
212 * g_free() the result.
214 gchar
*choices_find_xdg_path_load(const char *leaf
, const char *dir
,
219 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
221 for (i
=0; i
<xdg_dir_count
; i
++)
226 path
= g_build_filename(xdg_dir_list
[i
], site
,
229 path
= g_build_filename(xdg_dir_list
[i
], dir
,
238 return choices_find_path_load(leaf
, dir
);
241 /* Returns the pathname of a file to save to, or NULL if saving is
242 * disabled. If 'create' is TRUE then intermediate directories will
243 * be created (set this to FALSE if you just want to find out where
244 * a saved file would go without actually altering the filesystem).
246 * g_free() the result.
248 static gchar
*choices_find_path_save(const char *leaf
, const char *dir
,
251 gchar
*path
, *retval
;
253 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
258 if (create
&& !exists(dir_list
[0]))
260 if (mkdir(dir_list
[0], 0777))
261 g_warning("mkdir(%s): %s\n", dir_list
[0],
265 path
= g_build_filename(dir_list
[0], dir
, NULL
);
266 if (create
&& !exists(path
))
268 if (mkdir(path
, 0777))
269 g_warning("mkdir(%s): %s\n", path
, g_strerror(errno
));
272 retval
= g_build_filename(path
, leaf
, NULL
);
278 /* Returns the pathname of a file to save to, or NULL if saving is
279 * disabled. If 'create' is TRUE then intermediate directories will
280 * be created (set this to FALSE if you just want to find out where
281 * a saved file would go without actually altering the filesystem).
283 * g_free() the result.
285 gchar
*choices_find_xdg_path_save(const char *leaf
, const char *dir
,
286 const char *site
, gboolean create
)
288 gchar
*path
, *retval
, *tmp
;
290 g_return_val_if_fail(xdg_dir_list
!= NULL
, NULL
);
292 if (create
&& !exists(xdg_dir_list
[0]))
294 if (mkdir(xdg_dir_list
[0], 0777))
295 g_warning("mkdir(%s): %s\n", xdg_dir_list
[0],
301 path
= g_build_filename(xdg_dir_list
[0], site
, NULL
);
302 if (create
&& !exists(path
))
304 if (mkdir(path
, 0777))
305 g_warning("mkdir(%s): %s\n", path
,
310 tmp
=g_strdup(xdg_dir_list
[0]);
313 path
= g_build_filename(tmp
, dir
, NULL
);
315 if (create
&& !exists(path
))
317 if (mkdir(path
, 0777))
318 g_warning("mkdir(%s): %s\n", path
, g_strerror(errno
));
321 retval
= g_build_filename(path
, leaf
, NULL
);
328 * Returns an array of the directories in XDG_CONFIG_HOME and XDG_CONFIG_DIRS
329 * which contain a subdirectory called 'dir' (optionally in a subdirectory
332 * Lower-indexed results should override higher-indexed ones.
334 * Free the list using choices_free_list().
336 GPtrArray
*choices_list_xdg_dirs(char *dir
, char *site
)
341 g_return_val_if_fail(xdg_dir_list
!= NULL
, NULL
);
343 list
= g_ptr_array_new();
345 for (i
=0; i
<xdg_dir_count
; i
++)
350 path
= g_build_filename(xdg_dir_list
[i
], site
,
353 path
= g_build_filename(xdg_dir_list
[i
], dir
, NULL
);
356 g_ptr_array_add(list
, path
);
364 /****************************************************************
365 * INTERNAL FUNCTIONS *
366 ****************************************************************/
369 /* Returns TRUE if the object exists, FALSE if it doesn't */
370 static gboolean
exists(char *path
)
374 return stat(path
, &info
) == 0;
380 static void migrate_choices(void)
382 gchar
*opath
, *npath
;
386 gboolean migrated_something
= FALSE
;
388 npath
=choices_find_xdg_path_save("...", PROJECT
, SITE
, FALSE
);
389 opath
=choices_find_path_save("...", PROJECT
,FALSE
);
392 dest=choices_find_xdg_path_save(".", PROJECT, SITE, TRUE);
396 for(i
=0; to_migrate
[i
].dir
; i
++) {
397 src
=g_build_filename(dir_list
[0], to_migrate
[i
].dir
, NULL
);
398 dest
=choices_find_xdg_path_save(NULL
, NULL
,
399 to_migrate
[i
].site
, TRUE
);
401 dest
=choices_find_xdg_path_save(NULL
,
407 if(rename(src
, dest
)==0) {
408 if(to_migrate
[i
].symlink
)
410 migrated_something
= TRUE
;
412 g_warning("rename(%s, %s): %s\n",
417 } else if(to_migrate
[i
].symlink
) {
419 if(!exists(dir_list[0])) {
420 if (mkdir(dir_list[0], 0777))
421 g_warning("mkdir(%s): %s\n",
432 if (migrated_something
)
434 gchar
*failed_msg
= NULL
;
436 failed_msg
= g_strdup_printf(_("%d directories could not be migrated"),
438 info_message(_("Choices have been moved from \n"
440 "to the new location \n"
442 opath
, npath
, failed_msg
? failed_msg
: "");