Statistics
| Branch: | Revision:

ffmpeg / libavutil / file.c @ d112aa5a

History | View | Annotate | Download (3.93 KB)

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