Modify ua.h to ua_types.h for integrating header with tota-ua
[platform/core/system/libtota.git] / ss_engine / SS_PatchDelta.c
1 /*
2  * libtota
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <errno.h>
20 #include <libgen.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/statfs.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include "ua_types.h"
30 #include "sha1.h"
31 #include "SS_PatchDelta.h"
32 #include "fota_common.h"
33 #include "SS_Engine_Errors.h"
34
35 extern void *SS_Malloc(unsigned int size);
36
37 typedef struct {
38         unsigned char *buffer;
39         ssize_t size;
40         ssize_t pos;
41 } MemorySinkInfo;
42
43 ssize_t ss_memorySink(unsigned char *data, ssize_t len, void *token)
44 {
45         MemorySinkInfo *msi = (MemorySinkInfo *) token;
46         if (msi->size - msi->pos < len)
47                 return -1;
48         memcpy(msi->buffer + msi->pos, data, len);
49         msi->pos += len;
50         return len;
51 }
52
53 ssize_t ss_fileSink(unsigned char *data, ssize_t len, void *token)
54 {
55         int ss_fd = *(int *)token;
56         char buf[256];
57         ssize_t done = 0;
58         ssize_t wrote;
59         while (done < (ssize_t) len) {
60                 wrote = write(ss_fd, data + done, len - done);
61                 if (wrote <= 0) {
62                         if (errno == EINTR || errno == EAGAIN)
63                                 continue;          // try again
64                 strerror_r(errno, buf, sizeof(buf));
65                         LOGE("error writing %d bytes: %s\n", (int)(len - done), buf);
66                         return done;
67                 }
68                 done += wrote;
69         }
70         return done;
71 }
72
73 // Take a string 'str' of 40 hex digits and parse it into the 20
74 // byte array 'digest'.  'str' may contain only the digest or be of
75 // the form "<digest>:<anything>".  Return 0 on success, -1 on any
76 // error.
77 int ParseSha1(const char *str, uint8_t * digest)
78 {
79         int i;
80         const char *ps = str;
81         uint8_t *pd = digest;
82         for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
83                 int digit;
84                 if (*ps >= '0' && *ps <= '9')
85                         digit = *ps - '0';
86                 else if (*ps >= 'a' && *ps <= 'f')
87                         digit = *ps - 'a' + 10;
88                 else if (*ps >= 'A' && *ps <= 'F')
89                         digit = *ps - 'A' + 10;
90                 else
91                         return -1;
92                 if (i % 2 == 0) {
93                         *pd = digit << 4;
94                 } else {
95                         *pd |= digit;
96                         ++pd;
97                 }
98         }
99         if (*ps != '\0')
100                 return -1;
101         return 0;
102 }
103
104 //Function to find the start of gzipped part in compressed kernel
105 int getOffset(char *zimage_path)
106 {
107         char gzip_header[] = { 31, -117, 8 };      //header value for gzip which needs to be checked
108         char buf[4] = { 0, };
109         int offset = 0;//wgid:14074
110
111         FILE *f = fopen(zimage_path, "r");
112         if (!f) {
113                 LOGE("Fopen failed for path %s\n", zimage_path);
114                 SS_SetUpgradeState(E_SS_OPENFILE_ONLYR);
115                 return -1;
116         }
117         fseek(f, 0, SEEK_SET);
118         while (fread(buf, 1, 3, f) > 0) {
119                 if (gzip_header[0] == buf[0] && gzip_header[1] == buf[1] && gzip_header[2] == buf[2]) {
120                         LOGL(LOG_SSENGINE, "match for %d %d %d found at %d\n", buf[0], buf[1], buf[2], ftell(f) - 3);
121                         break;
122                 } else {
123                         if (fseek(f, -2, SEEK_CUR) < 0)
124                                 LOGE("Failed to fseek\n");
125                 }
126         }
127         offset = ftell(f) - 3;
128         fclose(f);
129         return offset;
130 }
131
132 int SS_LoadPartition(const char *filename, FileInfo * file)
133 {
134         size_t read = 0;
135         FILE *dev = NULL;
136         int i;
137         char buf[256];
138
139         dev = fopen(filename, "rb");
140         if (dev == NULL) {
141                 strerror_r(errno, buf, sizeof(buf));
142                 LOGE("failed to open partition \"%s\": %s\n", filename, buf);
143                 return -1;
144         }
145
146         sha1_ctx_t sha_ctx;
147         sha1_init(&sha_ctx);
148
149         file->data = SS_Malloc(file->size);
150         if (file->data) {
151                 read = fread(file->data, 1, file->size, dev);
152                 LOGL(LOG_SSENGINE, "Partition size read %d\n", read);
153                 sha1_update(&sha_ctx, file->data, read);
154                 file->size = read;
155         }
156
157         const uint8_t sha_final[SHA_DIGEST_SIZE] = { 0, };
158         sha1_final(&sha_ctx, (uint32_t *) & sha_final);
159         for (i = 0; i < SHA_DIGEST_SIZE; ++i)
160                 file->sha1[i] = sha_final[i];
161         //LOGL(LOG_SSENGINE, "Final SHA of Source (%s)\n", sha_final);
162
163         file->st.st_mode = 0644;
164         file->st.st_uid = 0;
165         file->st.st_gid = 0;
166         fclose(dev);
167         return 0;
168 }
169
170 //extern int write_data_to_blkdev(char* dev_name, int blk_start, int blk_cnt, char* data);
171
172 int SS_LoadFile(const char *filename, FileInfo * file)
173 {
174         char buf[256];
175
176         file->data = NULL;
177         //LOGL(LOG_SSENGINE,"SS_LoadFile --- [File name %s]\n",filename);
178
179         if (stat(filename, &file->st) != 0) {
180                 strerror_r(errno, buf, sizeof(buf));
181                 LOGE("failed to stat \"%s\": %s\n", filename, buf);
182                 return -1;
183         }
184
185         file->size = file->st.st_size;
186         file->data = SS_Malloc(file->size);
187         if (!file->data) {
188                 strerror_r(errno, buf, sizeof(buf));
189                 LOGE("failed to allocate memory for \"%s\": %s\n", filename, buf);
190                 return -1;
191         }
192
193         FILE *f = fopen(filename, "rb");
194         if (f == NULL) {
195                 strerror_r(errno, buf, sizeof(buf));
196                 LOGE("failed to open \"%s\": %s\n", filename, buf);
197                 SS_Free(file->data);
198                 file->data = NULL;
199                 return -1;
200         }
201
202         ssize_t bytes_read = fread(file->data, 1, file->size, f);
203         if (bytes_read != file->size) {
204                 LOGE("short read of \"%s\" (%ld bytes of %ld)\n", filename, (long)bytes_read, (long)file->size);
205                 SS_Free(file->data);
206                 file->data = NULL;
207                 fclose(f);
208                 return -1;
209         }
210         fclose(f);
211         //LOGL(LOG_SSENGINE,"SS_LoadFile --- [bytes_read %d]\n",bytes_read);
212         sha1(file->data, file->size, (uint32_t *) file->sha1);
213         return 0;
214 }
215
216 extern int gvalid_session;
217 extern void create_dir(char *pathname, int mode);
218
219 /*!
220  *********************************************************************************
221  *                                       SS_UpdateDeltaFS
222  *********************************************************************************
223  *
224  * @brief
225  *      This is used to apply patch for a file during delta FS upgrade
226  *
227  *
228  *      @param
229  *
230  *      @return                         0 - in case of success
231  *                                              1 - in case of error during patch application
232  *
233  *********************************************************************************
234  */
235
236 int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
237                                          const char *source_sha1_str, const char *target_sha1_str, int patch_data_size)
238 {
239         uint8_t target_sha1[SHA_DIGEST_SIZE];
240         sha1_ctx_t ctx1;
241         int output;
242         int retry = 1;
243         int use_backup = 0;
244         char *outname = NULL;
245         int backupsrc = -1;
246         int result = 0;
247         char buf[256];
248         FileInfo source_file;
249         uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
250
251         if (ParseSha1(target_sha1_str, target_sha1) != 0) {
252                 LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
253                 return E_SS_FAILURE;
254         }
255
256         /*
257            if battery removed in between update gvalid_session becomes 0
258            need to check file integrity in that case
259          */
260         if (0 == gvalid_session) {
261                 if (ParseSha1(source_sha1_str, source_sha1) != 0) {
262                         LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
263                         return E_SS_FAILURE;
264                 }
265                 if (SS_LoadFile(source_filename, &source_file) == 0) {
266                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
267                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
268                                 if (source_file.data)
269                                         SS_Free(source_file.data);
270                         } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
271                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
272                                 if (source_file.data)
273                                         SS_Free(source_file.data);
274                                 return S_SS_SUCCESS;
275                         } else {
276                                 //Check for backup file SHA
277                                 SS_Free(source_file.data);
278                                 source_file.data = NULL;
279                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
280                                 if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
281                                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
282                                                 if (SS_CopyFile(SS_BACKUP_SOURCE, source_filename) != S_SS_SUCCESS) {
283                                                         strerror_r(errno, buf, sizeof(buf));
284                                                         LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, buf);
285                                                         SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
286                                                         if (source_file.data)
287                                                                 SS_Free(source_file.data);
288                                                         return E_SS_FAILURE;
289                                                 }
290                                                 LOGL(LOG_SSENGINE,
291                                                          "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
292                                         } else {
293                                                 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
294                                                 if (source_file.data)
295                                                         SS_Free(source_file.data);
296                                                 return E_SS_FAILURE;
297                                         }
298                                 } else {
299                                         SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
300                                         if (source_file.data)
301                                                 SS_Free(source_file.data);
302                                         return E_SS_FAILURE;
303                                 }
304                         }
305                 } else {
306                         LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
307                         if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
308                                 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
309                                         use_backup = 1;
310                                         LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
311                                 } else {
312                                         SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
313                                         if (source_file.data)
314                                                 SS_Free(source_file.data);
315                                         return E_SS_FAILURE;
316                                 }
317                         } else {
318                                 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
319                                 if (source_file.data)
320                                         SS_Free(source_file.data);
321                                 return E_SS_FAILURE;
322                         }
323                 }
324         }
325         //Now proceed wit patch application since patch can be applied
326         do {
327                 int enough_space = 0;
328                 size_t free_space = 0;
329                 char *tok;
330
331                 if (retry > 0) {
332                         if (use_backup) {
333                                 tok = strrchr(source_filename, '/');
334                                 *tok = '\0';
335                         }
336                         SS_GetAvailableFreeSpace(source_filename, &free_space);
337                         enough_space = (free_space > (256 << 10)) &&            // 256k (two-block) minimum
338                                 (free_space > (patch_data_size * 3 / 2));          // 50% margin of error
339                         if (use_backup)
340                                 *tok = '/';
341                 }
342
343                 if (!use_backup) {
344 #ifndef ENHANCED_BSDIFF
345                         backupsrc = SS_BackupSource(source_filename);
346                         if (backupsrc != 0) {
347                                 LOGE("failed to Backup source File:[%s] \n", source_filename);
348                                 SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
349                                 return E_SS_FAILURE;
350                         }
351 #endif
352                 }
353                 if (!enough_space) {
354                         LOGL(LOG_SSENGINE, "For %s: free space %ld bytes; enough %d\n", source_filename, (long)free_space,
355                                  enough_space);
356                         retry = 0;
357                         use_backup = 1;
358                         unlink(source_filename);
359                 }
360                 //LOGL(LOG_SSENGINE, "For %s: target %ld bytes; free space %ld bytes; enough %d\n",
361                 // source_filename, (long)patch_data_size, (long)free_space, enough_space);
362                 //LOGL(LOG_SSENGINE,"Generate Target Space availabitiy [%d]\n", enough_space);
363
364                 SinkFn sink = NULL;
365                 void *token = NULL;
366                 output = -1;
367                 outname = NULL;
368
369                 {
370                         // We write the decoded output to "<tgt-file>.patch".
371                         //allocate some extra space to allow for concatinating ".patch" with the name
372                         outname = (char *)SS_Malloc(strlen(target_filename) + 10);
373                         if (outname == NULL)
374                                 return -1;
375                 snprintf(outname, strlen(target_filename) + 10,
376                                 "%s.patch", target_filename);
377
378                         output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
379                         if (output < 0) {
380                                 if (errno == 2) {
381                                         char *dir_path = strrchr(outname, '/');
382                                         *dir_path = '\0';
383                                         // need to create directory as the target may be different from source
384                                         LOGL(LOG_SSENGINE, "need to create directory [%s]\n", outname);
385                                         create_dir(outname, 0755);
386                                         *dir_path = '/';
387                                         output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
388                                         if (output < 0) {
389                                                 strerror_r(errno, buf, sizeof(buf));
390                                                 LOGE("failed to open output file %s: %s\n", outname, buf);
391                                                 SS_Free(outname);
392                                                 return E_SS_FAILURE;
393                                         }
394                                 }
395                         }
396                         sink = ss_fileSink;
397                         token = &output;
398                 }
399                 sha1_init(&ctx1);
400                 if (use_backup)
401                         result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
402                 else
403                         result = SS_ApplyBsdiff((char *)source_filename, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
404                 if (output >= 0) {
405                         fsync(output);
406                         close(output);
407                 }
408
409                 if (result != 0) {
410                         if (retry == 0) {
411                                 LOGE("applying patch failed result : [%d]\n", result);
412                                 SS_Free(outname);//wgid: 20739
413                                 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
414                                 return E_SS_FAILURE;
415                         } else {
416                                 LOGE("applying patch failed; retrying\n");
417                                 SS_Free(outname);//wgid: 20739
418                         }
419                 } else {
420                         // succeeded; no need to retry
421                         break;
422                 }
423         } while (retry-- > 0);
424         const uint8_t current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
425         sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
426         if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
427                 LOGE("patch did not produce expected sha1\n");
428                 SS_SetUpgradeState(E_SS_FSSHA_MISMATCH);
429                 if (outname != NULL)
430                         SS_Free(outname);
431                 return E_SS_FAILURE;
432         }
433         // Finally, rename the .patch file to replace the target file.
434 #ifdef ENHANCED_BSDIFF
435         if (SS_rename1(outname, target_filename) != 0) {
436                 strerror_r(errno, buf, sizeof(buf));
437                 LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, buf);
438                 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
439                 if (outname != NULL)
440                         SS_Free(outname);
441                 return E_SS_FAILURE;
442         }
443 #else
444         if (rename(outname, target_filename) != 0) {
445                 strerror_r(errno, buf, sizeof(buf));
446                 LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, buf);
447                 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
448                 if (outname != NULL)
449                         SS_Free(outname);
450                 return E_SS_FAILURE;
451         }
452         //remove source file if target is not same
453         if (strcmp(source_filename, target_filename) != 0)
454                 unlink(source_filename);
455         SS_BackupSourceClear();
456 #endif
457         SS_PatchSourceClear();
458         SS_Free(outname);
459
460         return result;
461 }
462
463 /*!
464  *********************************************************************************
465  *                                       SS_UpdateDeltaKernel
466  *********************************************************************************
467  *
468  * @brief
469  *      This is used to apply patch for kernel delta during delta Image upgrade
470  *
471  *
472  *      @param
473  *
474  *      @return                         0 - in case of success
475  *                                              1 - in case of error during patch application
476  *
477  *********************************************************************************
478  */
479
480 int SS_UpdateDeltaKernel(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
481 {
482         uint8_t target_sha1[SHA_DIGEST_SIZE];
483         uint8_t source_sha1[SHA_DIGEST_SIZE];
484         FileInfo source_file;
485         int result = S_SS_SUCCESS;
486         int blk_cnt, read_count = 0;
487         int blk_start = 0;
488         int backupsrc = -1;
489         int use_backup_img = -1;
490         FILE *fp = NULL, *wp = NULL, *kp = NULL;
491         int i = 0, j = 0, file_len = 0;
492         char *magic = NULL, *file_name = NULL, *tok_buf = NULL, *buf = NULL, a = '0';
493         char *saveptr;
494         char err_buf[256];
495         char cmd[1024] = { 0, };
496         char source_filename[MAX_FILE_PATH] = { 0, };
497         char part_filename[MAX_FILE_PATH] = { 0, };
498         int file_num = 0;
499         SinkFn sink = NULL;
500         void *tok = NULL;
501         int output = -1;
502         char *outname = NULL;
503         //Kernel Parts are created on unpacking kernel which is then used to apply delta
504         char *kernel_parts[] = { "decompression_code",
505                 "piggy.gz",
506                 "padding_piggy",
507                 "piggy_trailer"
508         };
509
510         if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
511                 LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
512                 return E_SS_FAILURE;
513         }
514
515         source_file.size = ua_dataSS->update_cfg->soure_img_size;
516         source_file.data = NULL;
517         if (0 == gvalid_session) {
518
519                 if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
520                         LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
521                         return E_SS_FAILURE;
522                 }
523
524                 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
525                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
526                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
527
528                         } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
529                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
530                                 SS_Free(source_file.data);
531                                 return S_SS_SUCCESS;
532                         } else {
533                                 SS_Free(source_file.data);
534                                 source_file.data = NULL;
535                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
536                                 if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
537                                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
538                                                 use_backup_img = 1;
539
540                                                 LOGL(LOG_SSENGINE,
541                                                          "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
542                                         } else {
543                                                 SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
544                                                 SS_Free(source_file.data);
545                                                 return E_SS_FAILURE;
546                                         }
547                                 }
548                         }
549                 }
550         } else {                                        //in case of kernel delta need to copy kernel data  from blk to buffer
551                 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) != 0) {
552                         SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
553                         LOGE("Fatal Error : Kernel block is corrupted\n");
554                         return E_SS_FAILURE;
555                 }
556         }
557         if (use_backup_img == -1) {
558                 backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
559                 if (backupsrc != 0) {
560                         LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
561                         SS_Free(source_file.data);
562                         SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
563                         return E_SS_FAILURE;
564                 }
565         }
566         //Cleanup workspace and copy helper executables to it before proceeding
567         SS_DeleteFolder(SS_KERNEL_WORKSPACE);
568         create_dir(SS_KERNEL_WORKSPACE, 0755);
569         SS_CopyFile(SS_GZIP_SOURCE, SS_GZIP_TARGET);
570         SS_CopyFile(SS_STAT_SOURCE, SS_STAT_TARGET);
571         SS_CopyFile(SS_DD_SOURCE, SS_DD_TARGET);
572
573         if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
574                 if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) > 0)
575                         LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
576                 else {
577                         LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
578                         SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
579                         result = E_SS_FAILURE;
580                         goto Cleanup;
581         } else {
582                 LOGE("Error size is not positive for item %s", SS_KERNEL_UNPACK_SCRIPT);
583                 SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
584                 result = E_SS_FAILURE;
585                 goto Cleanup;
586         }
587         //Now write the kernel data to the workplace and start applying patch
588         snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME);
589         fp = fopen(source_filename, "w");
590         if (!fp) {
591                 LOGE("file open error [%s] code [%d]\n", source_filename, errno);
592                 result = E_SS_FAILURE;
593                 goto Cleanup;
594         }
595         //write source kernel data to workspace
596         read_count = fwrite(source_file.data, 1, source_file.size, fp);
597         if (read_count != source_file.size) {
598                 LOGE("file write error read_count = %d for [%s]\n", read_count, source_filename);
599                 result = E_SS_FAILURE;
600                 goto Cleanup;
601         }
602         fclose(fp);
603         fp = NULL;//wgid: 59313
604
605         //Unpack source kernel
606         int offset = getOffset(source_filename);
607         if (offset < 0) {
608                 LOGE("Failed to get offset\n");
609                 result = E_SS_FAILURE;
610                 goto Cleanup;
611         }
612         snprintf(cmd, sizeof(cmd) - 1, "%s -u %s %s %d", SS_KERN_UNPK_SCRIPT_PATH, SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
613                          offset);
614         int ret = _system_cmd_wait(cmd);
615         LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
616
617         //open delta file, extract kernel delta parts and apply patch to previously unpacked kernel
618         fp = fopen(SS_PATCHFILE_SOURCE, "r");
619         if (fp == NULL) {
620                 LOGE("Failed to open kernel delta patch\n");
621                 result = E_SS_FAILURE;
622                 goto Cleanup;
623         }
624         //read kernel delta header for  delta names and size
625         buf = SS_Malloc(SS_KERNEL_DELTA_HEADER);
626         if (!buf) {//wgid: 13099
627                 LOGE("Failed to allocate memory\n");
628                 result = E_SS_MALLOC_ERROR;
629                 goto Cleanup;
630         }
631         ssize_t bytes_read = fread(buf, 1, SS_KERNEL_DELTA_HEADER, fp);
632         if (bytes_read != SS_KERNEL_DELTA_HEADER)
633                 LOGL(LOG_SSENGINE, "short read of \"%s\" (%ld bytes of %ld)\n", SS_PATCHFILE_SOURCE, (long)bytes_read, (long)SS_KERNEL_DELTA_HEADER);
634         magic = strtok_r(buf, ":", &saveptr);
635         LOGL(LOG_SSENGINE, "magic: %s\n", magic);
636         tok_buf = strtok_r(NULL, ":", &saveptr);
637         if (tok_buf)
638                 file_num = atoi(tok_buf);
639
640         //adjust offset to start of data section before proceeding
641         fseek(fp, SS_KERNEL_DELTA_HEADER, SEEK_SET);
642
643         while (file_num-- > 0) {
644                 file_name = strtok_r(NULL, ":", &saveptr);
645                 tok_buf = strtok_r(NULL, ":", &saveptr);
646                 if (tok_buf)
647                         file_len = atoi(tok_buf);
648                 j = file_len;
649                 snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s_unpacked/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
650                                  file_name);
651                 snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, file_name);
652                 wp = fopen(part_filename, "w");
653                 while (j-- > 0) {
654                         a = fgetc(fp);
655                         fputc(a, wp);
656                 }
657                 fclose(wp);
658
659                 //apply bspatch to the unpacked kernel parts
660
661                 {
662                         // We write the decoded output to "<tgt-file>.patch".
663                         //allocate some extra space to allow for concatinating ".patch" with the name
664                         outname = (char *)SS_Malloc(strlen(source_filename) + 10);
665                         if (outname == NULL) {
666                                 SS_SetUpgradeState(E_SS_MALLOC_ERROR);
667                                 result = E_SS_FAILURE;
668                                 goto Cleanup;
669                         }
670                         snprintf(outname, strlen(source_filename) + 10, "%s.patch",
671                                         source_filename);
672
673                         output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
674                         if (output < 0) {
675                                 strerror_r(errno, err_buf, sizeof(err_buf));
676                                 LOGE("failed to open output file %s: %s\n", outname, err_buf);
677                                 result = E_SS_FAILURE;
678                                 goto Cleanup;
679                         }
680                         sink = ss_fileSink;
681                         tok = &output;
682                 }
683                 result = SS_ApplyBsdiff(source_filename, outname, part_filename, sink, tok, NULL);
684                 LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
685                 if (output >= 0) {
686                         fsync(output);
687                         close(output);
688                 }
689
690                 if (result != S_SS_SUCCESS) {
691                         LOGE("applying patch failed %s\n", source_filename);
692                         if (outname != NULL)
693                                 unlink(outname);
694                         goto Cleanup;
695                 }
696                 result = rename(outname, source_filename);
697                 if (result != S_SS_SUCCESS) {
698                         LOGE("fatal error %s\n", source_filename);
699                         goto Cleanup;
700                 }
701                 if (file_name && strcmp(file_name, "piggy") == 0) {
702                         snprintf(cmd, sizeof(cmd) - 1,
703                                          "%s/gzip -n -9 -c %s/%s/%s > %s/%s/%s.gz",
704                                          SS_KERNEL_WORKSPACE, SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name,
705                                          SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name);
706                         result = _system_cmd_wait(cmd);
707                         LOGL(LOG_SSENGINE, "ret for %s = %d\n", cmd, result);
708                         unlink(source_filename);
709                 }
710                 unlink(part_filename);
711         }
712         //open new kernel file and append kernel parts to it in
713         snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_TARGET_NAME);
714         kp = fopen(source_filename, "w");
715         for (i = 0; i < 4; i++) {
716                 snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR,
717                                  kernel_parts[i]);
718                 wp = fopen(part_filename, "r");
719                 fseek(wp, SEEK_SET, SEEK_END);
720                 j = ftell(wp);
721                 fseek(wp, SEEK_SET, SEEK_SET);
722                 while (j-- > 0) {
723                         a = fgetc(wp);
724                         if (a != EOF)
725                                 fputc(a, kp);
726                         else
727                                 break;
728                 }
729                 fclose(wp);
730                 unlink(part_filename);
731         }
732         fclose(fp);
733         fp = NULL;
734         fclose(kp);
735
736         SS_Free(source_file.data);
737         source_file.data = NULL;
738         if (SS_LoadFile(source_filename, &source_file) == 0)
739                 result = memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE);
740         if (result != S_SS_SUCCESS) {
741                 LOGE("patch did not produce expected sha1 \n");
742                 SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
743                 goto Cleanup;
744         }
745         //Considering EMMC partition by deafult
746
747         blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
748         result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)source_file.data);
749         if (result != S_SS_SUCCESS) {
750                 LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name);          // All returns should go to CLEAN UP.
751                 SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
752                 goto Cleanup;
753         }
754
755  Cleanup:
756         SS_BackupSourceClear();
757         SS_PatchSourceClear();
758         SS_DeleteFile(SS_KERN_UNPK_SCRIPT_PATH);
759         SS_DeleteFolder(SS_KERNEL_WORKSPACE);
760         SS_Free(source_file.data);
761         SS_Free(buf);
762         SS_Free(outname);//wgid: 20740
763         if (result == S_SS_SUCCESS)
764                 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel  SUCCESS *****************\n");
765         else{
766                 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel  FAILED *****************\n");
767                 if (fp)
768                         fclose(fp);//wgid:14711
769         }
770         return result;
771
772 }
773
774 /*!
775  *********************************************************************************
776  *                                       SS_UpdateDeltaIMG
777  *********************************************************************************
778  *
779  * @brief
780  *      This is used to apply patch for an image during delta Image upgrade
781  *
782  *
783  *      @param
784  *
785  *      @return                         0 - in case of success
786  *                                              1 - in case of error during patch application
787  *
788  *********************************************************************************
789  */
790
791 int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
792 {
793         uint8_t target_sha1[SHA_DIGEST_SIZE];
794         uint8_t source_sha1[SHA_DIGEST_SIZE];
795         const uint8_t current_target_sha1[SHA_DIGEST_SIZE];
796         FileInfo source_file;
797         sha1_ctx_t ctx1;
798         MemorySinkInfo msi;
799         int result = S_SS_SUCCESS;
800         int blk_cnt;
801         int blk_start = 0;
802         int backupsrc = -1;
803         int use_backup_img = -1;
804         int fd = -1;
805         char buf[256];
806         if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
807                 LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
808                 return E_SS_FAILURE;
809         }
810
811         source_file.size = ua_dataSS->update_cfg->soure_img_size;
812         source_file.data = NULL;
813         if (0 == gvalid_session) {
814
815                 if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
816                         LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
817                         return E_SS_FAILURE;
818                 }
819
820                 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
821                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
822                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
823                                 SS_Free(source_file.data);
824                         } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
825                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
826                                 SS_Free(source_file.data);
827                                 return S_SS_SUCCESS;
828                         } else {
829                                 SS_Free(source_file.data);
830                                 source_file.data = NULL;
831                                 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
832                                 if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
833                                         if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
834                                                 use_backup_img = 1;
835                                                 SS_Free(source_file.data);
836                                                 LOGL(LOG_SSENGINE,
837                                                          "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
838                                         } else {
839                                                 SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
840                                                 SS_Free(source_file.data);
841                                                 return E_SS_FAILURE;
842                                         }
843                                 }
844                         }
845                 }
846         }
847         if (use_backup_img == -1) {
848                 backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
849                 if (backupsrc != 0) {
850                         LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
851                         SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
852                         return E_SS_FAILURE;
853                 }
854         }
855         SinkFn sink = NULL;
856         void *token = NULL;
857
858         blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
859
860         msi.buffer = SS_Malloc(blk_cnt * SECTOR_SIZE);
861         if (msi.buffer == NULL) {
862                 LOGE("failed to alloc %ld bytes for output\n", (long)ua_dataSS->update_cfg->target_img_size);
863                 SS_SetUpgradeState(E_SS_MALLOC_ERROR);
864                 return E_SS_FAILURE;
865         }
866         msi.pos = 0;
867         msi.size = ua_dataSS->update_cfg->target_img_size;
868         sink = ss_memorySink;
869         token = &msi;
870
871         sha1_init(&ctx1);
872         //if souce was corrupted, use backup to apply diff
873         if (use_backup_img == -1)
874                 result =
875                         SS_ApplyBsdiff((char *)ua_dataSS->parti_info->ua_blk_name, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
876         else
877                 result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
878         if (result != S_SS_SUCCESS) {
879                 LOGE("failed to SS_ApplyBsdiff\n");
880                 SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
881                 goto Cleanup;
882         }
883
884         sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
885         result = memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE);
886         if (result != S_SS_SUCCESS) {
887                 LOGE("patch did not produce expected sha1 \n");
888                 SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
889                 goto Cleanup;
890         }
891         //Considering EMMC partition by deafult
892
893         if (ua_dataSS->update_cfg->update_type == DELTA_IMG) {
894                 blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
895                 result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)msi.buffer);
896                 if (result != S_SS_SUCCESS) {
897                         LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name);   // All returns should go to CLEAN UP.
898                         SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
899                         goto Cleanup;
900                 }
901         } else if (ua_dataSS->update_cfg->update_type == EXTRA && ua_dataSS->update_data->ua_temp_path) {
902                 fd = open(ua_dataSS->update_data->ua_temp_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
903                 if (fd < 0) {
904                         strerror_r(errno, buf, sizeof(buf));
905                         LOGE("failed to open %s for write: %s\n", ua_dataSS->update_data->ua_temp_path, buf);
906                         SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
907                         result = E_SS_FAILURE;
908                         goto Cleanup;
909                 }
910                 result = SS_WriteFile(fd, 0, msi.buffer, msi.size);
911                 if (result != S_SS_SUCCESS) {
912                         LOGE("failed to write\n");
913                         SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
914                         goto Cleanup;
915                 }
916                 fsync(fd);
917         } else {
918                 SS_SetUpgradeState(E_SS_IMGUPDATEFAILED);
919                 result = E_SS_FAILURE;
920                 LOGE("failed to apply patch - Invalid Update type params \n");
921         }
922
923 Cleanup:
924         SS_BackupSourceClear();
925         SS_PatchSourceClear();
926         if (msi.buffer)
927                 SS_Free(msi.buffer);
928         if (fd >= 0)
929                 close(fd);
930         if (result == S_SS_SUCCESS)
931                 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaIMG  SUCCESS *****************\n");
932         return result;
933
934 }