#include <stdio.h>
#include <glib.h>
#include <errno.h>
-#include <sys/types.h>
+#include <sys/stat.h>
-#ifdef G_OS_UNIX
-#include <pthread.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
+#ifdef G_OS_WIN32
+#include <direct.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef G_OS_WIN32
-#include <direct.h>
-#include <io.h>
-#endif
-
-
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;
+ size_t slen;
g_return_val_if_fail (separator != NULL, NULL);
- g_return_val_if_fail (first_element != NULL, NULL);
-
- 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){
- next = va_arg (args, char *);
- p = (s + strlen (s));
-
- if (next && p - slen > s){
- for (; strncmp (p-slen, separator, slen) == 0; ){
- 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;
}
- g_string_append_len (result, s, p - s);
-
- if (next && *next){
- g_string_append (result, separator);
-
- for (; strncmp (next, separator, slen) == 0; )
+
+ /* 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);
}
- g_string_append_c (result, 0);
va_end (args);
+
+ return g_string_free (path, FALSE);
+}
- return g_string_free (result, FALSE);
+static gchar*
+strrchr_seperator (const gchar* filename)
+{
+#ifdef G_OS_WIN32
+ char *p2;
+#endif
+ char *p;
+
+ p = strrchr (filename, G_DIR_SEPARATOR);
+#ifdef G_OS_WIN32
+ p2 = strrchr (filename, '/');
+ if (p2 > p)
+ p = p2;
+#endif
+
+ 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);
return g_strdup (&r[1]);
}
-gboolean
-g_path_is_absolute (const char *filename)
+#ifndef HAVE_STRTOK_R
+// This is from BSD's strtok_r
+
+char *
+strtok_r(char *s, const char *delim, char **last)
{
- g_return_val_if_fail (filename != NULL, FALSE);
-#ifdef G_OS_WIN32
- if (filename[0] != '\0' && filename[1] != '\0' && filename[1] == ':' &&
- filename[2] != '\0' && filename[2] == '\\')
- return TRUE;
- else
- return FALSE;
-#else
- return (*filename == '/');
-#endif
+ char *spanp;
+ int c, sc;
+ char *tok;
+
+ if (s == NULL && (s = *last) == NULL)
+ return NULL;
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0; ){
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0){ /* no non-delimiter characters */
+ *last = NULL;
+ return NULL;
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;){
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else {
+ char *w = s - 1;
+ *w = '\0';
+ }
+ *last = s;
+ return tok;
+ }
+ }
+ while (sc != 0);
+ }
+ /* NOTREACHED */
}
+#endif
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};
+ int listx;
+ gboolean hasSuffix;
+#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 ();
x = curdir;
}
+#ifdef G_OS_WIN32
+ /* see if program already has a suffix */
+ listx = 0;
+ hasSuffix = FALSE;
+ while (!hasSuffix && suffix_list[listx]) {
+ hasSuffix = g_str_has_suffix(program,suffix_list[listx++]);
+ }
+#endif
+
while ((l = strtok_r (x, G_SEARCHPATH_SEPARATOR_S, &save)) != NULL){
char *probe_path;
return probe_path;
}
g_free (probe_path);
+
+#ifdef G_OS_WIN32
+ /* check for program with a suffix attached */
+ if (!hasSuffix) {
+ listx = 0;
+ while (suffix_list[listx]) {
+ program_exe = g_strjoin(NULL,program,suffix_list[listx],NULL);
+ probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program_exe, NULL);
+ if (access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */
+ g_free (curdir);
+ g_free (p);
+ g_free (program_exe);
+ return probe_path;
+ }
+ listx++;
+ g_free (probe_path);
+ g_free (program_exe);
+ }
+ }
+#endif
}
g_free (curdir);
g_free (p);
return NULL;
}
-gchar *
-g_get_current_dir (void)
-{
- int s = 32;
- char *buffer = NULL, *r;
- gboolean fail;
-
- do {
- buffer = g_realloc (buffer, s);
- r = getcwd (buffer, s);
- fail = (r == NULL && errno == ERANGE);
- if (fail) {
- s <<= 1;
- }
- } while (fail);
+static char *name;
- return r;
+void
+g_set_prgname (const gchar *prgname)
+{
+ name = g_strdup (prgname);
}
-#if defined (G_OS_UNIX)
-
-static pthread_mutex_t home_lock = PTHREAD_MUTEX_INITIALIZER;
-static const gchar *home_dir;
-
-/* Give preference to /etc/passwd than HOME */
-const gchar *
-g_get_home_dir (void)
+gchar *
+g_get_prgname (void)
{
- if (home_dir == NULL){
- pthread_mutex_lock (&home_lock);
- if (home_dir == NULL){
-#ifdef HAVE_GETPWENT_R
- struct passwd pwbuf, *track;
- char buf [4096];
- uid_t uid;
-
- uid = getuid ();
-
- setpwent ();
-
- while (getpwent_r (&pwbuf, buf, sizeof (buf), &track) == 0){
- if (pwbuf.pw_uid == uid){
- home_dir = g_strdup (pwbuf.pw_dir);
- break;
- }
- }
- endpwent ();
-#endif
- if (home_dir == NULL)
- home_dir = g_getenv ("HOME");
- pthread_mutex_unlock (&home_lock);
- }
- }
- return home_dir;
+ return name;
}
-#elif defined (G_OS_WIN32)
-#include <windows.h>
-
-const gchar *
-g_get_home_dir (void)
+gboolean
+g_ensure_directory_exists (const gchar *filename)
{
- /* FIXME */
- const gchar *drive = g_getenv ("HOMEDRIVE");
- const gchar *path = g_getenv ("HOMEPATH");
- gchar *home_dir = NULL;
+#ifdef G_OS_WIN32
+ gchar *dir_utf8 = g_path_get_dirname (filename);
+ gunichar2 *p;
+ gunichar2 *dir_utf16 = NULL;
+ int retval;
- if (drive && path) {
- home_dir = malloc(strlen(drive) + strlen(path) +1);
- if (home_dir) {
- sprintf(home_dir, "%s%s", drive, path);
- }
- }
+ if (!dir_utf8 || !dir_utf8 [0])
+ return FALSE;
- return home_dir;
-}
+ dir_utf16 = g_utf8_to_utf16 (dir_utf8, strlen (dir_utf8), NULL, NULL, NULL);
+ g_free (dir_utf8);
-#else
+ if (!dir_utf16)
+ return FALSE;
-const gchar *
-g_get_home_dir (void)
-{
- g_error ("%s", "g_get_home_dir not implemented on this platform");
- return NULL;
-}
+ p = dir_utf16;
-#endif
+ /* make life easy and only use one directory seperator */
+ while (*p != '\0')
+ {
+ if (*p == '/')
+ *p = '\\';
+ p++;
+ }
-static const char *tmp_dir;
+ p = dir_utf16;
-#ifdef G_OS_UNIX
-static pthread_mutex_t tmp_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
+ /* get past C:\ )*/
+ while (*p++ != '\\')
+ {
+ }
-const gchar *
-g_get_tmp_dir (void)
-{
- if (tmp_dir == NULL){
-#ifdef G_OS_UNIX
- pthread_mutex_lock (&tmp_lock);
-#endif
- if (tmp_dir == NULL){
- tmp_dir = g_getenv ("TMPDIR");
- if (tmp_dir == NULL){
- tmp_dir = g_getenv ("TMP");
- if (tmp_dir == NULL){
- tmp_dir = g_getenv ("TEMP");
- if (tmp_dir == NULL)
-#if defined (G_OS_WIN32)
- tmp_dir = "C:\\temp";
+ 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
- tmp_dir = "/tmp";
-#endif
- }
- }
+ 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;
}
-#ifdef G_OS_UNIX
- pthread_mutex_unlock (&tmp_lock);
-#endif
+ if (!p)
+ break;
+ *p++ = '/';
}
- return tmp_dir;
-}
-
-const char *
-g_get_user_name (void)
-{
- return g_getenv ("USER");
-}
-
-static char *name;
-
-void
-g_set_prgname (const gchar *prgname)
-{
- name = g_strdup (prgname);
+
+ g_free (dir);
+ return TRUE;
+#endif
}
-gchar *
-g_get_prgname (void)
-{
- return name;
-}