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