FFmpeg
file.c
Go to the documentation of this file.
1 /*
2  * buffered file I/O
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config_components.h"
23 
24 #include "libavutil/avstring.h"
25 #include "libavutil/internal.h"
26 #include "libavutil/opt.h"
27 #include "avformat.h"
28 #if HAVE_DIRENT_H
29 #include <dirent.h>
30 #endif
31 #include <fcntl.h>
32 #if HAVE_IO_H
33 #include <io.h>
34 #endif
35 #if HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <sys/stat.h>
39 #include <stdlib.h>
40 #include "os_support.h"
41 #include "url.h"
42 
43 /* Some systems may not have S_ISFIFO */
44 #ifndef S_ISFIFO
45 # ifdef S_IFIFO
46 # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
47 # else
48 # define S_ISFIFO(m) 0
49 # endif
50 #endif
51 
52 /* Not available in POSIX.1-1996 */
53 #ifndef S_ISLNK
54 # ifdef S_IFLNK
55 # define S_ISLNK(m) (((m) & S_IFLNK) == S_IFLNK)
56 # else
57 # define S_ISLNK(m) 0
58 # endif
59 #endif
60 
61 /* Not available in POSIX.1-1996 */
62 #ifndef S_ISSOCK
63 # ifdef S_IFSOCK
64 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
65 # else
66 # define S_ISSOCK(m) 0
67 # endif
68 #endif
69 
70 /* standard file protocol */
71 
72 typedef struct FileContext {
73  const AVClass *class;
74  int fd;
75  int trunc;
76  int blocksize;
77  int follow;
78  int seekable;
79 #if HAVE_DIRENT_H
80  DIR *dir;
81 #endif
82 } FileContext;
83 
84 static const AVOption file_options[] = {
85  { "truncate", "truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
86  { "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
87  { "follow", "Follow a file as it is being written", offsetof(FileContext, follow), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
88  { "seekable", "Sets if the file is seekable", offsetof(FileContext, seekable), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
89  { NULL }
90 };
91 
92 static const AVOption pipe_options[] = {
93  { "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
94  { NULL }
95 };
96 
97 static const AVClass file_class = {
98  .class_name = "file",
99  .item_name = av_default_item_name,
100  .option = file_options,
101  .version = LIBAVUTIL_VERSION_INT,
102 };
103 
104 static const AVClass pipe_class = {
105  .class_name = "pipe",
106  .item_name = av_default_item_name,
107  .option = pipe_options,
108  .version = LIBAVUTIL_VERSION_INT,
109 };
110 
111 static int file_read(URLContext *h, unsigned char *buf, int size)
112 {
113  FileContext *c = h->priv_data;
114  int ret;
115  size = FFMIN(size, c->blocksize);
116  ret = read(c->fd, buf, size);
117  if (ret == 0 && c->follow)
118  return AVERROR(EAGAIN);
119  if (ret == 0)
120  return AVERROR_EOF;
121  return (ret == -1) ? AVERROR(errno) : ret;
122 }
123 
124 static int file_write(URLContext *h, const unsigned char *buf, int size)
125 {
126  FileContext *c = h->priv_data;
127  int ret;
128  size = FFMIN(size, c->blocksize);
129  ret = write(c->fd, buf, size);
130  return (ret == -1) ? AVERROR(errno) : ret;
131 }
132 
134 {
135  FileContext *c = h->priv_data;
136  return c->fd;
137 }
138 
139 static int file_check(URLContext *h, int mask)
140 {
141  int ret = 0;
142  const char *filename = h->filename;
143  av_strstart(filename, "file:", &filename);
144 
145  {
146 #if HAVE_ACCESS && defined(R_OK)
147  if (access(filename, F_OK) < 0)
148  return AVERROR(errno);
149  if (mask&AVIO_FLAG_READ)
150  if (access(filename, R_OK) >= 0)
151  ret |= AVIO_FLAG_READ;
152  if (mask&AVIO_FLAG_WRITE)
153  if (access(filename, W_OK) >= 0)
154  ret |= AVIO_FLAG_WRITE;
155 #else
156  struct stat st;
157  ret = stat(filename, &st);
158  if (ret < 0)
159  return AVERROR(errno);
160 
161  ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
162  ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
163 #endif
164  }
165  return ret;
166 }
167 
168 #if CONFIG_FILE_PROTOCOL
169 
170 static int file_delete(URLContext *h)
171 {
172 #if HAVE_UNISTD_H
173  int ret;
174  const char *filename = h->filename;
175  av_strstart(filename, "file:", &filename);
176 
177  ret = rmdir(filename);
178  if (ret < 0 && (errno == ENOTDIR
179 # ifdef _WIN32
180  || errno == EINVAL
181 # endif
182  ))
183  ret = unlink(filename);
184  if (ret < 0)
185  return AVERROR(errno);
186 
187  return ret;
188 #else
189  return AVERROR(ENOSYS);
190 #endif /* HAVE_UNISTD_H */
191 }
192 
193 static int file_move(URLContext *h_src, URLContext *h_dst)
194 {
195  const char *filename_src = h_src->filename;
196  const char *filename_dst = h_dst->filename;
197  av_strstart(filename_src, "file:", &filename_src);
198  av_strstart(filename_dst, "file:", &filename_dst);
199 
200  if (rename(filename_src, filename_dst) < 0)
201  return AVERROR(errno);
202 
203  return 0;
204 }
205 
206 static int file_open(URLContext *h, const char *filename, int flags)
207 {
208  FileContext *c = h->priv_data;
209  int access;
210  int fd;
211  struct stat st;
212 
213  av_strstart(filename, "file:", &filename);
214 
216  access = O_CREAT | O_RDWR;
217  if (c->trunc)
218  access |= O_TRUNC;
219  } else if (flags & AVIO_FLAG_WRITE) {
220  access = O_CREAT | O_WRONLY;
221  if (c->trunc)
222  access |= O_TRUNC;
223  } else {
224  access = O_RDONLY;
225  }
226 #ifdef O_BINARY
227  access |= O_BINARY;
228 #endif
229  fd = avpriv_open(filename, access, 0666);
230  if (fd == -1)
231  return AVERROR(errno);
232  c->fd = fd;
233 
234  h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);
235 
236  /* Buffer writes more than the default 32k to improve throughput especially
237  * with networked file systems */
238  if (!h->is_streamed && flags & AVIO_FLAG_WRITE)
239  h->min_packet_size = h->max_packet_size = 262144;
240 
241  if (c->seekable >= 0)
242  h->is_streamed = !c->seekable;
243 
244  return 0;
245 }
246 
247 /* XXX: use llseek */
248 static int64_t file_seek(URLContext *h, int64_t pos, int whence)
249 {
250  FileContext *c = h->priv_data;
251  int64_t ret;
252 
253  if (whence == AVSEEK_SIZE) {
254  struct stat st;
255  ret = fstat(c->fd, &st);
256  return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
257  }
258 
259  ret = lseek(c->fd, pos, whence);
260 
261  return ret < 0 ? AVERROR(errno) : ret;
262 }
263 
264 static int file_close(URLContext *h)
265 {
266  FileContext *c = h->priv_data;
267  int ret = close(c->fd);
268  return (ret == -1) ? AVERROR(errno) : 0;
269 }
270 
271 static int file_open_dir(URLContext *h)
272 {
273 #if HAVE_LSTAT
274  FileContext *c = h->priv_data;
275 
276  c->dir = opendir(h->filename);
277  if (!c->dir)
278  return AVERROR(errno);
279 
280  return 0;
281 #else
282  return AVERROR(ENOSYS);
283 #endif /* HAVE_LSTAT */
284 }
285 
286 static int file_read_dir(URLContext *h, AVIODirEntry **next)
287 {
288 #if HAVE_LSTAT
289  FileContext *c = h->priv_data;
290  struct dirent *dir;
291  char *fullpath = NULL;
292 
293  *next = ff_alloc_dir_entry();
294  if (!*next)
295  return AVERROR(ENOMEM);
296  do {
297  errno = 0;
298  dir = readdir(c->dir);
299  if (!dir) {
300  av_freep(next);
301  return AVERROR(errno);
302  }
303  } while (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."));
304 
305  fullpath = av_append_path_component(h->filename, dir->d_name);
306  if (fullpath) {
307  struct stat st;
308  if (!lstat(fullpath, &st)) {
309  if (S_ISDIR(st.st_mode))
310  (*next)->type = AVIO_ENTRY_DIRECTORY;
311  else if (S_ISFIFO(st.st_mode))
312  (*next)->type = AVIO_ENTRY_NAMED_PIPE;
313  else if (S_ISCHR(st.st_mode))
314  (*next)->type = AVIO_ENTRY_CHARACTER_DEVICE;
315  else if (S_ISBLK(st.st_mode))
316  (*next)->type = AVIO_ENTRY_BLOCK_DEVICE;
317  else if (S_ISLNK(st.st_mode))
318  (*next)->type = AVIO_ENTRY_SYMBOLIC_LINK;
319  else if (S_ISSOCK(st.st_mode))
320  (*next)->type = AVIO_ENTRY_SOCKET;
321  else if (S_ISREG(st.st_mode))
322  (*next)->type = AVIO_ENTRY_FILE;
323  else
324  (*next)->type = AVIO_ENTRY_UNKNOWN;
325 
326  (*next)->group_id = st.st_gid;
327  (*next)->user_id = st.st_uid;
328  (*next)->size = st.st_size;
329  (*next)->filemode = st.st_mode & 0777;
330  (*next)->modification_timestamp = INT64_C(1000000) * st.st_mtime;
331  (*next)->access_timestamp = INT64_C(1000000) * st.st_atime;
332  (*next)->status_change_timestamp = INT64_C(1000000) * st.st_ctime;
333  }
334  av_free(fullpath);
335  }
336 
337  (*next)->name = av_strdup(dir->d_name);
338  return 0;
339 #else
340  return AVERROR(ENOSYS);
341 #endif /* HAVE_LSTAT */
342 }
343 
344 static int file_close_dir(URLContext *h)
345 {
346 #if HAVE_LSTAT
347  FileContext *c = h->priv_data;
348  closedir(c->dir);
349  return 0;
350 #else
351  return AVERROR(ENOSYS);
352 #endif /* HAVE_LSTAT */
353 }
354 
356  .name = "file",
357  .url_open = file_open,
358  .url_read = file_read,
359  .url_write = file_write,
360  .url_seek = file_seek,
361  .url_close = file_close,
362  .url_get_file_handle = file_get_handle,
363  .url_check = file_check,
364  .url_delete = file_delete,
365  .url_move = file_move,
366  .priv_data_size = sizeof(FileContext),
367  .priv_data_class = &file_class,
368  .url_open_dir = file_open_dir,
369  .url_read_dir = file_read_dir,
370  .url_close_dir = file_close_dir,
371  .default_whitelist = "file,crypto,data"
372 };
373 
374 #endif /* CONFIG_FILE_PROTOCOL */
375 
376 #if CONFIG_PIPE_PROTOCOL
377 
378 static int pipe_open(URLContext *h, const char *filename, int flags)
379 {
380  FileContext *c = h->priv_data;
381  int fd;
382  char *final;
383  av_strstart(filename, "pipe:", &filename);
384 
385  fd = strtol(filename, &final, 10);
386  if((filename == final) || *final ) {/* No digits found, or something like 10ab */
387  if (flags & AVIO_FLAG_WRITE) {
388  fd = 1;
389  } else {
390  fd = 0;
391  }
392  }
393 #if HAVE_SETMODE
394  setmode(fd, O_BINARY);
395 #endif
396  c->fd = fd;
397  h->is_streamed = 1;
398  return 0;
399 }
400 
402  .name = "pipe",
403  .url_open = pipe_open,
404  .url_read = file_read,
405  .url_write = file_write,
406  .url_get_file_handle = file_get_handle,
407  .url_check = file_check,
408  .priv_data_size = sizeof(FileContext),
409  .priv_data_class = &pipe_class,
410  .default_whitelist = "crypto,data"
411 };
412 
413 #endif /* CONFIG_PIPE_PROTOCOL */
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
S_ISSOCK
#define S_ISSOCK(m)
Definition: file.c:66
URLContext::filename
char * filename
specified URL
Definition: url.h:41
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AVOption
AVOption.
Definition: opt.h:251
AVSEEK_SIZE
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:479
AVIO_ENTRY_NAMED_PIPE
@ AVIO_ENTRY_NAMED_PIPE
Definition: avio.h:72
file_check
static int file_check(URLContext *h, int mask)
Definition: file.c:139
URLProtocol
Definition: url.h:53
os_support.h
AVIO_ENTRY_UNKNOWN
@ AVIO_ENTRY_UNKNOWN
Definition: avio.h:68
av_append_path_component
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition: avstring.c:307
AVIO_ENTRY_DIRECTORY
@ AVIO_ENTRY_DIRECTORY
Definition: avio.h:71
trunc
static __device__ float trunc(float a)
Definition: cuda_runtime.h:179
AVIO_ENTRY_CHARACTER_DEVICE
@ AVIO_ENTRY_CHARACTER_DEVICE
Definition: avio.h:70
FileContext::blocksize
int blocksize
Definition: file.c:76
file_write
static int file_write(URLContext *h, const unsigned char *buf, int size)
Definition: file.c:124
file_read
static int file_read(URLContext *h, unsigned char *buf, int size)
Definition: file.c:111
AVIO_ENTRY_SYMBOLIC_LINK
@ AVIO_ENTRY_SYMBOLIC_LINK
Definition: avio.h:73
mask
static const uint16_t mask[17]
Definition: lzw.c:38
FileContext::seekable
int seekable
Definition: file.c:78
AV_OPT_FLAG_ENCODING_PARAM
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:281
S_ISFIFO
#define S_ISFIFO(m)
Definition: file.c:48
avpriv_open
int avpriv_open(const char *filename, int flags,...)
A wrapper for open() setting O_CLOEXEC.
Definition: file_open.c:66
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:629
FileContext
Definition: file.c:72
pipe_class
static const AVClass pipe_class
Definition: file.c:104
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AVIO_ENTRY_FILE
@ AVIO_ENTRY_FILE
Definition: avio.h:75
FileContext::fd
int fd
Definition: file.c:74
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
pipe_options
static const AVOption pipe_options[]
Definition: file.c:92
FileContext::follow
int follow
Definition: file.c:77
ff_file_protocol
const URLProtocol ff_file_protocol
size
int size
Definition: twinvq_data.h:10344
AVIODirEntry
Describes single entry of the directory.
Definition: avio.h:87
URLProtocol::name
const char * name
Definition: url.h:54
FileContext::trunc
int trunc
Definition: file.c:75
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:37
AVIO_ENTRY_SOCKET
@ AVIO_ENTRY_SOCKET
Definition: avio.h:74
ff_alloc_dir_entry
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition: url.c:325
URLContext
Definition: url.h:37
file_options
static const AVOption file_options[]
Definition: file.c:84
internal.h
AV_OPT_FLAG_DECODING_PARAM
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:282
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
file_class
static const AVClass file_class
Definition: file.c:97
S_ISLNK
#define S_ISLNK(m)
Definition: file.c:57
O_BINARY
#define O_BINARY
ff_pipe_protocol
const URLProtocol ff_pipe_protocol
AVIO_ENTRY_BLOCK_DEVICE
@ AVIO_ENTRY_BLOCK_DEVICE
Definition: avio.h:69
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
file_get_handle
static int file_get_handle(URLContext *h)
Definition: file.c:133
pos
unsigned int pos
Definition: spdifenc.c:412
avformat.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:628
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:280
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
h
h
Definition: vp9dsp_template.c:2038
avstring.h