/** * Gunzip a given file and remove the .gz if successful. * @param ci container with filename * @return true if the gunzip completed */ static bool GunzipFile(const ContentInfo *ci) { #if defined(WITH_ZLIB) bool ret = true; FILE *ftmp = fopen(GetFullFilename(ci, true), "rb"); gzFile fin = gzdopen(fileno(ftmp), "rb"); FILE *fout = fopen(GetFullFilename(ci, false), "wb"); if (fin == NULL || fout == NULL) { ret = false; } else { byte buff[8192]; while (1) { int read = gzread(fin, buff, sizeof(buff)); if (read == 0) { /* If gzread() returns 0, either the end-of-file has been * reached or an underlying read error has occurred. * * gzeof() can't be used, because: * 1.2.5 - it is safe, 1 means 'everything was OK' * 1.2.3.5, 1.2.4 - 0 or 1 is returned 'randomly' * 1.2.3.3 - 1 is returned for truncated archive * * So we use gzerror(). When proper end of archive * has been reached, then: * errnum == Z_STREAM_END in 1.2.3.3, * errnum == 0 in 1.2.4 and 1.2.5 */ int errnum; gzerror(fin, &errnum); if (errnum != 0 && errnum != Z_STREAM_END) ret = false; break; } if (read < 0 || (size_t)read != fwrite(buff, 1, read, fout)) { /* If gzread() returns -1, there was an error in archive */ ret = false; break; } /* DO NOT DO THIS! It will fail to detect broken archive with 1.2.3.3! * if (read < sizeof(buff)) break; */ } } if (fin != NULL) { /* Closes ftmp too! */ gzclose(fin); } else if (ftmp != NULL) { /* In case the gz stream was opened correctly this will * be closed by gzclose. */ fclose(ftmp); } if (fout != NULL) fclose(fout); return ret; #else NOT_REACHED(); #endif /* defined(WITH_ZLIB) */ }
/*=========================================================================== * * Class CSrResourceInstance Method - const char* GetFullFilenameAbs (void); * *=========================================================================*/ const char* CSrResourceInstance::GetFullFilenameAbs (void) { static CSString s_Buffer; s_Buffer = GetBasePath(); s_Buffer += GetFullFilename(); return (s_Buffer); }
FILE *SDLS_fopen(const char *fname, const char *mode) { char buffer[256]; if (GetFullFilename(fname, buffer)) return NULL; return fopen(buffer, mode); }
/** * Gunzip a given file and remove the .gz if successful. * @param ci container with filename * @return true if the gunzip completed */ static bool GunzipFile(const ContentInfo *ci) { #if defined(WITH_ZLIB) bool ret = true; FILE *ftmp = fopen(GetFullFilename(ci, true), "rb"); gzFile fin = gzdopen(fileno(ftmp), "rb"); FILE *fout = fopen(GetFullFilename(ci, false), "wb"); if (fin == NULL || fout == NULL) { ret = false; goto exit; } byte buff[8192]; while (!gzeof(fin)) { int read = gzread(fin, buff, sizeof(buff)); if (read < 0 || (size_t)read != fwrite(buff, 1, read, fout)) { ret = false; break; } } exit: if (fin != NULL) { /* Closes ftmp too! */ gzclose(fin); } else if (ftmp != NULL) { /* In case the gz stream was opened correctly this will * be closed by gzclose. */ fclose(ftmp); } if (fout != NULL) fclose(fout); return ret; #else NOT_REACHED(); #endif /* defined(WITH_ZLIB) */ }
/** * Handle the closing and extracting of a file after * downloading it has been done. */ void ClientNetworkContentSocketHandler::AfterDownload() { /* We read nothing; that's our marker for end-of-stream. * Now gunzip the tar and make it known. */ fclose(this->curFile); this->curFile = NULL; if (GunzipFile(this->curInfo)) { unlink(GetFullFilename(this->curInfo, true)); 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); } }
/** * Handle the opening of the file before downloading. * @return false on any error. */ bool ClientNetworkContentSocketHandler::BeforeDownload() { if (!this->curInfo->IsValid()) { delete this->curInfo; this->curInfo = NULL; return false; } if (this->curInfo->filesize != 0) { /* The filesize is > 0, so we are going to download it */ const char *filename = GetFullFilename(this->curInfo, true); if (filename == NULL || (this->curFile = fopen(filename, "wb")) == NULL) { /* Unless that fails ofcourse... */ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR); return false; } } return true; }