@@ -68,40 +68,65 @@ private static Exception WindowsError(int code) {
6868 public static PythonType mmap {
6969 get {
7070 if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ) {
71- return DynamicHelpers . GetPythonTypeFromType ( typeof ( MmapDefault ) ) ;
71+ return DynamicHelpers . GetPythonTypeFromType ( typeof ( MmapWindows ) ) ;
7272 }
7373
7474 return DynamicHelpers . GetPythonTypeFromType ( typeof ( MmapUnix ) ) ;
7575 }
7676 }
7777
78+
7879 [ PythonType ( "mmap" ) , PythonHidden ]
7980 public class MmapUnix : MmapDefault {
8081 public MmapUnix ( CodeContext /*!*/ context , int fileno , long length , int flags = MAP_SHARED , int prot = PROT_WRITE | PROT_READ , int access = ACCESS_DEFAULT , long offset = 0 )
81- : base ( context , fileno , length , null , NormalizeAccess ( flags , prot , access ) , offset ) { }
82+ : base ( context , fileno , length , null , ToMmapFileAccess ( flags , prot , access ) , offset ) { }
8283
83- private static int NormalizeAccess ( int flags , int prot , int access ) {
84+ private static MemoryMappedFileAccess ToMmapFileAccess ( int flags , int prot , int access ) {
8485 if ( access == ACCESS_DEFAULT ) {
8586 if ( ( flags & ( MAP_PRIVATE | MAP_SHARED ) ) == 0 ) {
8687 throw PythonOps . OSError ( PythonErrorNumber . EINVAL , "Invalid argument" ) ;
8788 }
8889 if ( ( prot & PROT_WRITE ) != 0 ) {
89- return ( flags & MAP_PRIVATE ) != 0 ? ACCESS_COPY : ACCESS_WRITE ;
90- }
91- if ( ( prot & PROT_READ ) != 0 ) {
92- return ACCESS_READ ;
93- }
94- throw PythonOps . NotImplementedError ( "this combination of flags and prot is not supported" ) ;
90+ prot |= PROT_READ ;
91+ }
92+ return ( prot & ( PROT_READ | PROT_WRITE | PROT_EXEC ) ) switch {
93+ PROT_READ => MemoryMappedFileAccess . Read ,
94+ PROT_READ | PROT_WRITE => ( flags & MAP_PRIVATE ) == 0 ? MemoryMappedFileAccess . ReadWrite : MemoryMappedFileAccess . CopyOnWrite ,
95+ PROT_READ | PROT_EXEC => MemoryMappedFileAccess . ReadExecute ,
96+ PROT_READ | PROT_WRITE | PROT_EXEC when ( flags & MAP_PRIVATE ) == 0 => MemoryMappedFileAccess . ReadWriteExecute ,
97+ _ => throw PythonOps . NotImplementedError ( "this combination of prot is not supported" ) ,
98+ } ;
9599 } else if ( flags != MAP_SHARED || prot != ( PROT_WRITE | PROT_READ ) ) {
96100 throw PythonOps . ValueError ( "mmap can't specify both access and flags, prot." ) ;
97- } else if ( access != ACCESS_READ && access != ACCESS_WRITE && access != ACCESS_COPY ) {
98- throw PythonOps . ValueError ( "mmap invalid access parameter" ) ;
101+ } else {
102+ return access switch {
103+ ACCESS_READ => MemoryMappedFileAccess . Read ,
104+ ACCESS_WRITE => MemoryMappedFileAccess . ReadWrite ,
105+ ACCESS_COPY => MemoryMappedFileAccess . CopyOnWrite ,
106+ _ => throw PythonOps . ValueError ( "mmap invalid access parameter" ) ,
107+ } ;
99108 }
100- return access ;
101109 }
102110 }
103111
112+
104113 [ PythonType ( "mmap" ) , PythonHidden ]
114+ public class MmapWindows : MmapDefault {
115+ public MmapWindows ( CodeContext context , int fileno , long length , string tagname = null , int access = ACCESS_DEFAULT , long offset = 0 )
116+ : base ( context , fileno , length , tagname , ToMmapFileAccess ( access ) , offset ) { }
117+
118+ private static MemoryMappedFileAccess ToMmapFileAccess ( int access ) {
119+ return access switch {
120+ ACCESS_READ => MemoryMappedFileAccess . Read ,
121+ // On Windows, default access is write-through
122+ ACCESS_DEFAULT or ACCESS_WRITE => MemoryMappedFileAccess . ReadWrite ,
123+ ACCESS_COPY => MemoryMappedFileAccess . CopyOnWrite ,
124+ _ => throw PythonOps . ValueError ( "mmap invalid access parameter" ) ,
125+ } ;
126+ }
127+ }
128+
129+ [ PythonHidden ]
105130 public class MmapDefault : IWeakReferenceable {
106131 private MemoryMappedFile _file ;
107132 private MemoryMappedViewAccessor _view ;
@@ -115,21 +140,8 @@ public class MmapDefault : IWeakReferenceable {
115140 private volatile bool _isClosed ;
116141 private int _refCount = 1 ;
117142
118- public MmapDefault ( CodeContext /*!*/ context , int fileno , long length , string tagname = null , int access = ACCESS_DEFAULT , long offset = 0 ) {
119- switch ( access ) {
120- case ACCESS_READ :
121- _fileAccess = MemoryMappedFileAccess . Read ;
122- break ;
123- case ACCESS_DEFAULT : // On Windows, default access is write-through
124- case ACCESS_WRITE :
125- _fileAccess = MemoryMappedFileAccess . ReadWrite ;
126- break ;
127- case ACCESS_COPY :
128- _fileAccess = MemoryMappedFileAccess . CopyOnWrite ;
129- break ;
130- default :
131- throw PythonOps . ValueError ( "mmap invalid access parameter" ) ;
132- }
143+ public MmapDefault ( CodeContext /*!*/ context , int fileno , long length , string tagname , MemoryMappedFileAccess fileAccess , long offset ) {
144+ _fileAccess = fileAccess ;
133145
134146 if ( length < 0 ) {
135147 throw PythonOps . OverflowError ( "memory mapped size must be positive" ) ;
@@ -175,7 +187,7 @@ public MmapDefault(CodeContext/*!*/ context, int fileno, long length, string tag
175187 throw PythonOps . OSError ( PythonExceptions . _OSError . ERROR_INVALID_BLOCK , "Bad file descriptor" ) ;
176188 }
177189
178- if ( _fileAccess == MemoryMappedFileAccess . ReadWrite && ! _sourceStream . CanWrite ) {
190+ if ( _fileAccess is MemoryMappedFileAccess . ReadWrite or MemoryMappedFileAccess . ReadWriteExecute && ! _sourceStream . CanWrite ) {
179191 throw WindowsError ( PythonExceptions . _OSError . ERROR_ACCESS_DENIED ) ;
180192 }
181193
@@ -579,7 +591,7 @@ public string readline() {
579591
580592 public void resize ( long newsize ) {
581593 using ( new MmapLocker ( this ) ) {
582- if ( _fileAccess != MemoryMappedFileAccess . ReadWrite ) {
594+ if ( _fileAccess is not MemoryMappedFileAccess . ReadWrite and not MemoryMappedFileAccess . ReadWriteExecute ) {
583595 throw PythonOps . TypeError ( "mmap can't resize a readonly or copy-on-write memory map." ) ;
584596 }
585597
@@ -802,7 +814,7 @@ private long Position {
802814 }
803815
804816 private void EnsureWritable ( ) {
805- if ( _fileAccess == MemoryMappedFileAccess . Read ) {
817+ if ( _fileAccess is MemoryMappedFileAccess . Read or MemoryMappedFileAccess . ReadExecute ) {
806818 throw PythonOps . TypeError ( "mmap can't modify a read-only memory map." ) ;
807819 }
808820 }
0 commit comments