From 1de7a4cc09172bbc99912e1410f46fc16c1a05ec Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sun, 17 Sep 2006 14:34:46 -0700 Subject: [PATCH] FcStrCanonFileName buggy for mingw. (bug 8311) FcStrCanonFileName checks whether s[0] == '/', and recurses if not. This only works on POSIX. On dos, this crashes with a stack overflow. The patch attached splits this functionality in two functions (FcStrCanonAbsoluteFilename) and uses GetFullPathName on windows to get an absolute path. It also fixes a number of other issues. With this patch, LilyPond actually produces output on Windows. --- src/fccache.c | 5 +++ src/fcstr.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/fccache.c b/src/fccache.c index 7e2c1be..6a3d8e8 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -689,6 +689,11 @@ bail1: return NULL; } + +#ifdef _WIN32 +#define mkdir(path,mode) _mkdir(path) +#endif + static FcBool FcMakeDirectory (const FcChar8 *dir) { diff --git a/src/fcstr.c b/src/fcstr.c index 7ec2ab4..368761d 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef _WIN32 +#include +#endif FcChar8 * FcStrCopy (const FcChar8 *s) @@ -831,26 +834,13 @@ FcStrBasename (const FcChar8 *file) } FcChar8 * -FcStrCanonFilename (const FcChar8 *s) +FcStrCanonAbsoluteFilename (const FcChar8 *s) { FcChar8 *file; FcChar8 *f; const FcChar8 *slash; int size; - - if (*s != '/') - { - FcChar8 *full; - - FcChar8 cwd[FC_MAX_FILE_LEN + 2]; - if (getcwd ((char *) cwd, FC_MAX_FILE_LEN) == NULL) - return NULL; - strcat ((char *) cwd, "/"); - full = FcStrPlus (cwd, s); - file = FcStrCanonFilename (full); - FcStrFree (full); - return file; - } + size = strlen ((char *) s) + 1; file = malloc (size); if (!file) @@ -889,6 +879,74 @@ FcStrCanonFilename (const FcChar8 *s) } return file; } + +#ifdef _WIN32 +/* + * Convert '\\' to '/' , remove double '/' + */ +static void +FcConvertDosPath (char *str) +{ + size_t len = strlen (str); + char *p = str; + char *dest = str; + char *end = str + len; + char last = 0; + + while (p < end) + { + if (*p == '\\') + *p = '/'; + + if (*p != '/' + || last != '/') + { + *dest++ = *p; + } + + last = *p; + p++; + } + + *dest = 0; +} +#endif + +FcChar8 * +FcStrCanonFilename (const FcChar8 *s) +{ +#ifdef _WIN32 + FcChar8 full[FC_MAX_FILE_LEN + 2]; + FcChar8 basename[FC_MAX_FILE_LEN + 2]; + int size = GetFullPathName (s, sizeof (full) -1, + full, + basename); + + if (size == 0) + perror ("GetFullPathName"); + + FcConvertDosPath (full); + return FcStrCanonAbsoluteFilename (full); +#else + if (s[0] == '/') + return FcStrCanonAbsoluteFilename (s); + else + { + FcChar8 *full; + FcChar8 *file; + + FcChar8 cwd[FC_MAX_FILE_LEN + 2]; + if (getcwd ((char *) cwd, FC_MAX_FILE_LEN) == NULL) + return NULL; + strcat ((char *) cwd, "/"); + full = FcStrPlus (cwd, s); + file = FcStrCanonAbsoluteFilename (full); + FcStrFree (full); + return file; + } +#endif +} + FcStrSet * FcStrSetCreate (void)