Changeset - r11258:7a85130e9153
[Not reviewed]
master
0 1 0
rubidium - 15 years ago 2009-03-04 14:25:53
rubidium@openttd.org
(svn r15612) -Codechange: unduplicate directory creation
1 file changed with 8 insertions and 7 deletions:
0 comments (0 inline, 0 general)
src/fileio.cpp
Show inline comments
 
@@ -746,391 +746,392 @@ static int ScanPathForTarFiles(const cha
 
			/* Directory */
 
			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
 
			AppendPathSeparator(filename, lengthof(filename));
 
			num += ScanPathForTarFiles(filename, basepath_length);
 
		} else if (S_ISREG(sb.st_mode)) {
 
			/* File */
 
			char *ext = strrchr(filename, '.');
 

	
 
			/* If no extension or extension isn't .tar, skip the file */
 
			if (ext == NULL) continue;
 
			if (strcasecmp(ext, ".tar") != 0) continue;
 

	
 
			if (TarListAddFile(filename)) num++;
 
		}
 
	}
 

	
 
	closedir(dir);
 
	return num;
 
}
 

	
 
void ScanForTarFiles()
 
{
 
	Searchpath sp;
 
	char path[MAX_PATH];
 
	uint num = 0;
 

	
 
	DEBUG(misc, 1, "Scanning for tars");
 
	FOR_ALL_SEARCHPATHS(sp) {
 
		FioAppendDirectory(path, MAX_PATH, sp, DATA_DIR);
 
		num += ScanPathForTarFiles(path, strlen(path));
 
		FioAppendDirectory(path, MAX_PATH, sp, AI_DIR);
 
		num += ScanPathForTarFiles(path, strlen(path));
 
		FioAppendDirectory(path, MAX_PATH, sp, AI_LIBRARY_DIR);
 
		num += ScanPathForTarFiles(path, strlen(path));
 
		FioAppendDirectory(path, MAX_PATH, sp, SCENARIO_DIR);
 
		num += ScanPathForTarFiles(path, strlen(path));
 
	}
 
	DEBUG(misc, 1, "Scan complete, found %d files", num);
 
}
 

	
 
#if defined(WIN32) || defined(WINCE)
 
/**
 
 * Determine the base (personal dir and game data dir) paths
 
 * @param exe the path from the current path to the executable
 
 * @note defined in the OS related files (os2.cpp, win32.cpp, unix.cpp etc)
 
 */
 
extern void DetermineBasePaths(const char *exe);
 
#else /* defined(WIN32) || defined(WINCE) */
 

	
 
/**
 
 * Changes the working directory to the path of the give executable.
 
 * For OSX application bundles '.app' is the required extension of the bundle,
 
 * so when we crop the path to there, when can remove the name of the bundle
 
 * in the same way we remove the name from the executable name.
 
 * @param exe the path to the executable
 
 */
 
void ChangeWorkingDirectory(const char *exe)
 
{
 
#ifdef WITH_COCOA
 
	char *app_bundle = strchr(exe, '.');
 
	while (app_bundle != NULL && strncasecmp(app_bundle, ".app", 4) != 0) app_bundle = strchr(&app_bundle[1], '.');
 

	
 
	if (app_bundle != NULL) app_bundle[0] = '\0';
 
#endif /* WITH_COCOA */
 
	char *s = strrchr(exe, PATHSEPCHAR);
 
	if (s != NULL) {
 
		*s = '\0';
 
#if defined(__DJGPP__)
 
		/* If we want to go to the root, we can't use cd C:, but we must use '/' */
 
		if (s[-1] == ':') chdir("/");
 
#endif
 
		if (chdir(exe) != 0) DEBUG(misc, 0, "Directory with the binary does not exist?");
 
		*s = PATHSEPCHAR;
 
	}
 
#ifdef WITH_COCOA
 
	if (app_bundle != NULL) app_bundle[0] = '.';
 
#endif /* WITH_COCOA */
 
}
 

	
 
/**
 
 * Determine the base (personal dir and game data dir) paths
 
 * @param exe the path to the executable
 
 */
 
void DetermineBasePaths(const char *exe)
 
{
 
	char tmp[MAX_PATH];
 
#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) || !defined(WITH_PERSONAL_DIR)
 
	_searchpaths[SP_PERSONAL_DIR] = NULL;
 
#else
 
	const char *homedir = getenv("HOME");
 

	
 
	if (homedir == NULL) {
 
		const struct passwd *pw = getpwuid(getuid());
 
		homedir = (pw == NULL) ? "" : pw->pw_dir;
 
	}
 

	
 
	snprintf(tmp, MAX_PATH, "%s" PATHSEP "%s", homedir, PERSONAL_DIR);
 
	AppendPathSeparator(tmp, MAX_PATH);
 

	
 
	_searchpaths[SP_PERSONAL_DIR] = strdup(tmp);
 
#endif
 

	
 
#if defined(WITH_SHARED_DIR)
 
	snprintf(tmp, MAX_PATH, "%s", SHARED_DIR);
 
	AppendPathSeparator(tmp, MAX_PATH);
 
	_searchpaths[SP_SHARED_DIR] = strdup(tmp);
 
#else
 
	_searchpaths[SP_SHARED_DIR] = NULL;
 
#endif
 

	
 
#if defined(__MORPHOS__) || defined(__AMIGA__)
 
	_searchpaths[SP_WORKING_DIR] = NULL;
 
#else
 
	if (getcwd(tmp, MAX_PATH) == NULL) *tmp = '\0';
 
	AppendPathSeparator(tmp, MAX_PATH);
 
	_searchpaths[SP_WORKING_DIR] = strdup(tmp);
 
#endif
 

	
 
	/* Change the working directory to that one of the executable */
 
	ChangeWorkingDirectory((char*)exe);
 
	if (getcwd(tmp, MAX_PATH) == NULL) *tmp = '\0';
 
	AppendPathSeparator(tmp, MAX_PATH);
 
	_searchpaths[SP_BINARY_DIR] = strdup(tmp);
 

	
 
#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS)
 
	_searchpaths[SP_INSTALLATION_DIR] = NULL;
 
#else
 
	snprintf(tmp, MAX_PATH, "%s", GLOBAL_DATA_DIR);
 
	AppendPathSeparator(tmp, MAX_PATH);
 
	_searchpaths[SP_INSTALLATION_DIR] = strdup(tmp);
 
#endif
 
#ifdef WITH_COCOA
 
extern void cocoaSetApplicationBundleDir();
 
	cocoaSetApplicationBundleDir();
 
#else
 
	_searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
 
#endif
 
}
 
#endif /* defined(WIN32) || defined(WINCE) */
 

	
 
char *_personal_dir;
 

	
 
/**
 
 * Acquire the base paths (personal dir and game data dir),
 
 * fill all other paths (save dir, autosave dir etc) and
 
 * make the save and scenario directories.
 
 * @param exe the path from the current path to the executable
 
 */
 
void DeterminePaths(const char *exe)
 
{
 
	DetermineBasePaths(exe);
 

	
 
	Searchpath sp;
 
	FOR_ALL_SEARCHPATHS(sp) DEBUG(misc, 4, "%s added as search path", _searchpaths[sp]);
 

	
 
	if (_config_file != NULL) {
 
		_personal_dir = strdup(_config_file);
 
		char *end = strrchr(_personal_dir , PATHSEPCHAR);
 
		if (end == NULL) {
 
			_personal_dir[0] = '\0';
 
		} else {
 
			end[1] = '\0';
 
		}
 
	} else {
 
		char personal_dir[MAX_PATH];
 
		FioFindFullPath(personal_dir, lengthof(personal_dir), BASE_DIR, "openttd.cfg");
 

	
 
		if (FileExists(personal_dir)) {
 
			char *end = strrchr(personal_dir, PATHSEPCHAR);
 
			if (end != NULL) end[1] = '\0';
 
			_personal_dir = strdup(personal_dir);
 
			_config_file = str_fmt("%sopenttd.cfg", _personal_dir);
 
		} else {
 
			static const Searchpath new_openttd_cfg_order[] = {
 
					SP_PERSONAL_DIR, SP_BINARY_DIR, SP_WORKING_DIR, SP_SHARED_DIR, SP_INSTALLATION_DIR
 
				};
 

	
 
			for (uint i = 0; i < lengthof(new_openttd_cfg_order); i++) {
 
				if (IsValidSearchPath(new_openttd_cfg_order[i])) {
 
					_personal_dir = strdup(_searchpaths[new_openttd_cfg_order[i]]);
 
					_config_file = str_fmt("%sopenttd.cfg", _personal_dir);
 
					break;
 
				}
 
			}
 
		}
 
	}
 

	
 
	DEBUG(misc, 3, "%s found as personal directory", _personal_dir);
 

	
 
	_highscore_file = str_fmt("%shs.dat", _personal_dir);
 
	_log_file = str_fmt("%sopenttd.log",  _personal_dir);
 

	
 
	char *save_dir     = str_fmt("%s%s", _personal_dir, FioGetSubdirectory(SAVE_DIR));
 
	char *autosave_dir = str_fmt("%s%s", _personal_dir, FioGetSubdirectory(AUTOSAVE_DIR));
 

	
 
	/* Make the necessary folders */
 
#if !defined(__MORPHOS__) && !defined(__AMIGA__) && defined(WITH_PERSONAL_DIR)
 
	FioCreateDirectory(_personal_dir);
 
#endif
 

	
 
	FioCreateDirectory(save_dir);
 
	FioCreateDirectory(autosave_dir);
 
	static const Subdirectory default_subdirs[] = {
 
		SAVE_DIR, AUTOSAVE_DIR
 
	};
 

	
 
	free(save_dir);
 
	free(autosave_dir);
 
	for (uint i = 0; i < lengthof(default_subdirs); i++) {
 
		char *dir = str_fmt("%s%s", _personal_dir, FioGetSubdirectory(default_subdirs[i]));
 
		FioCreateDirectory(dir);
 
		free(dir);
 
	}
 

	
 
	/* If we have network we make a directory for the autodownloading of content */
 
	_searchpaths[SP_AUTODOWNLOAD_DIR] = str_fmt("%s%s", _personal_dir, "content_download" PATHSEP);
 
#ifdef ENABLE_NETWORK
 
	FioCreateDirectory(_searchpaths[SP_AUTODOWNLOAD_DIR]);
 

	
 
	/* Create the directory for each of the types of content */
 
	const Subdirectory dirs[] = { SCENARIO_DIR, HEIGHTMAP_DIR, DATA_DIR, AI_DIR, AI_LIBRARY_DIR };
 
	for (uint i = 0; i < lengthof(dirs); i++) {
 
		char *tmp = str_fmt("%s%s", _searchpaths[SP_AUTODOWNLOAD_DIR], FioGetSubdirectory(dirs[i]));
 
		FioCreateDirectory(tmp);
 
		free(tmp);
 
	}
 
#else /* ENABLE_NETWORK */
 
	/* If we don't have networking, we don't need to make the directory. But
 
	 * if it exists we keep it, otherwise remove it from the search paths. */
 
	if (!FileExists(_searchpaths[SP_AUTODOWNLOAD_DIR]))  {
 
		free((void*)_searchpaths[SP_AUTODOWNLOAD_DIR]);
 
		_searchpaths[SP_AUTODOWNLOAD_DIR] = NULL;
 
	}
 
#endif /* ENABLE_NETWORK */
 

	
 
	ScanForTarFiles();
 
}
 

	
 
/**
 
 * Sanitizes a filename, i.e. removes all illegal characters from it.
 
 * @param filename the "\0" terminated filename
 
 */
 
void SanitizeFilename(char *filename)
 
{
 
	for (; *filename != '\0'; filename++) {
 
		switch (*filename) {
 
			/* The following characters are not allowed in filenames
 
			 * on at least one of the supported operating systems: */
 
			case ':': case '\\': case '*': case '?': case '/':
 
			case '<': case '>': case '|': case '"':
 
				*filename = '_';
 
				break;
 
		}
 
	}
 
}
 

	
 
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize)
 
{
 
	FILE *in = fopen(filename, "rb");
 
	if (in == NULL) return NULL;
 

	
 
	fseek(in, 0, SEEK_END);
 
	size_t len = ftell(in);
 
	fseek(in, 0, SEEK_SET);
 
	if (len > maxsize) {
 
		fclose(in);
 
		return NULL;
 
	}
 
	byte *mem = MallocT<byte>(len + 1);
 
	mem[len] = 0;
 
	if (fread(mem, len, 1, in) != 1) {
 
		fclose(in);
 
		free(mem);
 
		return NULL;
 
	}
 
	fclose(in);
 

	
 
	*lenp = len;
 
	return mem;
 
}
 

	
 

	
 
/**
 
 * Scan a single directory (and recursively it's children) and add
 
 * any graphics sets that are found.
 
 * @param extension       the extension of files to search for.
 
 * @param path            full path we're currently at
 
 * @param basepath_length from where in the path are we 'based' on the search path
 
 */
 
static uint ScanPath(FileScanner *fs, const char *extension, const char *path, size_t basepath_length, bool recursive)
 
{
 
	extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
 

	
 
	uint num = 0;
 
	struct stat sb;
 
	struct dirent *dirent;
 
	DIR *dir;
 

	
 
	if (path == NULL || (dir = ttd_opendir(path)) == NULL) return 0;
 

	
 
	while ((dirent = readdir(dir)) != NULL) {
 
		const char *d_name = FS2OTTD(dirent->d_name);
 
		char filename[MAX_PATH];
 

	
 
		if (!FiosIsValidFile(path, dirent, &sb)) continue;
 

	
 
		snprintf(filename, lengthof(filename), "%s%s", path, d_name);
 

	
 
		if (S_ISDIR(sb.st_mode)) {
 
			/* Directory */
 
			if (!recursive) continue;
 
			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
 
			AppendPathSeparator(filename, lengthof(filename));
 
			num += ScanPath(fs, extension, filename, basepath_length, recursive);
 
		} else if (S_ISREG(sb.st_mode)) {
 
			/* File */
 
			if (extension != NULL) {
 
				char *ext = strrchr(filename, '.');
 

	
 
				/* If no extension or extension isn't .grf, skip the file */
 
				if (ext == NULL) continue;
 
				if (strcasecmp(ext, extension) != 0) continue;
 
			}
 

	
 
			if (fs->AddFile(filename, basepath_length)) num++;
 
		}
 
	}
 

	
 
	closedir(dir);
 

	
 
	return num;
 
}
 

	
 
/**
 
 * Scan the given tar and add graphics sets when it finds one.
 
 * @param extension the extension of files to search for.
 
 * @param tar       the tar to search in.
 
 */
 
static uint ScanTar(FileScanner *fs, const char *extension, TarFileList::iterator tar)
 
{
 
	uint num = 0;
 
	const char *filename = (*tar).first.c_str();
 

	
 
	if (extension != NULL) {
 
		const char *ext = strrchr(filename, '.');
 

	
 
		/* If no extension or extension isn't .grf, skip the file */
 
		if (ext == NULL) return false;
 
		if (strcasecmp(ext, extension) != 0) return false;
 
	}
 

	
 
	if (fs->AddFile(filename, 0)) num++;
 

	
 
	return num;
 
}
 

	
 
/**
 
 * Scan for files with the given extention in the given search path.
 
 * @param extension the extension of files to search for.
 
 * @param sd        the sub directory to search in.
 
 * @param tars      whether to search in the tars too.
 
 * @return the number of found files, i.e. the number of times that
 
 *         AddFile returned true.
 
 */
 
uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool recursive)
 
{
 
	Searchpath sp;
 
	char path[MAX_PATH];
 
	TarFileList::iterator tar;
 
	uint num = 0;
 

	
 
	FOR_ALL_SEARCHPATHS(sp) {
 
		FioAppendDirectory(path, MAX_PATH, sp, sd);
 
		num += ScanPath(this, extension, path, strlen(path), recursive);
 
	}
 

	
 
	if (tars) {
 
		FOR_ALL_TARS(tar) {
 
			num += ScanTar(this, extension, tar);
 
		}
 
	}
 

	
 
	return num;
 
}
 

	
 
/**
 
 * Scan for files with the given extention in the given search path.
 
 * @param extension the extension of files to search for.
 
 * @param directory the sub directory to search in.
 
 * @return the number of found files, i.e. the number of times that
 
 *         AddFile returned true.
 
 */
 
uint FileScanner::Scan(const char *extension, const char *directory, bool recursive)
 
{
 
	char path[MAX_PATH];
 
	strecpy(path, directory, lastof(path));
 
	AppendPathSeparator(path, lengthof(path));
 
	return ScanPath(this, extension, path, strlen(path), recursive);
 
}
0 comments (0 inline, 0 general)