summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base_media_base.h4
-rw-r--r--src/fileio.cpp73
-rw-r--r--src/fileio_func.h1
-rw-r--r--src/network/network_content.cpp6
-rw-r--r--src/network/network_content_gui.cpp5
5 files changed, 88 insertions, 1 deletions
diff --git a/src/base_media_base.h b/src/base_media_base.h
index 4b43c24fd..88b78374b 100644
--- a/src/base_media_base.h
+++ b/src/base_media_base.h
@@ -170,7 +170,9 @@ public:
static uint FindSets()
{
BaseMedia<Tbase_set> fs;
- return fs.Scan(GetExtension(), Tbase_set::SUBDIR);
+ /* GM_DIR == music set. Music sets don't support tars,
+ * so there is no need to search for tars in that case. */
+ return fs.Scan(GetExtension(), Tbase_set::SUBDIR, Tbase_set::SUBDIR != GM_DIR);
}
/**
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 253ad8ebb..1ae3c7e5e 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -743,6 +743,79 @@ bool TarListAddFile(const char *filename)
return true;
}
+/**
+ * Extract the tar with the given filename in the directory
+ * where the tar resides.
+ * @param tar_filename the name of the tar to extract.
+ * @return false on failure.
+ */
+bool ExtractTar(const char *tar_filename)
+{
+ TarList::iterator it = _tar_list.find(tar_filename);
+ /* We don't know the file. */
+ if (it == _tar_list.end()) return false;
+
+ const char *dirname = (*it).second.dirname;
+
+ /* The file doesn't have a sub directory! */
+ if (dirname == NULL) return false;
+
+ char filename[MAX_PATH];
+ strecpy(filename, tar_filename, lastof(filename));
+ char *p = strrchr(filename, PATHSEPCHAR);
+ /* The file's path does not have a separator? */
+ if (p == NULL) return false;
+
+ p++;
+ strecpy(p, dirname, lastof(filename));
+ DEBUG(misc, 8, "Extracting %s to directory %s", tar_filename, filename);
+ FioCreateDirectory(filename);
+
+ for (TarFileList::iterator it2 = _tar_filelist.begin(); it2 != _tar_filelist.end(); it2++) {
+ if (strcmp((*it2).second.tar_filename, tar_filename) != 0) continue;
+
+ strecpy(p, (*it2).first.c_str(), lastof(filename));
+
+ DEBUG(misc, 9, " extracting %s", filename);
+
+ /* First open the file in the .tar. */
+ size_t to_copy = 0;
+ FILE *in = FioFOpenFileTar(&(*it2).second, &to_copy);
+ if (in == NULL) {
+ DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, tar_filename);
+ return false;
+ }
+
+ /* Now open the 'output' file. */
+ FILE *out = fopen(filename, "wb");
+ if (out == NULL) {
+ DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, filename);
+ fclose(in);
+ return false;
+ }
+
+ /* Now read from the tar and write it into the file. */
+ char buffer[4096];
+ size_t read;
+ for (; to_copy != 0; to_copy -= read) {
+ read = fread(buffer, 1, min(to_copy, lengthof(buffer)), in);
+ if (read <= 0 || fwrite(buffer, 1, read, out) != read) break;
+ }
+
+ /* Close everything up. */
+ fclose(in);
+ fclose(out);
+
+ if (to_copy != 0) {
+ DEBUG(misc, 6, "Extracting %s failed; still %i bytes to copy", filename, (int)to_copy);
+ return false;
+ }
+ }
+
+ DEBUG(misc, 9, " extraction successful");
+ return true;
+}
+
static int ScanPathForTarFiles(const char *path, size_t basepath_length)
{
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
diff --git a/src/fileio_func.h b/src/fileio_func.h
index b2d2da803..53b3aa233 100644
--- a/src/fileio_func.h
+++ b/src/fileio_func.h
@@ -63,6 +63,7 @@ void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
bool FileExists(const char *filename);
const char *FioTarFirstDir(const char *tarname);
void FioTarAddLink(const char *src, const char *dest);
+bool ExtractTar(const char *tar_filename);
extern char *_personal_dir; ///< custom directory for personal settings, saves, newgrf, etc.
diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp
index d5ed2a374..76576f2c2 100644
--- a/src/network/network_content.cpp
+++ b/src/network/network_content.cpp
@@ -481,6 +481,12 @@ void ClientNetworkContentSocketHandler::AfterDownload()
TarListAddFile(GetFullFilename(this->curInfo, false));
+ if (this->curInfo->type == CONTENT_TYPE_BASE_MUSIC) {
+ /* Music can't be in a tar. So extract the tar! */
+ ExtractTar(GetFullFilename(this->curInfo, false));
+ unlink(GetFullFilename(this->curInfo, false));
+ }
+
this->OnDownloadComplete(this->curInfo->id);
} else {
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR);
diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp
index a25a5ad4a..8f377a0ba 100644
--- a/src/network/network_content_gui.cpp
+++ b/src/network/network_content_gui.cpp
@@ -106,6 +106,11 @@ public:
SetWindowDirty(WC_GAME_OPTIONS, 0);
break;
+ case CONTENT_TYPE_BASE_MUSIC:
+ BaseMusic::FindSets();
+ SetWindowDirty(WC_GAME_OPTIONS, 0);
+ break;
+
case CONTENT_TYPE_NEWGRF:
ScanNewGRFFiles();
/* Yes... these are the NewGRF windows */