Bsdiff,Bspatch 的差分增量升级(基于Win和Linux)

2023-10-28 11:45

本文主要是介绍Bsdiff,Bspatch 的差分增量升级(基于Win和Linux),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

背景

内容

准备工作

在windows平台上

在linux平台上

正式工作

生成差分文件思路

作用差分文件思路

在保持相同目录结构进行差分增量升级

服务端(生成差分文件)

客户端(作用差分文件)


背景

像常见的Android 的linux平台,游戏,系统更新都会用到这一种方式。

以我自己的理解,这种方式有些像git中的版本管理, 以最少的时间进行版本管理.核心在于如何去记录文件的差异.

服务器端:

通过

 bsdiff  old  new  patchfile_path 

生成差分文件.一般以.patch的文件命名.

客户端: 根据patch文件 通过

bspatch oldfile newfile patchfile_path

一般情况下,本以为可以直接通过压缩包的形式去进行, 安卓平台的.apk文件是可以的,单片机的可执行hex等格式的文件也是可以的. 但通过压缩的压缩包则可能会有隐患. 通过开会讨论以及本人查询资料发现 会因为压缩算法,压缩文件顺序的不一样而导致差分包出现问题.

原因有

主要原因有:

1. 不同的压缩算法会产生不同的压缩数据。即使原始数据相同,通过不同算法压缩结果也不完全一样。这会直接影响bsdiff的比较结果。

2. 即使使用同一压缩算法,压缩文件内原始数据的顺序改变也可能改变压缩效果。压缩算法利用重复模式来达到压缩效果。顺序改变会打乱这种模式。

3. bsdiff是按顺序比较数据生成差分的。所以就算压缩原理数据相同,其在压缩文件中的顺序变化也会导致bsdiff生成不同的差分补丁。

4. 压缩算法本身就利用了字典及顺序来提高压缩率。这与bsdiff的工作原理有一定冲突。综上,为了生成一致的bsdiff补丁,同一个数据生成压缩包时需要保证使用同一算法和稳定的顺序。否则差分结果可能会有较大变化。一般需要压缩数据再差分时,需要注意控制这两个因素,或者考虑在解压后对原始数据文件差分。

所以,考虑解压后保持相同的目录结构进行差分,即为生成的.patch文件和原工程有相同的目录.

所以需要写一个脚本,生成一个差分文件夹(目录),这个差分文件夹与原工程有相同的目录结构.

后面再根据这个差分文件夹进行升级,即为patch文件与原文件作用生成新文件,新目标和原目标相同.通过这种服务器上生成差分包,客户端上作用差分包的形式,差分包可以压缩,在客户端上解压缩,这样能更快更合理.

所以,总共需要有2个bash脚本,一个放服务器上,生成差分包.一个放客户端上,在收到差分包后进行本地升级.

内容

bsdiff和bspatch去官网上截至2023年10月27日没有下载源码的权限,所以得去别的地方找找源码.

准备工作

在windows平台上

参考

whistle713/bsdiff-win: bsdiff Windows binaries and Visual Studio 2015/2019 project. (github.com)

里面有提供能够在windows平台上允许的.exe可执行文件.

在linux平台上

参考

红橙Darren视频笔记 bsdiff bspatch 使用(Linux下)_洌冰的博客-CSDN博客

完成编译

正式工作

这里需要考虑到旧的目标和新的目标的一些特殊情况.

  1. 新目标有新增文件的情况
  2. 新目标有删除原来旧文件的情况
  3. 新目标和旧目标的目录和文件都能对上,只是有变化.
  4. 旧目标和新目标有 大小为0 bytes 文件的情况(bsdiff失效)

相信一般的升级都会遇到 1.2.3.4所有情况,

对于第4种情况,不清楚是不是bsdiff的版本问题还是linux系统的问题,我在本地的liunx没有这个问题.

bsdiff在处理 大小为 0 bytes的文件时在linux上报错

报错

bsdiff:mmap()  xxx:Invalid argument

思路:

对于第一种和第二种情况.

新目标新增: 在旧目标中生成一个相同名字的文件,不过大小为0 bytes

新目标有删除有原来旧文件的情况: 在新目标中生成一个相同名字的文件,大小依然为0bytes

这样的话,只要不出现 4 的这种问题都是能够通过bsdiff 生成相应的bspatch文件的.

生成差分文件思路

1.同步旧目标(对应新目标有文件增加时)

2.同步新目标(对应新目标删除了旧文件时)

3.递归遍历目标中的每一个文件,在另一个目标中进行查找, 可以直接通过bsdiiff 生成差分文件,

即使是两个相同的文件,也会生成patch文件,只不过bspatch 作用这个patch文件时并不会起作用,这样是非常方便了,都不需要进行判断了。这样表现为每一个文件都有对应的差分文件.(这个需要再我的代码上改一改)

而我下面并没有这么做,而是根据md5的值判断文件不同后再生成对应的patch文件.

作用差分文件思路

直接遍历生成的差分文件目录结构,调用bspatch.

在保持相同目录结构进行差分增量升级

服务端(生成差分文件)

调用.

 ./gen.sh(脚本名) ./old(旧目录) ./new (新目录)

最终会生成一个以日期后缀的差分文件的目录(和原目录保持相同的目录结构) 

#!/bin/bash# check if two arguments are given
if [ $# -ne 2 ]; thenecho "Usage: $0 oldfolder newfolder"exit 1
fi# check if the arguments are valid directories
if [ ! -d "$1" ] || [ ! -d "$2" ]; thenecho "Invalid directories"exit 2
fi# create a new directory for patch files
patch_dir="patch_$(date +%Y%m%d%H%M%S)"
mkdir -p "$patch_dir"# sync in new target
find "$1" -type f | while read oldfile; do# get the relative path of the filerel_path=${oldfile#$1/}# get the corresponding file in the second directorynewfile="$2/$rel_path"# exist in old and not exist in new and create same name to instead in the new folder if [ ! -f "$newfile" ]; thenecho -e "\033[0;36m [disapper in new]: $newfile Generate 0 Bytes to instead in new target \033[0m"mkdir -p "$(dirname $newfile)"> $newfile  fidone# sync in old target
find "$2" -type f | while read newfile; do# get the relative path of the filerel_path=${newfile#$2/}# get the corresponding file in the second directoryoldfile="$1/$rel_path"# exist in new and not exist in old and create same name to instead in the old folder if [ ! -f "$oldfile" ]; thenecho -e "\033[0;36m [disapper in old]: $oldfile Generate 0 Bytes to instead in old target  \033[0m"#  create the parent directory if neededmkdir -p "$(dirname oldfile)"> $oldfile  fidone# Generate patch 
find "$1" -type f | while read oldfile; do# get the relative path of the filerel_path=${oldfile#$1/}# get the corresponding file in the second directorynewfile="$2/$rel_path"# Haved sync and create the patch file namepatch_file="$patch_dir/$rel_path.patch"# create the parent directory if neededmkdir -p "$(dirname "$patch_file")"# use bsdiff to generate the patch fileoldmd5=$(md5sum $oldfile | awk '{print $1}')newmd5=$(md5sum $newfile | awk '{print $1}')if [ "$oldmd5" = "$newmd5" ]; thenecho -e "\033[0;32m Don't Need to Change \033[0m"elsebsdiff "$oldfile" "$newfile" "$patch_file"echo -e "\033[0;33mGenerated patch for $rel_path \033[0m"fidoneecho "Done. Patch files are in $patch_dir"

客户端(作用差分文件)

 调用

脚本名 旧目标 新目标(也可以是旧目标 ,相当与替换旧目标) 差分目录
#!/bin/bash# check if two arguments are given
if [ $# -ne 3 ]; thenecho "Usage: cmd  oldfolder newfolder patchfolders"exit 1
fi# new generate 
if [ ! -e "$2" ]; then
mkdir $2
fi# check if the arguments are valid directories
if [ ! -d "$1" ] || [ ! -d "$3" ] ; thenecho "Invalid directories"exit 2
fi#loop item in path_item
find "$3" -type f -name "*.patch" | while read patch_item; dotemp=${patch_item#$3/}temp=${temp%.patch}  #equal to   temp=${temp:0:${#temp}-6}oldfile="$1/$temp"newfile="$2/$temp"mkdir -p "$(dirname "$newfile")"echo -e "\033[0;32m Generate $oldfile $newfile \033[0m"# execute bspatchbspatch "$oldfile" "$newfile" "$patch_item"done

一般调用过程

diff -rq ./old ./new(此时会看到文件差异)./gen ./old ./new./upgrate ./old ./old ./patch_xxx diff -rq ./old ./new (没有输出表示更新升级完毕)

这篇关于Bsdiff,Bspatch 的差分增量升级(基于Win和Linux)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/292992

相关文章

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用