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