1/* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include "config.h" 20#include "internal.h" 21#include "mem.h" 22#include <stdarg.h> 23#include <fcntl.h> 24#include <sys/stat.h> 25#if HAVE_UNISTD_H 26#include <unistd.h> 27#endif 28#if HAVE_IO_H 29#include <io.h> 30#endif 31 32#ifdef _WIN32 33#undef open 34#undef lseek 35#undef stat 36#undef fstat 37#include <windows.h> 38#include <share.h> 39#include <errno.h> 40#include "wchar_filename.h" 41 42static int win32_open(const char *filename_utf8, int oflag, int pmode) 43{ 44 int fd; 45 wchar_t *filename_w; 46 47 /* convert UTF-8 to wide chars */ 48 if (get_extended_win32_path(filename_utf8, &filename_w)) 49 return -1; 50 if (!filename_w) 51 goto fallback; 52 53 fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode); 54 av_freep(&filename_w); 55 56 if (fd != -1 || (oflag & O_CREAT)) 57 return fd; 58 59fallback: 60 /* filename may be in CP_ACP */ 61 return _sopen(filename_utf8, oflag, SH_DENYNO, pmode); 62} 63#define open win32_open 64#endif 65 66int avpriv_open(const char *filename, int flags, ...) 67{ 68 int fd; 69 unsigned int mode = 0; 70 va_list ap; 71 72 va_start(ap, flags); 73 if (flags & O_CREAT) 74 mode = va_arg(ap, unsigned int); 75 va_end(ap); 76 77#ifdef O_CLOEXEC 78 flags |= O_CLOEXEC; 79#endif 80#ifdef O_NOINHERIT 81 flags |= O_NOINHERIT; 82#endif 83 84 fd = open(filename, flags, mode); 85#if HAVE_FCNTL 86 if (fd != -1) { 87 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) 88 av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n"); 89 } 90#endif 91 92 return fd; 93} 94 95typedef struct FileLogContext { 96 const AVClass *class; 97 int log_offset; 98 void *log_ctx; 99} FileLogContext; 100 101static const AVClass file_log_ctx_class = { 102 .class_name = "TEMPFILE", 103 .item_name = av_default_item_name, 104 .option = NULL, 105 .version = LIBAVUTIL_VERSION_INT, 106 .log_level_offset_offset = offsetof(FileLogContext, log_offset), 107 .parent_log_context_offset = offsetof(FileLogContext, log_ctx), 108}; 109 110int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) 111{ 112 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; 113 int fd = -1; 114#if !HAVE_MKSTEMP 115 void *ptr= tempnam(NULL, prefix); 116 if(!ptr) 117 ptr= tempnam(".", prefix); 118 *filename = av_strdup(ptr); 119#undef free 120 free(ptr); 121#else 122 size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */ 123 *filename = av_malloc(len); 124#endif 125 /* -----common section-----*/ 126 if (!*filename) { 127 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n"); 128 return AVERROR(ENOMEM); 129 } 130#if !HAVE_MKSTEMP 131# ifndef O_BINARY 132# define O_BINARY 0 133# endif 134# ifndef O_EXCL 135# define O_EXCL 0 136# endif 137 fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); 138#else 139 snprintf(*filename, len, "/tmp/%sXXXXXX", prefix); 140 fd = mkstemp(*filename); 141#if defined(_WIN32) || defined (__ANDROID__) || defined(__DJGPP__) 142 if (fd < 0) { 143 snprintf(*filename, len, "./%sXXXXXX", prefix); 144 fd = mkstemp(*filename); 145 } 146#endif 147#endif 148 /* -----common section-----*/ 149 if (fd < 0) { 150 int err = AVERROR(errno); 151 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename); 152 av_freep(filename); 153 return err; 154 } 155 return fd; /* success */ 156} 157 158FILE *avpriv_fopen_utf8(const char *path, const char *mode) 159{ 160 int fd; 161 int access; 162 const char *m = mode; 163 164 switch (*m++) { 165 case 'r': access = O_RDONLY; break; 166 case 'w': access = O_CREAT|O_WRONLY|O_TRUNC; break; 167 case 'a': access = O_CREAT|O_WRONLY|O_APPEND; break; 168 default : 169 errno = EINVAL; 170 return NULL; 171 } 172 while (*m) { 173 if (*m == '+') { 174 access &= ~(O_RDONLY | O_WRONLY); 175 access |= O_RDWR; 176 } else if (*m == 'b') { 177#ifdef O_BINARY 178 access |= O_BINARY; 179#endif 180 } else if (*m) { 181 errno = EINVAL; 182 return NULL; 183 } 184 m++; 185 } 186 fd = avpriv_open(path, access, 0666); 187 if (fd == -1) 188 return NULL; 189 return fdopen(fd, mode); 190} 191 192#if FF_API_AV_FOPEN_UTF8 193FILE *av_fopen_utf8(const char *path, const char *mode) 194{ 195 return avpriv_fopen_utf8(path, mode); 196} 197#endif 198