+#ifdef HAVE_MMAP
+# define MMAP_SIZE (1 << 20)
+
+static block_t *mmapBlock (access_t *p_access)
+{
+ access_sys_t *p_sys = p_access->p_sys;
+
+ const int flags = MAP_SHARED;
+ off_t offset = p_access->info.i_pos & ~p_sys->pagemask;
+ size_t align = p_access->info.i_pos & p_sys->pagemask;
+ size_t length = (MMAP_SIZE > p_sys->pagemask) ? MMAP_SIZE : (p_sys->pagemask + 1);
+ void *addr;
+
+#ifndef NDEBUG
+ int64_t dbgpos = lseek (p_sys->fd, 0, SEEK_CUR);
+ if (dbgpos != p_access->info.i_pos)
+ msg_Err (p_access, "position: 0x%08llx instead of 0x%08llx",
+ p_access->info.i_pos, dbgpos);
+#endif
+
+ if (p_access->info.i_pos >= p_access->info.i_size)
+ {
+ /* End of file - check if file size changed... */
+ struct stat st;
+
+ if ((fstat (p_sys->fd, &st) == 0)
+ && (st.st_size != p_access->info.i_size))
+ {
+ p_access->info.i_size = st.st_size;
+ p_access->info.i_update |= INPUT_UPDATE_SIZE;
+ }
+
+ /* Really at end of file then */
+ if (p_access->info.i_pos >= p_access->info.i_size)
+ {
+ p_access->info.b_eof = VLC_TRUE;
+ msg_Dbg (p_access, "at end of memory mapped file");
+ return NULL;
+ }
+ }
+
+ if (offset + length > p_access->info.i_size)
+ /* Don't mmap beyond end of file */
+ length = p_access->info.i_size - offset;
+
+ assert (offset <= p_access->info.i_pos); /* and */
+ assert (p_access->info.i_pos < p_access->info.i_size); /* imply */
+ assert (offset < p_access->info.i_size); /* imply */
+ assert (length > 0);
+
+ addr = mmap (NULL, length, PROT_READ, flags, p_sys->fd, offset);
+ if (addr == MAP_FAILED)
+ {
+ msg_Err (p_access, "memory mapping failed (%m)");
+ intf_UserFatal (p_access, VLC_FALSE, _("File reading failed"),
+ _("VLC could not read the file."));
+ msleep( INPUT_ERROR_SLEEP );
+ return NULL;
+ }
+
+ p_access->info.i_pos = offset + length;
+
+ block_t *block = block_mmap_Alloc (addr, length);
+ if (block == NULL)
+ return NULL;
+
+ block->p_buffer += align;
+ block->i_buffer -= align;
+
+#ifndef NDEBUG
+ msg_Dbg (p_access, "mapped 0x%lx bytes at %p from offset 0x%lx",
+ (unsigned long)length, addr, (unsigned long)offset);
+
+ /* Compare normal I/O with memory mapping */
+ char *buf = malloc (block->i_buffer);
+ ssize_t i_read = read (p_sys->fd, buf, block->i_buffer);
+
+ if (i_read != (ssize_t)block->i_buffer)
+ msg_Err (p_access, "read %u instead of %u bytes", (unsigned)i_read,
+ (unsigned)block->i_buffer);
+ if (memcmp (buf, block->p_buffer, block->i_buffer))
+ msg_Err (p_access, "inconsistent data buffer");
+ free (buf);
+#endif
+
+ return block;
+}
+#endif
+