bool LandsatGeotiffImporter::createRasterPager(RasterElement* pRaster) const
{
   VERIFY(pRaster != NULL);
   DataDescriptor* pDescriptor = pRaster->getDataDescriptor();
   VERIFY(pDescriptor != NULL);
   FileDescriptor* pFileDescriptor = pDescriptor->getFileDescriptor();
   VERIFY(pFileDescriptor != NULL);

   std::string filename = pRaster->getFilename();
   std::string datasetName = pFileDescriptor->getDatasetLocation();
   Progress* pProgress = getProgress();

   FactoryResource<Filename> pFilename;
   pFilename->setFullPathAndName(filename);

   ExecutableResource pagerPlugIn("Landsat GeoTIFF Raster Pager", std::string(), pProgress);
   pagerPlugIn->getInArgList().setPlugInArgValue(CachedPager::PagedElementArg(), pRaster);
   pagerPlugIn->getInArgList().setPlugInArgValue(CachedPager::PagedFilenameArg(), pFilename.get());

   bool success = pagerPlugIn->execute();

   RasterPager* pPager = dynamic_cast<RasterPager*>(pagerPlugIn->getPlugIn());
   if (!success || pPager == NULL)
   {
      std::string message = "Execution of Landsat Geotiff Raster Pager failed!";
      if (pProgress != NULL) pProgress->updateProgress(message, 0, ERRORS);
      return false;
   }

   pRaster->setPager(pPager);
   pagerPlugIn->releasePlugIn();

   return true;
}
Пример #2
0
void commands_ns::DiskInfo(FileSystem *fs, int argc, char *argv[], std::ostream& out){	
	if (argc != 0) {
		out << "Неправильное количество параметров" << std::endl;
		return;
	}
	//размеры файлов даны в байтах
	size_t totalUsedSpace = 0;
	size_t fileSystemSize = fs->GetMaxSize();
	FileIterator* fileIterator = fs->GetIterator();
	
	while(fileIterator->HasNext()){
		fileIterator->Next();
		FileDescriptor* fileDescriptor = fileIterator->GetFileDescriptor();
		totalUsedSpace += fileDescriptor->GetSize();
	}

	size_t freeDiskSpace = fileSystemSize - totalUsedSpace;
	double ratio = (double)freeDiskSpace/fileSystemSize; 
	
	out << "Сведения о диске:" << std::endl;
	out << "Наименование: " << fs->GetTomName() << std::endl;
	out << "Размер свободного места: " << freeDiskSpace << " б (" << ratio*100 << "%)" << std::endl;
	out << "Максимальный объем: " << fileSystemSize << " б" << std::endl;

}
Пример #3
0
bool ExportDlg::invokeOptionsDialog()
{
   // Update the file descriptor with the selected file
   QString strFilename = getExportFile();
   updateFromFile(strFilename);

   // Display the dialog
   ExportOptionsDlg optionsDlg(mpExporter, this);
   if (optionsDlg.exec() == QDialog::Accepted)
   {
      // Selecting file because the filename can be changed in Export Options widget (ie: ShapeFileOptionsWidget).
      if (mpExporter.get() != NULL)
      {
         FileDescriptor* pFileDesc = mpExporter->getFileDescriptor();
         if (pFileDesc != NULL)
         {
            std::string newFilename = pFileDesc->getFilename().getFullPathAndName();
            selectFile(QString::fromStdString(newFilename));
         }
      }

      mValidated = true;
      return true;
   }

   mValidated = false;
   return false;
}
Пример #4
0
MMap::MMap (const FileDescriptor& fd, bool const sequential)
    :
    size   (fd.size()),
    ptr    (mmap (NULL, size, PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_NORESERVE, fd.get(), 0)),
    mapped (ptr != GU_MAP_FAILED)
{
    if (!mapped)
    {
        gu_throw_error(errno) << "mmap() on '" << fd.name()
                              << "' failed";
    }

#if !defined(__sun__) && !defined(__APPLE__) && !defined(__FreeBSD__)
    /* Solaris, Darwin, and FreeBSD do not have MADV_DONTFORK */
    if (posix_madvise (ptr, size, MADV_DONTFORK))
    {
        int const err(errno);
        log_warn << "Failed to set MADV_DONTFORK on " << fd.name()
                 << ": " << err << " (" << strerror(err) << ")";
    }
#endif

    /* benefits are questionable */
    if (sequential && posix_madvise (ptr, size, MADV_SEQUENTIAL))
    {
        int const err(errno);
        log_warn << "Failed to set MADV_SEQUENTIAL on " << fd.name()
                 << ": " << err << " (" << strerror(err) << ")";
    }

    log_debug << "Memory mapped: " << ptr << " (" << size << " bytes)";
}
bool
nsTemporaryFileInputStream::Deserialize(const InputStreamParams& aParams,
                                        const FileDescriptorArray& aFileDescriptors)
{
  const TemporaryFileInputStreamParams& params = aParams.get_TemporaryFileInputStreamParams();

  uint32_t fileDescriptorIndex = params.fileDescriptorIndex();
  FileDescriptor fd;
  if (fileDescriptorIndex < aFileDescriptors.Length()) {
    fd = aFileDescriptors[fileDescriptorIndex];
    NS_WARN_IF_FALSE(fd.IsValid(), "Received an invalid file descriptor!");
  } else {
    NS_WARNING("Received a bad file descriptor index!");
  }

  if (fd.IsValid()) {
    auto rawFD = fd.ClonePlatformHandle();
    PRFileDesc* fileDesc = PR_ImportFile(PROsfd(rawFD.release()));
    if (!fileDesc) {
      NS_WARNING("Failed to import file handle!");
      return false;
    }
    mFileDescOwner = new FileDescOwner(fileDesc);
  } else {
    mClosed = true;
  }

  mStartPos = mCurPos = params.startPos();
  mEndPos = params.endPos();
  return true;
}
Пример #6
0
std::vector<std::string> InputDeviceHandle::enumeratePaths(SurgSim::Framework::Logger* logger)
{
	std::vector<std::string> results;

	for (int i = 0;  i < 100;  ++i)
	{
		char devicePath[128];
		snprintf(devicePath, sizeof(devicePath), "/dev/input/event%d", i);

		FileDescriptor handle;
		if (! handle.openForReadingAndMaybeWriting(devicePath))
		{
			int error = errno;
			if (error != ENOENT)
			{
				SURGSIM_LOG_INFO(logger) << "InputDeviceHandle::enumeratePaths: Could not open device " << devicePath <<
					": error " << error << ", " << getSystemErrorText(error);
			}
			continue;
		}

		results.push_back(devicePath);
	}

	return results;
}
Пример #7
0
bool PicturesExporter::extractInputArgs(const PlugInArgList* pInArgList)
{
   string exporter = getName();
   if (exporter.empty())
   {
      exporter = "Pictures Exporter";
   }

   PlugInArg* pArg = NULL;

   // Progress
   if (pInArgList->getArg(Executable::ProgressArg(), pArg) && (pArg != NULL))
   {
      mpProgress = pArg->getPlugInArgValue<Progress>();
   }

   // File Descriptor
   mOutPath.erase();
   FileDescriptor* pFileDescriptor = pInArgList->getPlugInArgValue<FileDescriptor>(Exporter::ExportDescriptorArg());
   if (pFileDescriptor != NULL)
   {
      mOutPath = pFileDescriptor->getFilename().getFullPathAndName();
   }
   if (mOutPath.empty())
   {
      mMessage = "The destination path is invalid.";
      return false;
   }

   return true;
}
Пример #8
0
void FS::copy(FileDescriptor src_file, FileDescriptor & dst_fold, std::string dst_filename){
	Block * src_block = new Block(src_file.first_block, config.block_size, _root);
	read_data(&src_file, sizeof(FileDescriptor), src_block);
	char * data = new char[src_file.size];
	read_data(data, src_file.size, src_block);

    FileDescriptor file;
    Block * file_block = get_free_block();
	write_data(&file, sizeof(FileDescriptor), file_block);
	write_data(data, src_file.size, file_block);

	Block * dst_block = new Block(dst_fold.first_block, config.block_size, _root);


    bool found = false;
	for(auto it = DirIterator(*this, dst_fold); it != DirIterator(*this); ++it){
		FileDescriptor f = *it;
		if (std::string(f.filename) == dst_filename ){
            if( f.directory){
                found = true;
                dst_fold = f;
                dst_block = new Block(dst_fold.first_block, config.block_size, _root);
            } else{
                throw std::runtime_error("File already exist");
            } 
        } 
	}

	file.first_block = file_block->get_index();
    if(!found){
        file.set_filename(dst_filename);
    } else{
        file.set_filename(src_file.filename);
    }
	file.parent_file = dst_fold.first_block;
	file.size = src_file.size;
    file.directory = src_file.directory;

	if(dst_fold.first_child != -1){
		Block * nb = new Block(dst_fold.first_child, config.block_size, _root);
		FileDescriptor nd;
		read_data(&nd, sizeof(FileDescriptor), nb);
		nd.prev_file = file.first_block;
		update_descriptor(nd,nb);
		file.next_file = nd.first_block;
	}
	dst_fold.first_child = file.first_block;
	update_descriptor(dst_fold, dst_block);
    update_descriptor(file, file_block);

	if(src_file.directory){
		for(auto it = DirIterator(*this, src_file); it != DirIterator(*this); ++it){
			FileDescriptor f = *it;
			copy(f, file, f.filename);
		}
	}
}
Пример #9
0
ssize_t write(int handle, const void *in, size_t length)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	ssize_t err = descriptor->Write(in, length);
	descriptor->ReleaseRef();
	return err;
}
Пример #10
0
int rewinddir(int handle)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	int ret = descriptor->RewindDir();
	descriptor->ReleaseRef();
	return ret;
}
Пример #11
0
int ioctl(int handle, int command, void *buffer)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	int ret = descriptor->Control(command, buffer);
	descriptor->ReleaseRef();
	return ret;
}
Пример #12
0
off_t lseek(int handle, off_t offs, int whence)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	off_t ret = descriptor->Seek(offs, whence);
	descriptor->ReleaseRef();
	return ret;
}
Пример #13
0
ssize_t write_pos(int handle, off_t offs, const void *in, size_t length)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	size_t ret = descriptor->WriteAt(offs, in, length);
	descriptor->ReleaseRef();
	return ret;
}
Пример #14
0
ssize_t read_pos(int handle, off_t offs, void *out, size_t length)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	ssize_t err = descriptor->ReadAt(offs, out, length);
	descriptor->ReleaseRef();
	return err;
}
Пример #15
0
status_t readdir(int handle, char out_path[], size_t length)
{
	FileDescriptor *descriptor = static_cast<FileDescriptor*>(GetResource(handle, OBJ_FD));
	if (descriptor == 0)
		return E_BAD_HANDLE;

	status_t ret = descriptor->ReadDir(out_path, length);
	descriptor->ReleaseRef();
	return ret;
}
Пример #16
0
void FS::import(std::string host_file, std::string fs_file){
    if (!initialized) {throw "Not initialized";}
    read_meta();
    
	if(fs_file[fs_file.size() - 1] == '/'){
		fs_file = fs_file.substr(0, fs_file.size() - 1);
	}
    int last_match = fs_file.find_last_of("/");
    std::string fs_file_path = fs_file.substr(0, last_match + 1);
    std::string fs_file_name = fs_file.substr(last_match + 1);
    
    FileDescriptor dst_fold = get_file(fs_file_path, false, false);
    Block * dst_block = new Block(dst_fold.first_block, config.block_size, _root);
    for(auto it = DirIterator(*this, dst_fold); it != DirIterator(*this); ++it){
		FileDescriptor file = *it;
		if (std::string(file.filename) == fs_file_name ) throw std::runtime_error("File already exist");
	}

	FileDescriptor file;
    Block * file_block = get_free_block();
	std::ifstream File (host_file, std::ios::in | std::ios::binary);
	if( File.fail() ) throw std::runtime_error("Can't open " + host_file);
	File.seekg( 0, std::ios::end );
	int fileLen = File.tellg();
	file.size = fileLen;
	File.seekg( 0, std::ios::beg);
	char * data = new char[fileLen];
	File.read(data, fileLen);
	if(File.fail()) throw std::runtime_error("Can't read file " + host_file);
	File.close();

	write_data(&file, sizeof(FileDescriptor), file_block);
	write_data(data, fileLen, file_block);

	file.directory = false;
    file.set_filename(fs_file_name);

	file.first_block = file_block->get_index();
	file.parent_file = dst_fold.first_block;
	file.prev_file = -1;
	file.next_file = -1;
	if(dst_fold.first_child != -1){
		Block * nb = new Block(dst_fold.first_child, config.block_size, _root);
		FileDescriptor nd;
		read_data(&nd, sizeof(FileDescriptor), nb);
		nd.prev_file = file.first_block;
		update_descriptor(nd,nb);
		file.next_file = nd.first_block;
	}
	dst_fold.first_child = file.first_block;
	update_descriptor(dst_fold, dst_block);
    update_descriptor(file, file_block);
	write_meta();
}
Пример #17
0
bool
nsFileInputStream::Deserialize(const InputStreamParams& aParams,
                               const FileDescriptorArray& aFileDescriptors)
{
    NS_ASSERTION(!mFD, "Already have a file descriptor?!");
    NS_ASSERTION(!mDeferredOpen, "Deferring open?!");
    NS_ASSERTION(!mFile, "Should never have a file here!");
    NS_ASSERTION(!mPerm, "This should always be 0!");

    if (aParams.type() != InputStreamParams::TFileInputStreamParams) {
        NS_WARNING("Received unknown parameters from the other process!");
        return false;
    }

    const FileInputStreamParams& params = aParams.get_FileInputStreamParams();

    uint32_t fileDescriptorIndex = params.fileDescriptorIndex();

    FileDescriptor fd;
    if (fileDescriptorIndex < aFileDescriptors.Length()) {
        fd = aFileDescriptors[fileDescriptorIndex];
        NS_WARNING_ASSERTION(fd.IsValid(),
                             "Received an invalid file descriptor!");
    } else {
        NS_WARNING("Received a bad file descriptor index!");
    }

    if (fd.IsValid()) {
        auto rawFD = fd.ClonePlatformHandle();
        PRFileDesc* fileDesc = PR_ImportFile(PROsfd(rawFD.release()));
        if (!fileDesc) {
            NS_WARNING("Failed to import file handle!");
            return false;
        }
        mFD = fileDesc;
    }

    mBehaviorFlags = params.behaviorFlags();

    if (!XRE_IsParentProcess()) {
        // A child process shouldn't close when it reads the end because it will
        // not be able to reopen the file later.
        mBehaviorFlags &= ~nsIFileInputStream::CLOSE_ON_EOF;

        // A child process will not be able to reopen the file so this flag is
        // meaningless.
        mBehaviorFlags &= ~nsIFileInputStream::REOPEN_ON_REWIND;
    }

    mIOFlags = params.ioFlags();

    return true;
}
Пример #18
0
bool
LogCatReader::OnFileEvent(int _fd, unsigned mask)
{
  assert(_fd == fd.Get());

  char buffer[1024];
  ssize_t nbytes = fd.Read(buffer, sizeof(buffer));
  if (nbytes > 0) {
    if (data.length() < 1024 * 1024)
      data.append(buffer, nbytes);
    return true;
  } else {
    EndOfFile();
    return false;
  }
}
Пример #19
0
mozilla::ipc::IPCResult
PDFiumChild::RecvConvertToEMF(const FileDescriptor& aFD,
                              const int& aPageWidth,
                              const int& aPageHeight)
{
  MOZ_ASSERT(aFD.IsValid() && aPageWidth != 0 && aPageHeight != 0);

  ipc::Shmem smem;
  PDFViaEMFPrintHelper convertor;
  if (NS_FAILED(convertor.OpenDocument(aFD))) {
    Unused << SendConvertToEMFDone(NS_ERROR_FAILURE, smem);
    return IPC_OK();
  }

  MOZ_ASSERT(convertor.GetPageCount() == 1, "we assume each given PDF contains"                                        "one page only");

  if (!convertor.SavePageToBuffer(0, aPageWidth, aPageHeight, smem, this)) {
    Unused << SendConvertToEMFDone(NS_ERROR_FAILURE, smem);
    return IPC_OK();
  }

  if (!smem.IsReadable()) {
    Unused << SendConvertToEMFDone(NS_ERROR_FAILURE, smem);
    return IPC_OK();
  }

  Unused << SendConvertToEMFDone(NS_OK, smem);
  return IPC_OK();
}
Пример #20
0
mozilla::ipc::IPCResult
TemporaryIPCBlobParent::RecvOperationDone(const nsCString& aContentType,
                                          const FileDescriptor& aFD)
{
  MOZ_ASSERT(mActive);
  mActive = false;

  // We have received a file descriptor because in this way we have kept the
  // file locked on windows during the IPC communication. After the creation of
  // the TemporaryFileBlobImpl, this prfile can be closed.
  auto rawFD = aFD.ClonePlatformHandle();
  PRFileDesc* prfile = PR_ImportFile(PROsfd(rawFD.release()));

  // Let's create the BlobImpl.
  nsCOMPtr<nsIFile> file = Move(mFile);

  RefPtr<TemporaryFileBlobImpl> blobImpl =
    new TemporaryFileBlobImpl(file, NS_ConvertUTF8toUTF16(aContentType));

  PR_Close(prfile);

  IPCBlob ipcBlob;
  nsresult rv = IPCBlobUtils::Serialize(blobImpl, Manager(), ipcBlob);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    Unused << Send__delete__(this, NS_ERROR_FAILURE);
    return IPC_OK();
  }

  Unused << Send__delete__(this, ipcBlob);
  return IPC_OK();
}
Пример #21
0
int32 DeviceFSSuperBlock::createFd(Inode* inode, uint32 flag)
{
  assert(inode);

  File* file = inode->link(flag);
  FileDescriptor* fd = new FileDescriptor(file);
  s_files_.push_back(fd);
  FileDescriptor::add(fd);

  if (ustl::find(used_inodes_, inode) == used_inodes_.end())
  {
    used_inodes_.push_back(inode);
  }

  return (fd->getFd());
}
Пример #22
0
int open(const char path[], int)
{
	VNode *node;
	int error = FileSystem::WalkPath(path, strlen(path), &node);
	if (error < 0)
		return error;

	FileDescriptor *desc;
	error = node->Open(&desc);
	if (error < 0) {
		node->ReleaseRef();
		return error;
	}

	desc->SetName(path);
	return OpenHandle(desc);
}
Пример #23
0
void FS::format(){
    if (!initialized) {throw "Not initialized";}
    meta.block_map_size = config.block_no/8 + 1;
    meta.block_map = new char[meta.block_map_size];
    memset(meta.block_map, 0, sizeof(char)*meta.block_map_size);
    int free_space_size = config.block_size - sizeof(BlockDescriptor);
    int no_of_blocks = (sizeof(meta) + meta.block_map_size)/free_space_size + 1;
    meta.root_block = no_of_blocks;
    for(int i = 0; i<no_of_blocks; ++i) reserve_block(i);

    FileDescriptor root;
    root.set_filename("/");
    root.first_block = meta.root_block;
    write_data(&root, sizeof(FileDescriptor), 0);

    write_meta();
}
Пример #24
0
void ExportDlg::updateFromFile(const QString& strFilename)
{
   FileDescriptor* pFileDescriptor = mpExporter->getFileDescriptor();
   if (pFileDescriptor != NULL)
   {
      string filename;
      if (strFilename.isEmpty() == false)
      {
         QFileInfo fileInfo(strFilename);
         if (fileInfo.isDir() == false)
         {
            filename = fileInfo.absoluteFilePath().toStdString();
         }
      }

      pFileDescriptor->setFilename(filename);
   }
}
GeckoExistingProcessHost::
GeckoExistingProcessHost(GeckoProcessType aProcessType,
                         base::ProcessHandle aProcess,
                         const FileDescriptor& aFileDescriptor,
                         ChildPrivileges aPrivileges)
  : GeckoChildProcessHost(aProcessType, aPrivileges)
  , mExistingProcessHandle(aProcess)
  , mExistingFileDescriptor(aFileDescriptor)
{
  NS_ASSERTION(aFileDescriptor.IsValid(),
               "Expected file descriptor to be valid");
}
Пример #26
0
bool Nitf::NitfImporterShell::createRasterPager(RasterElement *pRaster) const
{
   VERIFY(pRaster != NULL);

   DataDescriptor* pDd = pRaster->getDataDescriptor();
   VERIFY(pDd != NULL);
   FileDescriptor* pFd = pDd->getFileDescriptor();
   VERIFY(pFd != NULL);

   const string& datasetLocation = pFd->getDatasetLocation();
   if (datasetLocation.empty() == true)
   {
      return false;
   }

   stringstream imageNameStream(datasetLocation.substr(1));
   int imageSegment;
   imageNameStream >> imageSegment;

   FactoryResource<Filename> pFn;
   pFn->setFullPathAndName(pFd->getFilename());

   ExecutableResource pPlugIn("NitfPager");
   pPlugIn->getInArgList().setPlugInArgValue("Segment Number", &imageSegment);
   pPlugIn->getInArgList().setPlugInArgValue(CachedPager::PagedElementArg(), pRaster);
   pPlugIn->getInArgList().setPlugInArgValue(CachedPager::PagedFilenameArg(), pFn.get());

   if (pPlugIn->execute() == true)
   {
      RasterPager* pPager = dynamic_cast<RasterPager*>(pPlugIn->getPlugIn());
      if (pPager != NULL)
      {
         pRaster->setPager(pPager);
         pPlugIn->releasePlugIn();
         return true;
      }
   }

   return false;
}
Пример #27
0
bool
PluginModuleParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
{
#ifndef MOZ_X11
    NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
#else
    NS_ABORT_IF_FALSE(0 > mPluginXSocketFdDup.get(),
                      "Already backed up X resources??");
    mPluginXSocketFdDup.forget();
    mPluginXSocketFdDup.reset(aXSocketFd.PlatformHandle());
#endif
    return true;
}
Пример #28
0
void commands_ns::MkFile(FileSystem *fs, int argc, char *argv[], std::ostream& out)
{
	if (argc != 1)
	{
		out << "Неправильное количество параметров"<< std::endl;
		return;
	}
	if (strlen(argv[0]) > 41)
	{
		out << "Введены некорректные данные" << std::endl;
		return;
	};
	char *nt[2];
	nt[0] = strtok(argv[0], ".");
	nt[1] = strtok(NULL, "");
	char *s = strtok(NULL, ".,-!");
	if ((!nt[0]) || (!nt[1]) || (s))
	{
		out << "Введены некорректные данные" << std::endl;
		return;
	}

	if (fs->names_types(nt[0])||fs->names_types(nt[1]))
	{
		out << "Введены некорректные данные" << std::endl;
		return;
	}
	FileDescriptor* fd = new FileDescriptor();
	fd->SetName(nt[0]);
	fd->SetType(nt[1]);
	fd->SetSize(0);
	fd->SetOffset(0);
	fs->CreateFile(fd);

	out << "Файл создан." << std::endl;
	return;
}
Пример #29
0
bool
TTYKeyboard::OnFileEvent(FileDescriptor fd, unsigned mask)
{
  char buffer[256];
  const ssize_t nbytes = fd.Read(buffer, sizeof(buffer));
  if (nbytes > 0) {
    for (ssize_t i = 0; i < nbytes; ++i)
      HandleInputByte(buffer[i]);
  } else if (nbytes == 0 || errno != EAGAIN) {
    queue.Quit();
    return false;
  }

  return true;
}
Пример #30
0
Optional<Reflector> Reflector::create(size_t size)
{
    static const char *path = "reflector.shm";
    FileDescriptor fd;
    void *lower = nullptr;
    void *upper = nullptr;
    void *both = nullptr;
    int sts = -1;

    if ((size == 0) || (size % 4096)) {
        return Optional<Reflector>();
    }

    fd.reset(shm_open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR));
    if (fd.empty()) {
        return Optional<Reflector>();
    }

    sts = shm_unlink(path);
    if (sts < 0) {
        return Optional<Reflector>();
    }

    sts = ftruncate(fd.get(), size);
    if (sts < 0) {
        return Optional<Reflector>();
    }
    
    both = mmap(nullptr, size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
    if (both == MAP_FAILED) {
        return Optional<Reflector>();
    }

    lower = mremap(both, size * 2, size, 0);
    if (lower == MAP_FAILED) {
        sts = munmap(both, size * 2);
        assert(sts >= 0);
        return Optional<Reflector>();
    }
    else if (lower != both) {
        sts = munmap(lower, size);
        assert(sts);
        return Optional<Reflector>();
    }

    upper = static_cast<uint8_t*>(lower) + size;
    upper = mmap(upper, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd.get(), 0);
    if (upper == MAP_FAILED) {
        sts = munmap(lower, size);
        assert(sts >= 0);
        return Optional<Reflector>();
    }

    return Optional<Reflector>(Reflector(std::move(fd), lower, size));
}