libavformat: use avpriv_open()
[ffmpeg.git] / libavformat / file.c
1 /*
2  * buffered file I/O
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/avstring.h"
23 #include "libavutil/internal.h"
24 #include "libavutil/opt.h"
25 #include "avformat.h"
26 #include <fcntl.h>
27 #if HAVE_IO_H
28 #include <io.h>
29 #endif
30 #if HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #include <sys/stat.h>
34 #include <stdlib.h>
35 #include "os_support.h"
36 #include "url.h"
37
38
39 /* standard file protocol */
40
41 typedef struct FileContext {
42     const AVClass *class;
43     int fd;
44     int trunc;
45 } FileContext;
46
47 static const AVOption file_options[] = {
48     { "truncate", "Truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
49     { NULL }
50 };
51
52 static const AVClass file_class = {
53     .class_name = "file",
54     .item_name  = av_default_item_name,
55     .option     = file_options,
56     .version    = LIBAVUTIL_VERSION_INT,
57 };
58
59 static int file_read(URLContext *h, unsigned char *buf, int size)
60 {
61     FileContext *c = h->priv_data;
62     return read(c->fd, buf, size);
63 }
64
65 static int file_write(URLContext *h, const unsigned char *buf, int size)
66 {
67     FileContext *c = h->priv_data;
68     return write(c->fd, buf, size);
69 }
70
71 static int file_get_handle(URLContext *h)
72 {
73     FileContext *c = h->priv_data;
74     return c->fd;
75 }
76
77 static int file_check(URLContext *h, int mask)
78 {
79     struct stat st;
80     int ret = stat(h->filename, &st);
81     if (ret < 0)
82         return AVERROR(errno);
83
84     ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ  : 0;
85     ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
86
87     return ret;
88 }
89
90 #if CONFIG_FILE_PROTOCOL
91
92 static int file_open(URLContext *h, const char *filename, int flags)
93 {
94     FileContext *c = h->priv_data;
95     int access;
96     int fd;
97
98     av_strstart(filename, "file:", &filename);
99
100     if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
101         access = O_CREAT | O_RDWR;
102         if (c->trunc)
103             access |= O_TRUNC;
104     } else if (flags & AVIO_FLAG_WRITE) {
105         access = O_CREAT | O_WRONLY;
106         if (c->trunc)
107             access |= O_TRUNC;
108     } else {
109         access = O_RDONLY;
110     }
111 #ifdef O_BINARY
112     access |= O_BINARY;
113 #endif
114     fd = avpriv_open(filename, access, 0666);
115     if (fd == -1)
116         return AVERROR(errno);
117     c->fd = fd;
118     return 0;
119 }
120
121 /* XXX: use llseek */
122 static int64_t file_seek(URLContext *h, int64_t pos, int whence)
123 {
124     FileContext *c = h->priv_data;
125     int64_t ret;
126
127     if (whence == AVSEEK_SIZE) {
128         struct stat st;
129
130         ret = fstat(c->fd, &st);
131         return ret < 0 ? AVERROR(errno) : st.st_size;
132     }
133
134     ret = lseek(c->fd, pos, whence);
135
136     return ret < 0 ? AVERROR(errno) : ret;
137 }
138
139 static int file_close(URLContext *h)
140 {
141     FileContext *c = h->priv_data;
142     return close(c->fd);
143 }
144
145 URLProtocol ff_file_protocol = {
146     .name                = "file",
147     .url_open            = file_open,
148     .url_read            = file_read,
149     .url_write           = file_write,
150     .url_seek            = file_seek,
151     .url_close           = file_close,
152     .url_get_file_handle = file_get_handle,
153     .url_check           = file_check,
154     .priv_data_size      = sizeof(FileContext),
155     .priv_data_class     = &file_class,
156 };
157
158 #endif /* CONFIG_FILE_PROTOCOL */
159
160 #if CONFIG_PIPE_PROTOCOL
161
162 static int pipe_open(URLContext *h, const char *filename, int flags)
163 {
164     FileContext *c = h->priv_data;
165     int fd;
166     char *final;
167     av_strstart(filename, "pipe:", &filename);
168
169     fd = strtol(filename, &final, 10);
170     if((filename == final) || *final ) {/* No digits found, or something like 10ab */
171         if (flags & AVIO_FLAG_WRITE) {
172             fd = 1;
173         } else {
174             fd = 0;
175         }
176     }
177 #if HAVE_SETMODE
178     setmode(fd, O_BINARY);
179 #endif
180     c->fd = fd;
181     h->is_streamed = 1;
182     return 0;
183 }
184
185 URLProtocol ff_pipe_protocol = {
186     .name                = "pipe",
187     .url_open            = pipe_open,
188     .url_read            = file_read,
189     .url_write           = file_write,
190     .url_get_file_handle = file_get_handle,
191     .url_check           = file_check,
192     .priv_data_size      = sizeof(FileContext),
193 };
194
195 #endif /* CONFIG_PIPE_PROTOCOL */