mirror of
https://git.zap.org.au/git/trader.git
synced 2024-12-04 14:46:45 -05:00
Use the XDG Base Directory Specification for storing game files
This commit is contained in:
parent
88dc3b54a5
commit
b132686a63
8
NEWS
8
NEWS
@ -25,6 +25,14 @@ __ https://www.zap.org.au/
|
|||||||
Version 7.15 (not yet released)
|
Version 7.15 (not yet released)
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
Changed the default location where game files are saved from `~/.trader`
|
||||||
|
to `~/.local/share/trader`, so as to follow the `XDG Base Directory
|
||||||
|
Specification`__. If set, the ``XDG_DATA_HOME`` environment variable
|
||||||
|
will override this location. If the `~/.trader` directory is already
|
||||||
|
present, it will continue to be used. Updated the manual page to suit.
|
||||||
|
|
||||||
|
__ https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||||
|
|
||||||
Updated to GNU Gettext 0.20 or later. Updated to the latest snapshot of
|
Updated to GNU Gettext 0.20 or later. Updated to the latest snapshot of
|
||||||
the Gnulib GNU Portability Library. Also updated the `INSTALL` file to
|
the Gnulib GNU Portability Library. Also updated the `INSTALL` file to
|
||||||
list the latest tested versions of operating systems, including a new
|
list the latest tested versions of operating systems, including a new
|
||||||
|
23
doc/trader.6
23
doc/trader.6
@ -154,6 +154,15 @@ Or, if you prefer the old amber screens of yesteryear:
|
|||||||
.\" *********************************************************************
|
.\" *********************************************************************
|
||||||
.SH ENVIRONMENT
|
.SH ENVIRONMENT
|
||||||
.TP
|
.TP
|
||||||
|
.BR XDG_DATA_HOME ", " HOME
|
||||||
|
If \fBXDG_DATA_HOME\fR is set to an absolute pathname (that is, a path
|
||||||
|
that starts with \*(lq\fI/\fR\*(rq), Star Traders will use that
|
||||||
|
directory, with a subdirectory \fItrader\fR, to store game files. If
|
||||||
|
this environment variable is not set or does not start with
|
||||||
|
\*(lq\fI/\fR\*(rq, \fI\(ti/.local/share/trader\fR will be used instead,
|
||||||
|
where \*(lq\fI\(ti\fR\*(rq represents your home directory, as contained
|
||||||
|
in the \fBHOME\fR environment variable.
|
||||||
|
.TP
|
||||||
.BR LINES ", " COLUMNS
|
.BR LINES ", " COLUMNS
|
||||||
Star Traders uses the Curses library for displaying text on the screen.
|
Star Traders uses the Curses library for displaying text on the screen.
|
||||||
As such, it will access these two environment variables if the underlying
|
As such, it will access these two environment variables if the underlying
|
||||||
@ -177,11 +186,17 @@ manual pages for more details on locale settings.
|
|||||||
.\" *********************************************************************
|
.\" *********************************************************************
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.TP
|
.TP
|
||||||
|
.IB \(ti/.local/share/trader/game N
|
||||||
|
Star Traders stores saved game files in the \fI.local/share/trader\fR
|
||||||
|
subdirectory in your home directory (unless overriden by the
|
||||||
|
\fBXDG_DATA_HOME\fR environment variable). \fIN\fR is a number between
|
||||||
|
\fB1\fR and \fB9\fR inclusive. The game file is scrambled to prevent you
|
||||||
|
or others from casually cheating!
|
||||||
|
.TP
|
||||||
.IB \(ti/.trader/game N
|
.IB \(ti/.trader/game N
|
||||||
Star Traders stores saved game files in the \fI.trader\fR subdirectory in
|
If the \fI\(ti/.trader\fR directory exists, game files will be read from
|
||||||
your home directory. \fIN\fR is a number between \fB1\fR and \fB9\fR
|
and saved to this location instead. This is for compatibility with
|
||||||
inclusive. The game file is scrambled to prevent you or others from
|
versions of Star Traders prior to version 7.15.
|
||||||
casually cheating!
|
|
||||||
.\" *********************************************************************
|
.\" *********************************************************************
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
None yet known...
|
None yet known...
|
||||||
|
78
src/utils.c
78
src/utils.c
@ -53,6 +53,10 @@ wchar_t *mon_thousands_sep; // Locale's monetary thousands separator
|
|||||||
* Module-specific constants and macros *
|
* Module-specific constants and macros *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
#define DIRSEP "/" // Directory separator
|
||||||
|
#define HIDDEN_PATH "." // Hidden file start char
|
||||||
|
#define XDG_DATA_DEFAULT ".local" DIRSEP "share"
|
||||||
|
|
||||||
#define GAME_FILENAME_PROTO "game%d"
|
#define GAME_FILENAME_PROTO "game%d"
|
||||||
#define GAME_FILENAME_BUFSIZE 16
|
#define GAME_FILENAME_BUFSIZE 16
|
||||||
|
|
||||||
@ -306,10 +310,15 @@ void init_program_name (const char *argv0)
|
|||||||
/* This implementation assumes a POSIX environment with an ASCII-safe
|
/* This implementation assumes a POSIX environment with an ASCII-safe
|
||||||
character encoding (such as ASCII or UTF-8). */
|
character encoding (such as ASCII or UTF-8). */
|
||||||
|
|
||||||
|
const char *dirsep = DIRSEP;
|
||||||
|
|
||||||
|
|
||||||
|
assert(strlen(dirsep) == 1);
|
||||||
|
|
||||||
if (argv0 == NULL || *argv0 == '\0') {
|
if (argv0 == NULL || *argv0 == '\0') {
|
||||||
program_name = PACKAGE;
|
program_name = PACKAGE;
|
||||||
} else {
|
} else {
|
||||||
char *p = strrchr(argv0, '/');
|
char *p = strrchr(argv0, dirsep[0]);
|
||||||
|
|
||||||
if (p != NULL && *++p != '\0') {
|
if (p != NULL && *++p != '\0') {
|
||||||
program_name = xstrdup(p);
|
program_name = xstrdup(p);
|
||||||
@ -343,21 +352,74 @@ const char *home_directory (void)
|
|||||||
|
|
||||||
const char *data_directory (void)
|
const char *data_directory (void)
|
||||||
{
|
{
|
||||||
/* This implementation assumes a POSIX environment by using "/" as
|
/* This implementation assumes a POSIX environment by using DIRSEP as
|
||||||
the directory separator. It also assumes a dot-starting directory
|
the directory separator. It also assumes a dot-starting directory
|
||||||
name is permissible (again, true on POSIX systems) and that the
|
name is permissible (again, true on POSIX systems) and that the
|
||||||
character encoding is ASCII-safe. */
|
character encoding is ASCII-safe. */
|
||||||
|
|
||||||
|
const char *dirsep = DIRSEP;
|
||||||
|
const char *dirsep_hiddenpath = DIRSEP HIDDEN_PATH;
|
||||||
|
const char *datahome_part = DIRSEP XDG_DATA_DEFAULT DIRSEP;
|
||||||
|
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
|
||||||
|
assert(strlen(dirsep) == 1);
|
||||||
|
|
||||||
if (data_directory_str == NULL) {
|
if (data_directory_str == NULL) {
|
||||||
const char *home = home_directory();
|
const char *home = home_directory();
|
||||||
|
const char *xdg_data_home = getenv("XDG_DATA_HOME");
|
||||||
|
|
||||||
if (program_name != NULL && home != NULL) {
|
if (program_name != NULL) {
|
||||||
char *p = xmalloc(strlen(home) + strlen(program_name) + 3);
|
int len_program_name = strlen(program_name);
|
||||||
|
|
||||||
|
if (home != NULL) {
|
||||||
|
char *p = xmalloc(strlen(home) + strlen(dirsep_hiddenpath)
|
||||||
|
+ len_program_name + 1);
|
||||||
|
|
||||||
strcpy(p, home);
|
strcpy(p, home);
|
||||||
strcat(p, "/.");
|
strcat(p, dirsep_hiddenpath);
|
||||||
strcat(p, program_name);
|
strcat(p, program_name);
|
||||||
|
|
||||||
|
if (stat(p, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
|
||||||
|
// Directory "$HOME/.trader" exists: use that
|
||||||
data_directory_str = p;
|
data_directory_str = p;
|
||||||
|
} else {
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_directory_str == NULL && xdg_data_home != NULL
|
||||||
|
&& *xdg_data_home != '\0' && *xdg_data_home == dirsep[0]) {
|
||||||
|
// Use directory "$XDG_DATA_HOME/trader"
|
||||||
|
|
||||||
|
/* Note that the XDG Base Directory Specification v0.7
|
||||||
|
requires XDG_DATA_HOME to contain an absolute path:
|
||||||
|
the variable must be ignored if it does not start with
|
||||||
|
the directory separator DIRSEP ("/") */
|
||||||
|
|
||||||
|
char *p = xmalloc(strlen(xdg_data_home) + strlen(DIRSEP)
|
||||||
|
+ len_program_name + 1);
|
||||||
|
|
||||||
|
strcpy(p, xdg_data_home);
|
||||||
|
strcat(p, dirsep);
|
||||||
|
strcat(p, program_name);
|
||||||
|
|
||||||
|
data_directory_str = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_directory_str == NULL && home != NULL) {
|
||||||
|
// Use directory "$HOME/.local/share/trader"
|
||||||
|
|
||||||
|
char *p = xmalloc(strlen(home) + strlen(datahome_part)
|
||||||
|
+ len_program_name + 1);
|
||||||
|
|
||||||
|
strcpy(p, home);
|
||||||
|
strcat(p, datahome_part);
|
||||||
|
strcat(p, program_name);
|
||||||
|
|
||||||
|
data_directory_str = p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +435,8 @@ char *game_filename (int gamenum)
|
|||||||
/* This implementation assumes a POSIX environment and an ASCII-safe
|
/* This implementation assumes a POSIX environment and an ASCII-safe
|
||||||
character encoding. */
|
character encoding. */
|
||||||
|
|
||||||
|
const char *dirsep = DIRSEP;
|
||||||
|
|
||||||
char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename
|
char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename
|
||||||
const char *dd; // Data directory
|
const char *dd; // Data directory
|
||||||
|
|
||||||
@ -387,10 +451,10 @@ char *game_filename (int gamenum)
|
|||||||
if (dd == NULL) {
|
if (dd == NULL) {
|
||||||
return xstrdup(buf);
|
return xstrdup(buf);
|
||||||
} else {
|
} else {
|
||||||
char *p = xmalloc(strlen(dd) + strlen(buf) + 2);
|
char *p = xmalloc(strlen(dd) + strlen(dirsep) + strlen(buf) + 1);
|
||||||
|
|
||||||
strcpy(p, dd);
|
strcpy(p, dd);
|
||||||
strcat(p, "/");
|
strcat(p, dirsep);
|
||||||
strcat(p, buf);
|
strcat(p, buf);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
18
src/utils.h
18
src/utils.h
@ -99,12 +99,18 @@ extern const char *home_directory (void);
|
|||||||
Parameters: (none)
|
Parameters: (none)
|
||||||
Returns: const char * - Pointer to data directory
|
Returns: const char * - Pointer to data directory
|
||||||
|
|
||||||
This function returns the full pathname to a potentially-writable
|
This function returns the full pathname to a potentially-writable data
|
||||||
subdirectory within the user's home directory. Essentially, this
|
directory, usually within the user's home directory.
|
||||||
function returns home_directory() + "/." + program_name. Note that
|
|
||||||
this path is NOT created by this function, nor is the ability to write
|
Assuming program_name is set to "trader", if "$HOME/.trader" exists,
|
||||||
to this path checked. NULL is returned if this path cannot be
|
that directory is returned as the data directory. Otherwise, if the
|
||||||
determined.
|
environment variable XDG_DATA_HOME is set and contains an absolute
|
||||||
|
pathname, "$XDG_DATA_HOME/trader" is returned. Otherwise,
|
||||||
|
"$HOME/.local/share/trader" is returned.
|
||||||
|
|
||||||
|
Note that the returned path is NOT created by this function, nor is the
|
||||||
|
ability to read from or write to this path checked. NULL is returned
|
||||||
|
if the path cannot be determined.
|
||||||
*/
|
*/
|
||||||
extern const char *data_directory (void);
|
extern const char *data_directory (void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user