|
|
1.1 root 1: /*
2: Hatari - paths.c
3:
1.1.1.9 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: Set up the various path strings.
8: */
1.1.1.4 root 9: const char Paths_fileid[] = "Hatari paths.c : " __DATE__ " " __TIME__;
1.1 root 10:
11: #include <unistd.h>
12: #include <sys/stat.h>
13: #include <sys/types.h>
14:
15: #include "main.h"
16: #include "file.h"
17: #include "paths.h"
1.1.1.11 root 18: #include "str.h"
1.1 root 19:
1.1.1.5 root 20: #if defined(WIN32) && !defined(mkdir)
1.1.1.2 root 21: #define mkdir(name,mode) mkdir(name)
22: #endif /* WIN32 */
23:
1.1.1.10 root 24: #if defined(__MACOSX__)
25: #define HATARI_HOME_DIR "Library/Application Support/Hatari"
1.1.1.12! root 26: #elif defined(WIN32)
! 27: #define HATARI_HOME_DIR "AppData\\Local\\Hatari"
1.1.1.10 root 28: #else
1.1.1.12! root 29: #define HATARI_HOME_DIR ".config/hatari"
1.1.1.10 root 30: #endif
31:
1.1.1.3 root 32: static char sWorkingDir[FILENAME_MAX]; /* Working directory */
1.1 root 33: static char sDataDir[FILENAME_MAX]; /* Directory where data files of Hatari can be found */
34: static char sUserHomeDir[FILENAME_MAX]; /* User's home directory ($HOME) */
35: static char sHatariHomeDir[FILENAME_MAX]; /* Hatari's home directory ($HOME/.hatari/) */
36:
37:
38: /**
39: * Return pointer to current working directory string
40: */
41: const char *Paths_GetWorkingDir(void)
42: {
43: return sWorkingDir;
44: }
45:
46: /**
47: * Return pointer to data directory string
48: */
49: const char *Paths_GetDataDir(void)
50: {
51: return sDataDir;
52: }
53:
54: /**
55: * Return pointer to user's home directory string
56: */
57: const char *Paths_GetUserHome(void)
58: {
59: return sUserHomeDir;
60: }
61:
62: /**
63: * Return pointer to Hatari's home directory string
64: */
65: const char *Paths_GetHatariHome(void)
66: {
67: return sHatariHomeDir;
68: }
69:
70:
71: /**
72: * Explore the PATH environment variable to see where our executable is
73: * installed.
74: */
1.1.1.3 root 75: static void Paths_GetExecDirFromPATH(const char *argv0, char *pExecDir, int nMaxLen)
1.1 root 76: {
77: char *pPathEnv;
78: char *pAct;
79: char *pTmpName;
80: const char *pToken;
81:
82: /* Get the PATH environment string */
83: pPathEnv = getenv("PATH");
84: if (!pPathEnv)
85: return;
86: /* Duplicate the string because strtok destroys it later */
87: pPathEnv = strdup(pPathEnv);
88: if (!pPathEnv)
89: return;
90:
91: pTmpName = malloc(FILENAME_MAX);
92: if (!pTmpName)
1.1.1.10 root 93: {
94: perror("Paths_GetExecDirFromPATH");
95: free(pPathEnv);
1.1 root 96: return;
1.1.1.10 root 97: }
1.1 root 98:
99: /* If there is a semicolon in the PATH, we assume it is the PATH
100: * separator token (like on Windows), otherwise we use a colon. */
101: if (strchr((pPathEnv), ';'))
102: pToken = ";";
103: else
104: pToken = ":";
105:
106: pAct = strtok (pPathEnv, pToken);
107: while (pAct)
108: {
109: snprintf(pTmpName, FILENAME_MAX, "%s%c%s",
110: pAct, PATHSEP, argv0);
111: if (File_Exists(pTmpName))
112: {
113: /* Found the executable - so use the corresponding path: */
1.1.1.11 root 114: strlcpy(pExecDir, pAct, nMaxLen);
1.1 root 115: break;
116: }
1.1.1.12! root 117: pAct = strtok (NULL, pToken);
1.1 root 118: }
119:
120: free(pPathEnv);
121: free(pTmpName);
122: }
123:
124:
125: /**
126: * Locate the directory where the hatari executable resides
127: */
1.1.1.3 root 128: static char *Paths_InitExecDir(const char *argv0)
1.1 root 129: {
130: char *psExecDir; /* Path string where the hatari executable can be found */
131:
132: /* Allocate memory for storing the path string of the executable */
133: psExecDir = malloc(FILENAME_MAX);
134: if (!psExecDir)
135: {
136: fprintf(stderr, "Out of memory (Paths_Init)\n");
137: exit(-1);
138: }
139:
140: /* Determine the bindir...
141: * Start with empty string, then try to use OS specific functions,
142: * and finally analyze the PATH variable if it has not been found yet. */
143: psExecDir[0] = '\0';
144:
145: #if defined(__linux__)
146: {
147: int i;
148: /* On Linux, we can analyze the symlink /proc/self/exe */
1.1.1.11 root 149: i = readlink("/proc/self/exe", psExecDir, FILENAME_MAX-1);
1.1 root 150: if (i > 0)
151: {
152: char *p;
153: psExecDir[i] = '\0';
154: p = strrchr(psExecDir, '/'); /* Search last slash */
155: if (p)
156: *p = 0; /* Strip file name from path */
157: }
158: }
159: //#elif defined(WIN32) || defined(__CEGCC__)
160: // /* On Windows we can use GetModuleFileName for getting the exe path */
161: // GetModuleFileName(NULL, psExecDir, FILENAME_MAX);
162: #endif
163:
164: /* If we do not have the execdir yet, analyze argv[0] and the PATH: */
165: if (psExecDir[0] == 0)
166: {
1.1.1.12! root 167: if (strchr(argv0, PATHSEP) == NULL)
1.1 root 168: {
169: /* No separator in argv[0], we have to explore PATH... */
170: Paths_GetExecDirFromPATH(argv0, psExecDir, FILENAME_MAX);
171: }
172: else
173: {
174: /* There was a path separator in argv[0], so let's assume a
175: * relative or absolute path to the current directory in argv[0] */
176: char *p;
1.1.1.11 root 177: strlcpy(psExecDir, argv0, FILENAME_MAX);
1.1 root 178: p = strrchr(psExecDir, PATHSEP); /* Search last slash */
179: if (p)
180: *p = 0; /* Strip file name from path */
181: }
182: }
183:
184: return psExecDir;
185: }
186:
187:
188: /**
189: * Initialize the users home directory string
190: * and Hatari's home directory (~/.hatari)
191: */
192: static void Paths_InitHomeDirs(void)
193: {
194: char *psHome;
195:
196: psHome = getenv("HOME");
1.1.1.8 root 197: if (psHome)
198: strncpy(sUserHomeDir, psHome, FILENAME_MAX);
199: #if defined(WIN32)
200: else
1.1 root 201: {
1.1.1.8 root 202: char *psDrive;
203: int len = 0;
1.1.1.6 root 204: /* Windows home path? */
205: psHome = getenv("HOMEPATH");
1.1.1.8 root 206: psDrive = getenv("HOMEDRIVE");
207: if (psDrive)
208: {
209: len = strlen(psDrive);
210: len = len < FILENAME_MAX ? len : FILENAME_MAX;
211: strncpy(sUserHomeDir, psDrive, len);
212: }
213: if (psHome)
214: strncpy(sUserHomeDir+len, psHome, FILENAME_MAX-len);
1.1.1.6 root 215: }
1.1.1.8 root 216: #endif
1.1.1.6 root 217: if (!psHome)
218: {
1.1 root 219: /* $HOME not set, so let's use current working dir as home */
220: strcpy(sUserHomeDir, sWorkingDir);
221: strcpy(sHatariHomeDir, sWorkingDir);
1.1.1.12! root 222: return;
1.1 root 223: }
1.1.1.12! root 224:
! 225: sUserHomeDir[FILENAME_MAX-1] = 0;
! 226:
! 227: /* Try to use a private hatari directory in the users home directory */
! 228: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c%s", sUserHomeDir,
! 229: PATHSEP, HATARI_HOME_DIR);
! 230: if (File_DirExists(sHatariHomeDir))
1.1 root 231: {
1.1.1.12! root 232: return;
! 233: }
! 234: /* Try legacy location ~/.hatari */
! 235: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c.hatari", sUserHomeDir,
! 236: PATHSEP);
! 237: if (File_DirExists(sHatariHomeDir))
! 238: {
! 239: return;
! 240: }
1.1 root 241:
1.1.1.12! root 242: /* Hatari home directory does not exists yet...
! 243: * ... so let's try to create it: */
! 244: #if !defined(__MACOSX__) && !defined(WIN32)
! 245: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c.config", sUserHomeDir,
! 246: PATHSEP);
! 247: if (!File_DirExists(sHatariHomeDir))
! 248: {
! 249: /* ~/.config does not exist yet, create it first */
! 250: mkdir(sHatariHomeDir, 0700);
! 251: }
! 252: #endif
! 253: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c%s", sUserHomeDir,
! 254: PATHSEP, HATARI_HOME_DIR);
! 255: if (mkdir(sHatariHomeDir, 0750) != 0)
! 256: {
! 257: /* Failed to create, so use user's home dir instead */
! 258: strcpy(sHatariHomeDir, sUserHomeDir);
1.1 root 259: }
260: }
261:
262:
263: /**
264: * Initialize directory names
265: *
266: * The datadir will be initialized relative to the bindir (where the executable
267: * has been installed to). This means a lot of additional effort since we first
268: * have to find out where the executable is. But thanks to this effort, we get
269: * a relocatable package (we don't have any absolute path names in the program)!
270: */
1.1.1.3 root 271: void Paths_Init(const char *argv0)
1.1 root 272: {
273: char *psExecDir; /* Path string where the hatari executable can be found */
274:
275: /* Init working directory string */
1.1.1.5 root 276: if (getcwd(sWorkingDir, FILENAME_MAX) == NULL)
277: {
278: /* This should never happen... just in case... */
279: strcpy(sWorkingDir, ".");
280: }
1.1 root 281:
282: /* Init the user's home directory string */
283: Paths_InitHomeDirs();
284:
285: /* Get the directory where the executable resides */
286: psExecDir = Paths_InitExecDir(argv0);
287:
288: /* Now create the datadir path name from the bindir path name: */
289: if (psExecDir && strlen(psExecDir) > 0)
290: {
291: snprintf(sDataDir, sizeof(sDataDir), "%s%c%s",
292: psExecDir, PATHSEP, BIN2DATADIR);
293: }
294: else
295: {
296: /* bindir could not be determined, let's assume datadir is relative
297: * to current working directory... */
298: strcpy(sDataDir, BIN2DATADIR);
299: }
300:
301: /* And finally make a proper absolute path out of datadir: */
302: File_MakeAbsoluteName(sDataDir);
303:
304: free(psExecDir);
305:
306: /* fprintf(stderr, " WorkingDir = %s\n DataDir = %s\n UserHomeDir = %s\n HatariHomeDir = %s\n",
307: sWorkingDir, sDataDir, sUserHomeDir, sHatariHomeDir); */
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.