Skip to content

Commit

Permalink
Make IWAD search paths compliant with XDG spec.
Browse files Browse the repository at this point in the history
The XDG Base Directory Specification defines standard directories
that are searched for data files via the XDG_DATA_HOME and
XDG_DATA_DIRS environment variables:
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

To make Chocolate Doom a good citizen, use these directories to
determine some of the locations in which to look for IWAD files. This
includes /usr/share/games/doom, which is absorbed under the default
value of the XDG_DATA_DIRS variable. We also now support the alternative
~/.local/share/games/doom as a user-writeable path in the user's home
directory that doesn't require root privileges.

This is part of #597 (thanks to @chungy for the suggestion).
  • Loading branch information
fragglet committed Aug 23, 2015
1 parent f804a75 commit d1d65f2
Showing 1 changed file with 82 additions and 46 deletions.
128 changes: 82 additions & 46 deletions src/d_iwad.c
Expand Up @@ -509,85 +509,126 @@ static GameMission_t IdentifyIWADByName(char *name, int mask)
return mission;
}

//
// Add directories from the list in the DOOMWADPATH environment variable.
//

static void AddDoomWadPath(void)
// Add IWAD directories parsed from splitting a path string containing
// paths separated by PATH_SEPARATOR. 'suffix' is a string to concatenate
// to the end of the paths before adding them.
static void AddIWADPath(char *path, char *suffix)
{
char *doomwadpath;
char *p;

// Check the DOOMWADPATH environment variable.

doomwadpath = getenv("DOOMWADPATH");

if (doomwadpath == NULL)
{
return;
}
char *left, *p;

doomwadpath = M_StringDuplicate(doomwadpath);

// Add the initial directory

AddIWADDir(doomwadpath);
path = M_StringDuplicate(path);

// Split into individual dirs within the list.

p = doomwadpath;
left = path;

for (;;)
{
p = strchr(p, PATH_SEPARATOR);

p = strchr(left, PATH_SEPARATOR);
if (p != NULL)
{
// Break at the separator and store the right hand side
// Break at the separator and use the left hand side
// as another iwad dir

*p = '\0';
p += 1;

AddIWADDir(p);
AddIWADDir(M_StringJoin(left, suffix, NULL));
left = p + 1;
}
else
{
break;
}
}

AddIWADDir(M_StringJoin(left, suffix, NULL));

free(path);
}

// Add standard directories where IWADs are located on Unix systems.
// To respect the freedesktop.org specification we support overriding
// using standard environment variables. See the XDG Base Directory
// Specification:
// <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>
static void AddXdgDirs(void)

This comment has been minimized.

Copy link
@chungy

chungy Aug 29, 2015

Contributor

The Windows build emits a warning about this function not being used. For optimized builds, it shouldn't affect the binary, but it wouldn't hurt to wrap this in an #ifndef _WIN32 block.

{
char *env, *tmp_env;

// Quote:
// > $XDG_DATA_HOME defines the base directory relative to which
// > user specific data files should be stored. If $XDG_DATA_HOME
// > is either not set or empty, a default equal to
// > $HOME/.local/share should be used.
env = getenv("XDG_DATA_HOME");
tmp_env = NULL;

if (env == NULL)
{
char *homedir = getenv("HOME");
if (homedir == NULL)
{
homedir = "/";
}

tmp_env = M_StringJoin(homedir, "/.local/share", NULL);
env = tmp_env;
}

// We support $XDG_DATA_HOME/games/doom (which will usually be
// ~/.local/share/games/doom) as a user-writeable extension to
// the usual /usr/share/games/doom location.
AddIWADDir(M_StringJoin(env, "/games/doom", NULL));
free(tmp_env);

// Quote:
// > $XDG_DATA_DIRS defines the preference-ordered set of base
// > directories to search for data files in addition to the
// > $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS
// > should be seperated with a colon ':'.
// >
// > If $XDG_DATA_DIRS is either not set or empty, a value equal to
// > /usr/local/share/:/usr/share/ should be used.
env = getenv("XDG_DATA_DIRS");
if (env == NULL)
{
// (Trailing / omitted from paths, as it is added below)
env = "/usr/local/share:/usr/share";
}

// The "standard" location for IWADs on Unix that is supported by most
// source ports is /usr/share/games/doom - we support this through the
// XDG_DATA_DIRS mechanism, through which it can be overridden.
AddIWADPath(env, "/games/doom");
}

//
// Build a list of IWAD files
//

static void BuildIWADDirList(void)
{
char *doomwaddir;
char *env;

if (iwad_dirs_built)
{
return;
}

// Look in the current directory. Doom always does this.

AddIWADDir(".");

// Add DOOMWADDIR if it is in the environment

doomwaddir = getenv("DOOMWADDIR");

if (doomwaddir != NULL)
env = getenv("DOOMWADDIR");
if (env != NULL)
{
AddIWADDir(doomwaddir);
}

// Add dirs from DOOMWADPATH
AddIWADDir(env);
}

AddDoomWadPath();
// Add dirs from DOOMWADPATH:
env = getenv("DOOMWADPATH");
if (env != NULL)
{
AddIWADPath(env, "");
}

#ifdef _WIN32

Expand All @@ -603,12 +644,7 @@ static void BuildIWADDirList(void)
CheckSteamGUSPatches();

#else

// Standard places where IWAD files are installed under Unix.

AddIWADDir("/usr/share/games/doom");
AddIWADDir("/usr/local/share/games/doom");

AddXdgDirs();
#endif

// Don't run this function again.
Expand Down

0 comments on commit d1d65f2

Please sign in to comment.