Imported Debian version 2.4.3~trusty1
[deb_ffmpeg.git] / ffmpeg / libavutil / file.c
CommitLineData
2ba45a60
DM
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 "file.h"
21#include "internal.h"
22#include "log.h"
23#include "mem.h"
24#include <fcntl.h>
25#include <sys/stat.h>
26#if HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29#if HAVE_IO_H
30#include <io.h>
31#endif
32#if HAVE_MMAP
33#include <sys/mman.h>
34#elif HAVE_MAPVIEWOFFILE
35#include <windows.h>
36#endif
37
38typedef struct {
39 const AVClass *class;
40 int log_offset;
41 void *log_ctx;
42} FileLogContext;
43
44static const AVClass file_log_ctx_class = {
45 "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT,
46 offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx)
47};
48
49int av_file_map(const char *filename, uint8_t **bufptr, size_t *size,
50 int log_offset, void *log_ctx)
51{
52 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
53 int err, fd = avpriv_open(filename, O_RDONLY);
54 struct stat st;
55 av_unused void *ptr;
56 off_t off_size;
57 char errbuf[128];
58 *bufptr = NULL;
59
60 if (fd < 0) {
61 err = AVERROR(errno);
62 av_strerror(err, errbuf, sizeof(errbuf));
63 av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf);
64 return err;
65 }
66
67 if (fstat(fd, &st) < 0) {
68 err = AVERROR(errno);
69 av_strerror(err, errbuf, sizeof(errbuf));
70 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf);
71 close(fd);
72 return err;
73 }
74
75 off_size = st.st_size;
76 if (off_size > SIZE_MAX) {
77 av_log(&file_log_ctx, AV_LOG_ERROR,
78 "File size for file '%s' is too big\n", filename);
79 close(fd);
80 return AVERROR(EINVAL);
81 }
82 *size = off_size;
83
84#if HAVE_MMAP
85 ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
86 if (ptr == MAP_FAILED) {
87 err = AVERROR(errno);
88 av_strerror(err, errbuf, sizeof(errbuf));
89 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf);
90 close(fd);
91 return err;
92 }
93 *bufptr = ptr;
94#elif HAVE_MAPVIEWOFFILE
95 {
96 HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);
97
98 mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);
99 if (!mh) {
100 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n");
101 close(fd);
102 return -1;
103 }
104
105 ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);
106 CloseHandle(mh);
107 if (!ptr) {
108 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n");
109 close(fd);
110 return -1;
111 }
112
113 *bufptr = ptr;
114 }
115#else
116 *bufptr = av_malloc(*size);
117 if (!*bufptr) {
118 av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");
119 close(fd);
120 return AVERROR(ENOMEM);
121 }
122 read(fd, *bufptr, *size);
123#endif
124
125 close(fd);
126 return 0;
127}
128
129void av_file_unmap(uint8_t *bufptr, size_t size)
130{
131#if HAVE_MMAP
132 munmap(bufptr, size);
133#elif HAVE_MAPVIEWOFFILE
134 UnmapViewOfFile(bufptr);
135#else
136 av_free(bufptr);
137#endif
138}
139
140int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
141{
142 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
143 int fd = -1;
144#if !HAVE_MKSTEMP
145 void *ptr= tempnam(NULL, prefix);
146 if(!ptr)
147 ptr= tempnam(".", prefix);
148 *filename = av_strdup(ptr);
149#undef free
150 free(ptr);
151#else
152 size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
153 *filename = av_malloc(len);
154#endif
155 /* -----common section-----*/
156 if (!*filename) {
157 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
158 return AVERROR(ENOMEM);
159 }
160#if !HAVE_MKSTEMP
161# ifndef O_BINARY
162# define O_BINARY 0
163# endif
164# ifndef O_EXCL
165# define O_EXCL 0
166# endif
167 fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
168#else
169 snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
170 fd = mkstemp(*filename);
171#ifdef _WIN32
172 if (fd < 0) {
173 snprintf(*filename, len, "./%sXXXXXX", prefix);
174 fd = mkstemp(*filename);
175 }
176#endif
177#endif
178 /* -----common section-----*/
179 if (fd < 0) {
180 int err = AVERROR(errno);
181 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
182 av_freep(filename);
183 return err;
184 }
185 return fd; /* success */
186}
187
188#ifdef TEST
189
190#undef printf
191
192int main(void)
193{
194 uint8_t *buf;
195 size_t size;
196 if (av_file_map("file.c", &buf, &size, 0, NULL) < 0)
197 return 1;
198
199 buf[0] = 's';
200 printf("%s", buf);
201 av_file_unmap(buf, size);
202 return 0;
203}
204#endif
205