ref: 7a16076aa620d6596300066025672b4c0e2e743b
parent: 0769dde7ea94ff040a8c8120f069d3fbc02b1f1d
author: Doug Cook <idigdoug@users.sourceforge.net>
date: Tue Jan 24 22:31:23 EST 2012
Fix WIN32 temp files and arg[0] handling When checking for arg[0] == "play"/"rec"/"soxi", use sox_basename and lsx_strcasecmp instead of lsx_strends. This eliminates the need for ifdefs and handles more situations (such as PLAY.EXE vs. play.exe). Move the special Win32 handling of temp files from sox.c into libsox_i.c so that all clients can take advantage of the workaround. Make the workaround conditional on the WIN32 macro so that it works for all Win32 compilers (MinGW, MSVC, and Cygwin).
--- a/src/libsox_i.c
+++ b/src/libsox_i.c
@@ -45,14 +45,59 @@
#define FAKE_MKSTEMP
#endif
+#ifdef WIN32
+static int check_dir(char * buf, size_t buflen, char const * name)
+{
+ struct stat st;
+ if (!name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR)
+ {
+ return 0;
+ }
+ else
+ {
+ strncpy(buf, name, buflen);
+ buf[buflen - 1] = 0;
+ return strlen(name) == strlen(buf);
+ }
+}
+#endif
+
FILE * lsx_tmpfile(void)
{
- if (sox_globals.tmp_path) {
+ char const * path = sox_globals.tmp_path;
+
+ /*
+ On Win32, tmpfile() is broken - it creates the file in the root directory of
+ the current drive (the user probably doesn't have permission to write there!)
+ instead of in a valid temporary directory (like TEMP or TMP). So if tmp_path
+ is null, figure out a reasonable default.
+ To force use of tmpfile(), set sox_globals.tmp_path = "".
+ */
+#ifdef WIN32
+ if (!path)
+ {
+ static char default_path[260] = "";
+ if (default_path[0] == 0
+ && !check_dir(default_path, sizeof(default_path), getenv("TEMP"))
+ && !check_dir(default_path, sizeof(default_path), getenv("TMP"))
+ #ifdef __CYGWIN__
+ && !check_dir(default_path, sizeof(default_path), "/tmp")
+ #endif
+ )
+ {
+ strcpy(default_path, ".");
+ }
+
+ path = default_path;
+ }
+#endif
+
+ if (path && path[0]) {
/* Emulate tmpfile (delete on close); tmp dir is given tmp_path: */
char const * const end = "/libSoX.tmp.XXXXXX";
- char * name = lsx_malloc(strlen(sox_globals.tmp_path) + strlen(end) + 1);
+ char * name = lsx_malloc(strlen(path) + strlen(end) + 1);
int fildes;
- strcpy(name, sox_globals.tmp_path);
+ strcpy(name, path);
strcat(name, end);
fildes = mkstemp(name);
#ifdef HAVE_UNISTD_H
--- a/src/sox.c
+++ b/src/sox.c
@@ -2818,36 +2818,23 @@
return c1 && c2 && !strcasecmp(c1, c2);
}
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-static char * check_dir(char * name)
-{
- struct stat st;
- return !name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR?
- NULL : name;
-}
-#endif
-
int main(int argc, char **argv)
{
size_t i;
+ char mybase[6];
myname = argv[0];
sox_globals.output_message_handler = output_message;
- if (lsx_strends(myname, "play"))
- sox_mode = sox_play;
-#if defined(__CYGWIN__) || defined(__MINGW32__)
- else if (lsx_strends(myname, "play.exe"))
- sox_mode = sox_play;
-#endif
- else if (lsx_strends(myname, "rec"))
- sox_mode = sox_rec;
-#if defined(__CYGWIN__) || defined(__MINGW32__)
- else if (lsx_strends(myname, "rec.exe"))
- sox_mode = sox_rec;
-#endif
- else if (lsx_strends(myname, "soxi"))
- sox_mode = sox_soxi;
+ if (0 != sox_basename(mybase, sizeof(mybase), myname))
+ {
+ if (0 == lsx_strcasecmp(mybase, "play"))
+ sox_mode = sox_play;
+ else if (0 == lsx_strcasecmp(mybase, "rec"))
+ sox_mode = sox_rec;
+ else if (0 == lsx_strcasecmp(mybase, "soxi"))
+ sox_mode = sox_soxi;
+ }
if (!sox_mode && argc > 1 &&
(!strcmp(argv[1], "--i") || !strcmp(argv[1], "--info")))
@@ -2865,24 +2852,6 @@
exit(soxi(argc, argv));
parse_options_and_filenames(argc, argv);
-
-#if defined(__CYGWIN__) || defined(__MINGW32__)
- /* Workarounds for a couple of cygwin/mingw problems: */
- /* Allow command-line --temp "" to specify default behaviour: */
- if (sox_globals.tmp_path && !*sox_globals.tmp_path) {
- free(sox_globals.tmp_path);
- sox_globals.tmp_path = NULL;
- }
- else if (!sox_globals.tmp_path) {
- /* cygwin tmpfile does not use std. windows env. vars, so we do here: */
- if (!(sox_globals.tmp_path = check_dir(getenv("TEMP"))))
- if (!(sox_globals.tmp_path = check_dir(getenv("TMP"))))
- /* Std. values for T(E)MP don't work in cygwin shell so try these: */
- if (!(sox_globals.tmp_path = check_dir("/tmp")))
- sox_globals.tmp_path = ".";
- sox_globals.tmp_path = lsx_strdup(sox_globals.tmp_path);
- }
-#endif
if (sox_globals.verbosity > 2)
display_SoX_version(stderr);