Libav 0.7.1
|
00001 /* 00002 * This file is part of Libav. 00003 * 00004 * Libav is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * Libav is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with Libav; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00019 #include "file.h" 00020 #include <fcntl.h> 00021 #include <sys/stat.h> 00022 #include <unistd.h> 00023 #if HAVE_MMAP 00024 #include <sys/mman.h> 00025 #elif HAVE_MAPVIEWOFFILE 00026 #include <io.h> 00027 #include <windows.h> 00028 #endif 00029 00030 typedef struct { 00031 const AVClass *class; 00032 int log_offset; 00033 void *log_ctx; 00034 } FileLogContext; 00035 00036 static const AVClass file_log_ctx_class = { 00037 "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, 00038 offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx) 00039 }; 00040 00041 int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, 00042 int log_offset, void *log_ctx) 00043 { 00044 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; 00045 int err, fd = open(filename, O_RDONLY); 00046 struct stat st; 00047 av_unused void *ptr; 00048 off_t off_size; 00049 char errbuf[128]; 00050 *bufptr = NULL; 00051 00052 if (fd < 0) { 00053 err = AVERROR(errno); 00054 av_strerror(err, errbuf, sizeof(errbuf)); 00055 av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf); 00056 return err; 00057 } 00058 00059 if (fstat(fd, &st) < 0) { 00060 err = AVERROR(errno); 00061 av_strerror(err, errbuf, sizeof(errbuf)); 00062 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf); 00063 close(fd); 00064 return err; 00065 } 00066 00067 off_size = st.st_size; 00068 if (off_size > SIZE_MAX) { 00069 av_log(&file_log_ctx, AV_LOG_ERROR, 00070 "File size for file '%s' is too big\n", filename); 00071 close(fd); 00072 return AVERROR(EINVAL); 00073 } 00074 *size = off_size; 00075 00076 #if HAVE_MMAP 00077 ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 00078 if (ptr == MAP_FAILED) { 00079 err = AVERROR(errno); 00080 av_strerror(err, errbuf, sizeof(errbuf)); 00081 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf); 00082 close(fd); 00083 return err; 00084 } 00085 *bufptr = ptr; 00086 #elif HAVE_MAPVIEWOFFILE 00087 { 00088 HANDLE mh, fh = (HANDLE)_get_osfhandle(fd); 00089 00090 mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL); 00091 if (!mh) { 00092 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n"); 00093 close(fd); 00094 return -1; 00095 } 00096 00097 ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size); 00098 CloseHandle(mh); 00099 if (!ptr) { 00100 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n"); 00101 close(fd); 00102 return -1; 00103 } 00104 00105 *bufptr = ptr; 00106 } 00107 #else 00108 *bufptr = av_malloc(*size); 00109 if (!*bufptr) { 00110 av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n"); 00111 close(fd); 00112 return AVERROR(ENOMEM); 00113 } 00114 read(fd, *bufptr, *size); 00115 #endif 00116 00117 close(fd); 00118 return 0; 00119 } 00120 00121 void av_file_unmap(uint8_t *bufptr, size_t size) 00122 { 00123 #if HAVE_MMAP 00124 munmap(bufptr, size); 00125 #elif HAVE_MAPVIEWOFFILE 00126 UnmapViewOfFile(bufptr); 00127 #else 00128 av_free(bufptr); 00129 #endif 00130 } 00131 00132 #ifdef TEST 00133 00134 #undef printf 00135 00136 int main(void) 00137 { 00138 uint8_t *buf; 00139 size_t size; 00140 if (av_file_map("file.c", &buf, &size, 0, NULL) < 0) 00141 return 1; 00142 00143 buf[0] = 's'; 00144 printf("%s", buf); 00145 av_file_unmap(buf, size); 00146 return 0; 00147 } 00148 #endif