this repo has no description
at trunk 142 lines 4.7 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "mmap-module.h" 3 4#include <fcntl.h> 5#include <sys/mman.h> 6#include <sys/stat.h> 7 8#include <cerrno> 9 10#include "builtins.h" 11#include "file.h" 12#include "handles.h" 13#include "module-builtins.h" 14#include "modules.h" 15#include "objects.h" 16#include "os.h" 17#include "runtime.h" 18#include "symbols.h" 19#include "thread.h" 20#include "type-builtins.h" 21 22namespace py { 23 24void FUNC(mmap, __init_module__)(Thread* thread, const Module& module, 25 View<byte> bytecode) { 26 HandleScope scope(thread); 27 Object page_size(&scope, SmallInt::fromWord(OS::pageSize())); 28 moduleAtPutById(thread, module, ID(PAGESIZE), page_size); 29 30 Object prot_exec(&scope, SmallInt::fromWord(static_cast<word>(PROT_EXEC))); 31 moduleAtPutById(thread, module, ID(PROT_EXEC), prot_exec); 32 33 Object prot_read(&scope, SmallInt::fromWord(static_cast<word>(PROT_READ))); 34 moduleAtPutById(thread, module, ID(PROT_READ), prot_read); 35 36 Object prot_write(&scope, SmallInt::fromWord(static_cast<word>(PROT_WRITE))); 37 moduleAtPutById(thread, module, ID(PROT_WRITE), prot_write); 38 39 Object map_shared(&scope, SmallInt::fromWord(static_cast<word>(MAP_SHARED))); 40 moduleAtPutById(thread, module, ID(MAP_SHARED), map_shared); 41 42 Object map_private(&scope, 43 SmallInt::fromWord(static_cast<word>(MAP_PRIVATE))); 44 moduleAtPutById(thread, module, ID(MAP_PRIVATE), map_private); 45 46 executeFrozenModule(thread, module, bytecode); 47} 48 49RawObject FUNC(mmap, _mmap_new)(Thread* thread, Arguments args) { 50 HandleScope scope(thread); 51 Runtime* runtime = thread->runtime(); 52 word fd = intUnderlying(args.get(1)).asWord(); 53 word length = intUnderlying(args.get(2)).asWord(); 54 word flags = intUnderlying(args.get(3)).asWord(); 55 word prot = intUnderlying(args.get(4)).asWord(); 56 word offset = intUnderlying(args.get(5)).asWord(); 57 58 if (fd != -1) { 59 struct stat sbuf; 60 if (::fstat(fd, &sbuf) == 0 && S_ISREG(sbuf.st_mode)) { 61 if (length == 0) { 62 if (sbuf.st_size == 0) { 63 return thread->raiseWithFmt(LayoutId::kValueError, 64 "cannot mmap an empty file"); 65 } 66 if (offset >= sbuf.st_size) { 67 return thread->raiseWithFmt(LayoutId::kValueError, 68 "mmap offset is greater than file size"); 69 } 70 length = sbuf.st_size - offset; 71 } else if (offset > sbuf.st_size || sbuf.st_size - offset < length) { 72 return thread->raiseWithFmt(LayoutId::kValueError, 73 "mmap length is greater than file size"); 74 } 75 } 76 fd = ::fcntl(fd, F_DUPFD_CLOEXEC, 0); 77 if (fd < 0) { 78 return thread->raiseOSErrorFromErrno(errno); 79 } 80 } else { 81 flags |= MAP_ANONYMOUS; 82 } 83 84 void* address = ::mmap(nullptr, length, prot, flags, fd, offset); 85 if (address == MAP_FAILED) { 86 return thread->raiseOSErrorFromErrno(errno); 87 } 88 89 Type type(&scope, args.get(0)); 90 Layout layout(&scope, type.instanceLayout()); 91 Mmap result(&scope, runtime->newInstance(layout)); 92 result.setAccess(0); 93 if ((prot & PROT_READ) != 0) { 94 result.setReadable(); 95 } 96 if ((prot & PROT_WRITE) != 0) { 97 result.setWritable(); 98 } 99 if ((flags == MAP_PRIVATE) != 0) { 100 result.setCopyOnWrite(); 101 } 102 result.setData(runtime->newPointer(address, length)); 103 result.setFd(runtime->newInt(fd)); 104 return *result; 105} 106 107RawObject METH(mmap, close)(Thread* thread, Arguments args) { 108 HandleScope scope(thread); 109 Object self(&scope, args.get(0)); 110 if (!thread->runtime()->isInstanceOfMmap(*self)) { 111 return thread->raiseRequiresType(self, ID(mmap)); 112 } 113 Mmap mmap_obj(&scope, *self); 114 // TODO(T64468928): Take into account exporters 115 word fd = Int::cast(mmap_obj.fd()).asWord(); 116 if (fd >= 0) { 117 int close_result = File::close(fd); 118 if (close_result < 0) return thread->raiseOSErrorFromErrno(-close_result); 119 } 120 mmap_obj.setFd(SmallInt::fromWord(-1)); 121 Pointer pointer(&scope, mmap_obj.data()); 122 void* address = pointer.cptr(); 123 if (address != nullptr) { 124 OS::freeMemory(static_cast<byte*>(address), pointer.length()); 125 mmap_obj.setData(NoneType::object()); 126 } 127 return NoneType::object(); 128} 129 130static const BuiltinAttribute kMmapAttributes[] = { 131 {ID(_mmap__access), RawMmap::kAccessOffset, AttributeFlags::kHidden}, 132 {ID(_mmap__data), RawMmap::kDataOffset, AttributeFlags::kHidden}, 133 {ID(_mmap__fd), RawMmap::kFdOffset, AttributeFlags::kHidden}, 134}; 135 136void initializeMmapType(Thread* thread) { 137 addBuiltinType(thread, ID(mmap), LayoutId::kMmap, 138 /*superclass_id=*/LayoutId::kObject, kMmapAttributes, 139 Mmap::kSize, /*basetype=*/true); 140} 141 142} // namespace py