Example #1
0
bool BSDiff::Patch(char8 *origData, uint32 origSize, char8 *newData, uint32 newSize, File *patchFile)
{
    bool ret = false;
    ZLibIStream inStream(patchFile);

    // read BS type
    uint32 typeToRead = -1;
    patchFile->Read(&typeToRead);

    bspatch_stream patchStream;
    patchStream.read = &BSDiff::BSRead;
    patchStream.type = (BSType) typeToRead;

    switch(typeToRead)
    {
        case BS_ZLIB:
            patchStream.opaque = &inStream;
            break;
        case BS_PLAIN:
            patchStream.opaque = patchFile;
            break;
        default:
            DVASSERT(0 && "Unknow BS-type");
            break;
    }

    // apply bsdiff
    if(0 == bspatch((uint8_t *) origData, origSize, (uint8_t *) newData, newSize, &patchStream))
    {
        ret = true;
    }

    return ret;
}
JNIEXPORT jbyteArray JNICALL Java_cn_reactnative_modules_update_DownloadTask_bsdiffPatch
        (JNIEnv *env, jobject self, jbyteArray origin, jbyteArray patch){
    jclass newExcCls;
    jbyte* outPtr;
    struct bspatch_stream stream;
    bz_stream zip;

    jbyte* originPtr = (*env)->GetByteArrayElements(env, origin, NULL);
    size_t originLength = (*env)->GetArrayLength(env, origin);
    jbyte* patchPtr = (*env)->GetByteArrayElements(env, patch, NULL);
    size_t patchLength = (*env)->GetArrayLength(env, patch);
    jbyteArray ret = NULL;

    if (patchLength < 32) {
        newExcCls = (*env)->FindClass(env,"java/lang/Error");
        if (newExcCls != NULL) /* Unable to find the new exception class, give up. */
            (*env)->ThrowNew(env,newExcCls, "Corrupt patch");
        (*env)->ReleaseByteArrayElements(env, origin, originPtr, JNI_ABORT);
        (*env)->ReleaseByteArrayElements(env, patch, patchPtr, JNI_ABORT);
        return NULL;
    }
    int64_t newsize=offtin((uint8_t*)patchPtr + 16);
    if (memcmp(patchPtr, "ENDSLEY/BSDIFF43", 16) != 0 || newsize<0) {
        newExcCls = (*env)->FindClass(env, "java/lang/Error");
        if (newExcCls != NULL) /* Unable to find the new exception class, give up. */
            (*env)->ThrowNew(env, newExcCls, "Corrupt patch");
        (*env)->ReleaseByteArrayElements(env, origin, originPtr, JNI_ABORT);
        (*env)->ReleaseByteArrayElements(env, patch, patchPtr, JNI_ABORT);
        return NULL;
    }
    ret = (*env)->NewByteArray(env, newsize);
    if (ret == NULL) {
        return NULL; //  out of memory error thrown
    }
    outPtr = (*env)->GetByteArrayElements(env, ret, NULL);

    zip.bzalloc = NULL;
    zip.bzfree = NULL;
    zip.opaque = NULL;
    BZ2_bzDecompressInit(&zip, 0, 1);

    zip.next_in = (char*)patchPtr + 32;
    zip.avail_in = patchLength - 32;

    stream.read = bz2_read;
    stream.opaque = &zip;
    if (bspatch((const uint8_t*)originPtr, originLength, (uint8_t*)outPtr, newsize, &stream)) {
        newExcCls = (*env)->FindClass(env, "java/lang/Error");
        if (newExcCls != NULL) /* Unable to find the new exception class, give up. */
            (*env)->ThrowNew(env, newExcCls, "bspatch");
    }

    BZ2_bzDecompressEnd(&zip);

    (*env)->ReleaseByteArrayElements(env, ret, outPtr, 0);
    (*env)->ReleaseByteArrayElements(env, origin, originPtr, JNI_ABORT);
    (*env)->ReleaseByteArrayElements(env, patch, patchPtr, JNI_ABORT);
    return ret;
}
static gboolean
dispatch_bspatch (OstreeRepo                 *repo,
                  StaticDeltaExecutionState  *state,
                  GCancellable               *cancellable,
                  GError                    **error)
{
  gboolean ret = FALSE;
  guint64 offset, length;
  g_autoptr(GInputStream) in_stream = NULL;
  g_autoptr(GMappedFile) input_mfile = NULL;
  g_autofree guchar *buf = NULL;
  struct bspatch_stream stream;
  struct bzpatch_opaque_s opaque;
  gsize bytes_written;

  if (!read_varuint64 (state, &offset, error))
    goto out;
  if (!read_varuint64 (state, &length, error))
    goto out;

  if (!state->have_obj)
    {
      input_mfile = g_mapped_file_new_from_fd (state->read_source_fd, FALSE, error);
      if (!input_mfile)
        goto out;

      buf = g_malloc0 (state->content_size);

      opaque.state = state;
      opaque.offset = offset;
      opaque.length = length;
      stream.read = bspatch_read;
      stream.opaque = &opaque;
      if (bspatch ((const guint8*)g_mapped_file_get_contents (input_mfile),
                   g_mapped_file_get_length (input_mfile),
                   buf,
                   state->content_size,
                   &stream) < 0)
        goto out;

      if (!g_output_stream_write_all (state->content_out,
                                      buf,
                                      state->content_size,
                                      &bytes_written,
                                      cancellable, error))
        goto out;

      g_assert (bytes_written == state->content_size);
    }

  ret = TRUE;
 out:
  return ret;
}
jstring Java_com_jackwang_patchapk_PatchJNI_bspatch(JNIEnv* env, jobject thiz,
		jstring oldFilePath, jstring newFilePath, jstring patchFilePath) {

	const char* oldFilePathChar = (*env)->GetStringUTFChars(env, oldFilePath, 0);
	const char* newFilePathChar = (*env)->GetStringUTFChars(env, newFilePath, 0);
	const char* patchFilePathChar = (*env)->GetStringUTFChars(env, patchFilePath, 0);

	LOGI("oldFilePath = %s", oldFilePathChar);
	LOGI("newFilePath = %s", newFilePathChar);
	LOGI("patchFilePath = %s", patchFilePathChar);

	bspatch(oldFilePathChar, newFilePathChar, patchFilePathChar);
	//releaseString
	(*env)->ReleaseStringUTFChars(env, oldFilePath, oldFilePathChar);
	(*env)->ReleaseStringUTFChars(env, newFilePath, newFilePathChar);
	(*env)->ReleaseStringUTFChars(env, patchFilePath, patchFilePathChar);

	return (*env)->NewStringUTF(env, "patch success");
}
Example #5
0
bool ApplyPatch(const char* patch_file, const char* path)
{
	FILE* patch = fopen(patch_file, "rb");
	int bzerror;
	FILE* tmp_file = NULL;
	FILE* src_file = NULL;
	BZFILE* bzs = NULL;
	BZFILE* bzf = NULL;

	if(!patch)
	{
		goto error;
	}

	char header[16];
	fread(header, 1, 16, patch);
	if(memcmp(header, "JPATCH10", 8)!=0)
	{
		goto error;
	}
	unsigned int ctrl_offset = (unsigned int)(*((unsigned int*)(header+8 )));
	unsigned int data_offset = (unsigned int)(*((unsigned int*)(header+12)));

	bzs = NULL;
	bzf = BZ2_bzReadOpen(&bzerror, patch, 0, 0, NULL, 0);
	if(!bzf)
	{
		goto error;
	}

	for(;;)
	{
		unsigned short len;
		char fname[500], src_md5[60], dst_md5[60];
		BZ2_bzRead(&bzerror, bzf, &len, sizeof(len));
		if(bzerror!=BZ_OK)
		{
			goto error;
		}
		BZ2_bzRead(&bzerror, bzf, &fname, len);
		if(bzerror!=BZ_OK)
		{
			if(bzerror==BZ_STREAM_END)
			{
				break;
			}
			else
			{
				goto error;
			}
		}
		fname[len] = '\0';

		BZ2_bzRead(&bzerror, bzf, &len, sizeof(len));
		if(bzerror!=BZ_OK)
		{
			goto error;
		}
		if(len>=sizeof(src_md5))
		{
			goto error;
		}
		BZ2_bzRead(&bzerror, bzf, &src_md5, len);
		if(bzerror!=BZ_OK)
		{
			goto error;
		}
		src_md5[len] = '\0';

		BZ2_bzRead(&bzerror, bzf, &len, sizeof(len));
		if(bzerror!=BZ_OK)
		{
			goto error;
		}
		if(len>=sizeof(dst_md5))
		{
			goto error;
		}
		BZ2_bzRead(&bzerror, bzf, &dst_md5, len);
		if(bzerror!=BZ_OK)
		{
			goto error;
		}
		dst_md5[len] = '\0';

		char dst_filename[400];
		sprintf(dst_filename, "%s%s", path, fname);
		char tmp_filename[400];
		sprintf(tmp_filename, "%s.tmp", dst_filename);
		bool skip = false;

		src_file = fopen(dst_filename, "rb");
		if(src_file)
		{
			char md5[60];
			if(!GetMD5(src_file, md5))
			{
				goto error;
			}
			if(strcmp(md5, dst_md5)==0)
			{
				skip = true;
			}
			else
			{
				if(src_md5[0]!='\0' && strcmp(md5, src_md5)!=0)
				{
					goto error;
				}
			}
		}
		else
		{
			if(src_md5[0]!='\0')
			{
				goto error;
			}
			MakeDir_P(tmp_filename);
			tmp_file = fopen(tmp_filename, "wb");
			if(!tmp_file)
			{
				goto error;
			}
		}

		for(;;)
		{
			unsigned char code;
			BZ2_bzRead(&bzerror, bzf, &code, sizeof(code));
			if(bzerror!=BZ_OK)
			{
				goto error;
			}
			if(code==OPERATOR_END)
				break;

			if(code==OPERATOR_APPEND)
			{
				printf("%s\n", fname);
				unsigned int size, offset;
				BZ2_bzRead(&bzerror, bzf, &size, sizeof(size));
				if(bzerror!=BZ_OK)
				{
					goto error;
				}
				BZ2_bzRead(&bzerror, bzf, &offset, sizeof(offset));
				if(bzerror!=BZ_OK)
				{
					goto error;
				}
				printf("- append %d %d\n", size, offset);

				if(!skip)
				{
					fseek(patch, offset+data_offset, SEEK_SET);
					bzs = BZ2_bzReadOpen(&bzerror, patch, 0, 0, NULL, 0);
					if(!bzs)
					{
						goto error;
					}
					while(size>0)
					{
						char mem[1000];
						size_t rsize = size>sizeof(mem)?sizeof(mem):size;
						BZ2_bzRead(&bzerror, bzs, mem, rsize);
						if(bzerror!=BZ_OK && size!=rsize && bzerror!=BZ_STREAM_END)
						{
							goto error;
						}
						if(fwrite(mem, 1, rsize, tmp_file)!=rsize)
						{
							goto error;
						}
						size -= rsize;
					}
					BZ2_bzReadClose(&bzerror, bzs);
					bzs = NULL;
					if(bzerror!=BZ_OK)
					{
						goto error;
					}
				}
				continue;
			}

			if(code==OPERATOR_PATCH)
			{
				printf("%s\n", fname);
				unsigned int offset, size, patch_offset;
				BZ2_bzRead(&bzerror, bzf, &offset, sizeof(offset));
				if(bzerror!=BZ_OK)
				{
					goto error;
				}
				BZ2_bzRead(&bzerror, bzf, &size, sizeof(size));
				if(bzerror!=BZ_OK)
				{
					goto error;
				}
				BZ2_bzRead(&bzerror, bzf, &patch_offset, sizeof(patch_offset));
				if(bzerror!=BZ_OK)
				{
					goto error;
				}

				if(!skip)
				{
					void* mem;
					mem = ReadFile(src_file, size, offset);
					if(!mem)
					{
						goto error;
					}

					fseek(patch, patch_offset+data_offset, SEEK_SET);
					u_char* newp;
					off_t newsize;
					if(bspatch((u_char*)mem, (off_t)size, patch, &newp, &newsize)!=0)
					{
						free(mem);
						goto error;
					}
					if(fwrite(newp, 1, newsize, tmp_file)!=newsize)
					{
						free(newp);
						free(mem);
						goto error;
					}
					free(newp);
					free(mem);
				}

				continue;
			}

			if(code==OPERATOR_COPY)
			{
				unsigned int size, offset;
				BZ2_bzWrite(&bzerror, bzf, &size, 4);
				if(bzerror!=BZ_OK)
				{
					goto error;
				}
				BZ2_bzWrite(&bzerror, bzf, &offset, 4);
				if(bzerror!=BZ_OK)
				{
					goto error;
				}

				fseek(src_file, offset, SEEK_SET);
				while(size>0)
				{
					char data[10*1024];
					unsigned int s = size;
					if(s>sizeof(data)) s = sizeof(data);
					if(fread(data, 1, s, src_file)!=s)
					{
						goto error;
					}
					if(fwrite(data, 1, s, tmp_file)!=s)
					{
						goto error;
					}
					size -= s;
				}

				continue;
			}

			goto error;
		}

		if(src_file)
		{
			fclose(src_file);
			src_file = NULL;
		}
		fclose(tmp_file);
		tmp_file = NULL;

		if(_unlink(dst_filename)!=0 && errno!=ENOENT)
			goto error;
		if(rename(tmp_filename, dst_filename)!=0)
			goto error;
	}

	BZ2_bzReadClose(&bzerror, bzf);
	fclose(patch);
	return true;

error:
	if(bzs) BZ2_bzReadClose(&bzerror, bzs);
	if(bzf) BZ2_bzReadClose(&bzerror, bzf);
	if(patch) fclose(patch);
	if(tmp_file) fclose(tmp_file);
	if(src_file) fclose(src_file);
	return false;
}
Example #6
0
int main(int argc,char * argv[])
{
	FILE * f;
	int fd;
	int bz2err;
	uint8_t header[24];
	uint8_t *olddata, *newdata;
	int64_t oldsize, newsize;
	BZFILE* bz2;
	struct bspatch_stream stream;

	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);

	/* Open patch file */
	if ((f = fopen(argv[3], "r")) == NULL)
		err(1, "fopen(%s)", argv[3]);

	/* Read header */
	if (fread(header, 1, 16, f) != 16) {
		if (feof(f))
			errx(1, "Corrupt patch\n");
		err(1, "fread(%s)", argv[3]);
	}

	/* Check for appropriate magic */
	if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
		errx(1, "Corrupt patch\n");

	/* Read lengths from header */
	newsize=offtin(header+16)
	if(newsize<0)
		errx(1,"Corrupt patch\n");

	/* Close patch file and re-open it via libbzip2 at the right places */
	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
		((olddata=malloc(oldsize+1))==NULL) ||
		(lseek(fd,0,SEEK_SET)!=0) ||
		(read(fd,olddata,oldsize)!=oldsize) ||
		(close(fd)==-1)) err(1,"%s",argv[1]);
	if((newdata=malloc(newsize+1))==NULL) err(1,NULL);

	if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0)))
		errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err);

	stream.read = bz2_read;
	stream.opaque = bz2;
	if (bspatch(olddata, oldsize, newdata, newsize, &stream))
		errx(1, "bspatch");

	/* Clean up the bzip2 reads */
	BZ2_bzReadClose(&bz2err, bz2);
	fclose(f);

	/* Write the newdata file */
	if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
		(write(fd,newdata,newsize)!=newsize) || (close(fd)==-1))
		err(1,"%s",argv[2]);

	free(newdata);
	free(olddata);

	return 0;
}
Example #7
0
void testPatch(const char *baseFile, const char *variantFile, const char *patchFile) {
    uint8_t *base = NULL;
    size_t baseSize;
    uint8_t *patch = NULL;
    size_t patchSize;

    off_t result;

    FILE *fbase = NULL;
    FILE *fpatch = NULL;
    FILE *fvariant = NULL;

    fbase = fopen(baseFile, "r");

    //get baseSize
    if (fseek(fbase, 0, SEEK_END) != 0) {
        goto fail;
    }
    result = ftello(fbase);
    if (result == -1) {
        goto fail;
    }
    baseSize = (size_t) result;

    // allocate base buffer
    base = (uint8_t *) malloc(baseSize + 1);
    if (fseek(fbase, 0, SEEK_SET) != 0) {
        goto fail;
    }
    fread(base, sizeof(uint8_t), baseSize, fbase);
    fclose(fbase);
    fbase = NULL;

    fpatch = fopen(patchFile, "r");

    if (fpatch == NULL) {
        fprintf(stderr, "Failed to open patch file\n");
        return;
    }

    // get patch size
    if (fseek(fpatch, 0, SEEK_END) != 0) {
        goto fail;
    }
    result = ftello(fpatch);
    if (result == -1) {
        goto fail;
    }
    patchSize = (size_t) result;

    // allocate patch buffer
    patch = (uint8_t *) malloc(patchSize);
    fseek(fpatch, 0, SEEK_SET);
    fread(patch, sizeof(uint8_t), patchSize, fpatch);
    fclose(fpatch);
    fpatch = NULL;

    fvariant = fopen(variantFile, "w");

    PatchStream stream;
    stream.write = writeStream;
    stream.init = initStream;
    stream.end = endStream;
    stream.opaque = fvariant;

    bspatch(base, baseSize, patch, patchSize, &stream);

    fclose(fvariant);
    fvariant = NULL;

    fail:
    if (fbase != NULL) {
        fclose(fbase);
    }
    if (base != NULL) {
        free(base);
    }
    if (patch != NULL) {
        free(patch);
    }
    if (fpatch != NULL) {
        fclose(fpatch);
    }
}