| | 212 | /** |
|---|
| | 213 | * Creates a block from a virtual address memory mapping (mmap). |
|---|
| | 214 | * This is provided by LibVLC so that mmap blocks can safely be deallocated |
|---|
| | 215 | * even after the allocating plugin has been unloaded from memory. |
|---|
| | 216 | * |
|---|
| | 217 | * @param addr base address of the mapping (as returned by mmap) |
|---|
| | 218 | * @param length length (bytes) of the mapping (as passed to mmap) |
|---|
| | 219 | * @return NULL if addr is MAP_FAILED, or an error occurred (in the later |
|---|
| | 220 | * case, munmap(addr, length) is invoked before returning). |
|---|
| | 221 | */ |
|---|
| | 261 | /** |
|---|
| | 262 | * Loads a file into a block of memory. If possible a private file mapping is |
|---|
| | 263 | * created. Otherwise, the file is read normally. On 32-bits platforms, this |
|---|
| | 264 | * function will not work for very large files, due to memory space |
|---|
| | 265 | * constraints. |
|---|
| | 266 | * |
|---|
| | 267 | * @param fd file descriptor to load from |
|---|
| | 268 | * @return a new block with the file content at p_buffer, and file length at |
|---|
| | 269 | * i_buffer (release it with block_Release()), or NULL upon error (see errno). |
|---|
| | 270 | */ |
|---|
| | 271 | block_t *block_File (int fd) |
|---|
| | 272 | { |
|---|
| | 273 | size_t length; |
|---|
| | 274 | struct stat st; |
|---|
| | 275 | |
|---|
| | 276 | /* First, get the file size */ |
|---|
| | 277 | if (fstat (fd, &st)) |
|---|
| | 278 | return NULL; |
|---|
| | 279 | |
|---|
| | 280 | /* st_size is meaningful for regular files, shared memory and typed memory. |
|---|
| | 281 | * It's also meaning for symlinks, but that's not possible with fstat(). |
|---|
| | 282 | * In other cases, it's undefined, and we should really not go further. */ |
|---|
| | 283 | #ifndef S_TYPEISSHM |
|---|
| | 284 | # define S_TYPEISSHM( buf ) (0) |
|---|
| | 285 | #endif |
|---|
| | 286 | if (S_ISDIR (st.st_mode)) |
|---|
| | 287 | { |
|---|
| | 288 | errno = EISDIR; |
|---|
| | 289 | return NULL; |
|---|
| | 290 | } |
|---|
| | 291 | if (!S_ISREG (st.st_mode) && !S_TYPEISSHM (&st)) |
|---|
| | 292 | { |
|---|
| | 293 | errno = ESPIPE; |
|---|
| | 294 | return NULL; |
|---|
| | 295 | } |
|---|
| | 296 | |
|---|
| | 297 | /* Prevent an integer overflow in mmap() and malloc() */ |
|---|
| | 298 | if (st.st_size >= SIZE_MAX) |
|---|
| | 299 | { |
|---|
| | 300 | errno = ENOMEM; |
|---|
| | 301 | return NULL; |
|---|
| | 302 | } |
|---|
| | 303 | length = (size_t)st.st_size; |
|---|
| | 304 | |
|---|
| | 305 | #ifdef HAVE_MMAP |
|---|
| | 306 | if (length > 0) |
|---|
| | 307 | { |
|---|
| | 308 | void *addr; |
|---|
| | 309 | |
|---|
| | 310 | addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); |
|---|
| | 311 | if (addr != MAP_FAILED) |
|---|
| | 312 | return block_mmap_Alloc (addr, length); |
|---|
| | 313 | } |
|---|
| | 314 | #endif |
|---|
| | 315 | |
|---|
| | 316 | /* If mmap() is not implemented by the OS _or_ the filesystem... */ |
|---|
| | 317 | block_t *block = block_Alloc (length); |
|---|
| | 318 | if (block == NULL) |
|---|
| | 319 | return NULL; |
|---|
| | 320 | |
|---|
| | 321 | for (size_t i = 0; i < length;) |
|---|
| | 322 | { |
|---|
| | 323 | ssize_t len = pread (fd, block->p_buffer + i, length - i, i); |
|---|
| | 324 | if (len == -1) |
|---|
| | 325 | { |
|---|
| | 326 | block_Release (block); |
|---|
| | 327 | return NULL; |
|---|
| | 328 | } |
|---|
| | 329 | i += len; |
|---|
| | 330 | } |
|---|
| | 331 | return block; |
|---|
| | 332 | } |
|---|
| | 333 | |
|---|