Exemple #1
0
void DataDirLocater::Check()
{
	if (IsIsolationMode()) {
		LOG("[DataDirLocater::%s] Isolation Mode!", __func__);
	} else
	if (IsPortableMode()) {
		LOG("[DataDirLocater::%s] Portable Mode!", __func__);
	}

	// Filter usable DataDirs
	FilterUsableDataDirs();

	if (writeDir == nullptr) {
		// bail out
		const std::string errstr =
				"Not a single writable data directory found!\n\n"
				"Configure a writable data directory using either:\n"
				"- the SPRING_DATADIR environment variable,\n"
			#ifdef WIN32
				"- a SpringData=C:/path/to/data declaration in spring's config file ./springsettings.cfg\n"
				"- by giving your user-account write access to the installation directory";
			#else
				"- a SpringData=/path/to/data declaration in ~/.springrc or\n"
				"- the configuration file /etc/spring/datadir";
			#endif
		throw content_error(errstr);
	}

	if (Platform::FreeDiskSpace(writeDir->path) <= 1024)
		throw content_error("not enough free space on drive containing writeable data-directory " + writeDir->path);

	ChangeCwdToWriteDir();
	CreateCacheDir(writeDir->path + FileSystem::GetCacheDir());
}
Exemple #2
0
void DataDirLocater::LocateDataDirs()
{
	// Construct the list of dataDirs from various sources.
	// Note: The first dir added will be the writable data dir!
	dataDirs.clear();


	// Note: first pushed dir is writeDir & dir priority decreases with pos in queue

	// LEVEL 1: User defined write dirs
	{
		if (!forcedWriteDir.empty())
			AddDirs(forcedWriteDir);

		const char* env = getenv("SPRING_WRITEDIR");

		if (env != nullptr && *env != 0)
			AddDirs(env); // ENV{SPRING_WRITEDIR}
	}

	// LEVEL 2: automated dirs
	if (IsIsolationMode()) {
		// LEVEL 2a: Isolation Mode (either installDir or user set one)
		if (isolationModeDir.empty()) {
			AddPortableDir(); // better use curWorkDir?
		} else {
			AddDirs(isolationModeDir);
		}
	} else {
		// LEVEL 2b: InstallDir, HomeDirs & Shared dirs
		if (IsPortableMode())
			AddPortableDir();

		AddHomeDirs();
		//AddCurWorkDir();
		AddEtcDirs();
		AddShareDirs();
	}

	// LEVEL 3: additional custom data sources
	{
		const char* env = getenv("SPRING_DATADIR");

		if (env != nullptr && *env != 0)
			AddDirs(env); // ENV{SPRING_DATADIR}

		// user defined in spring config (Linux: ~/.springrc, Windows: .\springsettings.cfg)
		if (configHandler != nullptr)
			AddDirs(configHandler->GetString("SpringData"));
	}

	// Find the folder we save to
	FindWriteableDataDir();
}
Exemple #3
0
/* ----------------------------------------------------------------------
 * Main program. Parse arguments etc.
 */
int main(int argc, char *argv[])
{
    int ret;
#ifdef PERSOPORT
	IniFileFlag = 0 ;
	DirectoryBrowseFlag = 0 ;
	IsPortableMode() ;
#endif
    ret = psftp_main(argc, argv);

    return ret;
}
Exemple #4
0
/* ----------------------------------------------------------------------
 * Main program. Parse arguments etc.
 */
int main(int argc, char *argv[])
{
    int ret;

#ifdef PERSOPORT
	IsPortableMode() ;
	//if( IsPortableMode() ) { printf( "Portable mode on\n" ) ; }
#endif

    ret = psftp_main(argc, argv);

    return ret;
}
Exemple #5
0
void DataDirLocater::AddCwdOrParentDir(const std::string& curWorkDir, bool forceAdd)
{
	// This is useful in case of multiple engine/unitsync versions installed
	// together in a sub-dir of the data-dir
	// The data-dir structure then might look similar to this:
	// maps/
	// games/
	// engines/engine-0.83.0.0.exe
	// engines/engine-0.83.1.0.exe
	// unitsyncs/unitsync-0.83.0.0.exe
	// unitsyncs/unitsync-0.83.1.0.exe
	const std::string curWorkDirParent = FileSystem::GetParent(curWorkDir);

	// we can not add both ./ and ../ as data-dir
	if ((curWorkDirParent != "") && LooksLikeMultiVersionDataDir(curWorkDirParent)) {
		AddDirs(curWorkDirParent); // "../"
	} else if (IsPortableMode() || forceAdd) {
		// always using this would be unclean, because spring and unitsync
		// would end up with different sets of data-dirs
		AddDirs(curWorkDir); // "./"
	}
}
Exemple #6
0
int plink_main(int argc, char **argv)
{
    int sending;
    int portnumber = -1;
    SOCKET *sklist;
    int skcount, sksize;
    int exitcode;
    int errors;
    int got_host = FALSE;
    int use_subsystem = 0;
    unsigned long now, next, then;
	
    IsPortableMode() ;
    //if( IsPortableMode() ) { printf( "Portable mode on\n" ) ; }

#else

int main(int argc, char **argv)
{
    int sending;
    int portnumber = -1;
    SOCKET *sklist;
    int skcount, sksize;
    int exitcode;
    int errors;
    int got_host = FALSE;
    int use_subsystem = 0;
    unsigned long now, next, then;
#endif

    sklist = NULL;
    skcount = sksize = 0;
    /*
     * Initialise port and protocol to sensible defaults. (These
     * will be overridden by more or less anything.)
     */
    default_protocol = PROT_SSH;
    default_port = 22;

    flags = FLAG_STDERR;
    /*
     * Process the command line.
     */
    conf = conf_new();
    do_defaults(NULL, conf);
    loaded_session = FALSE;
    default_protocol = conf_get_int(conf, CONF_protocol);
    default_port = conf_get_int(conf, CONF_port);
    errors = 0;
    {
	/*
	 * Override the default protocol if PLINK_PROTOCOL is set.
	 */
	char *p = getenv("PLINK_PROTOCOL");
	if (p) {
	    const Backend *b = backend_from_name(p);
	    if (b) {
		default_protocol = b->protocol;
		default_port = b->default_port;
		conf_set_int(conf, CONF_protocol, default_protocol);
		conf_set_int(conf, CONF_port, default_port);
	    }
	}
    }
    while (--argc) {
	char *p = *++argv;
	if (*p == '-') {
	    int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
					    1, conf);
	    if (ret == -2) {
		fprintf(stderr,
			"plink: option \"%s\" requires an argument\n", p);
		errors = 1;
	    } else if (ret == 2) {
		--argc, ++argv;
	    } else if (ret == 1) {
		continue;
	    } else if (!strcmp(p, "-batch")) {
		console_batch_mode = 1;
	    } else if (!strcmp(p, "-s")) {
		/* Save status to write to conf later. */
		use_subsystem = 1;
	    } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) {
                version();
	    } else if (!strcmp(p, "--help")) {
                usage();
            } else if (!strcmp(p, "-pgpfp")) {
                pgp_fingerprints();
                exit(1);
	    } else {
		fprintf(stderr, "plink: unknown option \"%s\"\n", p);
		errors = 1;
	    }
	} else if (*p) {
	    if (!conf_launchable(conf) || !(got_host || loaded_session)) {
		char *q = p;
		/*
		 * If the hostname starts with "telnet:", set the
		 * protocol to Telnet and process the string as a
		 * Telnet URL.
		 */
		if (!strncmp(q, "telnet:", 7)) {
		    char c;

		    q += 7;
		    if (q[0] == '/' && q[1] == '/')
			q += 2;
		    conf_set_int(conf, CONF_protocol, PROT_TELNET);
		    p = q;
		    while (*p && *p != ':' && *p != '/')
			p++;
		    c = *p;
		    if (*p)
			*p++ = '\0';
		    if (c == ':')
			conf_set_int(conf, CONF_port, atoi(p));
		    else
			conf_set_int(conf, CONF_port, -1);
		    conf_set_str(conf, CONF_host, q);
		    got_host = TRUE;
		} else {
		    char *r, *user, *host;
		    /*
		     * Before we process the [user@]host string, we
		     * first check for the presence of a protocol
		     * prefix (a protocol name followed by ",").
		     */
		    r = strchr(p, ',');
		    if (r) {
			const Backend *b;
			*r = '\0';
			b = backend_from_name(p);
			if (b) {
			    default_protocol = b->protocol;
			    conf_set_int(conf, CONF_protocol,
					 default_protocol);
			    portnumber = b->default_port;
			}
			p = r + 1;
		    }

		    /*
		     * A nonzero length string followed by an @ is treated
		     * as a username. (We discount an _initial_ @.) The
		     * rest of the string (or the whole string if no @)
		     * is treated as a session name and/or hostname.
		     */
		    r = strrchr(p, '@');
		    if (r == p)
			p++, r = NULL; /* discount initial @ */
		    if (r) {
			*r++ = '\0';
			user = p, host = r;
		    } else {
			user = NULL, host = p;
		    }

		    /*
		     * Now attempt to load a saved session with the
		     * same name as the hostname.
		     */
		    {
			Conf *conf2 = conf_new();
			do_defaults(host, conf2);
			if (loaded_session || !conf_launchable(conf2)) {
			    /* No settings for this host; use defaults */
			    /* (or session was already loaded with -load) */
			    conf_set_str(conf, CONF_host, host);
			    conf_set_int(conf, CONF_port, default_port);
			    got_host = TRUE;
			} else {
			    conf_copy_into(conf, conf2);
			    loaded_session = TRUE;
			}
			conf_free(conf2);
		    }

		    if (user) {
			/* Patch in specified username. */
			conf_set_str(conf, CONF_username, user);
		    }

		}
	    } else {
		char *command;
		int cmdlen, cmdsize;
		cmdlen = cmdsize = 0;
		command = NULL;

		while (argc) {
		    while (*p) {
			if (cmdlen >= cmdsize) {
			    cmdsize = cmdlen + 512;
			    command = sresize(command, cmdsize, char);
			}
			command[cmdlen++]=*p++;
		    }
		    if (cmdlen >= cmdsize) {
			cmdsize = cmdlen + 512;
			command = sresize(command, cmdsize, char);
		    }
		    command[cmdlen++]=' '; /* always add trailing space */
		    if (--argc) p = *++argv;
		}
		if (cmdlen) command[--cmdlen]='\0';
				       /* change trailing blank to NUL */
		conf_set_str(conf, CONF_remote_cmd, command);
		conf_set_str(conf, CONF_remote_cmd2, "");
		conf_set_int(conf, CONF_nopty, TRUE);  /* command => no tty */

		break;		       /* done with cmdline */
	    }
	}
void DataDirLocater::LocateDataDirs()
{
    // Prepare the data-dirs defined in different places

    // environment variable
    std::string dd_env = "";
    {
        char* env = getenv("SPRING_DATADIR");
        if (env && *env) {
            dd_env = SubstEnvVars(env);
        }
    }

#if       defined(UNITSYNC)
    const std::string dd_curWorkDir = Platform::GetModulePath();
#else  // defined(UNITSYNC)
    const std::string dd_curWorkDir = Platform::GetProcessExecutablePath();
#endif // defined(UNITSYNC)

    // This is useful in case of multiple engine/unitsync versions installed
    // together in a sub-dir of the data-dir
    // The data-dir structure then might look similar to this:
    // maps/
    // games/
    // engines/engine-0.83.0.0.exe
    // engines/engine-0.83.1.0.exe
    // unitsyncs/unitsync-0.83.0.0.exe
    // unitsyncs/unitsync-0.83.1.0.exe
    const std::string dd_curWorkDirParent = FileSystemHandler::GetParent(dd_curWorkDir);

#if    defined(WIN32)
    // fetch my documents path
    TCHAR pathMyDocs[MAX_PATH];
    SHGetFolderPath( NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, pathMyDocs);

    // fetch app-data path
    TCHAR pathAppData[MAX_PATH];
    SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, pathAppData);

    std::string dd_myDocs = pathMyDocs;
    // e.g. F:\Dokumente und Einstellungen\Karl-Robert\Eigene Dateien\Spring
    dd_myDocs += "\\Spring";

    std::string dd_myDocsMyGames = pathMyDocs;
    // My Documents\My Games seems to be the MS standard even if no official guidelines exist
    // most if not all new Games For Windows(TM) games use this dir
    dd_myDocsMyGames += "\\My Games\\Spring";

    std::string dd_appData = pathAppData;
    // e.g. F:\Dokumente und Einstellungen\All Users\Anwendungsdaten\Spring
    dd_appData += "\\Spring";
#elif     defined(MACOSX_BUNDLE)
    const std::string dd_curWorkDirData = dd_curWorkDir + "/" + SubstEnvVars(DATADIR);
    const std::string dd_curWorkDirLib  = dd_curWorkDir + "/" + SubstEnvVars(LIBDIR);
#else // *nix (-OSX)
    // settings in /etc
    std::string dd_etc = "";
    {
        FILE* fileH = ::fopen("/etc/spring/datadir", "r");
        if (fileH) {
            const char whiteSpaces[3] = {'\t', ' ', '\0'};
            char lineBuf[1024];
            while (fgets(lineBuf, sizeof(lineBuf), fileH)) {
                char* newLineCharPos = strchr(lineBuf, '\n');
                if (newLineCharPos) {
                    // remove the new line char
                    *newLineCharPos = '\0';
                }
                // ignore lines consisting of only whitespaces
                if ((strlen(lineBuf) > 0) && strspn(lineBuf, whiteSpaces) != strlen(lineBuf)) {
                    // append, separated by sPD (depending on OS): ';' or ':'
                    dd_etc = dd_etc + (dd_etc.empty() ? "" : sPD) + SubstEnvVars(lineBuf);
                }
            }
            fclose(fileH);
        }
    }
#endif // defined(WIN32), defined(MACOSX_BUNDLE), else

    // Construct the list of datadirs from various sources.
    datadirs.clear();
    // The first dir added will be the writeable data dir.

    // same on all platforms
    AddDirs(dd_env);    // ENV{SPRING_DATADIR}
    // user defined in spring config handler
    // (Linux: ~/.springrc, Windows: .\springsettings.cfg)
    AddDirs(SubstEnvVars(configHandler->GetString("SpringData", "")));

#ifdef WIN32
    // All MS Windows variants

    if ((dd_curWorkDirParent != "") && LooksLikeMultiVersionDataDir(dd_curWorkDirParent)) {
        AddDirs(dd_curWorkDirParent); // "../"
    } else if (IsPortableMode()) { // we can not add both ./ and ../ as data-dir
        AddDirs(dd_curWorkDir); // "./"
    }
    AddDirs(dd_myDocsMyGames);  // "C:/.../My Documents/My Games/Spring/"
    AddDirs(dd_myDocs);         // "C:/.../My Documents/Spring/"
    AddDirs(dd_appData);        // "C:/.../All Users/Applications/Spring/"

#elif defined(MACOSX_BUNDLE)
    // Mac OS X

    // Maps and mods are supposed to be located in spring's executable location on Mac, but unitsync
    // cannot find them since it does not know spring binary path. I have no idea but to force users
    // to locate lobby executables in the same as spring's dir and add its location to search dirs.
#ifdef UNITSYNC
    AddDirs(dd_curWorkDir);     // "./"
#endif

    // libs and data are supposed to be located in subdirectories of spring executable, so they
    // sould be added instead of SPRING_DATADIR definition.
    AddDirs(dd_curWorkDirData); // "./data/"
    AddDirs(dd_curWorkDirLib);  // "./lib/"

#else
    // Linux, FreeBSD, Solaris, Apple non-bundle

    if ((dd_curWorkDirParent != "") && LooksLikeMultiVersionDataDir(dd_curWorkDirParent)) {
        AddDirs(dd_curWorkDirParent); // "../"
    } else if (IsPortableMode()) { // we can not add both ./ and ../ as data-dir
        // always using this would be unclean, because spring and unitsync
        // would end up with different sets of data-dirs
        AddDirs(dd_curWorkDir); // "./"
    }
    AddDirs(SubstEnvVars("$HOME/.spring")); // "~/.spring/"
    AddDirs(dd_etc);            // from /etc/spring/datadir
#endif

#ifdef SPRING_DATADIR
    AddDirs(SubstEnvVars(SPRING_DATADIR)); // from -DSPRING_DATADIR
#endif

    // Figure out permissions of all datadirs
    DeterminePermissions();

    if (!writedir) {
        // bail out
        const std::string errstr = "Not a single writable data directory found!\n\n"
                                   "Configure a writable data directory using either:\n"
                                   "- the SPRING_DATADIR environment variable,\n"
#ifdef WIN32
                                   "- a SpringData=C:/path/to/data declaration in spring's config file ./springsettings.cfg\n"
                                   "- by giving you write access to the installation directory";
#else
                                   "- a SpringData=/path/to/data declaration in ~/.springrc or\n"
                                   "- the configuration file /etc/spring/datadir";
#endif
        throw content_error(errstr);
    }

    // for now, chdir to the data directory as a safety measure:
    // Not only safety anymore, it's just easier if other code can safely assume that
    // writedir == current working directory
    FileSystemHandler::GetInstance().Chdir(GetWriteDir()->path.c_str());

    // Initialize the log. Only after this moment log will be written to file.
    logOutput.Initialize();
    // Logging MAY NOT start before the chdir, otherwise the logfile ends up
    // in the wrong directory.
    // Update: now it actually may start before, log has preInitLog.
    for (std::vector<DataDir>::const_iterator d = datadirs.begin(); d != datadirs.end(); ++d) {
        if (d->writable) {
            logOutput.Print("Using read-write data directory: %s", d->path.c_str());

            // tag the cache dir
            const std::string cacheDir = d->path + "cache";
            if (filesystem.CreateDirectory(cacheDir)) {
                CacheDir::SetCacheDir(cacheDir, true);
            }
        } else {
            logOutput.Print("Using read-only data directory: %s",  d->path.c_str());
        }
    }
}