#include <unistd.h>
#include <sys/time.h>
#include <getopt.h>
+#include <inttypes.h>
#include <brotli/encode.h>
const char *old_file;
const char *new_file;
const char *patch_file;
+ const char *block_count_file;
};
struct data_thread data;
-int Function(int);
+int Function(int, uint64_t *block_count);
#endif
return bytes_read;
}
-int create_patch(const char *old_file, const char *new_file, const char *temp_patch, int offset_oldscore)
+int write_block_count_to_file(const char *block_count_file, uint64_t block_count)
+{
+ FILE *fp = fopen(block_count_file, "w");
+ if (!fp) {
+ fprintf(stderr, "Failed to open %s\n", block_count_file);
+ return -1;
+ }
+
+ const size_t buf_size = 20;
+ char buf[buf_size];
+ snprintf(buf, buf_size, "%ld\n", block_count);
+
+ size_t str_len = strlen(buf);
+
+ int ret = 0;
+ if (fwrite(buf, sizeof(char), str_len, fp) != str_len) {
+ fprintf(stderr, "Failed to write block count to %s\n", block_count_file);
+ ret = -1;
+ }
+
+ if (fclose(fp) != 0) {
+ fprintf(stderr, "Failed to close %s\n", block_count_file);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int create_patch(const char *old_file, const char *new_file, const char *temp_patch, int offset_oldscore, const char *block_count_file)
{
assert(old_file);
assert(new_file);
//BZ2_bzWriteClose(&data.bz2err, data.pfbz2, 0, NULL, NULL);
//if (data.bz2err != BZ_OK)
//errx(1, "BZ2_bzWriteClose, bz2err = %d", data.bz2err);
-
- int ret = Function(offset_oldscore);
+ uint64_t block_count;
+ int ret = Function(offset_oldscore, &block_count);
#ifdef TIME_LIMIT_CHECK
if (ret != 0) {
printf("bsdiff fails to create delta with offset score %d\n", offset_oldscore);
free(data.old);
free(data.new);
+ if (block_count_file) {
+ ret = write_block_count_to_file(block_count_file, block_count);
+ }
+
return ret;
}
-int Function(int offset_oldscore)
+int Function(int offset_oldscore, uint64_t *block_count)
{
unsigned int thread_num = 0;
off_t end;
get_time_stamp(); //total time capturing
t1 = atoi(ts1);
+ *block_count = 0;
+
#ifdef PATCH_FILE_FORMAT_MOD
u_char* db;
u_char* eb;
lastscan = scan - lenb;
lastpos = pos - lenb;
lastoffset = pos - scan;
+
+ (*block_count)++;
};
};
return 0;
void print_help(const char *arg0)
{
assert(arg0);
- errx(1, "ss_bsdiff\nUsage: %s oldfile newfile patchfile\n", arg0);
+ errx(1, "ss_bsdiff\nUsage: %s oldfile newfile patchfile block_count_file\nblock_count_file is optional\n", arg0);
}
int parse_args(struct bsdiff_info *info, int argc, char *argv[])
assert(info);
assert(argv);
- if (3 >= argc) {
+ if (argc < 4) {
err(1, "Not enough parameters");
- print_help(argv[0]);
- return -1;
+ goto invalid_args;
+ } else if (argc > 5) {
+ err(1, "Too many parameters");
+ goto invalid_args;
}
info->old_file = argv[1];
info->new_file = argv[2];
info->patch_file = argv[3];
+ if (argc == 5) {
+ info->block_count_file = argv[4];
+ } else {
+ info->block_count_file = NULL;
+ }
+
return 0;
+
+invalid_args:
+ print_help(argv[0]);
+ return -1;
}
int main(int argc, char *argv[])
if (parse_args(&info, argc, argv) != 0)
return 1;
- int ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, 8);
+ int ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, 8, info.block_count_file);
#ifdef TIME_LIMIT_CHECK
if (ret != 0) {
/*
*/
int score = 4;
printf("Trying with offset score %d\n", score);
- ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, score);
+ ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, score, info.block_count_file);
}
if (ret != 0) {
if (remove(TEMP_PATCH_NAME) < 0)
PARENT_DIR = ".."
MEM_REQ = 0
MEM_FILE = "NULL"
+TEMP_BLOCK_COUNT_FILE="temp_block_count.txt"
SUPPORT_RENAME = "TRUE"
patchLoc = '%s/%s' % (args.OUT_DIR, DELTA)
logging.info('Make DELTA_IMAGE type delta %s <--> %s ==> %s %s' % (args.BASE_OLD, args.BASE_NEW, args.PART_NAME, patchLoc))
- subprocess.call([DIFF_UTIL, args.BASE_OLD, args.BASE_NEW, patchLoc])
+ if args.UPDATE_PROGRESS_INFO_PATH:
+ subprocess.call([DIFF_UTIL, args.BASE_OLD, args.BASE_NEW, patchLoc, TEMP_BLOCK_COUNT_FILE])
+
+ with open(TEMP_BLOCK_COUNT_FILE, 'r') as f:
+ read_string = f.readline().strip()
+ try:
+ block_count = int(read_string)
+ except (TypeError, ValueError) as exc:
+ logging.error('Failed to get block count from %s' % (TEMP_BLOCK_COUNT_FILE))
+ raise exc
+
+ os.remove(TEMP_BLOCK_COUNT_FILE)
+
+ if block_count != 0:
+ if not os.path.isdir(os.path.dirname(args.UPDATE_PROGRESS_INFO_PATH)):
+ logging.log('Unable to write to %s. Parent directory does not exist' % (args.UPDATE_PROGRESS_INFO_PATH))
+ raise OSError
+ with open(args.UPDATE_PROGRESS_INFO_PATH, 'a') as f:
+ f.write(f'{DELTA}={block_count}\n')
+ else:
+ subprocess.call([DIFF_UTIL, args.BASE_OLD, args.BASE_NEW, patchLoc])
def generate_full_image(args):
logging.info('Make FULL_IMAGE type delta %s <--> %s ==> %s' % (args.BASE_OLD, args.BASE_NEW, args.PART_NAME))
parser.add_argument('BASE_NEW', type=str, help='newer image path / mount point of the newer version of the partition')
parser.add_argument('OUT_DIR', type=str, help='directory where generated delta nad logs will be placed')
parser.add_argument('UPDATE_CFG_PATH', type=str, help='path to config file which will be updated')
+ parser.add_argument('--update_progress_info_path', type=str, dest='UPDATE_PROGRESS_INFO_PATH', required=False,
+ help='path to file which will include data needed for upgrade progress reporting (only DETA_IMG supported)')
parser.add_argument('--attr_old', type=str, dest='ATTR_OLD', help='path to old attribute file')
parser.add_argument('--attr_new', type=str, dest='ATTR_NEW', help='path to new attribute file')
args.UPDATE_CFG_PATH = os.path.join(PARENT_DIR, args.UPDATE_CFG_PATH)
+ if args.UPDATE_PROGRESS_INFO_PATH:
+ args.UPDATE_PROGRESS_INFO_PATH = os.path.join(PARENT_DIR, args.UPDATE_PROGRESS_INFO_PATH)
+
if not (os.path.isfile(DIFF_UTIL) and os.access(DIFF_UTIL, os.X_OK)):
DIFF_UTIL = os.path.join(COMMON_BIN_PATH, DIFF_UTIL_NAME)
if not (os.path.isfile(DIFF_UTIL) and os.access(DIFF_UTIL, os.X_OK)):
UPDATE_CFG_PATH=./cfg/update.cfg
UPDATE_INFO_FILE=update-info.ini
UPDATE_INFO_PATH=./${UPDATE_INFO_FILE}
+ UPDATE_PROGRESS_INFO_FILE="update-progress-info.ini"
+ UPDATE_PROGRESS_INFO_PATH=./${UPDATE_PROGRESS_INFO_FILE}
SETUP_SCRIPT_PATH=./cfg/setup.sh
UPDATE_MANAGER=./data/upgrade-trigger.sh
UPDATE_INFO_BUILDER="update-info-builder.py"
cp ${UPDATE_CFG_PATH} ${DELTA_DIR}/update.cfg
rm ${UPDATE_CFG_PATH}
fi
+
+ if [ -r ${UPDATE_PROGRESS_INFO_PATH} ]; then
+ sudo cp ${UPDATE_PROGRESS_INFO_PATH} ${DELTA_DIR}/${UPDATE_PROGRESS_INFO_FILE}
+ sudo rm ${UPDATE_PROGRESS_INFO_PATH}
+ fi
+
if [ -r ${LOG_PATH} ]; then
cp ${LOG_PATH} ${RESULT_DIR}/Delta.log
rm ${LOG_PATH}
#---- make delta file ----
echo "make ${DELTA}"
- python3 ${COMMON_BINDIR}/CreatePatch.py ${UPDATE_TYPE} ${PART_NAME} ${PART_IMG_OLD} ${PART_IMG_NEW} ${OUTPUT_DIR} ${UPDATE_CFG_PATH}
+ python3 ${COMMON_BINDIR}/CreatePatch.py ${UPDATE_TYPE} ${PART_NAME} ${PART_IMG_OLD} ${PART_IMG_NEW} \
+ ${OUTPUT_DIR} ${UPDATE_CFG_PATH} --update_progress_info_path ${UPDATE_PROGRESS_INFO_PATH}
PythonRet=$?
- #xdelta delta ${PART_IMG_OLD} ${PART_IMG_NEW} ./${OUTPUT_DIR}/${PART_NAME}".delta"
#---- remove files & directories ----
echo "remove temp files/directory & move delta/log to result directory"
#XML_DIR=./xml
COMMON_BINDIR=${CUR_DIR}/../common/bin
UPDATE_CFG_PATH=./cfg/update.cfg
+UPDATE_PROGRESS_INFO_PATH=./update-progress-info.ini
#--- check if the current working directory is the parent directory of bin, data, cfg, xml ---
TEST_DIR=${DATA_DIR}