# include "config.h"
#endif
-#include <vlc/vlc.h>
+#include <vlc_common.h>
+#include <sys/stat.h>
#include "vlc_block.h"
/*****************************************************************************
{
block_t self;
size_t i_allocated_buffer;
- uint8_t p_allocated_buffer[0];
+ uint8_t p_allocated_buffer[];
};
#ifndef NDEBUG
block_t *block_Realloc( block_t *p_block, ssize_t i_prebody, size_t i_body )
{
block_sys_t *p_sys = (block_sys_t *)p_block;
- ssize_t i_buffer_size;
+ ssize_t i_buffer_size = i_prebody + i_body;
+
+ if( i_buffer_size <= 0 )
+ {
+ block_Release( p_block );
+ return NULL;
+ }
if( p_block->pf_release != BlockRelease )
{
p_block = p_dup;
}
- i_buffer_size = i_prebody + i_body;
-
- if( i_buffer_size <= 0 )
- {
- block_Release( p_block );
- return NULL;
- }
-
/* Adjust reserved header if there is enough room */
if( p_block->p_buffer - i_prebody > p_sys->p_allocated_buffer &&
p_block->p_buffer - i_prebody < p_sys->p_allocated_buffer +
- ((uintptr_t)p_sys->p_allocated_buffer % BLOCK_ALIGN);
}
}
-
return p_block;
}
free (p_sys);
}
+/**
+ * Creates a block from a virtual address memory mapping (mmap).
+ * This is provided by LibVLC so that mmap blocks can safely be deallocated
+ * even after the allocating plugin has been unloaded from memory.
+ *
+ * @param addr base address of the mapping (as returned by mmap)
+ * @param length length (bytes) of the mapping (as passed to mmap)
+ * @return NULL if addr is MAP_FAILED, or an error occurred (in the later
+ * case, munmap(addr, length) is invoked before returning).
+ */
block_t *block_mmap_Alloc (void *addr, size_t length)
{
if (addr == MAP_FAILED)
block->length = length;
return &block->self;
}
+#else
+block_t *block_mmap_Alloc (void *addr, size_t length)
+{
+ (void)addr; (void)length; return NULL;
+}
#endif
+
#ifdef WIN32
+#ifdef UNDER_CE
+#define _get_osfhandle(a) ((long) (a))
+#endif
+
static
ssize_t pread (int fd, void *buf, size_t count, off_t offset)
{
}
#endif
+/**
+ * Loads a file into a block of memory. If possible a private file mapping is
+ * created. Otherwise, the file is read normally. On 32-bits platforms, this
+ * function will not work for very large files, due to memory space
+ * constraints. Cancellation point.
+ *
+ * @param fd file descriptor to load from
+ * @return a new block with the file content at p_buffer, and file length at
+ * i_buffer (release it with block_Release()), or NULL upon error (see errno).
+ */
+block_t *block_File (int fd)
+{
+ size_t length;
+ struct stat st;
+
+ /* First, get the file size */
+ if (fstat (fd, &st))
+ return NULL;
+
+ /* st_size is meaningful for regular files, shared memory and typed memory.
+ * It's also meaning for symlinks, but that's not possible with fstat().
+ * In other cases, it's undefined, and we should really not go further. */
+#ifndef S_TYPEISSHM
+# define S_TYPEISSHM( buf ) (0)
+#endif
+ if (S_ISDIR (st.st_mode))
+ {
+ errno = EISDIR;
+ return NULL;
+ }
+ if (!S_ISREG (st.st_mode) && !S_TYPEISSHM (&st))
+ {
+ errno = ESPIPE;
+ return NULL;
+ }
+
+ /* Prevent an integer overflow in mmap() and malloc() */
+ if (st.st_size >= SIZE_MAX)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ length = (size_t)st.st_size;
+
+#ifdef HAVE_MMAP
+ if (length > 0)
+ {
+ void *addr;
+
+ addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (addr != MAP_FAILED)
+ return block_mmap_Alloc (addr, length);
+ }
+#endif
+
+ /* If mmap() is not implemented by the OS _or_ the filesystem... */
+ block_t *block = block_Alloc (length);
+ if (block == NULL)
+ return NULL;
+ block_cleanup_push (block);
+
+ for (size_t i = 0; i < length;)
+ {
+ ssize_t len = pread (fd, block->p_buffer + i, length - i, i);
+ if (len == -1)
+ {
+ block_Release (block);
+ block = NULL;
+ break;
+ }
+ i += len;
+ }
+ vlc_cleanup_pop ();
+ return block;
+}
+
/*****************************************************************************
* block_fifo_t management
*****************************************************************************/
return NULL;
vlc_mutex_init( &p_fifo->lock );
- vlc_cond_init( NULL, &p_fifo->wait );
+ vlc_cond_init( &p_fifo->wait );
p_fifo->p_first = NULL;
p_fifo->pp_last = &p_fifo->p_first;
p_fifo->i_depth = p_fifo->i_size = 0;
block_t *b;
vlc_mutex_lock( &p_fifo->lock );
+ mutex_cleanup_push( &p_fifo->lock );
/* Remember vlc_cond_wait() may cause spurious wakeups
* (on both Win32 and POSIX) */
while( ( p_fifo->p_first == NULL ) && !p_fifo->b_force_wake )
- {
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
- }
+ vlc_cleanup_pop();
b = p_fifo->p_first;
p_fifo->b_force_wake = false;
block_t *b;
vlc_mutex_lock( &p_fifo->lock );
+ mutex_cleanup_push( &p_fifo->lock );
if( p_fifo->p_first == NULL )
- {
vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
- }
b = p_fifo->p_first;
- vlc_mutex_unlock( &p_fifo->lock );
-
- return( b );
+ vlc_cleanup_run ();
+ return b;
}
+/* FIXME: not thread-safe */
size_t block_FifoSize( const block_fifo_t *p_fifo )
{
return p_fifo->i_size;
}
+/* FIXME: not thread-safe */
size_t block_FifoCount( const block_fifo_t *p_fifo )
{
return p_fifo->i_depth;