shithub: sox

Download patch

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);