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 "file.h"
21cabdff1aSopenharmony_ci#include "internal.h"
22cabdff1aSopenharmony_ci#include "log.h"
23cabdff1aSopenharmony_ci#include "mem.h"
24cabdff1aSopenharmony_ci#include <fcntl.h>
25cabdff1aSopenharmony_ci#include <sys/stat.h>
26cabdff1aSopenharmony_ci#if HAVE_UNISTD_H
27cabdff1aSopenharmony_ci#include <unistd.h>
28cabdff1aSopenharmony_ci#endif
29cabdff1aSopenharmony_ci#if HAVE_IO_H
30cabdff1aSopenharmony_ci#include <io.h>
31cabdff1aSopenharmony_ci#endif
32cabdff1aSopenharmony_ci#if HAVE_MMAP
33cabdff1aSopenharmony_ci#include <sys/mman.h>
34cabdff1aSopenharmony_ci#elif HAVE_MAPVIEWOFFILE
35cabdff1aSopenharmony_ci#include <windows.h>
36cabdff1aSopenharmony_ci#endif
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_citypedef struct FileLogContext {
39cabdff1aSopenharmony_ci    const AVClass *class;
40cabdff1aSopenharmony_ci    int   log_offset;
41cabdff1aSopenharmony_ci    void *log_ctx;
42cabdff1aSopenharmony_ci} FileLogContext;
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_cistatic const AVClass file_log_ctx_class = {
45cabdff1aSopenharmony_ci    .class_name                = "FILE",
46cabdff1aSopenharmony_ci    .item_name                 = av_default_item_name,
47cabdff1aSopenharmony_ci    .option                    = NULL,
48cabdff1aSopenharmony_ci    .version                   = LIBAVUTIL_VERSION_INT,
49cabdff1aSopenharmony_ci    .log_level_offset_offset   = offsetof(FileLogContext, log_offset),
50cabdff1aSopenharmony_ci    .parent_log_context_offset = offsetof(FileLogContext, log_ctx),
51cabdff1aSopenharmony_ci};
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ciint av_file_map(const char *filename, uint8_t **bufptr, size_t *size,
54cabdff1aSopenharmony_ci                int log_offset, void *log_ctx)
55cabdff1aSopenharmony_ci{
56cabdff1aSopenharmony_ci    FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
57cabdff1aSopenharmony_ci    int err, fd = avpriv_open(filename, O_RDONLY);
58cabdff1aSopenharmony_ci    struct stat st;
59cabdff1aSopenharmony_ci    av_unused void *ptr;
60cabdff1aSopenharmony_ci    off_t off_size;
61cabdff1aSopenharmony_ci    char errbuf[128];
62cabdff1aSopenharmony_ci    *bufptr = NULL;
63cabdff1aSopenharmony_ci    *size = 0;
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ci    if (fd < 0) {
66cabdff1aSopenharmony_ci        err = AVERROR(errno);
67cabdff1aSopenharmony_ci        av_strerror(err, errbuf, sizeof(errbuf));
68cabdff1aSopenharmony_ci        av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf);
69cabdff1aSopenharmony_ci        return err;
70cabdff1aSopenharmony_ci    }
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    if (fstat(fd, &st) < 0) {
73cabdff1aSopenharmony_ci        err = AVERROR(errno);
74cabdff1aSopenharmony_ci        av_strerror(err, errbuf, sizeof(errbuf));
75cabdff1aSopenharmony_ci        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf);
76cabdff1aSopenharmony_ci        close(fd);
77cabdff1aSopenharmony_ci        return err;
78cabdff1aSopenharmony_ci    }
79cabdff1aSopenharmony_ci
80cabdff1aSopenharmony_ci    off_size = st.st_size;
81cabdff1aSopenharmony_ci    if (off_size > SIZE_MAX) {
82cabdff1aSopenharmony_ci        av_log(&file_log_ctx, AV_LOG_ERROR,
83cabdff1aSopenharmony_ci               "File size for file '%s' is too big\n", filename);
84cabdff1aSopenharmony_ci        close(fd);
85cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
86cabdff1aSopenharmony_ci    }
87cabdff1aSopenharmony_ci    *size = off_size;
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci    if (!*size) {
90cabdff1aSopenharmony_ci        *bufptr = NULL;
91cabdff1aSopenharmony_ci        goto out;
92cabdff1aSopenharmony_ci    }
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci#if HAVE_MMAP
95cabdff1aSopenharmony_ci    ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
96cabdff1aSopenharmony_ci    if (ptr == MAP_FAILED) {
97cabdff1aSopenharmony_ci        err = AVERROR(errno);
98cabdff1aSopenharmony_ci        av_strerror(err, errbuf, sizeof(errbuf));
99cabdff1aSopenharmony_ci        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf);
100cabdff1aSopenharmony_ci        close(fd);
101cabdff1aSopenharmony_ci        *size = 0;
102cabdff1aSopenharmony_ci        return err;
103cabdff1aSopenharmony_ci    }
104cabdff1aSopenharmony_ci    *bufptr = ptr;
105cabdff1aSopenharmony_ci#elif HAVE_MAPVIEWOFFILE
106cabdff1aSopenharmony_ci    {
107cabdff1aSopenharmony_ci        HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci        mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);
110cabdff1aSopenharmony_ci        if (!mh) {
111cabdff1aSopenharmony_ci            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n");
112cabdff1aSopenharmony_ci            close(fd);
113cabdff1aSopenharmony_ci            *size = 0;
114cabdff1aSopenharmony_ci            return -1;
115cabdff1aSopenharmony_ci        }
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci        ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);
118cabdff1aSopenharmony_ci        CloseHandle(mh);
119cabdff1aSopenharmony_ci        if (!ptr) {
120cabdff1aSopenharmony_ci            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n");
121cabdff1aSopenharmony_ci            close(fd);
122cabdff1aSopenharmony_ci            *size = 0;
123cabdff1aSopenharmony_ci            return -1;
124cabdff1aSopenharmony_ci        }
125cabdff1aSopenharmony_ci
126cabdff1aSopenharmony_ci        *bufptr = ptr;
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci#else
129cabdff1aSopenharmony_ci    *bufptr = av_malloc(*size);
130cabdff1aSopenharmony_ci    if (!*bufptr) {
131cabdff1aSopenharmony_ci        av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");
132cabdff1aSopenharmony_ci        close(fd);
133cabdff1aSopenharmony_ci        *size = 0;
134cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
135cabdff1aSopenharmony_ci    }
136cabdff1aSopenharmony_ci    read(fd, *bufptr, *size);
137cabdff1aSopenharmony_ci#endif
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ciout:
140cabdff1aSopenharmony_ci    close(fd);
141cabdff1aSopenharmony_ci    return 0;
142cabdff1aSopenharmony_ci}
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_civoid av_file_unmap(uint8_t *bufptr, size_t size)
145cabdff1aSopenharmony_ci{
146cabdff1aSopenharmony_ci    if (!size || !bufptr)
147cabdff1aSopenharmony_ci        return;
148cabdff1aSopenharmony_ci#if HAVE_MMAP
149cabdff1aSopenharmony_ci    munmap(bufptr, size);
150cabdff1aSopenharmony_ci#elif HAVE_MAPVIEWOFFILE
151cabdff1aSopenharmony_ci    UnmapViewOfFile(bufptr);
152cabdff1aSopenharmony_ci#else
153cabdff1aSopenharmony_ci    av_free(bufptr);
154cabdff1aSopenharmony_ci#endif
155cabdff1aSopenharmony_ci}
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_ciint av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) {
158cabdff1aSopenharmony_ci    return avpriv_tempfile(prefix, filename, log_offset, log_ctx);
159cabdff1aSopenharmony_ci}
160