Changeset 840 – HoverRace

Changeset 840

Show
Ignore:
Timestamp:
01/30/10 18:28:45 (6 weeks ago)
Author:
ryan
Message:

Inline CreatePatch() and PatchHoverRace(), include a couple headers that were necessary but not included (yet it still compiled for some reason), update bsdiff and bspatch to give error messages and wait upon failure, and finally fix some code that looks for files in ZIP archives (remove leading slashes). Then fix code that creates the ZIP archives and DIGEST file to not include those slashes either.

Location:
trunk/updater
Files:
4 removed
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/updater/bsdiff/bsdiff.cpp

    r781 r840  
    2121void err(char a, char* format, char* param) 
    2222{ 
    23     printf(format,param); 
     23        printf("bsdiff error: "); 
     24        printf(format,param); 
     25        printf("\n"); 
     26        Sleep(4000); 
    2427    exit(1); 
    2528} 
    2629void err(char a, char* format) 
    2730{ 
    28     printf(format); 
     31        printf("bsdiff error: "); 
     32        printf(format); 
     33        printf("\n"); 
     34        Sleep(4000); 
    2935    exit(1); 
    3036} 
  • trunk/updater/bsdiff/bspatch.cpp

    r779 r840  
    2121 
    2222#include "bspatch.h" 
     23#include <string> 
    2324 
    2425void errx(char a, char* format, char* param) 
    2526{ 
    26     printf(format,param); 
     27        printf("bspatch error: "); 
     28        printf(format,param); 
     29        Sleep(4000); 
    2730    exit(1); 
    2831} 
    2932void errx(char a, char* format) 
    3033{ 
    31     printf(format); 
     34        printf("bspatch error: "); 
     35        printf(format); 
     36        Sleep(4000); 
    3237    exit(1); 
    3338} 
  • trunk/updater/main.cpp

    r837 r840  
    2222#include "StdAfx.h" 
    2323#include <string> 
     24#include <vector> 
    2425#include <stdio.h> 
    2526#include <stdlib.h> 
     
    3233 
    3334#include <boost/filesystem.hpp> 
    34  
    35 #include "PatchHoverRace.h" 
    36 #include "CreatePatch.h" 
     35#include <windows.h> 
     36 
     37#include "bsdiff/bspatch.h" 
     38#include "bsdiff/bsdiff.h" 
     39 
     40// for zip/unzip of patches 
     41#include <LiteUnzip.h> 
     42#include <LiteZip.h> 
    3743 
    3844#define new DEBUG_NEW 
     
    4551void waitExit(int code); 
    4652 
     53vector<string> EnumerateDirectory(string dir); 
     54 
    4755int main(int argc, const char **argv) { 
    4856        printf("HoverRace automatic updater and patch generator\n"); 
     57        //Sleep(25000); // time to attach 
    4958 
    5059        bool createUpdate = false; // if createUpdate is false we are updating 
     
    5564        // Windows has no getopt() therefore we must do it by hand and as a result my implementation is not the best or the 
    5665        // cleanest but it does work 
     66        printf("argc %d\n", argc); 
    5767        for(int i = 1; i < argc; i++) { 
     68                printf("next arg is %s\n", argv[i]); 
     69                printf("after that is %s\n", argv[i + 1]); 
    5870                if(argv[i][0] == '-') { 
    5971                        if(argv[i][1] == 'c') { 
     
    8395                                waitExit(1); 
    8496                        } else { 
     97                                printf("going to set our patch file to %s\n", argv[i + 1]); 
    8598                                patchFile = argv[i + 1]; 
     99                                printf("patchFile is %s\n", patchFile.c_str()); 
    86100                        } 
    87101 
     
    116130                // diff source and target 
    117131                printf("Creating patch from %s to %s\n", sourceDir, targetDir); 
    118                 return (CreatePatch(targetDir, sourceDir, patchFile)); 
     132                //return (CreatePatch(targetDir, sourceDir, patchFile)); 
     133 
     134                /*********************************** 
     135                 * create a patch                  * 
     136                 ***********************************/ 
     137                { 
     138                        // list all the files we will need to look at 
     139                        printf("Enumerating files...\n"); 
     140 
     141                        vector<string> dirListing = EnumerateDirectory(sourceDir); 
     142                        vector<string> oldListing = EnumerateDirectory(targetDir); 
     143 
     144                        // set up vectors for the possible actions needed to take on each file 
     145                        // the vectors will hold the filenames 
     146                        vector<string> patchFiles; 
     147                        vector<string> newFiles; // need to be added 
     148 
     149                        // create directory for temporary files 
     150                        // if this directory already exists we throw an error and exit 
     151                        if(is_directory("temp_patch")) { 
     152                                fprintf(stdout, "Directory temp_patch exists!  Exiting before bad things happen.  Remove directory and try again...\n"); 
     153                                return -1; 
     154                        } 
     155 
     156                        create_directory("temp_patch"); 
     157 
     158                        // now we must create an individual patchfile for each listed file we must diff 
     159                        for(vector<string>::iterator it = dirListing.begin(); it != dirListing.end(); it++) { 
     160                                printf("Creating patch for %s\n", (*it).c_str()); 
     161 
     162                                // see if this file exists in the old directory structure 
     163                                vector<string>::iterator index = find(oldListing.begin(), oldListing.end(), *it); 
     164                                if(index == oldListing.end()) { 
     165                                        // file does not exist in old directory 
     166                                        // so we have to copy the file over directly 
     167                                        string oldFile = path(targetDir).file_string() + "\\" + *it; 
     168                                        string patchName = "\\temp_patch\\" + *it; // same filename 
     169                                        string newFile = current_path().file_string() + patchName; 
     170 
     171                                        copy_file(path(oldFile), path(newFile)); 
     172 
     173                                        newFiles.push_back(*it); 
     174                                } else { 
     175                                        // we must create a patch 
     176                                        string oldFile = path(sourceDir).file_string() + "/" + *index; 
     177                                        string newFile = path(targetDir).file_string() + "/" + *it; 
     178                                        // separate the actual filename to construct the patch filename and add '.bsdiff' 
     179                                        string patchName = *it + ".bsdiff"; 
     180                                        string curPatchFile = current_path().file_string() + "/temp_patch/" + patchName; 
     181 
     182                                        // remove from old listing vector (not necessary to remove from new listing vector) 
     183                                        index = oldListing.erase(index); 
     184 
     185                                        // ensure directory exists 
     186                                        if(!exists("temp_patch/" + path(patchName).branch_path().file_string())) 
     187                                                create_directory("temp_patch/" + path(patchName).branch_path().file_string()); 
     188 
     189                                        // now create the patch 
     190                                        bsdiff_create_patch((char *) curPatchFile.c_str(), (char *) oldFile.c_str(), (char *) newFile.c_str()); 
     191 
     192                                        // verify patch file exists 
     193                                        if(!exists(curPatchFile)) { 
     194                                                fprintf(stderr, "Error creating patch file %s! Exiting...\n", patchFile.c_str()); 
     195                                                return -1; 
     196                                        } 
     197 
     198                                        // with the patch created we must add to our list of files that need patching 
     199                                        patchFiles.push_back(patchName); 
     200                                } 
     201                        } 
     202 
     203                        // now, what is left in our old listing that we haven't removed, we will need to erase 
     204                        string digestFile = current_path().file_string() + "/temp_patch/DIGEST"; 
     205                        FILE *digest = fopen(digestFile.c_str(), "wb"); 
     206 
     207                        // write files to patch to digest 
     208                        for(vector<string>::iterator it = patchFiles.begin(); it != patchFiles.end(); it++) { 
     209                                // erase any leading slashes 
     210                                if((*it).at(0) == '\\' || (*it).at(0) == '/') 
     211                                        (*it).erase(0, 1); 
     212                                fprintf(digest, "P %s\n", (*it).c_str()); 
     213                        } 
     214 
     215                        // write files to add to digest 
     216                        for(vector<string>::iterator it = newFiles.begin(); it != newFiles.end(); it++) { 
     217                                if((*it).at(0) == '\\' || (*it).at(0) == '/') 
     218                                        (*it).erase(0, 1); 
     219                                fprintf(digest, "A %s\n", (*it).c_str()); 
     220                        } 
     221 
     222                        // write files to remove to digest 
     223                        for(vector<string>::iterator it = oldListing.begin(); it != oldListing.end(); it++) { 
     224                                if((*it).at(0) == '\\' || (*it).at(0) == '/') 
     225                                        (*it).erase(0, 1); 
     226                                fprintf(digest, "D %s\n", (*it).c_str()); 
     227                        } 
     228 
     229                        fclose(digest); 
     230 
     231                        // now, we zip everything up 
     232                        HZIP hz; 
     233 
     234                        ZipCreateFile(&hz, patchFile.c_str(), 0); 
     235 
     236                        vector<string> filesToZip = EnumerateDirectory(current_path().file_string() + "/temp_patch/"); 
     237 
     238                        for(vector<string>::iterator it = filesToZip.begin(); it != filesToZip.end(); it++) { 
     239                                int ret = ZipAddFile(hz, (*it).c_str(), ("temp_patch/" + *it).c_str()); 
     240                                if(ret) { 
     241                                        char msg[1000]; 
     242                                        ZipFormatMessage(ret, msg, sizeof(msg)); 
     243                                        printf("Error zipping file %s: %s\n", (*it).c_str(), msg); 
     244                                } 
     245                        } 
     246 
     247                        ZipClose(hz); 
     248 
     249                        // remove all our temporary files 
     250                        remove_all("temp_patch"); 
     251 
     252                        return 0; 
     253                } 
    119254        } else { 
     255                /*********************************** 
     256                 * apply a patch                   * 
     257                 ***********************************/ 
     258 
    120259                // check that patch exists 
    121260                if(!exists(patchFile)) { 
     
    129268                if(hrWin != NULL) { 
    130269                        // kill it, with user confirmation 
    131                         SendMessage(hrWin, WM_CLOSE, 0, 0); 
     270                        printf("HoverRace is running, we must kill it first.\n"); 
     271                        printf("For now just letting it run...\n"); 
     272                        //SendMessage(hrWin, WM_CLOSE, 0, 0); 
    132273                        // if we wanted to kill instantly we would use WM_DESTROY 
    133274                } 
    134275 
    135276                // now, HoverRace is closed; do the patching 
    136                 printf("Will patch with file %s\n", patchFile); 
    137                 PatchHoverRace(targetDir, patchFile); 
     277                printf("Will patch with file %s\n", patchFile.c_str()); 
     278                //PatchHoverRace(targetDir, patchFile); 
     279                { 
     280                        // we assume that the files are valid 
     281                        printf("Beginning patch process...\n"); 
     282 
     283                        // first, we must unpack the patch file, which is a zip 
     284                        HUNZIP huz; 
     285                        ZIPENTRY ze; 
     286                        DWORD numItems; 
     287 
     288                        UnzipOpenFile(&huz, patchFile.c_str(), 0); 
     289 
     290                        ze.Index = (DWORD) - 1; 
     291                        UnzipGetItem(huz, &ze); 
     292                        numItems = ze.Index; 
     293 
     294                        // find digest 
     295                        lstrcpy(ze.Name, "DIGEST"); 
     296                        UnzipFindItem(huz, &ze, 0); 
     297                        UnzipItemToFile(huz, ze.Name, &ze); 
     298 
     299                        printf("Opening DIGEST...\n"); 
     300 
     301                        FILE *digest = fopen("DIGEST", "rb"); 
     302 
     303                        if(digest == NULL) { 
     304                                fprintf(stderr, "Cannot open DIGEST!\n"); 
     305                                return -1; 
     306                        } 
     307 
     308                        // unpack each file 
     309                        // we do not have to worry about changing directory as the compressed files 
     310                        // are in a directory with the same name as the patch file 
     311                        bool fail = false; 
     312                        while(!feof(digest) && !fail) { 
     313                                char digLine[1024]; 
     314                                fgets(digLine, 1024, digest); 
     315 
     316                                if(feof(digest)) 
     317                                        break; 
     318 
     319                                // strip newline from end of string 
     320                                if(digLine[strlen(digLine) - 1] == 0x0A) 
     321                                        digLine[strlen(digLine) - 1] = 0; 
     322 
     323                                char action = digLine[0]; 
     324                                string filename = &digLine[2]; // first character is action, second char is space 
     325 
     326                                if(filename.at(0) == '\\' || filename.at(0) == '/') // strip leading slash 
     327                                        filename.erase(0, 1); 
     328 
     329                                //printf("Searching for %s\n", filename.c_str()); 
     330                                lstrcpy(ze.Name, filename.c_str()); 
     331                                ze.Index = 0; 
     332                                if(UnzipFindItem(huz, &ze, 0) == ZR_NOTFOUND) { 
     333                                        fprintf(stderr, "Not found in archive: %s\n", filename.c_str()); 
     334                                        break; 
     335                                } 
     336 
     337                                UnzipItemToFile(huz, ze.Name, &ze); 
     338 
     339                                switch(action) { 
     340                                        case 'P': // patch file 
     341                                                { 
     342                                                        string bsdiffPatch = filename; 
     343 
     344                                                        // now that     we have the filename, patch it 
     345                                                        // we will have to strip the patch directory from the filename and the suffix 
     346                                                        // of the patch file (i.e. hoverrace-1.23.2/bin/HoverRace.exe.bsdiff -> 
     347                                                        //                                                      bin/HoverRace.exe 
     348                                                        size_t bsdiffLoc = bsdiffPatch.rfind(".bsdiff"); 
     349                                                        if(bsdiffLoc == string::npos) { 
     350                                                                fprintf(stderr, "Invalid patchfile name %s\n", bsdiffPatch.c_str()); 
     351                                                                fail = true; 
     352                                                        } else { 
     353                                                                // strip patch directory (it may not exist) 
     354                                                                size_t slashLoc = bsdiffPatch.find("/"); 
     355 
     356                                                                string absPatchLoc = current_path().file_string() + "\\" + bsdiffPatch; 
     357                                                                string fileToPatch = targetDir + "/" + (bsdiffPatch.substr(0, bsdiffLoc)); 
     358                                                                string newFile = fileToPatch + ".tmp"; // append .tmp for temporary file, we will move it later 
     359 
     360                                                                bsdiff_patch_file((char *) absPatchLoc.c_str(), 
     361                                                                                                  (char *) fileToPatch.c_str(), 
     362                                                                                                  (char *) newFile.c_str()); 
     363 
     364                                                                // now move .tmp to original 
     365                                                                if(remove(fileToPatch.c_str()) != 0) { 
     366                                                                        fprintf(stderr, "Error removing %s\n", fileToPatch.c_str()); 
     367                                                                        fail = true; 
     368                                                                } else { 
     369                                                                        if(rename(newFile.c_str(), fileToPatch.c_str()) != 0) { 
     370                                                                                fprintf(stderr, "Error moving %s to %s\n", newFile.c_str(), fileToPatch.c_str()); 
     371                                                                                fail = true; 
     372                                                                        } 
     373                                                         
     374                                                                        // file has been patched successfully... 
     375                                                                        // now we should update the statusbar but unfortunately it does not exist yet 
     376                                                                        fprintf(stdout, "File %s patched\n", fileToPatch.c_str()); 
     377                                                                } 
     378                                                        } 
     379                                                } 
     380                                                break; 
     381         
     382                                        case 'A': // add file 
     383                                                { 
     384                                                        string oldFile = current_path().file_string() + "\\" + filename; 
     385                                                        string newFile = targetDir + "\\" + filename; 
     386 
     387                                                        if(exists(newFile)) { 
     388                                                                fprintf(stderr, "File %s already exists!\n", newFile.c_str()); 
     389                                                                fail = true; 
     390                                                        } else { 
     391                                                                rename(path(oldFile), path(newFile)); 
     392                                                                fprintf(stdout, "File %s added\n", filename.c_str()); 
     393                                                        } 
     394 
     395                                                        break; 
     396                                                } 
     397 
     398                                        case 'D': // delete file 
     399                                                remove(path(targetDir + "\\" + filename)); 
     400                                                fprintf(stdout, "File %s removed\n", filename); 
     401                                                break; 
     402                                } 
     403 
     404                                if(action != 'D') { 
     405                                        // remove extracted file 
     406                                        remove(path(current_path().file_string() + "\\" + filename)); 
     407 
     408                                        if(strcmp(path(filename).branch_path().file_string().c_str(), "") != 0) // must remove parent directory if it exists 
     409                                                remove_all(path(filename).branch_path()); 
     410                                } 
     411                        } 
     412 
     413                        // close and remove digest 
     414                        fclose(digest); 
     415                        remove(path(current_path().file_string() + "\\DIGEST")); 
     416 
     417                        UnzipClose(huz); 
     418 
     419                        if(!fail) 
     420                                fprintf(stdout, "Patching complete!\n"); 
     421                } 
    138422        } 
    139423 
     
    145429        exit(code); 
    146430} 
     431 
     432/** 
     433 * Return a string vector of all the files in the directory, searching recursively. 
     434 */ 
     435vector<string> EnumerateDirectory(string directory) { 
     436        vector<string> ret; 
     437         
     438        recursive_directory_iterator it_end; 
     439        recursive_directory_iterator it((path(directory))); 
     440         
     441        string dir = string(path(directory).file_string()); 
     442        int dirlen = dir.length(); 
     443 
     444        while(it != it_end) { 
     445                // check if file is directory or not 
     446                // then do stuff with it 
     447                if(is_regular(it->status())) { 
     448                        // we have a file... now we must add it to our list 
     449                        string item = it->path().file_string(); 
     450                        // remove directory from path 
     451                        ret.push_back(item.substr(dirlen, string::npos)); 
     452                } 
     453 
     454                it++; 
     455        } 
     456 
     457        return ret; 
     458}