1/*
2 * Buffered file io for ffmpeg system
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 "libavutil/avstring.h"
23#include "avformat.h"
24#include <fcntl.h>
25#if HAVE_SETMODE
26#include <io.h>
27#endif
28#include <unistd.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <stdlib.h>
32#include "os_support.h"
33
34
35/* standard file protocol */
36
37static int file_open(URLContext *h, const char *filename, int flags)
38{
39    int access;
40    int fd;
41
42    av_strstart(filename, "file:", &filename);
43
44    if (flags & URL_RDWR) {
45        access = O_CREAT | O_TRUNC | O_RDWR;
46    } else if (flags & URL_WRONLY) {
47        access = O_CREAT | O_TRUNC | O_WRONLY;
48    } else {
49        access = O_RDONLY;
50    }
51#ifdef O_BINARY
52    access |= O_BINARY;
53#endif
54    fd = open(filename, access, 0666);
55    if (fd == -1)
56        return AVERROR(errno);
57    h->priv_data = (void *) (intptr_t) fd;
58    return 0;
59}
60
61static int file_read(URLContext *h, unsigned char *buf, int size)
62{
63    int fd = (intptr_t) h->priv_data;
64    return read(fd, buf, size);
65}
66
67static int file_write(URLContext *h, unsigned char *buf, int size)
68{
69    int fd = (intptr_t) h->priv_data;
70    return write(fd, buf, size);
71}
72
73/* XXX: use llseek */
74static int64_t file_seek(URLContext *h, int64_t pos, int whence)
75{
76    int fd = (intptr_t) h->priv_data;
77    if (whence == AVSEEK_SIZE) {
78        struct stat st;
79        int ret = fstat(fd, &st);
80        return ret < 0 ? AVERROR(errno) : st.st_size;
81    }
82    return lseek(fd, pos, whence);
83}
84
85static int file_close(URLContext *h)
86{
87    int fd = (intptr_t) h->priv_data;
88    return close(fd);
89}
90
91static int file_get_handle(URLContext *h)
92{
93    return (intptr_t) h->priv_data;
94}
95
96URLProtocol file_protocol = {
97    "file",
98    file_open,
99    file_read,
100    file_write,
101    file_seek,
102    file_close,
103    .url_get_file_handle = file_get_handle,
104};
105
106/* pipe protocol */
107
108static int pipe_open(URLContext *h, const char *filename, int flags)
109{
110    int fd;
111    char *final;
112    av_strstart(filename, "pipe:", &filename);
113
114    fd = strtol(filename, &final, 10);
115    if((filename == final) || *final ) {/* No digits found, or something like 10ab */
116        if (flags & URL_WRONLY) {
117            fd = 1;
118        } else {
119            fd = 0;
120        }
121    }
122#if HAVE_SETMODE
123    setmode(fd, O_BINARY);
124#endif
125    h->priv_data = (void *) (intptr_t) fd;
126    h->is_streamed = 1;
127    return 0;
128}
129
130URLProtocol pipe_protocol = {
131    "pipe",
132    pipe_open,
133    file_read,
134    file_write,
135    .url_get_file_handle = file_get_handle,
136};
137