├── .gitignore ├── Makefile.inc ├── Makefile.txt ├── Readme.markdown ├── bsdiff.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── bsdiff distro.xcscheme │ ├── bsdiff.xcscheme │ ├── bspatch.xcscheme │ └── bsreplace.xcscheme ├── bsdiff ├── Makefile ├── bsdiff.1 └── bsdiff.c ├── bspatch ├── Makefile ├── bspatch.1 └── bspatch.c └── bsreplace ├── bsreplace-Prefix.pch ├── bsreplace.1 └── bsreplace.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | -------------------------------------------------------------------------------- /Makefile.inc: -------------------------------------------------------------------------------- 1 | # $FreeBSD: src/usr.bin/bsdiff/Makefile.inc,v 1.2.2.1 2005/08/15 18:34:21 cperciva Exp $ 2 | 3 | WARNS?= 6 4 | 5 | .include "../Makefile.inc" 6 | 7 | -------------------------------------------------------------------------------- /Makefile.txt: -------------------------------------------------------------------------------- 1 | # $FreeBSD: src/usr.bin/bsdiff/Makefile,v 1.1.2.1 2005/08/15 18:34:21 cperciva Exp $ 2 | 3 | SUBDIR= bsdiff bspatch 4 | 5 | .include 6 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | This project is a copy of Colin Percival's [binary diff/patch](http://www.daemonology.net/bsdiff/) with an Xcode project. The project includes a new utility bsreplace, which performs a binary search and replace. 2 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 96ED08B413DDB9FB006C6B6A /* all */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 96ED08B513DDB9FB006C6B6A /* Build configuration list for PBXAggregateTarget "all" */; 13 | buildPhases = ( 14 | ); 15 | dependencies = ( 16 | 963CCC1714E971D4008228EA /* PBXTargetDependency */, 17 | 96ED08B913DDBA0A006C6B6A /* PBXTargetDependency */, 18 | 96ED08BB13DDBA0A006C6B6A /* PBXTargetDependency */, 19 | ); 20 | name = all; 21 | productName = all; 22 | }; 23 | /* End PBXAggregateTarget section */ 24 | 25 | /* Begin PBXBuildFile section */ 26 | 96347C1114D32B87008AFCBC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96347C1014D32B87008AFCBC /* Foundation.framework */; }; 27 | 96347C1414D32B87008AFCBC /* bsreplace.m in Sources */ = {isa = PBXBuildFile; fileRef = 96347C1314D32B87008AFCBC /* bsreplace.m */; }; 28 | 96347C1814D32B87008AFCBC /* bsreplace.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 96347C1714D32B87008AFCBC /* bsreplace.1 */; }; 29 | 96ED089013DDB3EE006C6B6A /* bsdiff.c in Sources */ = {isa = PBXBuildFile; fileRef = 96ED088F13DDB3EE006C6B6A /* bsdiff.c */; }; 30 | 96ED089213DDB3EE006C6B6A /* bsdiff.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 96ED089113DDB3EE006C6B6A /* bsdiff.1 */; }; 31 | 96ED089E13DDB401006C6B6A /* bspatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 96ED089D13DDB401006C6B6A /* bspatch.c */; }; 32 | 96ED08A013DDB401006C6B6A /* bspatch.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 96ED089F13DDB401006C6B6A /* bspatch.1 */; }; 33 | 96ED08AF13DDB6CF006C6B6A /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 96ED08AE13DDB6CF006C6B6A /* libbz2.dylib */; }; 34 | 96ED08B113DDB6DA006C6B6A /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 96ED08B013DDB6DA006C6B6A /* libbz2.dylib */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXContainerItemProxy section */ 38 | 963CCC1614E971D4008228EA /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = 96ED088013DDB3C0006C6B6A /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = 96347C0C14D32B87008AFCBC; 43 | remoteInfo = bsreplace; 44 | }; 45 | 96ED08B813DDBA0A006C6B6A /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = 96ED088013DDB3C0006C6B6A /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = 96ED088A13DDB3EE006C6B6A; 50 | remoteInfo = bsdiff; 51 | }; 52 | 96ED08BA13DDBA0A006C6B6A /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = 96ED088013DDB3C0006C6B6A /* Project object */; 55 | proxyType = 1; 56 | remoteGlobalIDString = 96ED089913DDB401006C6B6A; 57 | remoteInfo = bspatch; 58 | }; 59 | /* End PBXContainerItemProxy section */ 60 | 61 | /* Begin PBXCopyFilesBuildPhase section */ 62 | 96347C0B14D32B87008AFCBC /* CopyFiles */ = { 63 | isa = PBXCopyFilesBuildPhase; 64 | buildActionMask = 2147483647; 65 | dstPath = /usr/share/man/man1/; 66 | dstSubfolderSpec = 0; 67 | files = ( 68 | 96347C1814D32B87008AFCBC /* bsreplace.1 in CopyFiles */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 1; 71 | }; 72 | 96ED088913DDB3EE006C6B6A /* CopyFiles */ = { 73 | isa = PBXCopyFilesBuildPhase; 74 | buildActionMask = 2147483647; 75 | dstPath = /usr/share/man/man1/; 76 | dstSubfolderSpec = 0; 77 | files = ( 78 | 96ED089213DDB3EE006C6B6A /* bsdiff.1 in CopyFiles */, 79 | ); 80 | runOnlyForDeploymentPostprocessing = 1; 81 | }; 82 | 96ED089813DDB401006C6B6A /* CopyFiles */ = { 83 | isa = PBXCopyFilesBuildPhase; 84 | buildActionMask = 2147483647; 85 | dstPath = /usr/share/man/man1/; 86 | dstSubfolderSpec = 0; 87 | files = ( 88 | 96ED08A013DDB401006C6B6A /* bspatch.1 in CopyFiles */, 89 | ); 90 | runOnlyForDeploymentPostprocessing = 1; 91 | }; 92 | /* End PBXCopyFilesBuildPhase section */ 93 | 94 | /* Begin PBXFileReference section */ 95 | 96347C0D14D32B87008AFCBC /* bsreplace */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bsreplace; sourceTree = BUILT_PRODUCTS_DIR; }; 96 | 96347C1014D32B87008AFCBC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 97 | 96347C1314D32B87008AFCBC /* bsreplace.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = bsreplace.m; sourceTree = ""; }; 98 | 96347C1614D32B87008AFCBC /* bsreplace-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bsreplace-Prefix.pch"; sourceTree = ""; }; 99 | 96347C1714D32B87008AFCBC /* bsreplace.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = bsreplace.1; sourceTree = ""; }; 100 | 96347C3514D6AAFE008AFCBC /* Readme.markdown */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.markdown; sourceTree = ""; }; 101 | 96ED088B13DDB3EE006C6B6A /* bsdiff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bsdiff; sourceTree = BUILT_PRODUCTS_DIR; }; 102 | 96ED088F13DDB3EE006C6B6A /* bsdiff.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bsdiff.c; sourceTree = ""; }; 103 | 96ED089113DDB3EE006C6B6A /* bsdiff.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = bsdiff.1; sourceTree = ""; }; 104 | 96ED089A13DDB401006C6B6A /* bspatch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bspatch; sourceTree = BUILT_PRODUCTS_DIR; }; 105 | 96ED089D13DDB401006C6B6A /* bspatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bspatch.c; sourceTree = ""; }; 106 | 96ED089F13DDB401006C6B6A /* bspatch.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = bspatch.1; sourceTree = ""; }; 107 | 96ED08A913DDB532006C6B6A /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 108 | 96ED08AB13DDB577006C6B6A /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 109 | 96ED08AC13DDB587006C6B6A /* Makefile.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.txt; sourceTree = ""; }; 110 | 96ED08AD13DDB587006C6B6A /* Makefile.inc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.pascal; path = Makefile.inc; sourceTree = ""; }; 111 | 96ED08AE13DDB6CF006C6B6A /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libbz2.dylib; sourceTree = DEVELOPER_DIR; }; 112 | 96ED08B013DDB6DA006C6B6A /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libbz2.dylib; sourceTree = DEVELOPER_DIR; }; 113 | /* End PBXFileReference section */ 114 | 115 | /* Begin PBXFrameworksBuildPhase section */ 116 | 96347C0A14D32B87008AFCBC /* Frameworks */ = { 117 | isa = PBXFrameworksBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | 96347C1114D32B87008AFCBC /* Foundation.framework in Frameworks */, 121 | ); 122 | runOnlyForDeploymentPostprocessing = 0; 123 | }; 124 | 96ED088813DDB3EE006C6B6A /* Frameworks */ = { 125 | isa = PBXFrameworksBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | 96ED08B113DDB6DA006C6B6A /* libbz2.dylib in Frameworks */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | 96ED089713DDB401006C6B6A /* Frameworks */ = { 133 | isa = PBXFrameworksBuildPhase; 134 | buildActionMask = 2147483647; 135 | files = ( 136 | 96ED08AF13DDB6CF006C6B6A /* libbz2.dylib in Frameworks */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXFrameworksBuildPhase section */ 141 | 142 | /* Begin PBXGroup section */ 143 | 96347C0F14D32B87008AFCBC /* Frameworks */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 96347C1014D32B87008AFCBC /* Foundation.framework */, 147 | ); 148 | name = Frameworks; 149 | sourceTree = ""; 150 | }; 151 | 96347C1214D32B87008AFCBC /* bsreplace */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 96347C1314D32B87008AFCBC /* bsreplace.m */, 155 | 96347C1714D32B87008AFCBC /* bsreplace.1 */, 156 | 96347C1514D32B87008AFCBC /* Supporting Files */, 157 | ); 158 | path = bsreplace; 159 | sourceTree = ""; 160 | }; 161 | 96347C1514D32B87008AFCBC /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 96347C1614D32B87008AFCBC /* bsreplace-Prefix.pch */, 165 | ); 166 | name = "Supporting Files"; 167 | sourceTree = ""; 168 | }; 169 | 96ED087E13DDB3C0006C6B6A = { 170 | isa = PBXGroup; 171 | children = ( 172 | 96347C3514D6AAFE008AFCBC /* Readme.markdown */, 173 | 96ED08AC13DDB587006C6B6A /* Makefile.txt */, 174 | 96ED08AD13DDB587006C6B6A /* Makefile.inc */, 175 | 96ED088E13DDB3EE006C6B6A /* bsdiff */, 176 | 96ED089C13DDB401006C6B6A /* bspatch */, 177 | 96347C1214D32B87008AFCBC /* bsreplace */, 178 | 96347C0F14D32B87008AFCBC /* Frameworks */, 179 | 96ED088C13DDB3EE006C6B6A /* Products */, 180 | ); 181 | sourceTree = ""; 182 | }; 183 | 96ED088C13DDB3EE006C6B6A /* Products */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 96ED088B13DDB3EE006C6B6A /* bsdiff */, 187 | 96ED089A13DDB401006C6B6A /* bspatch */, 188 | 96347C0D14D32B87008AFCBC /* bsreplace */, 189 | ); 190 | name = Products; 191 | sourceTree = ""; 192 | }; 193 | 96ED088E13DDB3EE006C6B6A /* bsdiff */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 96ED08B313DDB711006C6B6A /* Libraries and Frameworks */, 197 | 96ED08A913DDB532006C6B6A /* Makefile */, 198 | 96ED088F13DDB3EE006C6B6A /* bsdiff.c */, 199 | 96ED089113DDB3EE006C6B6A /* bsdiff.1 */, 200 | ); 201 | path = bsdiff; 202 | sourceTree = ""; 203 | }; 204 | 96ED089C13DDB401006C6B6A /* bspatch */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 96ED08B213DDB6EB006C6B6A /* Libraries and Frameworks */, 208 | 96ED08AB13DDB577006C6B6A /* Makefile */, 209 | 96ED089D13DDB401006C6B6A /* bspatch.c */, 210 | 96ED089F13DDB401006C6B6A /* bspatch.1 */, 211 | ); 212 | path = bspatch; 213 | sourceTree = ""; 214 | }; 215 | 96ED08B213DDB6EB006C6B6A /* Libraries and Frameworks */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 96ED08AE13DDB6CF006C6B6A /* libbz2.dylib */, 219 | ); 220 | name = "Libraries and Frameworks"; 221 | sourceTree = ""; 222 | }; 223 | 96ED08B313DDB711006C6B6A /* Libraries and Frameworks */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | 96ED08B013DDB6DA006C6B6A /* libbz2.dylib */, 227 | ); 228 | name = "Libraries and Frameworks"; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXGroup section */ 232 | 233 | /* Begin PBXNativeTarget section */ 234 | 96347C0C14D32B87008AFCBC /* bsreplace */ = { 235 | isa = PBXNativeTarget; 236 | buildConfigurationList = 96347C1B14D32B87008AFCBC /* Build configuration list for PBXNativeTarget "bsreplace" */; 237 | buildPhases = ( 238 | 96347C0914D32B87008AFCBC /* Sources */, 239 | 96347C0A14D32B87008AFCBC /* Frameworks */, 240 | 96347C0B14D32B87008AFCBC /* CopyFiles */, 241 | ); 242 | buildRules = ( 243 | ); 244 | dependencies = ( 245 | ); 246 | name = bsreplace; 247 | productName = bsreplace; 248 | productReference = 96347C0D14D32B87008AFCBC /* bsreplace */; 249 | productType = "com.apple.product-type.tool"; 250 | }; 251 | 96ED088A13DDB3EE006C6B6A /* bsdiff */ = { 252 | isa = PBXNativeTarget; 253 | buildConfigurationList = 96ED089313DDB3EE006C6B6A /* Build configuration list for PBXNativeTarget "bsdiff" */; 254 | buildPhases = ( 255 | 96ED088713DDB3EE006C6B6A /* Sources */, 256 | 96ED088813DDB3EE006C6B6A /* Frameworks */, 257 | 96ED088913DDB3EE006C6B6A /* CopyFiles */, 258 | ); 259 | buildRules = ( 260 | ); 261 | dependencies = ( 262 | ); 263 | name = bsdiff; 264 | productName = bsdiff; 265 | productReference = 96ED088B13DDB3EE006C6B6A /* bsdiff */; 266 | productType = "com.apple.product-type.tool"; 267 | }; 268 | 96ED089913DDB401006C6B6A /* bspatch */ = { 269 | isa = PBXNativeTarget; 270 | buildConfigurationList = 96ED08A113DDB401006C6B6A /* Build configuration list for PBXNativeTarget "bspatch" */; 271 | buildPhases = ( 272 | 96ED089613DDB401006C6B6A /* Sources */, 273 | 96ED089713DDB401006C6B6A /* Frameworks */, 274 | 96ED089813DDB401006C6B6A /* CopyFiles */, 275 | ); 276 | buildRules = ( 277 | ); 278 | dependencies = ( 279 | ); 280 | name = bspatch; 281 | productName = bspatch; 282 | productReference = 96ED089A13DDB401006C6B6A /* bspatch */; 283 | productType = "com.apple.product-type.tool"; 284 | }; 285 | /* End PBXNativeTarget section */ 286 | 287 | /* Begin PBXProject section */ 288 | 96ED088013DDB3C0006C6B6A /* Project object */ = { 289 | isa = PBXProject; 290 | attributes = { 291 | LastUpgradeCheck = 0420; 292 | }; 293 | buildConfigurationList = 96ED088313DDB3C0006C6B6A /* Build configuration list for PBXProject "bsdiff" */; 294 | compatibilityVersion = "Xcode 3.2"; 295 | developmentRegion = English; 296 | hasScannedForEncodings = 0; 297 | knownRegions = ( 298 | en, 299 | ); 300 | mainGroup = 96ED087E13DDB3C0006C6B6A; 301 | productRefGroup = 96ED088C13DDB3EE006C6B6A /* Products */; 302 | projectDirPath = ""; 303 | projectRoot = ""; 304 | targets = ( 305 | 96ED088A13DDB3EE006C6B6A /* bsdiff */, 306 | 96ED089913DDB401006C6B6A /* bspatch */, 307 | 96347C0C14D32B87008AFCBC /* bsreplace */, 308 | 96ED08B413DDB9FB006C6B6A /* all */, 309 | ); 310 | }; 311 | /* End PBXProject section */ 312 | 313 | /* Begin PBXSourcesBuildPhase section */ 314 | 96347C0914D32B87008AFCBC /* Sources */ = { 315 | isa = PBXSourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | 96347C1414D32B87008AFCBC /* bsreplace.m in Sources */, 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | }; 322 | 96ED088713DDB3EE006C6B6A /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 96ED089013DDB3EE006C6B6A /* bsdiff.c in Sources */, 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | }; 330 | 96ED089613DDB401006C6B6A /* Sources */ = { 331 | isa = PBXSourcesBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | 96ED089E13DDB401006C6B6A /* bspatch.c in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | /* End PBXSourcesBuildPhase section */ 339 | 340 | /* Begin PBXTargetDependency section */ 341 | 963CCC1714E971D4008228EA /* PBXTargetDependency */ = { 342 | isa = PBXTargetDependency; 343 | target = 96347C0C14D32B87008AFCBC /* bsreplace */; 344 | targetProxy = 963CCC1614E971D4008228EA /* PBXContainerItemProxy */; 345 | }; 346 | 96ED08B913DDBA0A006C6B6A /* PBXTargetDependency */ = { 347 | isa = PBXTargetDependency; 348 | target = 96ED088A13DDB3EE006C6B6A /* bsdiff */; 349 | targetProxy = 96ED08B813DDBA0A006C6B6A /* PBXContainerItemProxy */; 350 | }; 351 | 96ED08BB13DDBA0A006C6B6A /* PBXTargetDependency */ = { 352 | isa = PBXTargetDependency; 353 | target = 96ED089913DDB401006C6B6A /* bspatch */; 354 | targetProxy = 96ED08BA13DDBA0A006C6B6A /* PBXContainerItemProxy */; 355 | }; 356 | /* End PBXTargetDependency section */ 357 | 358 | /* Begin XCBuildConfiguration section */ 359 | 96347C1914D32B87008AFCBC /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ALWAYS_SEARCH_USER_PATHS = NO; 363 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 364 | COPY_PHASE_STRIP = NO; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 370 | GCC_PREFIX_HEADER = "bsreplace/bsreplace-Prefix.pch"; 371 | GCC_PREPROCESSOR_DEFINITIONS = ( 372 | "DEBUG=1", 373 | "$(inherited)", 374 | ); 375 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 378 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 379 | GCC_WARN_UNUSED_VARIABLE = YES; 380 | MACOSX_DEPLOYMENT_TARGET = 10.7; 381 | ONLY_ACTIVE_ARCH = YES; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | SDKROOT = macosx; 384 | }; 385 | name = Debug; 386 | }; 387 | 96347C1A14D32B87008AFCBC /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ALWAYS_SEARCH_USER_PATHS = NO; 391 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 392 | COPY_PHASE_STRIP = YES; 393 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 394 | GCC_C_LANGUAGE_STANDARD = gnu99; 395 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 396 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 397 | GCC_PREFIX_HEADER = "bsreplace/bsreplace-Prefix.pch"; 398 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 399 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 400 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 401 | GCC_WARN_UNUSED_VARIABLE = YES; 402 | MACOSX_DEPLOYMENT_TARGET = 10.7; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SDKROOT = macosx; 405 | }; 406 | name = Release; 407 | }; 408 | 96ED088513DDB3C0006C6B6A /* Debug */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 412 | }; 413 | name = Debug; 414 | }; 415 | 96ED088613DDB3C0006C6B6A /* Release */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 419 | }; 420 | name = Release; 421 | }; 422 | 96ED089413DDB3EE006C6B6A /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ALWAYS_SEARCH_USER_PATHS = NO; 426 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 427 | COPY_PHASE_STRIP = NO; 428 | GCC_C_LANGUAGE_STANDARD = gnu99; 429 | GCC_DYNAMIC_NO_PIC = NO; 430 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 431 | GCC_OPTIMIZATION_LEVEL = 0; 432 | GCC_PREPROCESSOR_DEFINITIONS = ( 433 | "DEBUG=1", 434 | "$(inherited)", 435 | ); 436 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 437 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 438 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 439 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 441 | GCC_WARN_UNUSED_VARIABLE = YES; 442 | MACOSX_DEPLOYMENT_TARGET = 10.7; 443 | ONLY_ACTIVE_ARCH = YES; 444 | PRODUCT_NAME = "$(TARGET_NAME)"; 445 | SDKROOT = macosx; 446 | }; 447 | name = Debug; 448 | }; 449 | 96ED089513DDB3EE006C6B6A /* Release */ = { 450 | isa = XCBuildConfiguration; 451 | buildSettings = { 452 | ALWAYS_SEARCH_USER_PATHS = NO; 453 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 454 | COPY_PHASE_STRIP = YES; 455 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 456 | GCC_C_LANGUAGE_STANDARD = gnu99; 457 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 458 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 460 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 461 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 462 | GCC_WARN_UNUSED_VARIABLE = YES; 463 | MACOSX_DEPLOYMENT_TARGET = 10.7; 464 | PRODUCT_NAME = "$(TARGET_NAME)"; 465 | SDKROOT = macosx; 466 | }; 467 | name = Release; 468 | }; 469 | 96ED08A213DDB401006C6B6A /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_SEARCH_USER_PATHS = NO; 473 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 474 | COPY_PHASE_STRIP = NO; 475 | GCC_C_LANGUAGE_STANDARD = gnu99; 476 | GCC_DYNAMIC_NO_PIC = NO; 477 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 478 | GCC_OPTIMIZATION_LEVEL = 0; 479 | GCC_PREPROCESSOR_DEFINITIONS = ( 480 | "DEBUG=1", 481 | "$(inherited)", 482 | ); 483 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 484 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 487 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 488 | GCC_WARN_UNUSED_VARIABLE = YES; 489 | MACOSX_DEPLOYMENT_TARGET = 10.7; 490 | ONLY_ACTIVE_ARCH = YES; 491 | PRODUCT_NAME = "$(TARGET_NAME)"; 492 | SDKROOT = macosx; 493 | }; 494 | name = Debug; 495 | }; 496 | 96ED08A313DDB401006C6B6A /* Release */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | ALWAYS_SEARCH_USER_PATHS = NO; 500 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 501 | COPY_PHASE_STRIP = YES; 502 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 505 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 506 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 507 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 508 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 509 | GCC_WARN_UNUSED_VARIABLE = YES; 510 | MACOSX_DEPLOYMENT_TARGET = 10.7; 511 | PRODUCT_NAME = "$(TARGET_NAME)"; 512 | SDKROOT = macosx; 513 | }; 514 | name = Release; 515 | }; 516 | 96ED08B613DDB9FB006C6B6A /* Debug */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | PRODUCT_NAME = "$(TARGET_NAME)"; 520 | }; 521 | name = Debug; 522 | }; 523 | 96ED08B713DDB9FB006C6B6A /* Release */ = { 524 | isa = XCBuildConfiguration; 525 | buildSettings = { 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | }; 528 | name = Release; 529 | }; 530 | /* End XCBuildConfiguration section */ 531 | 532 | /* Begin XCConfigurationList section */ 533 | 96347C1B14D32B87008AFCBC /* Build configuration list for PBXNativeTarget "bsreplace" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 96347C1914D32B87008AFCBC /* Debug */, 537 | 96347C1A14D32B87008AFCBC /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | 96ED088313DDB3C0006C6B6A /* Build configuration list for PBXProject "bsdiff" */ = { 543 | isa = XCConfigurationList; 544 | buildConfigurations = ( 545 | 96ED088513DDB3C0006C6B6A /* Debug */, 546 | 96ED088613DDB3C0006C6B6A /* Release */, 547 | ); 548 | defaultConfigurationIsVisible = 0; 549 | defaultConfigurationName = Release; 550 | }; 551 | 96ED089313DDB3EE006C6B6A /* Build configuration list for PBXNativeTarget "bsdiff" */ = { 552 | isa = XCConfigurationList; 553 | buildConfigurations = ( 554 | 96ED089413DDB3EE006C6B6A /* Debug */, 555 | 96ED089513DDB3EE006C6B6A /* Release */, 556 | ); 557 | defaultConfigurationIsVisible = 0; 558 | defaultConfigurationName = Release; 559 | }; 560 | 96ED08A113DDB401006C6B6A /* Build configuration list for PBXNativeTarget "bspatch" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | 96ED08A213DDB401006C6B6A /* Debug */, 564 | 96ED08A313DDB401006C6B6A /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | 96ED08B513DDB9FB006C6B6A /* Build configuration list for PBXAggregateTarget "all" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 96ED08B613DDB9FB006C6B6A /* Debug */, 573 | 96ED08B713DDB9FB006C6B6A /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | /* End XCConfigurationList section */ 579 | }; 580 | rootObject = 96ED088013DDB3C0006C6B6A /* Project object */; 581 | } 582 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/xcshareddata/xcschemes/bsdiff distro.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 49 | 50 | 52 | 53 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/xcshareddata/xcschemes/bsdiff.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/xcshareddata/xcschemes/bspatch.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /bsdiff.xcodeproj/xcshareddata/xcschemes/bsreplace.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /bsdiff/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD: src/usr.bin/bsdiff/bsdiff/Makefile,v 1.1.2.1 2005/08/15 18:34:21 cperciva Exp $ 2 | 3 | PROG= bsdiff 4 | 5 | DPADD= ${LIBBZ2} 6 | LDADD= -lbz2 7 | 8 | .include 9 | -------------------------------------------------------------------------------- /bsdiff/bsdiff.1: -------------------------------------------------------------------------------- 1 | .\"- 2 | .\" Copyright 2003-2005 Colin Percival 3 | .\" All rights reserved 4 | .\" 5 | .\" Redistribution and use in source and binary forms, with or without 6 | .\" modification, are permitted providing that the following conditions 7 | .\" are met: 8 | .\" 1. Redistributions of source code must retain the above copyright 9 | .\" notice, this list of conditions and the following disclaimer. 10 | .\" 2. Redistributions in binary form must reproduce the above copyright 11 | .\" notice, this list of conditions and the following disclaimer in the 12 | .\" documentation and/or other materials provided with the distribution. 13 | .\" 14 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 | .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 | .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 | .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | .\" POSSIBILITY OF SUCH DAMAGE. 25 | .\" 26 | .\" $FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.1,v 1.1.2.1 2005/08/15 18:34:21 cperciva Exp $ 27 | .\" 28 | .Dd May 18, 2003 29 | .Dt BSDIFF 1 30 | .Os FreeBSD 31 | .Sh NAME 32 | .Nm bsdiff 33 | .Nd generate a patch between two binary files 34 | .Sh SYNOPSIS 35 | .Nm 36 | .Ao Ar oldfile Ac Ao Ar newfile Ac Ao Ar patchfile Ac 37 | .Sh DESCRIPTION 38 | .Nm 39 | compares 40 | .Ao Ar oldfile Ac 41 | to 42 | .Ao Ar newfile Ac 43 | and writes to 44 | .Ao Ar patchfile Ac 45 | a binary patch suitable for use by bspatch(1). 46 | When 47 | .Ao Ar oldfile Ac 48 | and 49 | .Ao Ar newfile Ac 50 | are two versions of an executable program, the 51 | patches produced are on average a factor of five smaller 52 | than those produced by any other binary patch tool known 53 | to the author. 54 | .Pp 55 | .Nm 56 | uses memory equal to 17 times the size of 57 | .Ao Ar oldfile Ac , 58 | and requires 59 | an absolute minimum working set size of 8 times the size of oldfile. 60 | .Sh SEE ALSO 61 | .Xr bspatch 1 62 | .Sh AUTHORS 63 | .An Colin Percival Aq cperciva@freebsd.org 64 | -------------------------------------------------------------------------------- /bsdiff/bsdiff.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2003-2005 Colin Percival 3 | * All rights reserved 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted providing that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define MIN(x,y) (((x)<(y)) ? (x) : (y)) 40 | 41 | static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h) 42 | { 43 | off_t i,j,k,x,tmp,jj,kk; 44 | 45 | if(len<16) { 46 | for(k=start;kstart) split(I,V,start,jj-start,h); 95 | 96 | for(i=0;ikk) split(I,V,kk,start+len-kk,h); 100 | } 101 | 102 | static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize) 103 | { 104 | off_t buckets[256]; 105 | off_t i,h,len; 106 | 107 | for(i=0;i<256;i++) buckets[i]=0; 108 | for(i=0;i0;i--) buckets[i]=buckets[i-1]; 111 | buckets[0]=0; 112 | 113 | for(i=0;iy) { 160 | *pos=I[st]; 161 | return x; 162 | } else { 163 | *pos=I[en]; 164 | return y; 165 | } 166 | }; 167 | 168 | x=st+(en-st)/2; 169 | if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) { 170 | return search(I,old,oldsize,new,newsize,x,en,pos); 171 | } else { 172 | return search(I,old,oldsize,new,newsize,st,x,pos); 173 | }; 174 | } 175 | 176 | static void offtout(off_t x,u_char *buf) 177 | { 178 | off_t y; 179 | 180 | if(x<0) y=-x; else y=x; 181 | 182 | buf[0]=y%256;y-=buf[0]; 183 | y=y/256;buf[1]=y%256;y-=buf[1]; 184 | y=y/256;buf[2]=y%256;y-=buf[2]; 185 | y=y/256;buf[3]=y%256;y-=buf[3]; 186 | y=y/256;buf[4]=y%256;y-=buf[4]; 187 | y=y/256;buf[5]=y%256;y-=buf[5]; 188 | y=y/256;buf[6]=y%256;y-=buf[6]; 189 | y=y/256;buf[7]=y%256; 190 | 191 | if(x<0) buf[7]|=0x80; 192 | } 193 | 194 | int main(int argc,char *argv[]) 195 | { 196 | int fd; 197 | u_char *old,*new; 198 | off_t oldsize,newsize; 199 | off_t *I,*V; 200 | off_t scan,pos,len; 201 | off_t lastscan,lastpos,lastoffset; 202 | off_t oldscore,scsc; 203 | off_t s,Sf,lenf,Sb,lenb; 204 | off_t overlap,Ss,lens; 205 | off_t i; 206 | off_t dblen,eblen; 207 | u_char *db,*eb; 208 | u_char buf[8]; 209 | u_char header[32]; 210 | FILE * pf; 211 | BZFILE * pfbz2; 212 | int bz2err; 213 | 214 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); 215 | 216 | /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure 217 | that we never try to malloc(0) and get a NULL pointer */ 218 | if(((fd=open(argv[1],O_RDONLY,0))<0) || 219 | ((oldsize=lseek(fd,0,SEEK_END))==-1) || 220 | ((old=malloc(oldsize+1))==NULL) || 221 | (lseek(fd,0,SEEK_SET)!=0) || 222 | (read(fd,old,oldsize)!=oldsize) || 223 | (close(fd)==-1)) err(1,"%s",argv[1]); 224 | 225 | if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) || 226 | ((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL); 227 | 228 | qsufsort(I,V,old,oldsize); 229 | 230 | free(V); 231 | 232 | /* Allocate newsize+1 bytes instead of newsize bytes to ensure 233 | that we never try to malloc(0) and get a NULL pointer */ 234 | if(((fd=open(argv[2],O_RDONLY,0))<0) || 235 | ((newsize=lseek(fd,0,SEEK_END))==-1) || 236 | ((new=malloc(newsize+1))==NULL) || 237 | (lseek(fd,0,SEEK_SET)!=0) || 238 | (read(fd,new,newsize)!=newsize) || 239 | (close(fd)==-1)) err(1,"%s",argv[2]); 240 | 241 | if(((db=malloc(newsize+1))==NULL) || 242 | ((eb=malloc(newsize+1))==NULL)) err(1,NULL); 243 | dblen=0; 244 | eblen=0; 245 | 246 | /* Create the patch file */ 247 | if ((pf = fopen(argv[3], "w")) == NULL) 248 | err(1, "%s", argv[3]); 249 | 250 | /* Header is 251 | 0 8 "BSDIFF40" 252 | 8 8 length of bzip2ed ctrl block 253 | 16 8 length of bzip2ed diff block 254 | 24 8 length of new file */ 255 | /* File is 256 | 0 32 Header 257 | 32 ?? Bzip2ed ctrl block 258 | ?? ?? Bzip2ed diff block 259 | ?? ?? Bzip2ed extra block */ 260 | memcpy(header,"BSDIFF40",8); 261 | offtout(0, header + 8); 262 | offtout(0, header + 16); 263 | offtout(newsize, header + 24); 264 | if (fwrite(header, 32, 1, pf) != 1) 265 | err(1, "fwrite(%s)", argv[3]); 266 | 267 | /* Compute the differences, writing ctrl as we go */ 268 | if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) 269 | errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); 270 | scan=0;len=0; 271 | lastscan=0;lastpos=0;lastoffset=0; 272 | while(scanoldscore+8)) break; 286 | 287 | if((scan+lastoffsetSf*2-lenf) { Sf=s; lenf=i; }; 298 | }; 299 | 300 | lenb=0; 301 | if(scan=lastscan+i)&&(pos>=i);i++) { 304 | if(old[pos-i]==new[scan-i]) s++; 305 | if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; 306 | }; 307 | }; 308 | 309 | if(lastscan+lenf>scan-lenb) { 310 | overlap=(lastscan+lenf)-(scan-lenb); 311 | s=0;Ss=0;lens=0; 312 | for(i=0;iSs) { Ss=s; lens=i+1; }; 318 | }; 319 | 320 | lenf+=lens-overlap; 321 | lenb-=lens; 322 | }; 323 | 324 | for(i=0;i 9 | -------------------------------------------------------------------------------- /bspatch/bspatch.1: -------------------------------------------------------------------------------- 1 | .\"- 2 | .\" Copyright 2003-2005 Colin Percival 3 | .\" All rights reserved 4 | .\" 5 | .\" Redistribution and use in source and binary forms, with or without 6 | .\" modification, are permitted providing that the following conditions 7 | .\" are met: 8 | .\" 1. Redistributions of source code must retain the above copyright 9 | .\" notice, this list of conditions and the following disclaimer. 10 | .\" 2. Redistributions in binary form must reproduce the above copyright 11 | .\" notice, this list of conditions and the following disclaimer in the 12 | .\" documentation and/or other materials provided with the distribution. 13 | .\" 14 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 | .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 | .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 | .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | .\" POSSIBILITY OF SUCH DAMAGE. 25 | .\" 26 | .\" $FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.1,v 1.1.2.1 2005/08/15 18:34:21 cperciva Exp $ 27 | .\" 28 | .Dd May 18, 2003 29 | .Dt BSPATCH 1 30 | .Os FreeBSD 31 | .Sh NAME 32 | .Nm bspatch 33 | .Nd apply a patch built with bsdiff(1) 34 | .Sh SYNOPSIS 35 | .Nm 36 | .Ao Ar oldfile Ac Ao Ar newfile Ac Ao Ar patchfile Ac 37 | .Sh DESCRIPTION 38 | .Nm 39 | generates 40 | .Ao Ar newfile Ac 41 | from 42 | .Ao Ar oldfile Ac 43 | and 44 | .Ao Ar patchfile Ac 45 | where 46 | .Ao Ar patchfile Ac 47 | is a binary patch built by bsdiff(1). 48 | .Pp 49 | .Nm 50 | uses memory equal to the size of 51 | .Ao Ar oldfile Ac 52 | plus the size of 53 | .Ao Ar newfile Ac , 54 | but can tolerate a very small working set without a dramatic loss 55 | of performance. 56 | .Sh SEE ALSO 57 | .Xr bsdiff 1 58 | .Sh AUTHORS 59 | .An Colin Percival Aq cperciva@freebsd.org 60 | -------------------------------------------------------------------------------- /bspatch/bspatch.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2003-2005 Colin Percival 3 | * All rights reserved 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted providing that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | typedef unsigned char u_char; 38 | 39 | static off_t offtin(u_char *buf) 40 | { 41 | off_t y; 42 | 43 | y=buf[7]&0x7F; 44 | y=y*256;y+=buf[6]; 45 | y=y*256;y+=buf[5]; 46 | y=y*256;y+=buf[4]; 47 | y=y*256;y+=buf[3]; 48 | y=y*256;y+=buf[2]; 49 | y=y*256;y+=buf[1]; 50 | y=y*256;y+=buf[0]; 51 | 52 | if(buf[7]&0x80) y=-y; 53 | 54 | return y; 55 | } 56 | 57 | int main(int argc,char * argv[]) 58 | { 59 | FILE * f, * cpf, * dpf, * epf; 60 | BZFILE * cpfbz2, * dpfbz2, * epfbz2; 61 | int cbz2err, dbz2err, ebz2err; 62 | int fd; 63 | ssize_t oldsize,newsize; 64 | ssize_t bzctrllen,bzdatalen; 65 | u_char header[32],buf[8]; 66 | u_char *old, *new; 67 | off_t oldpos,newpos; 68 | off_t ctrl[3]; 69 | off_t lenread; 70 | off_t i; 71 | 72 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); 73 | 74 | /* Open patch file */ 75 | if ((f = fopen(argv[3], "r")) == NULL) 76 | err(1, "fopen(%s)", argv[3]); 77 | 78 | /* 79 | File format: 80 | 0 8 "BSDIFF40" 81 | 8 8 X 82 | 16 8 Y 83 | 24 8 sizeof(newfile) 84 | 32 X bzip2(control block) 85 | 32+X Y bzip2(diff block) 86 | 32+X+Y ??? bzip2(extra block) 87 | with control block a set of triples (x,y,z) meaning "add x bytes 88 | from oldfile to x bytes from the diff block; copy y bytes from the 89 | extra block; seek forwards in oldfile by z bytes". 90 | */ 91 | 92 | /* Read header */ 93 | if (fread(header, 1, 32, f) < 32) { 94 | if (feof(f)) 95 | errx(1, "Corrupt patch\n"); 96 | err(1, "fread(%s)", argv[3]); 97 | } 98 | 99 | /* Check for appropriate magic */ 100 | if (memcmp(header, "BSDIFF40", 8) != 0) 101 | errx(1, "Corrupt patch\n"); 102 | 103 | /* Read lengths from header */ 104 | bzctrllen=offtin(header+8); 105 | bzdatalen=offtin(header+16); 106 | newsize=offtin(header+24); 107 | if((bzctrllen<0) || (bzdatalen<0) || (newsize<0)) 108 | errx(1,"Corrupt patch\n"); 109 | 110 | /* Close patch file and re-open it via libbzip2 at the right places */ 111 | if (fclose(f)) 112 | err(1, "fclose(%s)", argv[3]); 113 | if ((cpf = fopen(argv[3], "r")) == NULL) 114 | err(1, "fopen(%s)", argv[3]); 115 | if (fseeko(cpf, 32, SEEK_SET)) 116 | err(1, "fseeko(%s, %lld)", argv[3], 117 | (long long)32); 118 | if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) 119 | errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); 120 | if ((dpf = fopen(argv[3], "r")) == NULL) 121 | err(1, "fopen(%s)", argv[3]); 122 | if (fseeko(dpf, 32 + bzctrllen, SEEK_SET)) 123 | err(1, "fseeko(%s, %lld)", argv[3], 124 | (long long)(32 + bzctrllen)); 125 | if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) 126 | errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); 127 | if ((epf = fopen(argv[3], "r")) == NULL) 128 | err(1, "fopen(%s)", argv[3]); 129 | if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET)) 130 | err(1, "fseeko(%s, %lld)", argv[3], 131 | (long long)(32 + bzctrllen + bzdatalen)); 132 | if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) 133 | errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); 134 | 135 | if(((fd=open(argv[1],O_RDONLY,0))<0) || 136 | ((oldsize=lseek(fd,0,SEEK_END))==-1) || 137 | ((old=malloc(oldsize+1))==NULL) || 138 | (lseek(fd,0,SEEK_SET)!=0) || 139 | (read(fd,old,oldsize)!=oldsize) || 140 | (close(fd)==-1)) err(1,"%s",argv[1]); 141 | if((new=malloc(newsize+1))==NULL) err(1,NULL); 142 | 143 | oldpos=0;newpos=0; 144 | while(newposnewsize) 156 | errx(1,"Corrupt patch\n"); 157 | 158 | /* Read diff string */ 159 | lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); 160 | if ((lenread < ctrl[0]) || 161 | ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) 162 | errx(1, "Corrupt patch\n"); 163 | 164 | /* Add old data to diff string */ 165 | for(i=0;i=0) && (oldpos+inewsize) 175 | errx(1,"Corrupt patch\n"); 176 | 177 | /* Read extra string */ 178 | lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); 179 | if ((lenread < ctrl[1]) || 180 | ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) 181 | errx(1, "Corrupt patch\n"); 182 | 183 | /* Adjust pointers */ 184 | newpos+=ctrl[1]; 185 | oldpos+=ctrl[2]; 186 | }; 187 | 188 | /* Clean up the bzip2 reads */ 189 | BZ2_bzReadClose(&cbz2err, cpfbz2); 190 | BZ2_bzReadClose(&dbz2err, dpfbz2); 191 | BZ2_bzReadClose(&ebz2err, epfbz2); 192 | if (fclose(cpf) || fclose(dpf) || fclose(epf)) 193 | err(1, "fclose(%s)", argv[3]); 194 | 195 | /* Write the new file */ 196 | if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || 197 | (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) 198 | err(1,"%s",argv[2]); 199 | 200 | free(new); 201 | free(old); 202 | 203 | return 0; 204 | } 205 | -------------------------------------------------------------------------------- /bsreplace/bsreplace-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'bsreplace' target in the 'bsreplace' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /bsreplace/bsreplace.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd 1/27/2012 7 | .Dt bsreplace 1 8 | .Os Darwin 9 | .Sh NAME 10 | .Nm bsreplace 11 | .Nd Insert, overwrite, or find-and-replace bytes. 12 | .Sh SYNOPSIS 13 | .Nm 14 | .Op Fl r \" allow resize 15 | .Op Fl m \" allow multiple 16 | .Op Fl i Ar offset bytes 17 | .Op Fl s Ar offset bytes 18 | .Op Fl f Ar old_bytes new_bytes 19 | .Op Fl o Ar outfile 20 | .Ar file 21 | .Sh DESCRIPTION 22 | Insert, overwrite, or find-and-replace bytes. By default, find-and-replace requires 23 | the search bytes to be unique and the counts of the search and the replacement bytes 24 | must be equal. Inserting implies the size will change; overwriting implies the 25 | size will not change. 26 | .Pp 27 | A list of flags and their descriptions: 28 | .Bl -tag -width -indent 29 | .It Fl r 30 | Allow resizing. 31 | .It Fl m 32 | Allow multiple occurrences to be be replaced. 33 | .It Fl i Ar offset bytes 34 | Inserts bytes at offset bytes from the beginning of the file. 35 | .It Fl s Ar offset bytes 36 | Substitute bytes beginning at the file offset with "bytes". 37 | .It Fl f Ar old_bytes new_bytes 38 | Find "old_bytes" and replace with "new_bytes". 39 | .It Fl o Ar outfile 40 | Write the output to outfile instead of overwriting the input file. 41 | .El 42 | .Pp 43 | .Sh SEE ALSO 44 | .Xr bsdiff 1 , 45 | .Xr bspatch 1 46 | .\" .Sh BUGS 47 | 48 | .\" .Sh HISTORY \" Document history if command behaves in a unique manner -------------------------------------------------------------------------------- /bsreplace/bsreplace.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // bsreplace 4 | // 5 | // Created on 1/27/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | #include 12 | #include 13 | 14 | #define AllowResizing (1 << 0) 15 | #define AllowMultiples (1 << 1) 16 | 17 | #pragma mark - Categories 18 | 19 | @interface NSObject (NSObjectAdditions) 20 | @property (readonly) const char * UTF8Description; 21 | 22 | - (__strong const char *)UTF8Description; 23 | @end 24 | 25 | @implementation NSObject (NSObjectAdditions) 26 | 27 | - (__strong const char *)UTF8Description { 28 | return [[self description] UTF8String]; 29 | } 30 | @end 31 | 32 | #pragma mark - Prototypes 33 | 34 | /* The hex string format requires each byte have both nibbles. Whitespace 35 | is consumed and does not affect interpretation of low/high nibble. 36 | I.e.: "1 2 3 FFAF EE" is read as 0x12, 0x3f, 0xfa, 0xfe 37 | 38 | Recommended formats are: "01 02 03 FF AF EE" and "010203FFAFEE" 39 | */ 40 | NSData * HexToData(NSString *hex); 41 | 42 | BOOL insert_at_offset(NSMutableData *data, NSNumber *offset, NSData *replacementData); 43 | 44 | BOOL replace_at_offset(NSMutableData *data, NSNumber *offset, NSData *replacementData); 45 | 46 | BOOL find_and_replace(NSMutableData *data, NSData *oldBytes, NSData *newBytes, NSUInteger options); 47 | 48 | NSNumber * parse_offset_arg(NSString *arg); 49 | 50 | NSData * parse_hex_arg(NSString *arg); 51 | 52 | void print_usage(FILE *outfile, const char *progname); 53 | 54 | void exit_usage(NSString *progname, int status); 55 | 56 | #pragma mark - Declarations 57 | 58 | NSData *HexToData(NSString *hexString) { 59 | 60 | const char *hexBytes = [hexString UTF8String]; 61 | NSUInteger hexCount = strlen(hexBytes); 62 | 63 | NSMutableData *data = [NSMutableData dataWithLength:hexCount]; 64 | uint8_t *bytes = [data mutableBytes]; 65 | 66 | uint8_t x = 0; // nibble value 67 | NSUInteger i, j; 68 | BOOL hiNibble = YES; 69 | 70 | for (i = 0, j = 0; i < hexCount; i++) { 71 | 72 | switch (hexBytes[i]) { 73 | case '0': x = 0; break; 74 | case '1': x = 1; break; 75 | case '2': x = 2; break; 76 | case '3': x = 3; break; 77 | case '4': x = 4; break; 78 | case '5': x = 5; break; 79 | case '6': x = 6; break; 80 | case '7': x = 7; break; 81 | case '8': x = 8; break; 82 | case '9': x = 9; break; 83 | case 'a': 84 | case 'A': x = 10; break; 85 | case 'b': 86 | case 'B': x = 11; break; 87 | case 'c': 88 | case 'C': x = 12; break; 89 | case 'd': 90 | case 'D': x = 13; break; 91 | case 'e': 92 | case 'E': x = 14; break; 93 | case 'f': 94 | case 'F': x = 15; break; 95 | case ' ': 96 | case '\t': 97 | case '\n': 98 | case '\r': 99 | // interpret the previous nibble as the low-nibble 100 | if (!hiNibble) 101 | bytes[j++] = x; 102 | hiNibble = YES; 103 | continue; 104 | default: 105 | err(EXIT_FAILURE, "invalid char: %c at offset: %ld", hexBytes[i], i); 106 | break; 107 | } 108 | if (hiNibble) { 109 | bytes[j] = (x << 4); 110 | hiNibble = NO; 111 | } 112 | else { 113 | bytes[j] += x; 114 | hiNibble = YES; 115 | j++; 116 | } 117 | } 118 | if (!hiNibble) bytes[j++] = x; 119 | 120 | [data setLength:j]; 121 | 122 | return data; 123 | } 124 | 125 | BOOL insert_at_offset(NSMutableData *data, NSNumber *offsetNumber, NSData *replacementData) { 126 | 127 | NSUInteger offset = [offsetNumber unsignedIntegerValue]; 128 | 129 | NSRange range = NSMakeRange(offset, 0); 130 | 131 | if (offset > data.length) { 132 | warnx("offset %lu exceeds data size, skipping %s", offset, replacementData.UTF8Description); 133 | return NO; 134 | } 135 | [data replaceBytesInRange:range withBytes:replacementData.bytes length:replacementData.length]; 136 | 137 | return YES; 138 | } 139 | 140 | BOOL replace_at_offset(NSMutableData *data, NSNumber *offsetNumber, NSData *replacementData) { 141 | 142 | NSUInteger offset = [offsetNumber unsignedIntegerValue]; 143 | 144 | NSRange range = NSMakeRange(offset, replacementData.length); 145 | 146 | if (NSMaxRange(range) > data.length) { 147 | warnx("new bytes extend beyond data, skipping: data length: %lu, offset: %lu, replacements length: %lu", data.length, offset, replacementData.length); 148 | return NO; 149 | } 150 | 151 | [data replaceBytesInRange:range withBytes:replacementData.bytes length:replacementData.length]; 152 | return YES; 153 | } 154 | 155 | BOOL find_and_replace(NSMutableData *data, NSData *oldBytes, NSData *newBytes, NSUInteger options) { 156 | 157 | BOOL limitToOne = ( (options & AllowMultiples) == 0); 158 | 159 | if ( (options & AllowResizing) == 0 && oldBytes.length != newBytes.length) { 160 | warnx("length of byte array %s differs from %s, skipping...", oldBytes.UTF8Description, newBytes.UTF8Description); 161 | return NO; 162 | } 163 | 164 | // Count occurrences 165 | NSRange found, search; 166 | NSUInteger count; 167 | 168 | search = NSMakeRange(0, data.length); 169 | 170 | for (count = 0; search.location < data.length; count++) { 171 | 172 | found = [data rangeOfData:oldBytes options:0 range:search]; 173 | if (found.location == NSNotFound) 174 | break; 175 | 176 | search = NSMakeRange(NSMaxRange(found), data.length - NSMaxRange(found)); 177 | } 178 | 179 | if ( count == 0 || (limitToOne && count != 1) ) { 180 | warnx("Found %ld occurrences, skipping sequence %s", count, oldBytes.UTF8Description); 181 | return NO; 182 | } 183 | 184 | // Do replacement 185 | search = NSMakeRange(0, data.length); 186 | 187 | while (search.length > newBytes.length) { 188 | 189 | found = [data rangeOfData:oldBytes options:0 range:search]; 190 | 191 | if (found.location == NSNotFound) break; 192 | 193 | [data replaceBytesInRange:found withBytes:newBytes.bytes length:newBytes.length]; 194 | 195 | search.location = found.location + newBytes.length; 196 | search.length = data.length - search.location; 197 | } 198 | 199 | return YES; 200 | } 201 | 202 | NSNumber * parse_offset_arg(NSString *arg) { 203 | 204 | errno = 0; 205 | 206 | long long value = strtoll([arg UTF8String], NULL, 0); 207 | 208 | if (errno) 209 | errx(EXIT_FAILURE, "error converting offset: %s", [arg UTF8String]); 210 | 211 | return [NSNumber numberWithLongLong:value]; 212 | } 213 | 214 | NSData * parse_hex_arg(NSString *arg) { 215 | 216 | NSData *data = HexToData(arg); 217 | 218 | if (!data) 219 | errx(EXIT_FAILURE, "error converting hex: %s", [arg UTF8String]); 220 | 221 | return data; 222 | } 223 | 224 | void print_usage(FILE *outfile, const char * progname) { 225 | 226 | fprintf(outfile, "usage: %s [-m] [-r] [-i offset newbytes] [[-s offset newbytes] | [-f oldbytes newbytes]] [-o outfile] file \n", progname); 227 | fprintf(outfile, " -m allow multiple occurences \n"); 228 | fprintf(outfile, " -o write to outfile instead of modifying file \n"); 229 | fprintf(outfile, " -i insert newbytes at offset (implies allow resizing) \n"); 230 | fprintf(outfile, " -s replace bytes starting at offset \n"); 231 | fprintf(outfile, " -r allow content to be resized \n"); 232 | fprintf(outfile, " -f search for search_bytes, replace with replace_bytes \n"); 233 | } 234 | 235 | void exit_usage(NSString *progname, int status) { 236 | 237 | FILE *outfile = (status == EXIT_SUCCESS) ? stdout : stderr; 238 | 239 | print_usage(outfile, [progname UTF8String]); 240 | 241 | exit(status); 242 | } 243 | 244 | int main (int argc, char * argv[]) { 245 | 246 | NSUInteger options = 0; 247 | NSString *inFile = nil; 248 | NSString *outFile = nil; 249 | 250 | 251 | @autoreleasepool { 252 | 253 | NSError *error; 254 | NSArray *args = [[NSProcessInfo processInfo] arguments]; 255 | NSString *progname = [[args objectAtIndex:0] lastPathComponent]; 256 | NSMutableArray *transforms = [NSMutableArray array]; 257 | 258 | NSCAssert(argc == [args count], @"argc != [arguments count]"); 259 | 260 | for (NSUInteger i = 1; i < argc; i++) { 261 | 262 | NSString *arg = [args objectAtIndex:i]; 263 | 264 | if ([arg isEqual:@"-h"] || [arg isEqual:@"-?"]) { 265 | exit_usage(progname, EXIT_SUCCESS); 266 | } 267 | else if ([arg isEqual:@"-m"]) { 268 | options |= AllowMultiples; 269 | } 270 | else if ([arg isEqual:@"-r"]) { 271 | options |= AllowResizing; 272 | } 273 | else if ([arg isEqual:@"-o"]) { 274 | 275 | if (++i < argc) { 276 | outFile = [args objectAtIndex:i]; 277 | } 278 | else { 279 | warnx("too few arguments for %s", "-o"); 280 | exit_usage(progname, EXIT_FAILURE); 281 | } 282 | } 283 | else if ([arg isEqual:@"-i"] || [arg isEqual:@"-s"]) { 284 | 285 | if ((i + 2) < argc) { 286 | [transforms addObject:arg]; 287 | [transforms addObject: parse_offset_arg( [args objectAtIndex:++i] ) ]; 288 | [transforms addObject: parse_hex_arg( [args objectAtIndex:++i] ) ]; 289 | } 290 | else { 291 | warnx("too few arguments for %s", [arg UTF8String]); 292 | exit_usage(progname, EXIT_FAILURE); 293 | } 294 | } 295 | else if ([arg isEqual:@"-f"]) { 296 | 297 | if ((i + 2) < argc) { 298 | [transforms addObject:arg]; 299 | [transforms addObject: parse_hex_arg( [args objectAtIndex:++i] ) ]; 300 | [transforms addObject: parse_hex_arg( [args objectAtIndex:++i] ) ]; 301 | } 302 | else { 303 | warnx("too few arguments for %s", [arg UTF8String]); 304 | exit_usage(progname, EXIT_FAILURE); 305 | } 306 | } 307 | else { 308 | inFile = arg; 309 | } 310 | } 311 | 312 | if (!inFile) { 313 | warnx("missing input file"); 314 | exit_usage(progname, EXIT_FAILURE); 315 | } 316 | if (!outFile) outFile = inFile; 317 | 318 | NSMutableData *contents = [NSMutableData dataWithContentsOfFile:inFile options:0 error:&error]; 319 | if (!contents) 320 | err(EXIT_FAILURE, "open %s", argv[1]); 321 | 322 | for (NSUInteger j = 0; j < [transforms count]; ) { 323 | 324 | NSString *option = [transforms objectAtIndex:j++]; 325 | id arg1 = [transforms objectAtIndex:j++]; 326 | id arg2 = [transforms objectAtIndex:j++]; 327 | 328 | if ([option isEqual:@"-i"]) { 329 | insert_at_offset(contents, arg1, arg2); 330 | } 331 | else if ([option isEqual:@"-s"]) { 332 | replace_at_offset(contents, arg1, arg2); 333 | } 334 | else if ([option isEqual:@"-f"]) { 335 | find_and_replace(contents, arg1, arg2, options); 336 | } 337 | 338 | } 339 | 340 | if ([contents writeToFile:outFile options:NSDataWritingAtomic error:&error] == NO) 341 | errx(EXIT_FAILURE, "error writing %s: %s", argv[2], [[error localizedDescription] UTF8String]); 342 | 343 | } 344 | return EXIT_SUCCESS; 345 | } 346 | 347 | --------------------------------------------------------------------------------