| 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 | } |
| 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 | } |