// Defines the member functions for the memory mapping facility. #include "ace/Mem_Map.h" #if !defined (__ACE_INLINE__) #include "ace/Mem_Map.inl" #endif /* __ACE_INLINE__ */ #include "ace/OS_NS_sys_stat.h" #include "ace/OS_NS_fcntl.h" #include "ace/OS_NS_string.h" #include "ace/Log_Category.h" #include "ace/Truncate.h" #if defined (ACE_HAS_ALLOC_HOOKS) # include "ace/Malloc_Base.h" #endif /* ACE_HAS_ALLOC_HOOKS */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_ALLOC_HOOK_DEFINE(ACE_Mem_Map) void ACE_Mem_Map::dump () const { #if defined (ACE_HAS_DUMP) ACE_TRACE ("ACE_Mem_Map::dump"); ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("base_addr_ = %x"), this->base_addr_)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfilename_ = %s"), this->filename_)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlength_ = %d"), this->length_)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhandle_ = %d"), this->handle_)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfile_mapping_ = %d"), this->file_mapping_)); ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nclose_handle_ = %d"), this->close_handle_)); ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP)); #endif /* ACE_HAS_DUMP */ } int ACE_Mem_Map::close () { ACE_TRACE ("ACE_Mem_Map::close"); this->unmap (); return this->close_handle (); } ACE_Mem_Map::~ACE_Mem_Map () { ACE_TRACE ("ACE_Mem_Map::~ACE_Mem_Map"); this->close (); } // This function does the dirty work of actually calling ACE_OS::mmap // to map the file into memory. int ACE_Mem_Map::map_it (ACE_HANDLE handle, size_t length_request, int prot, int share, void *addr, ACE_OFF_T offset, LPSECURITY_ATTRIBUTES sa) { ACE_TRACE ("ACE_Mem_Map::map_it"); #if defined (ACE_LACKS_AUTO_MMAP_REPLACEMENT) // If the system does not replace any previous mappings, then // unmap() before (potentially) mapping to the same location. int const unmap_result = this->unmap (); if (unmap_result != 0) return unmap_result; #endif /* ACE_LACKS_AUTO_MMAP_REPLACEMENT */ this->base_addr_ = addr; this->handle_ = handle; // mmap through character device doens't care about it's size // So map with /dev/* is done with a special case. ACE_stat current_file_type; int result = ACE_OS::fstat (this->handle_, ¤t_file_type); if (result == -1) { // Something wrong found, bail out. return -1; } else if ((current_file_type.st_mode & S_IFMT) == S_IFCHR) { // Set length to length_request this->length_ = length_request; } else if ((current_file_type.st_mode & S_IFMT) == S_IFREG) { // Get the current filesize ACE_OFF_T const current_file_length = ACE_OS::filesize (this->handle_); // Flag to indicate if we need to extend the back store bool extend_backing_store = false; // File length requested by user ACE_OFF_T requested_file_length = 0; // Check if (length_request == static_cast (-1)) { // Set length to file_request or size_t max. this->length_ = ACE_Utils::truncate_cast (current_file_length - offset); #if defined (ACE_MMAP_NO_ZERO) if (this->length_ == 0) { this->length_ = ACE_OS::getpagesize (); } #endif /* ACE_MMAP_NO_ZERO */ } else { // Make sure that we have not been asked to do the impossible. if (static_cast (length_request) + static_cast (offset) > static_cast (ACE_Numeric_Limits::max ())) return -1; // File length implicitly requested by user requested_file_length = static_cast (length_request) + offset; // Check to see if we need to extend the backing store if (requested_file_length > current_file_length) { // If the length of the mapped region is less than the // length of the file then we force a complete new remapping // by setting the descriptor to ACE_INVALID_HANDLE (closing // down the descriptor if necessary). this->close_filemapping_handle (); // Remember to extend the backing store extend_backing_store = true; } // Set length to length_request this->length_ = length_request; } // Check if we need to extend the backing store. if (extend_backing_store) { // Remember than write increases the size by one. ACE_OFF_T null_byte_position = 0; if (requested_file_length > 0) { // This will make the file size null_byte_position = requested_file_length - 1; } if (ACE_OS::pwrite (this->handle_, "", 1, null_byte_position) == -1) return -1; } } else // Unmappable file type. return -1; this->base_addr_ = ACE_OS::mmap (this->base_addr_, this->length_, prot, share, this->handle_, offset, &this->file_mapping_, sa); return this->base_addr_ == MAP_FAILED ? -1 : 0; } int ACE_Mem_Map::open (const ACE_TCHAR *file_name, int flags, mode_t perms, LPSECURITY_ATTRIBUTES sa) { ACE_TRACE ("ACE_Mem_Map::open"); #if defined (INTEGRITY) || defined (__QNXNTO__) || defined (ACE_VXWORKS) this->handle_ = ACE_OS::shm_open (file_name, flags, perms, sa); #elif defined (ACE_OPENVMS) ACE_OSCALL (::open (file_name, flags, perms, "shr=get,put,upd"), ACE_HANDLE, this->handle_); #else this->handle_ = ACE_OS::open (file_name, flags, perms, sa); #endif /* INTEGRITY */ if (this->handle_ == ACE_INVALID_HANDLE) return -1; else { ACE_OS::strsncpy (this->filename_, file_name, MAXPATHLEN); this->close_handle_ = true; return 0; } } int ACE_Mem_Map::map (const ACE_TCHAR *file_name, size_t len, int flags, mode_t mode, int prot, int share, void *addr, ACE_OFF_T offset, LPSECURITY_ATTRIBUTES sa) { ACE_TRACE ("ACE_Mem_Map::map"); this->length_ = 0; if (this->open (file_name, flags, mode, sa) == -1) return -1; else return this->map_it (this->handle (), len, prot, share, addr, offset, sa); } ACE_Mem_Map::ACE_Mem_Map () : base_addr_ (MAP_FAILED), length_ (0), handle_ (ACE_INVALID_HANDLE), file_mapping_ (ACE_INVALID_HANDLE), close_handle_ (false) { ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); ACE_OS::memset (this->filename_, 0, sizeof this->filename_); } // Map a file specified by FILE_NAME. ACE_Mem_Map::ACE_Mem_Map (const ACE_TCHAR *file_name, size_t len, int flags, mode_t mode, int prot, int share, void *addr, ACE_OFF_T offset, LPSECURITY_ATTRIBUTES sa) : base_addr_ (MAP_FAILED), length_ (0), handle_ (ACE_INVALID_HANDLE), file_mapping_ (ACE_INVALID_HANDLE), close_handle_ (false) { ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); if (this->map (file_name, len, flags, mode, prot, share, addr, offset, sa) < 0) ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Mem_Map::ACE_Mem_Map"))); } // Map a file from an open file descriptor HANDLE. This function will // lookup the length of the file if it is not given. ACE_Mem_Map::ACE_Mem_Map (ACE_HANDLE handle, size_t len, int prot, int share, void *addr, ACE_OFF_T offset, LPSECURITY_ATTRIBUTES sa) : base_addr_ (MAP_FAILED), length_ (0), handle_ (ACE_INVALID_HANDLE), file_mapping_ (ACE_INVALID_HANDLE), close_handle_ (false) { ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); ACE_OS::memset (this->filename_, 0, sizeof this->filename_); if (this->map (handle, len, prot, share, addr, offset, sa) < 0) ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Mem_Map::ACE_Mem_Map"))); } // Close down and remove the file from the file system. int ACE_Mem_Map::remove () { ACE_TRACE ("ACE_Mem_Map::remove"); ACE_OS::ftruncate (this->handle_, 0); this->close (); if (this->filename_[0] != '\0') #if defined (INTEGRITY) || defined (__QNXNTO__) || defined (ACE_VXWORKS) return ACE_OS::shm_unlink (this->filename_); #else return ACE_OS::unlink (this->filename_); #endif /* __QNXNTO__ */ else return 0; } ACE_END_VERSIONED_NAMESPACE_DECL