Changeset 840 – HoverRace

Changeset 840

Show
Ignore:
Timestamp:
01/30/10 18:28:45 (7 months 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}