1 /** 2 * OS-specific paths. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.sys.paths; 15 16 import std.path; 17 18 version (Windows) 19 { 20 import core.stdc.wctype; 21 22 import std.exception; 23 import std.file; 24 import std.utf; 25 26 import win32.shlobj; 27 import win32.objidl; 28 import win32.windef; 29 import win32.winbase; 30 31 string getExecutableName() 32 { 33 auto path = new char[MAX_PATH]; 34 path.length = enforce(GetModuleFileNameA(null, path.ptr, cast(uint)path.length)); 35 return baseName(assumeUnique(path)); 36 } 37 38 private string getShellPath(int csidl) 39 { 40 LPITEMIDLIST pidl; 41 SHGetSpecialFolderLocation(null, csidl, &pidl); 42 scope(exit) 43 { 44 IMalloc aMalloc; 45 SHGetMalloc(&aMalloc); 46 aMalloc.Free(pidl); 47 } 48 49 auto path = new wchar[MAX_PATH]; 50 if (!SHGetPathFromIDListW(pidl, path.ptr)) 51 return null; 52 path.length = wcslen(path.ptr); 53 54 return toUTF8(path); 55 } 56 57 private string getAppDir(string appName, int csidl) 58 { 59 string dir = getShellPath(csidl) ~ `\` ~ (appName ? appName : getExecutableName()); 60 if (!exists(dir)) 61 mkdir(dir); 62 return dir; 63 } 64 65 string getLocalAppProfile (string appName = null) { return getAppDir(appName, CSIDL_LOCAL_APPDATA); } 66 string getRoamingAppProfile(string appName = null) { return getAppDir(appName, CSIDL_APPDATA); } 67 } 68 else // POSIX 69 { 70 import std.string; 71 import std.ascii; 72 import std.file; 73 74 alias toLower = std.ascii.toLower; 75 76 string getExecutableName() 77 { 78 // TODO: is this valid with OS X app bundles? 79 return baseName(readLink("/proc/self/exe")); 80 } 81 82 private string getPosixAppName(string appName) 83 { 84 string s = appName ? appName : getExecutableName(); 85 string s2; 86 foreach (c; s) 87 if (isAlphaNum(c)) 88 s2 ~= toLower(c); 89 else 90 if (!s2.endsWith('-')) 91 s2 ~= '-'; 92 return s2; 93 } 94 95 string getAppProfile(string appName = null) 96 { 97 string path = expandTilde("~/." ~ getPosixAppName(appName)); 98 if (!exists(path)) 99 mkdir(path); 100 return path; 101 } 102 103 alias getAppProfile getLocalAppProfile; 104 alias getAppProfile getRoamingAppProfile; 105 }