Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 "libavutil/avstring.h"
  23. #include "libavutil/internal.h"
  24. #include "libavutil/opt.h"
  25. #include "avformat.h"
  26. #if HAVE_DIRENT_H
  27. #include <dirent.h>
  28. #endif
  29. #include <fcntl.h>
  30. #if HAVE_IO_H
  31. #include <io.h>
  32. #endif
  33. #if HAVE_UNISTD_H
  34. #include <unistd.h>
  35. #endif
  36. #include <sys/stat.h>
  37. #include <stdlib.h>
  38. #include "os_support.h"
  39. #include "url.h"
  40.  
  41. /* Some systems may not have S_ISFIFO */
  42. #ifndef S_ISFIFO
  43. #  ifdef S_IFIFO
  44. #    define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
  45. #  else
  46. #    define S_ISFIFO(m) 0
  47. #  endif
  48. #endif
  49.  
  50. /* Not available in POSIX.1-1996 */
  51. #ifndef S_ISLNK
  52. #  ifdef S_IFLNK
  53. #    define S_ISLNK(m) (((m) & S_IFLNK) == S_IFLNK)
  54. #  else
  55. #    define S_ISLNK(m) 0
  56. #  endif
  57. #endif
  58.  
  59. /* Not available in POSIX.1-1996 */
  60. #ifndef S_ISSOCK
  61. #  ifdef S_IFSOCK
  62. #    define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
  63. #  else
  64. #    define S_ISSOCK(m) 0
  65. #  endif
  66. #endif
  67.  
  68. /* standard file protocol */
  69.  
  70. typedef struct FileContext {
  71.     const AVClass *class;
  72.     int fd;
  73.     int trunc;
  74.     int blocksize;
  75. #if HAVE_DIRENT_H
  76.     DIR *dir;
  77. #endif
  78. } FileContext;
  79.  
  80. static const AVOption file_options[] = {
  81.     { "truncate", "truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
  82.     { "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 },
  83.     { NULL }
  84. };
  85.  
  86. static const AVOption pipe_options[] = {
  87.     { "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 },
  88.     { NULL }
  89. };
  90.  
  91. static const AVClass file_class = {
  92.     .class_name = "file",
  93.     .item_name  = av_default_item_name,
  94.     .option     = file_options,
  95.     .version    = LIBAVUTIL_VERSION_INT,
  96. };
  97.  
  98. static const AVClass pipe_class = {
  99.     .class_name = "pipe",
  100.     .item_name  = av_default_item_name,
  101.     .option     = pipe_options,
  102.     .version    = LIBAVUTIL_VERSION_INT,
  103. };
  104.  
  105. static int file_read(URLContext *h, unsigned char *buf, int size)
  106. {
  107.     FileContext *c = h->priv_data;
  108.     int r;
  109.     size = FFMIN(size, c->blocksize);
  110.     r = read(c->fd, buf, size);
  111.     return (-1 == r)?AVERROR(errno):r;
  112. }
  113.  
  114. static int file_write(URLContext *h, const unsigned char *buf, int size)
  115. {
  116.     FileContext *c = h->priv_data;
  117.     int r;
  118.     size = FFMIN(size, c->blocksize);
  119.     r = write(c->fd, buf, size);
  120.     return (-1 == r)?AVERROR(errno):r;
  121. }
  122.  
  123. static int file_get_handle(URLContext *h)
  124. {
  125.     FileContext *c = h->priv_data;
  126.     return c->fd;
  127. }
  128.  
  129. static int file_check(URLContext *h, int mask)
  130. {
  131.     return AVIO_FLAG_READ | AVIO_FLAG_WRITE ;
  132. }
  133.  
  134. static int file_delete(URLContext *h)
  135. {
  136.     return AVERROR(ENOSYS);
  137. }
  138.  
  139. static int file_move(URLContext *h_src, URLContext *h_dst)
  140. {
  141.     return AVERROR(ENOSYS);
  142. }
  143.  
  144. #if CONFIG_FILE_PROTOCOL
  145.  
  146. static int file_open(URLContext *h, const char *filename, int flags)
  147. {
  148.     FileContext *c = h->priv_data;
  149.     int access;
  150.     int fd;
  151.     struct stat st;
  152.  
  153.     av_strstart(filename, "file:", &filename);
  154.  
  155.     if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
  156.         access = O_CREAT | O_RDWR;
  157.         if (c->trunc)
  158.             access |= O_TRUNC;
  159.     } else if (flags & AVIO_FLAG_WRITE) {
  160.         access = O_CREAT | O_WRONLY;
  161.         if (c->trunc)
  162.             access |= O_TRUNC;
  163.     } else {
  164.         access = O_RDONLY;
  165.     }
  166. #ifdef O_BINARY
  167.     access |= O_BINARY;
  168. #endif
  169.     fd = avpriv_open(filename, access, 0666);
  170.     if (fd == -1)
  171.         return AVERROR(errno);
  172.     c->fd = fd;
  173.  
  174.     h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);
  175.  
  176.     return 0;
  177. }
  178.  
  179. /* XXX: use llseek */
  180. static int64_t file_seek(URLContext *h, int64_t pos, int whence)
  181. {
  182.     FileContext *c = h->priv_data;
  183.     int64_t ret;
  184.  
  185.     if (whence == AVSEEK_SIZE) {
  186.         struct stat st;
  187.         ret = fstat(c->fd, &st);
  188.         return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
  189.     }
  190.  
  191.     ret = lseek(c->fd, pos, whence);
  192.  
  193.     return ret < 0 ? AVERROR(errno) : ret;
  194. }
  195.  
  196. static int file_close(URLContext *h)
  197. {
  198.     FileContext *c = h->priv_data;
  199.     return close(c->fd);
  200. }
  201.  
  202. static int file_open_dir(URLContext *h)
  203. {
  204. #if HAVE_LSTAT
  205.     FileContext *c = h->priv_data;
  206.  
  207.     c->dir = opendir(h->filename);
  208.     if (!c->dir)
  209.         return AVERROR(errno);
  210.  
  211.     return 0;
  212. #else
  213.     return AVERROR(ENOSYS);
  214. #endif /* HAVE_LSTAT */
  215. }
  216.  
  217. static int file_read_dir(URLContext *h, AVIODirEntry **next)
  218. {
  219.     return AVERROR(ENOSYS);
  220. }
  221.  
  222. static int file_close_dir(URLContext *h)
  223. {
  224.     return AVERROR(ENOSYS);
  225.  
  226. }
  227.  
  228. URLProtocol ff_file_protocol = {
  229.     .name                = "file",
  230.     .url_open            = file_open,
  231.     .url_read            = file_read,
  232.     .url_write           = file_write,
  233.     .url_seek            = file_seek,
  234.     .url_close           = file_close,
  235.     .url_get_file_handle = file_get_handle,
  236.     .url_check           = file_check,
  237.     .url_delete          = file_delete,
  238.     .url_move            = file_move,
  239.     .priv_data_size      = sizeof(FileContext),
  240.     .priv_data_class     = &file_class,
  241.     .url_open_dir        = file_open_dir,
  242.     .url_read_dir        = file_read_dir,
  243.     .url_close_dir       = file_close_dir,
  244. };
  245.  
  246. #endif /* CONFIG_FILE_PROTOCOL */
  247.  
  248. #if CONFIG_PIPE_PROTOCOL
  249.  
  250. static int pipe_open(URLContext *h, const char *filename, int flags)
  251. {
  252.     FileContext *c = h->priv_data;
  253.     int fd;
  254.     char *final;
  255.     av_strstart(filename, "pipe:", &filename);
  256.  
  257.     fd = strtol(filename, &final, 10);
  258.     if((filename == final) || *final ) {/* No digits found, or something like 10ab */
  259.         if (flags & AVIO_FLAG_WRITE) {
  260.             fd = 1;
  261.         } else {
  262.             fd = 0;
  263.         }
  264.     }
  265. #if HAVE_SETMODE
  266.     setmode(fd, O_BINARY);
  267. #endif
  268.     c->fd = fd;
  269.     h->is_streamed = 1;
  270.     return 0;
  271. }
  272.  
  273. URLProtocol ff_pipe_protocol = {
  274.     .name                = "pipe",
  275.     .url_open            = pipe_open,
  276.     .url_read            = file_read,
  277.     .url_write           = file_write,
  278.     .url_get_file_handle = file_get_handle,
  279.     .url_check           = file_check,
  280.     .priv_data_size      = sizeof(FileContext),
  281.     .priv_data_class     = &pipe_class,
  282. };
  283.  
  284. #endif /* CONFIG_PIPE_PROTOCOL */
  285.