00001 /* 00002 * This file is part of FFmpeg. 00003 * 00004 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 "log.h" 00021 #include <fcntl.h> 00022 #include <sys/stat.h> 00023 #include <unistd.h> 00024 #if HAVE_MMAP 00025 #include <sys/mman.h> 00026 #elif HAVE_MAPVIEWOFFILE 00027 #include <io.h> 00028 #include <windows.h> 00029 #endif 00030 00031 typedef struct { 00032 const AVClass *class; 00033 int log_offset; 00034 void *log_ctx; 00035 } FileLogContext; 00036 00037 static const AVClass file_log_ctx_class = { 00038 "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, 00039 offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx) 00040 }; 00041 00042 int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, 00043 int log_offset, void *log_ctx) 00044 { 00045 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; 00046 int err, fd = open(filename, O_RDONLY); 00047 struct stat st; 00048 av_unused void *ptr; 00049 off_t off_size; 00050 char errbuf[128]; 00051 *bufptr = NULL; 00052 00053 if (fd < 0) { 00054 err = AVERROR(errno); 00055 av_strerror(err, errbuf, sizeof(errbuf)); 00056 av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf); 00057 return err; 00058 } 00059 00060 if (fstat(fd, &st) < 0) { 00061 err = AVERROR(errno); 00062 av_strerror(err, errbuf, sizeof(errbuf)); 00063 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf); 00064 close(fd); 00065 return err; 00066 } 00067 00068 off_size = st.st_size; 00069 if (off_size > SIZE_MAX) { 00070 av_log(&file_log_ctx, AV_LOG_ERROR, 00071 "File size for file '%s' is too big\n", filename); 00072 close(fd); 00073 return AVERROR(EINVAL); 00074 } 00075 *size = off_size; 00076 00077 #if HAVE_MMAP 00078 ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 00079 if (ptr == MAP_FAILED) { 00080 err = AVERROR(errno); 00081 av_strerror(err, errbuf, sizeof(errbuf)); 00082 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf); 00083 close(fd); 00084 return err; 00085 } 00086 *bufptr = ptr; 00087 #elif HAVE_MAPVIEWOFFILE 00088 { 00089 HANDLE mh, fh = (HANDLE)_get_osfhandle(fd); 00090 00091 mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL); 00092 if (!mh) { 00093 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n"); 00094 close(fd); 00095 return -1; 00096 } 00097 00098 ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size); 00099 CloseHandle(mh); 00100 if (!ptr) { 00101 av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n"); 00102 close(fd); 00103 return -1; 00104 } 00105 00106 *bufptr = ptr; 00107 } 00108 #else 00109 *bufptr = av_malloc(*size); 00110 if (!*bufptr) { 00111 av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n"); 00112 close(fd); 00113 return AVERROR(ENOMEM); 00114 } 00115 read(fd, *bufptr, *size); 00116 #endif 00117 00118 close(fd); 00119 return 0; 00120 } 00121 00122 void av_file_unmap(uint8_t *bufptr, size_t size) 00123 { 00124 #if HAVE_MMAP 00125 munmap(bufptr, size); 00126 #elif HAVE_MAPVIEWOFFILE 00127 UnmapViewOfFile(bufptr); 00128 #else 00129 av_free(bufptr); 00130 #endif 00131 } 00132 00133 int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) { 00134 FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; 00135 int fd=-1; 00136 #if !HAVE_MKSTEMP 00137 void *ptr= tempnam(NULL, prefix); 00138 if(!ptr) 00139 ptr= tempnam(".", prefix); 00140 *filename = av_strdup(ptr); 00141 #undef free 00142 free(ptr); 00143 #else 00144 size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX0円" */ 00145 *filename = av_malloc(len); 00146 #endif 00147 /* -----common section-----*/ 00148 if (*filename == NULL) { 00149 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n"); 00150 return AVERROR(ENOMEM); 00151 } 00152 #if !HAVE_MKSTEMP 00153 # ifndef O_BINARY 00154 # define O_BINARY 0 00155 # endif 00156 # ifndef O_EXCL 00157 # define O_EXCL 0 00158 # endif 00159 fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); 00160 #else 00161 snprintf(*filename, len, "/tmp/%sXXXXXX", prefix); 00162 fd = mkstemp(*filename); 00163 #ifdef _WIN32 00164 if (fd < 0) { 00165 snprintf(*filename, len, "./%sXXXXXX", prefix); 00166 fd = mkstemp(*filename); 00167 } 00168 #endif 00169 #endif 00170 /* -----common section-----*/ 00171 if (fd < 0) { 00172 int err = AVERROR(errno); 00173 av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename); 00174 av_freep(filename); 00175 return err; 00176 } 00177 return fd; /* success */ 00178 } 00179 00180 #ifdef TEST 00181 00182 #undef printf 00183 00184 int main(void) 00185 { 00186 uint8_t *buf; 00187 size_t size; 00188 if (av_file_map("file.c", &buf, &size, 0, NULL) < 0) 00189 return 1; 00190 00191 buf[0] = 's'; 00192 printf("%s", buf); 00193 av_file_unmap(buf, size); 00194 return 0; 00195 } 00196 #endif