(_cls: &Py<PyType>, args: Self::Args, vm: &VirtualMachine)
| 443 | |
| 444 | #[cfg(unix)] |
| 445 | fn py_new(_cls: &Py<PyType>, args: Self::Args, vm: &VirtualMachine) -> PyResult<Self> { |
| 446 | use libc::{MAP_PRIVATE, MAP_SHARED, PROT_READ, PROT_WRITE}; |
| 447 | |
| 448 | let mut map_size = args.validate_new_args(vm)?; |
| 449 | let MmapNewArgs { |
| 450 | fileno: fd, |
| 451 | flags, |
| 452 | prot, |
| 453 | access, |
| 454 | offset, |
| 455 | .. |
| 456 | } = args; |
| 457 | |
| 458 | if (access != AccessMode::Default) |
| 459 | && ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))) |
| 460 | { |
| 461 | return Err(vm.new_value_error("mmap can't specify both access and flags, prot.")); |
| 462 | } |
| 463 | |
| 464 | // TODO: memmap2 doesn't support mapping with prot and flags right now |
| 465 | let (_flags, _prot, access) = match access { |
| 466 | AccessMode::Read => (MAP_SHARED, PROT_READ, access), |
| 467 | AccessMode::Write => (MAP_SHARED, PROT_READ | PROT_WRITE, access), |
| 468 | AccessMode::Copy => (MAP_PRIVATE, PROT_READ | PROT_WRITE, access), |
| 469 | AccessMode::Default => { |
| 470 | let access = if (prot & PROT_READ) != 0 && (prot & PROT_WRITE) != 0 { |
| 471 | access |
| 472 | } else if (prot & PROT_WRITE) != 0 { |
| 473 | AccessMode::Write |
| 474 | } else { |
| 475 | AccessMode::Read |
| 476 | }; |
| 477 | (flags, prot, access) |
| 478 | } |
| 479 | }; |
| 480 | |
| 481 | let fd = unsafe { crt_fd::Borrowed::try_borrow_raw(fd) }; |
| 482 | |
| 483 | // macOS: Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific |
| 484 | // fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug |
| 485 | #[cfg(target_os = "macos")] |
| 486 | if let Ok(fd) = fd { |
| 487 | use std::os::fd::AsRawFd; |
| 488 | unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_FULLFSYNC) }; |
| 489 | } |
| 490 | |
| 491 | if let Ok(fd) = fd { |
| 492 | let metadata = fstat(fd) |
| 493 | .map_err(|err| io::Error::from_raw_os_error(err as i32).to_pyexception(vm))?; |
| 494 | let file_len = metadata.st_size as i64; |
| 495 | |
| 496 | if map_size == 0 { |
| 497 | if file_len == 0 { |
| 498 | return Err(vm.new_value_error("cannot mmap an empty file")); |
| 499 | } |
| 500 | |
| 501 | if offset > file_len { |
| 502 | return Err(vm.new_value_error("mmap offset is greater than file size")); |
nothing calls this directly
no test coverage detected