示例#1
0
static size_t file_write(const void * const p, size_t len, stream_t *stream)
{
  PHYSFS_sint64 count;
  int error;
  PHYSFS_File *file;

  if (file_check_context(stream))
    return 0;

  file = stream->context.pfs.file;

  count = PHYSFS_writeBytes(file, p, len);

  if (count < len && (error = PHYSFS_getLastErrorCode())) {
    s_log_error("Error writing to file stream (pfs: %s). (File: %s)",
      PHYSFS_getErrorByCode(error), stream->context.pfs.file_path);

    stream->error = STREAM_ERROR_FAILURE;

    if (count == -1)
      return 0;
  }

  return (size_t)count;
}
示例#2
0
OFileStreambuf::OFileStreambuf(const std::string& filename) :
  file()
{
  file = PHYSFS_openWrite(filename.c_str());
  if(file == nullptr) {
    std::stringstream msg;
    msg << "Couldn't open file '" << filename << "': "
        << PHYSFS_getLastErrorCode();
    throw std::runtime_error(msg.str());
  }

  setp(buf, buf+sizeof(buf));
}
示例#3
0
文件: files.cpp 项目: sponge/sdlgame
void FS_Init(const char *argv0) {
	int err = PHYSFS_init(argv0);

	if (err == 0) {
		Con_Errorf(ERR_FATAL, "Error in PHYSFS_init: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
		return;
	}

	const char *baseDir = PHYSFS_getBaseDir();
	fs_basepath = Con_GetVarDefault("fs.basepath", baseDir, CONVAR_STARTUP);
	fs_basegame = Con_GetVarDefault("fs.basegame", "base", CONVAR_STARTUP);
	fs_game = Con_GetVarDefault("fs.game", DEFAULT_GAME, CONVAR_STARTUP);

	bool modLoaded = fs_game->string[0] != '\0';

	char **baseFiles, **gameFiles;

	// get the file listing for the basegame dir, then immediately unmount
	const char *fullBasePath = tempstr("%s/%s", fs_basepath->string, fs_basegame->string);
	PHYSFS_mount(fullBasePath, "/", 1);
	baseFiles = PHYSFS_enumerateFiles("/");
	PHYSFS_removeFromSearchPath(fullBasePath);

	// if fs_game is set, do the same thing for the fs_game dir
	if (modLoaded) {
		const char *fullGamePath = tempstr("%s/%s", fs_basepath->string, fs_game->string);
		PHYSFS_mount(fullGamePath, "/", 1);
		gameFiles = PHYSFS_enumerateFiles("/");
		PHYSFS_removeFromSearchPath(fullGamePath);

		// mount the mod dir first, then mount mod PK3s
		PHYSFS_mount(tempstr("%s/%s", fs_basepath->string, fs_game->string), "/", 1);
		FS_AddPaksFromList(gameFiles, fs_basepath->string, fs_game->string);
		PHYSFS_freeList(gameFiles);
	}

	// then mount the base game dir, then the mount base game PK3s
	PHYSFS_mount(tempstr("%s/%s", fs_basepath->string, fs_basegame->string), "/", 1);
	FS_AddPaksFromList(baseFiles, fs_basepath->string, fs_basegame->string);
	PHYSFS_freeList(baseFiles);

	// print all the files we've found in order of priority
	Con_Printf("Current filesystem search path:\n");
	PHYSFS_getSearchPathCallback(printSearchPath, NULL);
	Con_Printf("\n");

	// add command handler for dir to view virtual filesystem
	Con_AddCommand("dir", Cmd_Dir_f);
}
示例#4
0
IFileStreambuf::IFileStreambuf(const std::string& filename) :
  file(),
  buf()
{
  // check this as PHYSFS seems to be buggy and still returns a
  // valid pointer in this case
  if(filename.empty()) {
    throw std::runtime_error("Couldn't open file: empty filename");
  }
  file = PHYSFS_openRead(filename.c_str());
  if(file == nullptr) {
    std::stringstream msg;
    msg << "Couldn't open file '" << filename << "': "
        << PHYSFS_getLastErrorCode();
    throw std::runtime_error(msg.str());
  }
}
示例#5
0
  Transfer(Downloader& downloader, TransferId id,
           const std::string& url,
           const std::string& outfile) :
    m_downloader(downloader),
    m_id(id),
    m_url(url),
    m_handle(),
    m_error_buffer({{'\0'}}),
    m_status(new TransferStatus(m_downloader, id)),
    m_fout(PHYSFS_openWrite(outfile.c_str()), PHYSFS_close)
  {
    if (!m_fout)
    {
      std::ostringstream out;
      out << "PHYSFS_openRead() failed: " << PHYSFS_getLastErrorCode();
      throw std::runtime_error(out.str());
    }

    m_handle = curl_easy_init();
    if (!m_handle)
    {
      throw std::runtime_error("curl_easy_init() failed");
    }
    else
    {
      curl_easy_setopt(m_handle, CURLOPT_URL, url.c_str());
      curl_easy_setopt(m_handle, CURLOPT_USERAGENT, "SuperTux/" PACKAGE_VERSION " libcURL");

      curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
      curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &Transfer::on_data_wrap);

      curl_easy_setopt(m_handle, CURLOPT_ERRORBUFFER, m_error_buffer.data());
      curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, 1);
      curl_easy_setopt(m_handle, CURLOPT_FAILONERROR, 1);
      curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1);

      curl_easy_setopt(m_handle, CURLOPT_NOPROGRESS, 0);
      curl_easy_setopt(m_handle, CURLOPT_PROGRESSDATA, this);
      curl_easy_setopt(m_handle, CURLOPT_PROGRESSFUNCTION, &Transfer::on_progress_wrap);
    }
  }
示例#6
0
  PhysfsSubsystem(const char* argv0,
                  boost::optional<std::string> forced_datadir,
                  boost::optional<std::string> forced_userdir) :
    m_forced_datadir(forced_datadir),
    m_forced_userdir(forced_userdir)
  {
    if (!PHYSFS_init(argv0))
    {
      std::stringstream msg;
      msg << "Couldn't initialize physfs: " << PHYSFS_getLastErrorCode();
      throw std::runtime_error(msg.str());
    }
    else
    {
      // allow symbolic links
      PHYSFS_permitSymbolicLinks(1);

      find_userdir();
      find_datadir();
    }
  }
示例#7
0
  void find_datadir() const
  {
    std::string datadir;
    if (m_forced_datadir)
    {
      datadir = *m_forced_datadir;
    }
    else if (const char* env_datadir = getenv("SUPERTUX2_DATA_DIR"))
    {
      datadir = env_datadir;
    }
    else
    {
      // check if we run from source dir
      char* basepath_c = SDL_GetBasePath();
      std::string basepath = basepath_c ? basepath_c : "./";
      SDL_free(basepath_c);

      if (FileSystem::exists(FileSystem::join(BUILD_DATA_DIR, "credits.stxt")))
      {
        datadir = BUILD_DATA_DIR;
        // Add config dir for supplemental files
        PHYSFS_mount(boost::filesystem::canonical(BUILD_CONFIG_DATA_DIR).string().c_str(), NULL, 1);
      }
      else
      {
        // if the game is not run from the source directory, try to find
        // the global install location
        datadir = basepath.substr(0, basepath.rfind(INSTALL_SUBDIR_BIN));
        datadir = FileSystem::join(datadir, INSTALL_SUBDIR_SHARE);
      }
    }

    if (!PHYSFS_mount(boost::filesystem::canonical(datadir).string().c_str(), NULL, 1))
    {
      log_warning << "Couldn't add '" << datadir << "' to physfs searchpath: " << PHYSFS_getLastErrorCode() << std::endl;
    }
  }
示例#8
0
FileSystem::FileSystem(std::vector<UString> paths)
{
	// FIXME: Is this the right thing to do that?
	LogInfo("Registering external archivers...");
	PHYSFS_registerArchiver(getCueArchiver());
	// Paths are supplied in inverse-search order (IE the last in 'paths' should be the first
	// searched)
	for (auto &p : paths)
	{
		if (!PHYSFS_mount(p.cStr(), "/", 0))
		{
			LogInfo("Failed to add resource dir \"%s\", error: %s", p,
			        PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
			continue;
		}
		else
			LogInfo("Resource dir \"%s\" mounted to \"%s\"", p, PHYSFS_getMountPoint(p.cStr()));
	}
	this->writeDir = PHYSFS_getPrefDir(PROGRAM_ORGANISATION, PROGRAM_NAME);
	LogInfo("Setting write directory to \"%s\"", this->writeDir);
	PHYSFS_setWriteDir(this->writeDir.cStr());
	// Finally, the write directory trumps all
	PHYSFS_mount(this->writeDir.cStr(), "/", 0);
}
示例#9
0
void
Level::save(const std::string& filepath, bool retry)
{
  //FIXME: It tests for directory in supertux/data, but saves into .supertux2.

  try {

    { // make sure the level directory exists
      std::string dirname = FileSystem::dirname(filepath);
      if(!PHYSFS_exists(dirname.c_str()))
      {
        if(!PHYSFS_mkdir(dirname.c_str()))
        {
          std::ostringstream msg;
          msg << "Couldn't create directory for level '"
              << dirname << "': " <<PHYSFS_getLastErrorCode();
          throw std::runtime_error(msg.str());
        }
      }

      if(!PhysFSFileSystem::is_directory(dirname))
      {
        std::ostringstream msg;
        msg << "Level path '" << dirname << "' is not a directory";
        throw std::runtime_error(msg.str());
      }
    }

    Writer writer(filepath);
    writer.start_list("supertux-level");
    // Starts writing to supertux level file. Keep this at the very beginning.

    writer.write("version", 2);
    writer.write("name", m_name, true);
    writer.write("author", m_author, false);
    writer.write("tileset", m_tileset, false);
    if (m_contact != "") {
      writer.write("contact", m_contact, false);
    }
    if (m_license != "") {
      writer.write("license", m_license, false);
    }
    if (m_target_time != 0.0f){
      writer.write("target-time", m_target_time);
    }

    for(auto& sector : m_sectors) {
      sector->save(writer);
    }

    // Ends writing to supertux level file. Keep this at the very end.
    writer.end_list("supertux-level");
    log_warning << "Level saved as " << filepath << "." << std::endl;
  } catch(std::exception& e) {
    if (retry) {
      std::stringstream msg;
      msg << "Problem when saving level '" << filepath << "': " << e.what();
      throw std::runtime_error(msg.str());
    } else {
      log_warning << "Failed to save the level, retrying..." << std::endl;
      { // create the level directory again
        std::string dirname = FileSystem::dirname(filepath);
        if(!PHYSFS_mkdir(dirname.c_str()))
        {
          std::ostringstream msg;
          msg << "Couldn't create directory for level '"
              << dirname << "': " <<PHYSFS_getLastErrorCode();
          throw std::runtime_error(msg.str());
        }
      }
      save(filepath, true);
    }
  }
}
示例#10
0
  void find_userdir() const
  {
    std::string userdir;
    if (m_forced_userdir)
    {
      userdir = *m_forced_userdir;
    }
    else if (const char* env_userdir = getenv("SUPERTUX2_USER_DIR"))
    {
      userdir = env_userdir;
    }
    else
    {
		userdir = PHYSFS_getPrefDir("SuperTux","supertux2");
    }
	//Kept for backwards-compatability only, hence the silence
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
	std::string physfs_userdir = PHYSFS_getUserDir();
#pragma GCC diagnostic pop

#ifdef _WIN32
	std::string olduserdir = FileSystem::join(physfs_userdir, PACKAGE_NAME);
#else
	std::string olduserdir = FileSystem::join(physfs_userdir, "." PACKAGE_NAME);
#endif
	if (FileSystem::is_directory(olduserdir)) {
	  boost::filesystem::path olduserpath(olduserdir);
	  boost::filesystem::path userpath(userdir);

	  boost::filesystem::directory_iterator end_itr;

	  bool success = true;

	  // cycle through the directory
	  for (boost::filesystem::directory_iterator itr(olduserpath); itr != end_itr; ++itr) {
		try
		{
		  boost::filesystem::rename(itr->path().string().c_str(), userpath / itr->path().filename());
		}
		catch (const boost::filesystem::filesystem_error& err)
		{
		  success = false;
		  log_warning << "Failed to move contents of config directory: " << err.what() << std::endl;
		}
	  }
	  if (success) {
	    try
		{
		  boost::filesystem::remove_all(olduserpath);
		}
		catch (const boost::filesystem::filesystem_error& err)
		{
		  success = false;
		  log_warning << "Failed to remove old config directory: " << err.what();
		}
	  }
	  if (success) {
	    log_info << "Moved old config dir " << olduserdir << " to " << userdir << std::endl;
	  }
	}

    if (!FileSystem::is_directory(userdir))
    {
	  FileSystem::mkdir(userdir);
	  log_info << "Created SuperTux userdir: " << userdir << std::endl;
    }

    if (!PHYSFS_setWriteDir(userdir.c_str()))
    {
      std::ostringstream msg;
      msg << "Failed to use userdir directory '"
          <<  userdir << "': " << PHYSFS_getLastErrorCode();
      throw std::runtime_error(msg.str());
    }

    PHYSFS_mount(userdir.c_str(), NULL, 0);
  }