1 /* libSoX internal functions that apply to both formats and effects
2  * All public functions & data are prefixed with lsx_ .
3  *
4  * Copyright (c) 2008 robs@users.sourceforge.net
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or (at
9  * your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 
22 #include "sox_i.h"
23 
24 #ifdef HAVE_IO_H
25   #include <io.h>
26 #endif
27 
28 #ifdef HAVE_UNISTD_H
29   #include <unistd.h>
30 #endif
31 
32 #if defined(_MSC_VER) || defined(__MINGW32__)
33   #define MKTEMP_X _O_BINARY|_O_TEMPORARY
34 #else
35   #define MKTEMP_X 0
36 #endif
37 
38 #ifndef HAVE_MKSTEMP
39   #include <fcntl.h>
40   #include <sys/types.h>
41   #include <sys/stat.h>
42   #define mkstemp(t) open(mktemp(t), MKTEMP_X|O_RDWR|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE)
43   #define FAKE_MKSTEMP "fake "
44 #else
45   #define FAKE_MKSTEMP
46 #endif
47 
48 #ifdef WIN32
49 static int check_dir(char * buf, size_t buflen, char const * name)
50 {
51   struct stat st;
52   if (!name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR)
53   {
54     return 0;
55   }
56   else
57   {
58     strncpy(buf, name, buflen);
59     buf[buflen - 1] = 0;
60     return strlen(name) == strlen(buf);
61   }
62 }
startread(sox_format_t * ft)63 #endif
64 
65 FILE * lsx_tmpfile(void)
66 {
67   char const * path = sox_globals.tmp_path;
68 
69   /*
70   On Win32, tmpfile() is broken - it creates the file in the root directory of
71   the current drive (the user probably doesn't have permission to write there!)
72   instead of in a valid temporary directory (like TEMP or TMP). So if tmp_path
73   is null, figure out a reasonable default.
74   To force use of tmpfile(), set sox_globals.tmp_path = "".
75   */
76 #ifdef WIN32
77   if (!path)
78   {
79     static char default_path[260] = "";
80     if (default_path[0] == 0
81         && !check_dir(default_path, sizeof(default_path), getenv("TEMP"))
82         && !check_dir(default_path, sizeof(default_path), getenv("TMP"))
83     #ifdef __CYGWIN__
84         && !check_dir(default_path, sizeof(default_path), "/tmp")
85     #endif
86         )
87     {
88       strcpy(default_path, ".");
89     }
90 
91     path = default_path;
92   }
93 #endif
94 
95   if (path && path[0]) {
96     /* Emulate tmpfile (delete on close); tmp dir is given tmp_path: */
97     char const * const end = "/libSoX.tmp.XXXXXX";
98     char * name = lsx_malloc(strlen(path) + strlen(end) + 1);
99     int fildes;
100     strcpy(name, path);
101     strcat(name, end);
102     fildes = mkstemp(name);
103 #ifdef HAVE_UNISTD_H
104     lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (unlinked)", name);
105     unlink(name);
106 #else
107     lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (O_TEMPORARY)", name);
108 #endif
109     free(name);
110     return fildes == -1? NULL : fdopen(fildes, "w+b");
111   }
112 
113   /* Use standard tmpfile (delete on close); tmp dir is undefined: */
114   lsx_debug("tmpfile()");
115   return tmpfile();
116 }
117