#include <stdio.h>
#include <glib.h>
#include <errno.h>
+#include <sys/stat.h>
#ifdef G_OS_WIN32
#include <direct.h>
gchar *
g_build_path (const gchar *separator, const gchar *first_element, ...)
{
- GString *result;
- const char *s, *p, *next;
- size_t slen;
+ const char *elem, *next, *endptr;
+ gboolean trimmed;
+ GString *path;
va_list args;
- gboolean found;
-#ifdef G_OS_WIN32
- const gchar alt_separator = '/';
-#endif
+ size_t slen;
g_return_val_if_fail (separator != NULL, NULL);
-
- if (first_element == NULL)
- return g_strdup ("");
-
- result = g_string_sized_new (48);
-
+
+ path = g_string_sized_new (48);
slen = strlen (separator);
va_start (args, first_element);
- for (s = first_element; s != NULL; s = next){
- found = FALSE;
- next = va_arg (args, char *);
- p = (s + strlen (s));
-
- /* Strip all but one trailing separator */
- if (next && p - slen >= s){
- for (; strncmp (p-slen, separator, slen) == 0
-#ifdef G_OS_WIN32
- || alt_separator == *(p-slen)
-#endif
- ;){
- found = TRUE;
- p -= slen;
- }
+ for (elem = first_element; elem != NULL; elem = next) {
+ /* trim any trailing separators from @elem */
+ endptr = elem + strlen (elem);
+ trimmed = FALSE;
+
+ while (endptr >= elem + slen) {
+ if (strncmp (endptr - slen, separator, slen) != 0)
+ break;
+
+ endptr -= slen;
+ trimmed = TRUE;
}
- if (found) p += slen;
-
- /* Append path token */
- g_string_append_len (result, s, p - s);
+
+ /* append elem, not including any trailing separators */
+ if (endptr > elem)
+ g_string_append_len (path, elem, endptr - elem);
+
+ /* get the next element */
+ do {
+ if (!(next = va_arg (args, char *)))
+ break;
+
+ /* remove leading separators */
+ while (!strncmp (next, separator, slen))
+ next += slen;
+ } while (*next == '\0');
+
+ if (next || trimmed)
+ g_string_append_len (path, separator, slen);
+ }
+ va_end (args);
+
+ return g_string_free (path, FALSE);
+}
- if (next && *next){
- /* Append separator if needed */
- if (!found)
- g_string_append (result, separator);
+static gchar*
+strrchr_seperator (const gchar* filename)
+{
+#ifdef G_OS_WIN32
+ char *p2;
+#endif
+ char *p;
- /* Strip multiple contiguous separators */
- for (; strncmp (next, separator, slen) == 0
+ p = strrchr (filename, G_DIR_SEPARATOR);
#ifdef G_OS_WIN32
- || alt_separator == *next
+ p2 = strrchr (filename, '/');
+ if (p2 > p)
+ p = p2;
#endif
- ; )
- next += slen;
- }
- }
- /* Nul-terminate */
- g_string_append_c (result, 0);
- va_end (args);
- return g_string_free (result, FALSE);
+ return p;
}
gchar *
size_t count;
g_return_val_if_fail (filename != NULL, NULL);
- p = strrchr (filename, G_DIR_SEPARATOR);
+ p = strrchr_seperator (filename);
if (p == NULL)
return g_strdup (".");
if (p == filename)
return g_strdup (".");
/* No separator -> filename */
- r = strrchr (filename, G_DIR_SEPARATOR);
+ r = strrchr_seperator (filename);
if (r == NULL)
return g_strdup (filename);
if (r [1] == 0){
char *copy = g_strdup (filename);
copy [r-filename] = 0;
- r = strrchr (copy, G_DIR_SEPARATOR);
+ r = strrchr_seperator (copy);
if (r == NULL){
g_free (copy);
gchar *
g_find_program_in_path (const gchar *program)
{
- char *p = g_strdup (g_getenv ("PATH"));
- char *x = p, *l;
+ char *p;
+ char *x, *l;
gchar *curdir = NULL;
- char *save;
+ char *save = NULL;
#ifdef G_OS_WIN32
char *program_exe;
char *suffix_list[5] = {".exe",".cmd",".bat",".com",NULL};
#endif
g_return_val_if_fail (program != NULL, NULL);
+ x = p = g_strdup (g_getenv ("PATH"));
if (x == NULL || *x == '\0') {
curdir = g_get_current_dir ();
{
return name;
}
+
+gboolean
+g_ensure_directory_exists (const gchar *filename)
+{
+#ifdef G_OS_WIN32
+ gchar *dir_utf8 = g_path_get_dirname (filename);
+ gunichar2 *p;
+ gunichar2 *dir_utf16 = NULL;
+ int retval;
+
+ if (!dir_utf8 || !dir_utf8 [0])
+ return FALSE;
+
+ dir_utf16 = g_utf8_to_utf16 (dir_utf8, strlen (dir_utf8), NULL, NULL, NULL);
+ g_free (dir_utf8);
+
+ if (!dir_utf16)
+ return FALSE;
+
+ p = dir_utf16;
+
+ /* make life easy and only use one directory seperator */
+ while (*p != '\0')
+ {
+ if (*p == '/')
+ *p = '\\';
+ p++;
+ }
+
+ p = dir_utf16;
+
+ /* get past C:\ )*/
+ while (*p++ != '\\')
+ {
+ }
+
+ while (1) {
+ gboolean bRet = FALSE;
+ p = wcschr (p, '\\');
+ if (p)
+ *p = '\0';
+ retval = _wmkdir (dir_utf16);
+ if (retval != 0 && errno != EEXIST) {
+ g_free (dir_utf16);
+ return FALSE;
+ }
+ if (!p)
+ break;
+ *p++ = '\\';
+ }
+
+ g_free (dir_utf16);
+ return TRUE;
+#else
+ char *p;
+ gchar *dir = g_path_get_dirname (filename);
+ int retval;
+ struct stat sbuf;
+
+ if (!dir || !dir [0]) {
+ g_free (dir);
+ return FALSE;
+ }
+
+ if (stat (dir, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
+ g_free (dir);
+ return TRUE;
+ }
+
+ p = dir;
+ while (*p == '/')
+ p++;
+
+ while (1) {
+ p = strchr (p, '/');
+ if (p)
+ *p = '\0';
+ retval = mkdir (dir, 0777);
+ if (retval != 0 && errno != EEXIST) {
+ g_free (dir);
+ return FALSE;
+ }
+ if (!p)
+ break;
+ *p++ = '/';
+ }
+
+ g_free (dir);
+ return TRUE;
+#endif
+}
+