Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search for files in XDG_DATA_HOME and XDG_DATA_DIRS #443

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 81 additions & 34 deletions prboom2/src/SDL/i_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,11 +354,47 @@ static const char *I_GetBasePath(void)
*/

#ifdef _WIN32
#define PATH_SEPARATOR ';'
#define PATH_SEPARATOR ";"
#else
#define PATH_SEPARATOR ':'
#define PATH_SEPARATOR ":"
#endif

// Reference for XDG directories:
// <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>
static const char *I_GetXDGDataHome(void)
{
static char *datahome = 0;

if (!datahome)
{
const char *xdgdatahome = M_getenv("XDG_DATA_HOME");

if (!xdgdatahome || !*xdgdatahome)
{
const char *home = M_getenv("HOME");

if (!home)
home = "/";
datahome = Z_Malloc(strlen(home) + 1 + sizeof(".local/share"));
sprintf(datahome, "%s%s%s", home, !HasTrailingSlash(home) ? "/" : "", ".local/share");
}
else
{
datahome = Z_Strdup(xdgdatahome);
}
}
return datahome;
}

static const char *I_GetXDGDataDirs(void)
{
const char *datadirs = M_getenv("XDG_DATA_DIRS");

if (!datadirs || !*datadirs)
return "/usr/local/share/"PATH_SEPARATOR"/usr/share/";
return datadirs;
}

char* I_FindFileInternal(const char* wfname, const char* ext, dboolean isStatic)
{
// lookup table of directories to search
Expand All @@ -376,10 +412,7 @@ char* I_FindFileInternal(const char* wfname, const char* ext, dboolean isStatic)
{NULL, NULL, NULL, I_GetBasePath}, // search the base path provided by SDL
{NULL, "doom", "HOME"}, // ~/doom
{NULL, NULL, "HOME"}, // ~
{"/usr/local/share/games/doom"},
{"/usr/share/games/doom"},
{"/usr/local/share/doom"},
{"/usr/share/doom"},
{NULL, "games/doom", NULL, I_GetXDGDataHome}, // $HOME/.local/share/games/doom
}, *search;

static size_t num_search;
Expand All @@ -395,46 +428,60 @@ char* I_FindFileInternal(const char* wfname, const char* ext, dboolean isStatic)

if (!num_search)
{
char *dwp;
int extra = 0;
int datadirs = 0;
const char *dwp;

// calculate how many extra entries we need to add to the table
dwp = I_GetXDGDataDirs();
datadirs++;
while ((dwp = strchr(dwp, *PATH_SEPARATOR)))
dwp++, datadirs++;
extra += datadirs * 2; // two entries for each datadir
if ((dwp = M_getenv("DOOMWADPATH")))
{
extra++;
while ((dwp = strchr(dwp, *PATH_SEPARATOR)))
dwp++, extra++;
}

// initialize with the static lookup table
num_search = sizeof(search0)/sizeof(*search0);
search = Z_Malloc(num_search * sizeof(*search));
search = Z_Malloc((num_search + extra) * sizeof(*search));
memcpy(search, search0, num_search * sizeof(*search));
memset(&search[num_search], 0, extra * sizeof(*search));

// add $XDG_DATA_DIRS/games/doom and $XDG_DATA_DIRS/doom
{
char *ptr, *dup_dwp;

dup_dwp = Z_Strdup(I_GetXDGDataDirs());
ptr = strtok(dup_dwp, PATH_SEPARATOR);
while (ptr)
{
search[num_search].dir = Z_Strdup(ptr);
search[num_search].sub = "games/doom";
search[num_search + datadirs].dir = Z_Strdup(ptr);
search[num_search + datadirs].sub = "doom";
num_search++;
ptr = strtok(NULL, PATH_SEPARATOR);
}
Z_Free(dup_dwp);
num_search += datadirs;
}
// add each directory from the $DOOMWADPATH environment variable
if ((dwp = M_getenv("DOOMWADPATH")))
{
char *left, *ptr, *dup_dwp;
char *ptr, *dup_dwp;

dup_dwp = Z_Strdup(dwp);
left = dup_dwp;

for (;;)
ptr = strtok(dup_dwp, PATH_SEPARATOR);
while (ptr)
{
ptr = strchr(left, PATH_SEPARATOR);
if (ptr != NULL)
{
*ptr = '\0';

num_search++;
search = Z_Realloc(search, num_search * sizeof(*search));
memset(&search[num_search-1], 0, sizeof(*search));
search[num_search-1].dir = Z_Strdup(left);

left = ptr + 1;
}
else
{
break;
}
search[num_search].dir = Z_Strdup(ptr);
num_search++;
ptr = strtok(NULL, PATH_SEPARATOR);
}

num_search++;
search = Z_Realloc(search, num_search * sizeof(*search));
memset(&search[num_search-1], 0, sizeof(*search));
search[num_search-1].dir = Z_Strdup(left);

Z_Free(dup_dwp);
}
}
Expand Down