- sanitization of temporary file stuff for Timidity++.

* do not use the global temp directory. Instead create one in the AppData folder.
* removed lots of unneeded code from tmpfileplus.
* use C++ strings in there.
This commit is contained in:
Christoph Oelckers 2017-12-02 17:33:43 +01:00
parent f6f17fbfb4
commit 7cbcbe66c0
7 changed files with 105 additions and 83 deletions

View file

@ -53,6 +53,7 @@ FString M_ZLibError(int zerrnum);
#ifdef __unix__
FString GetUserFile (const char *path); // Prepends ~/.zdoom to path
#endif
FString M_GetAppDataPath(bool create);
FString M_GetCachePath(bool create);
FString M_GetAutoexecPath();
FString M_GetCajunPath(const char *filename);

View file

@ -39,6 +39,35 @@
#include "m_misc.h"
#include "version.h" // for GAMENAME
//===========================================================================
//
// M_GetAppDataPath macOS
//
// Returns the path for the AppData folder.
//
//===========================================================================
FString M_GetAppDataPath(bool create)
{
FString path;
char pathstr[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX))
{
path = pathstr;
}
else
{
path = progdir;
}
path += "/" GAMENAMELOWERCASE;
if (create) CreatePath(path);
return path;
}
//===========================================================================
//
// M_GetCachePath macOS
@ -64,6 +93,7 @@ FString M_GetCachePath(bool create)
path = progdir;
}
path += "/zdoom/cache";
if (create) CreatePath(path);
return path;
}

View file

@ -98,6 +98,26 @@ FString GetUserFile (const char *file)
return path;
}
//===========================================================================
//
// M_GetAppDataPath Unix
//
// Returns the path for the AppData folder.
//
//===========================================================================
FString M_GetAppDataPath(bool create)
{
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
FString path = NicePath("~/.config/" GAMENAMELOWERCASE);
if (create)
{
CreatePath(path);
}
return path;
}
//===========================================================================
//
// M_GetCachePath Unix

View file

@ -43,6 +43,7 @@
#include "templates.h"
#include "version.h"
#include "tmpfileplus.h"
#include "m_misc.h"
#ifndef _WIN32
#include <unistd.h>
@ -82,7 +83,7 @@ public:
protected:
bool LaunchTimidity();
char* DiskName;
FString DiskName;
#ifdef _WIN32
HANDLE ReadWavePipe;
HANDLE WriteWavePipe;
@ -165,8 +166,7 @@ CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
//
//==========================================================================
TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
: DiskName(nullptr),
TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) :
#ifdef _WIN32
ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE),
ChildProcess(INVALID_HANDLE_VALUE),
@ -204,10 +204,9 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
TimidityPPMIDIDevice::~TimidityPPMIDIDevice ()
{
if (nullptr != DiskName)
if (DiskName.IsNotEmpty())
{
remove(DiskName);
free(DiskName);
}
#if _WIN32
@ -257,7 +256,10 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
// Write MIDI song to temporary file
song->CreateSMF(midi, looping ? 0 : 1);
f = tmpfileplus(nullptr, "zmid", &DiskName, 1);
FString path = M_GetAppDataPath(false);
path += "/tmp";
CreatePath(path);
f = tmpfileplus(path, "zmid", &DiskName, 1);
if (f == NULL)
{
Printf(PRINT_BOLD, "Could not open temp music file\n");
@ -454,7 +456,7 @@ bool TimidityPPMIDIDevice::ValidateTimidity()
bool TimidityPPMIDIDevice::LaunchTimidity ()
{
if (ExeName.IsEmpty() || nullptr == DiskName)
if (ExeName.IsEmpty() || DiskName.IsEmpty())
{
return false;
}
@ -565,7 +567,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity ()
arglist.push_back("-");
arglist.push_back(outmodearg.c_str());
arglist.push_back(ifacearg.c_str());
arglist.push_back(DiskName);
arglist.push_back(DiskName.GetChars());
DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", exename);
int i = 1;

View file

@ -97,10 +97,9 @@
#include "m_random.h"
#include "cmdlib.h"
#include "zstring.h"
#define FILE_SEPARATOR "/"
#define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
#define NRANDCHARS (sizeof(RANDCHARS) - 1)
@ -121,27 +120,13 @@ static char *set_randpart(char *s)
return s;
}
/** Call getenv and save a copy in buf */
static char *getenv_save(const char *varname, char *buf, size_t bufsize)
{
char *ptr = getenv(varname);
buf[0] = '\0';
if (ptr)
{
strncpy(buf, ptr, bufsize);
buf[bufsize-1] = '\0';
return buf;
}
return NULL;
}
/**
* Try and create a randomly-named file in directory `tmpdir`.
* If successful, allocate memory and set `tmpname_ptr` to full filepath, and return file pointer;
* otherwise return NULL.
* If `keep` is zero then create the file as temporary and it should not exist once closed.
*/
static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmpname_ptr, int keep)
static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *tmpname_ptr, int keep)
/* PRE:
* pfx is not NULL and points to a valid null-terminated string
* tmpname_ptr is not NULL.
@ -150,9 +135,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp
FILE *fp;
int fd;
char randpart[] = "1234567890";
size_t lentempname;
int i;
char *tmpname = NULL;
int oflag, pmode;
/* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed.
@ -176,18 +159,13 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp
return NULL;
}
lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart);
tmpname = (char*)malloc(lentempname + 1);
if (!tmpname)
{
errno = ENOMEM;
return NULL;
}
FString tempname;
/* If we don't manage to create a file after 10 goes, there is something wrong... */
for (i = 0; i < 10; i++)
{
sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart));
fd = OPEN_(tmpname, oflag, pmode);
tempname.Format("%s/%s%s", tmpdir, pfx, set_randpart(randpart));
fd = OPEN_(tempname, oflag, pmode);
if (fd != -1) break;
}
if (fd != -1)
@ -205,13 +183,8 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp
{ /* We failed */
fp = NULL;
}
if (!fp)
{
free(tmpname);
tmpname = NULL;
}
*tmpname_ptr = tmpname;
if (tmpname_ptr) *tmpname_ptr = tempname;
return fp;
}
@ -219,47 +192,10 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp
/* EXPORTED FUNCTIONS */
/**********************/
FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep)
FILE *tmpfileplus(const char *dir, const char *prefix, FString *pathname, int keep)
{
FILE *fp = NULL;
char *tmpname = NULL;
char *tmpdir = NULL;
const char *pfx = (prefix ? prefix : "tmp.");
char *tempdirs[12] = { 0 };
char env1[FILENAME_MAX+1] = { 0 };
char env2[FILENAME_MAX+1] = { 0 };
char env3[FILENAME_MAX+1] = { 0 };
int ntempdirs = 0;
int i;
/* Set up a list of temp directories we will try in order */
i = 0;
tempdirs[i++] = (char *)dir;
#ifdef _WIN32
tempdirs[i++] = getenv_save("TMP", env1, sizeof(env1));
tempdirs[i++] = getenv_save("TEMP", env2, sizeof(env2));
#else
tempdirs[i++] = getenv_save("TMPDIR", env3, sizeof(env3));
tempdirs[i++] = P_tmpdir;
#endif
tempdirs[i++] = ".";
ntempdirs = i;
errno = 0;
/* Work through list we set up before, and break once we are successful */
for (i = 0; i < ntempdirs; i++)
{
tmpdir = tempdirs[i];
fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep);
if (fp) break;
}
/* If we succeeded and the user passed a pointer, set it to the alloc'd pathname: the user must free this */
if (fp && pathname)
*pathname = tmpname;
else /* Otherwise, free the alloc'd memory */
free(tmpname);
FILE *fp = mktempfile_internal(dir, (prefix ? prefix : "tmp."), pathname, keep);
if (!fp && pathname) *pathname = "";
return fp;
}

View file

@ -23,6 +23,8 @@
#include <stdio.h>
class FString;
/** Create a unique temporary file.
@param dir (optional) directory to create file. If NULL use default TMP directory.
@param prefix (optional) prefix for file name. If NULL use "tmp.".
@ -33,7 +35,7 @@
@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
@exception ENOMEM Not enough memory to allocate filename.
*/
FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep);
FILE *tmpfileplus(const char *dir, const char *prefix, FString *pathname, int keep);
#define TMPFILE_KEEP 1

View file

@ -153,6 +153,33 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
}
}
//===========================================================================
//
// M_GetAppDataPath Windows
//
// Returns the path for the AppData folder.
//
//===========================================================================
FString M_GetAppDataPath(bool create)
{
FString path;
if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path))
{ // Failed (e.g. On Win9x): use program directory
path = progdir;
}
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
path += "/" GAMENAMELOWERCASE;
path.Substitute("//", "/"); // needed because progdir ends with a slash.
if (create)
{
CreatePath(path);
}
return path;
}
//===========================================================================
//
// M_GetCachePath Windows
@ -173,6 +200,10 @@ FString M_GetCachePath(bool create)
// share the node cache.
path += "/zdoom/cache";
path.Substitute("//", "/"); // needed because progdir ends with a slash.
if (create)
{
CreatePath(path);
}
return path;
}