yading@11: /* yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "config.h" yading@11: #include "file.h" yading@11: #include "log.h" yading@11: #include "mem.h" yading@11: #include yading@11: #include yading@11: #if HAVE_UNISTD_H yading@11: #include yading@11: #endif yading@11: #if HAVE_IO_H yading@11: #include yading@11: #endif yading@11: #if HAVE_MMAP yading@11: #include yading@11: #elif HAVE_MAPVIEWOFFILE yading@11: #include yading@11: #endif yading@11: yading@11: typedef struct { yading@11: const AVClass *class; yading@11: int log_offset; yading@11: void *log_ctx; yading@11: } FileLogContext; yading@11: yading@11: static const AVClass file_log_ctx_class = { yading@11: "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, yading@11: offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx) yading@11: }; yading@11: yading@11: int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, yading@11: int log_offset, void *log_ctx) yading@11: { yading@11: FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; yading@11: int err, fd = open(filename, O_RDONLY); yading@11: struct stat st; yading@11: av_unused void *ptr; yading@11: off_t off_size; yading@11: char errbuf[128]; yading@11: *bufptr = NULL; yading@11: yading@11: if (fd < 0) { yading@11: err = AVERROR(errno); yading@11: av_strerror(err, errbuf, sizeof(errbuf)); yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf); yading@11: return err; yading@11: } yading@11: yading@11: if (fstat(fd, &st) < 0) { yading@11: err = AVERROR(errno); yading@11: av_strerror(err, errbuf, sizeof(errbuf)); yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf); yading@11: close(fd); yading@11: return err; yading@11: } yading@11: yading@11: off_size = st.st_size; yading@11: if (off_size > SIZE_MAX) { yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, yading@11: "File size for file '%s' is too big\n", filename); yading@11: close(fd); yading@11: return AVERROR(EINVAL); yading@11: } yading@11: *size = off_size; yading@11: yading@11: #if HAVE_MMAP yading@11: ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); yading@11: if (ptr == MAP_FAILED) { yading@11: err = AVERROR(errno); yading@11: av_strerror(err, errbuf, sizeof(errbuf)); yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf); yading@11: close(fd); yading@11: return err; yading@11: } yading@11: *bufptr = ptr; yading@11: #elif HAVE_MAPVIEWOFFILE yading@11: { yading@11: HANDLE mh, fh = (HANDLE)_get_osfhandle(fd); yading@11: yading@11: mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL); yading@11: if (!mh) { yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n"); yading@11: close(fd); yading@11: return -1; yading@11: } yading@11: yading@11: ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size); yading@11: CloseHandle(mh); yading@11: if (!ptr) { yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n"); yading@11: close(fd); yading@11: return -1; yading@11: } yading@11: yading@11: *bufptr = ptr; yading@11: } yading@11: #else yading@11: *bufptr = av_malloc(*size); yading@11: if (!*bufptr) { yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n"); yading@11: close(fd); yading@11: return AVERROR(ENOMEM); yading@11: } yading@11: read(fd, *bufptr, *size); yading@11: #endif yading@11: yading@11: close(fd); yading@11: return 0; yading@11: } yading@11: yading@11: void av_file_unmap(uint8_t *bufptr, size_t size) yading@11: { yading@11: #if HAVE_MMAP yading@11: munmap(bufptr, size); yading@11: #elif HAVE_MAPVIEWOFFILE yading@11: UnmapViewOfFile(bufptr); yading@11: #else yading@11: av_free(bufptr); yading@11: #endif yading@11: } yading@11: yading@11: int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) { yading@11: FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx }; yading@11: int fd=-1; yading@11: #if !HAVE_MKSTEMP yading@11: void *ptr= tempnam(NULL, prefix); yading@11: if(!ptr) yading@11: ptr= tempnam(".", prefix); yading@11: *filename = av_strdup(ptr); yading@11: #undef free yading@11: free(ptr); yading@11: #else yading@11: size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */ yading@11: *filename = av_malloc(len); yading@11: #endif yading@11: /* -----common section-----*/ yading@11: if (*filename == NULL) { yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n"); yading@11: return AVERROR(ENOMEM); yading@11: } yading@11: #if !HAVE_MKSTEMP yading@11: # ifndef O_BINARY yading@11: # define O_BINARY 0 yading@11: # endif yading@11: # ifndef O_EXCL yading@11: # define O_EXCL 0 yading@11: # endif yading@11: fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); yading@11: #else yading@11: snprintf(*filename, len, "/tmp/%sXXXXXX", prefix); yading@11: fd = mkstemp(*filename); yading@11: #ifdef _WIN32 yading@11: if (fd < 0) { yading@11: snprintf(*filename, len, "./%sXXXXXX", prefix); yading@11: fd = mkstemp(*filename); yading@11: } yading@11: #endif yading@11: #endif yading@11: /* -----common section-----*/ yading@11: if (fd < 0) { yading@11: int err = AVERROR(errno); yading@11: av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename); yading@11: av_freep(filename); yading@11: return err; yading@11: } yading@11: return fd; /* success */ yading@11: } yading@11: yading@11: #ifdef TEST yading@11: yading@11: #undef printf yading@11: yading@11: int main(void) yading@11: { yading@11: uint8_t *buf; yading@11: size_t size; yading@11: if (av_file_map("file.c", &buf, &size, 0, NULL) < 0) yading@11: return 1; yading@11: yading@11: buf[0] = 's'; yading@11: printf("%s", buf); yading@11: av_file_unmap(buf, size); yading@11: return 0; yading@11: } yading@11: #endif yading@11: