/* * path.c * This file is part of Paddle Puffle * * Copyright (C) 2015 - Félix Arreola Rodríguez * * Paddle Puffle is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Paddle Puffle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Paddle Puffle. If not, see . */ #include #include #include #include #include #include #ifdef MACOSX // for search paths #include "NSSystemDirectories.h" #include #include #include #endif #ifdef __MINGW32__ #include #include #endif #include "path.h" static char *systemdata_path; static char *l10n_path; static char *userdata_path; //#ifdef __MINGW32__ //const char *PathSeparator = "\\"; // for path assembly //#else //const char *PathSeparator = "/"; // for path assembly //#endif //const char *PathSeparators = "/\\"; // for path splits #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE !FALSE #endif #ifndef MAX_PATH # define MAX_PATH 2048 #endif int folder_exists (const char *fname) { struct stat s; return (stat(fname, &s) == 0 && S_ISDIR(s.st_mode)); } int file_exists (const char *fname) { struct stat s; return (stat(fname, &s) == 0 && S_ISREG(s.st_mode)); } static int split_path (const char *path, char * dir_part, char * filename_part) { int lslash, lnslash; int g; char *dup; lslash = -1; for (g = strlen (path) - 1; g >= 0; g--) { if (path[g] == '/' || path[g] == '\\') { lslash = g; break; } } if ( #ifdef __MINGW32__ lslash == 2 && path[1] == ':' && (path[0] >= 'A' && path[0] <= 'Z') #else lslash == 0 #endif ) { return FALSE; // we cannot split the root directory apart } if (lslash == strlen (path) - 1) { // trailing slash dup = strdup (path); dup[lslash] = 0; g = split_path (dup, dir_part, filename_part); free (dup); return g; } if (lslash == -1) { return FALSE; } for (g = lslash; g >= 0; g--) { if (path[g] != '/' && path[g] != '\\') { lnslash = g; break; } } if (dir_part) { strncpy (dir_part, path, lnslash + 1); dir_part[lnslash + 1] = 0; } if (filename_part) { strcpy (filename_part, &path[lslash + 1]); } return TRUE; } int folder_create (const char *fname) { char *parent_folder; char *sub_folder; int ok = TRUE; if (folder_exists (fname)) return TRUE; parent_folder = strdup (fname); sub_folder = strdup (fname); if (split_path (fname, parent_folder, sub_folder)) { if (!folder_exists (parent_folder)) { ok = folder_create(parent_folder); } } if (ok) { #ifdef __MINGW32__ ok = mkdir(fname) == 0; #else ok = mkdir(fname, 0775) == 0; #endif } free (parent_folder); free (sub_folder); return ok; } #ifdef __MINGW32__ // should be ecl_system_windows.cc ? static void ApplicationDataPath (char * buffer) { typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD, LPTSTR ); # define CSIDL_FLAG_CREATE 0x8000 # define CSIDL_APPDATA 0x1A # define SHGFP_TYPE_CURRENT 0 HINSTANCE shfolder_dll; SHGETFOLDERPATH SHGetFolderPath ; /* load the shfolder.dll to retreive SHGetFolderPath */ if ((shfolder_dll = LoadLibrary("shfolder.dll")) != NULL) { SHGetFolderPath = (SHGETFOLDERPATH)GetProcAddress(shfolder_dll, "SHGetFolderPathA"); if (SHGetFolderPath != NULL) { TCHAR szPath[MAX_PATH] = ""; /* get the "Application Data" folder for the current user */ if (S_OK == SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, szPath)) { strcpy (buffer, szPath); } } else { buffer[0] = '\0'; } FreeLibrary (shfolder_dll); } else { buffer[0] = '\0'; } } #endif void initSystemPaths (const char *argv_0) { char *progCallPath; int progdirexists; char *progdir; char *pref_path; #ifdef __MINGW32__ char winappdata_path[MAX_PATH]; ApplicationDataPath (winappdata_path); #endif progCallPath = strdup (argv_0); #if MACOSX CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef cfurlmain = CFBundleCopyExecutableURL(mainBundle); CFStringRef cffileStr = CFURLCopyFileSystemPath(cfurlmain, kCFURLPOSIXPathStyle); CFIndex cfmax = CFStringGetMaximumSizeOfFileSystemRepresentation(cffileStr); char *localbuffer; localbuffer = (char *) malloc (sizeof (char) * cfmax); if (CFStringGetFileSystemRepresentation(cffileStr, localbuffer, cfmax)) { free (progCallPath); progCallPath = localbuffer; // error skips this and defaults to argv[0] which works for most purposes } CFRelease(mainBundle); CFRelease(cfurlmain); CFRelease(cffileStr); #endif progdir = strdup (progCallPath); progdirexists = split_path (progCallPath, progdir, NULL); /* Primero conseguir el system path */ #ifdef __MINGW32__ if (!progdirexists) { systemdata_path = "./data/"; } else { systemdata_path = (char *) malloc (strlen (progdir) + 50); sprintf (systemdata_path, "%s/data/", progdir); } #elif MACOSX // Mac OS X applications are self-contained bundles, // i.e., directories like "Enigma.app". Resources are // placed in those bundles under "Enigma.app/Contents/Resources", // the main executable would be "Enigma.app/Contents/MacOS/enigma". // Here, we get the executable name, clip off the last bit, chdir into it, // then chdir to ../Resources. The original SDL implementation chdirs to // "../../..", i.e. the directory the bundle is placed in. This breaks // the self-containedness. systemdata_path = (char *) malloc (sizeof (char) * (strlen (progdir) + 30)); sprintf (systemdata_path, "%s/../Resources/data/", progdir); #else /* Para Linux */ systemdata_path = GAMEDATA_DIR; #endif /* Ahora, conseguir el L10n */ l10n_path = LOCALEDIR; #ifdef __MINGW32__ if (progdirexists) { l10n_path = (char *) malloc (strlen (progdir) + strlen (l10n_path) + 10); if (strncmp (LOCALEDIR, "/", 1) == 0 || strncmp (LOCALEDIR, "\\", 1) == 0) { /* No necesita slash final */ sprintf (l10n_path, "%s%s", progdir, LOCALEDIR); } else { sprintf (l10n_path, "%s/%s", progdir, LOCALEDIR); } } #elif MACOSX l10n_path = (char *) malloc (sizeof (char) * (strlen (progdir) + 30)); sprintf (l10n_path, "%s/../Resources/locale", progdir); #endif /* Ahora conseguir el user path */ if (getenv ("HOME") != 0) { pref_path = getenv ("HOME"); if (!folder_exists (pref_path)) { if (!folder_create (pref_path)) { fprintf (stderr, "Error Home directory does not exist.\n"); userdata_path = NULL; } } #ifdef MACOSX userdata_path = (char *) malloc (strlen (pref_path) + 40); sprintf (userdata_path, "%s/Library/Application Support", pref_path); #else userdata_path = strdup (pref_path); #endif #ifdef __MINGW32__ } else if (winappdata_path[0] != 0) { userdata_path = strdup (winappdata_path); #endif } else { userdata_path = NULL; } /* Liberar las cadenas temporales */ free (progdir); free (progCallPath); } char *get_systemdata_path (void) { return systemdata_path; } char *get_l10n_path (void) { return l10n_path; } char *get_userdata_path (void) { return userdata_path; }