upgrade-apply-deltafs: Add possibility to build this binary on host by adding a cmake...
[platform/core/system/upgrade.git] / src / upgrade-apply-deltafs / ua.c
1 /*
2  * upgrade-apply-deltafs
3  *
4  * Copyright (c) 2017 - 2022 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 <assert.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/reboot.h>
28 #include <sys/wait.h>
29 #include <sys/time.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <getopt.h>
35
36 #ifndef HOST_BUILD
37 #include <hal/device/hal-board.h>
38 #endif
39
40 #include "ua.h"
41 #include "fota_util.h"
42 #include "engine/SS_Common.h"
43 #include "engine/SS_UPI.h"
44 #include "engine/fota_common.h"
45 #include "engine/fota_tar.h"
46 #include "engine/ua_types.h"
47
48
49 #define SYSTEM_LOG_DIR          "/opt/var/log"
50 #define TEMP_FOLDER         "/tmp" // TODO
51
52 //char ua_slot_mode = 0;
53 int dm_verity_status = DM_VERITY_DISABLED;
54
55 // TODO: Consider changing all to PATH_MAX
56 static char fota_result[MAX_FILE_PATH];
57 static char fota_cause[MAX_FILE_PATH];
58 static char delta_folder[MAX_FOLDER_PATH];
59 static char delta_path[MAX_FILE_PATH];
60 static char log_folder[MAX_FOLDER_PATH];
61 static char result_folder[MAX_FOLDER_PATH];
62 static char temp_folder[MAX_FOLDER_PATH];
63 static char log_path[MAX_FILE_PATH];
64 static char mnt_point[MAX_FILE_PATH];
65
66 static ua_part_info_t s_part_info;
67
68 static ua_update_cfg_t s_update_cfg;
69
70 static ua_update_data_t s_update_data;
71
72 static tar_info s_tar_data;
73
74 static text_file_info s_text_files_info[NO_OF_TEXT_FILES];
75
76 static file_7z_info s_new_files_info;
77
78 typedef struct temp_opt{
79     char * archive;
80     char * archive_file;
81     char * dest;
82 }temp_opt;
83
84 static ua_delta_info_t s_delta_info;
85
86 unsigned int __log_level__ =
87         (LOG_DEBUG | LOG_FLASH | LOG_FILE | LOG_FUNCS | LOG_GUI | LOG_ENGINE | LOG_INFO);
88 FILE *__log_out_file__;
89
90 static void save_result(int result);
91 static void save_cause(int cause);
92
93 #define TMP_DIR "/tmp/upgrade"
94 #define PROGRESS_FILE TMP_DIR "/ro_progress"
95
96 #define HAL_PROGRESS_MIN 40
97 #define HAL_PROGRESS_MAX 80
98
99 void print_usage(const char *msg)
100 {
101         if (msg) {
102                 printf("%s\n", msg);
103         }
104         printf("print_usage: upgrade-apply-deltafs --archive delta_path --dest directory --archive-file label.img/\n"
105         "delta_path: filepath of delta (allowed file extensions: .tar, .tar.gz, .tgz)\n"
106         "directory: directory where partition to be upgraded is mounted\n"
107         "label.img: name of the directory inside of delta that is to be used during upgrade\n"
108         );
109 }
110
111 void print_error_code(int err)
112 {
113         char msg[]="upgrade-apply-deltafs error:";
114         switch (err) {
115         case UPI_CONFIG_ERROR:
116                 printf("%s config error.\n", msg);
117                 break;
118         case UPI_DELTA_PATH_ERROR:
119                 printf("%s delta path error.\n", msg);
120                 break;
121         case UPI_DELTA_PATH_LENGTH_ERROR:
122                 printf("%s delta path length error.\n", msg);
123                 break;
124         case UPI_VERSION_ERROR:
125                 printf("%s version error.\n", msg);
126                 break;
127         case UPI_VERIFY_ERROR:
128                 printf("%s verify error.\n", msg);
129                 break;
130         case UPI_UPDATE_ERROR:
131                 printf("%s update error.\n", msg);
132                 break;
133         case UPI_INVALID_PARAM_ERROR:
134                 printf("%s invalid parameter error.\n", msg);
135                 break;
136         case UPI_DELTACOUNT_ERROR:
137                 printf("%s delta count error.\n", msg);
138                 break;
139         case UPI_PARTINFO_ERROR:
140                 printf("%s partition information error.\n", msg);
141                 break;
142         default:
143                 printf("upgrade-apply-deltafs unable to determine error code: %d\n", err);
144         }
145 }
146
147 void fota_gui_update_progress(int percent)
148 {
149         int ret;
150         int fd;
151         struct stat s;
152
153         // Check directory
154         ret = stat(TMP_DIR, &s);
155         if (ret == 0) {
156                 // TMP_DIR exists but it is not directory
157                 if (!S_ISDIR(s.st_mode))
158                         goto remove_file;
159                 else
160                         goto update_progress;
161         } else if (errno == ENOENT)     // TMP_DIR not exists
162                 goto make_directory;
163         else {
164                 LOG("stat failed : %m\n");
165                 return;
166         }
167
168 remove_file:
169         ret = remove(TMP_DIR);
170         if (ret != 0) {
171                 LOG("remove failed : %m\n");
172                 return;
173         }
174
175 make_directory:
176         ret = mkdir(TMP_DIR, 0755);
177         if (ret != 0) {
178                 LOG("mkdir failed : %m\n");
179                 return;
180         }
181
182 update_progress:
183         fd = creat(PROGRESS_FILE, 0644);
184         if (fd < 0) {
185                 LOG("creat failed : %m\n");
186                 return;
187         }
188
189         ret = dprintf(fd, "%d\n", percent);
190         if (close(fd) != 0) {
191                 LOG("close failed : %m\n");
192                 return;
193         }
194         if (ret < 2) {
195                 LOG("write failed (%d) : %m\n", ret);
196                 return;
197         }
198
199         LOG("Succeed to write\n");
200 }
201
202 static void set_upgrade_progress(int percent)
203 {
204         int relative_precent = HAL_PROGRESS_MIN + ((HAL_PROGRESS_MAX - HAL_PROGRESS_MIN) * percent)/100;
205
206 #ifndef HOST_BUILD
207         if (hal_device_board_set_upgrade_status(relative_precent) < 0) {
208                 LOG("set_upgrade_status failed: %d\n", relative_precent);
209                 return;
210         }
211 #endif
212
213         LOG("set_upgrade_status success: %d\n", relative_precent);
214 }
215
216 /*-----------------------------------------------------------------------------
217   fota_gui_progress
218  ----------------------------------------------------------------------------*/
219  // TODO - remove this mechanism, only makes log less readable
220 void fota_gui_progress(void * pbUserData, unsigned long uPercent)
221 {
222         int percent;
223         int from, to;
224         ua_dataSS_t *ua_data = (ua_dataSS_t *)pbUserData;
225         ua_update_data_t *ua_update_data = ua_data->update_data;
226
227         LOGL(LOG_FUNCS|LOG_GUI, "%s: ++ uPercent(%lu%%), config->weight=%lu\n", __func__,
228                 uPercent, (long unsigned int)ua_update_data->weight);
229
230         if (uPercent == 100)
231                 percent = ua_update_data->weight_offset + ua_update_data->weight;
232         else
233                 percent = ua_update_data->weight_offset + (ua_update_data->weight * uPercent / 100);
234
235         set_upgrade_progress(percent);
236         /**
237          * re-arrange progress percentage between scout & update
238          *
239          * 0 ~ 100 -> from ~ to
240          */
241         switch (ua_data->ua_operation) {
242         case UI_OP_SCOUT:
243                 from = 0;
244                 to = 20;
245                 break;
246         case UI_OP_SCOUT_UPDATE:
247         case UI_OP_UPDATE:
248                 from = 20;
249                 to = (dm_verity_status == DM_VERITY_ENABLED) ? 80 : 100;
250                 break;
251         default:
252                 from = 0;
253                 to = 100;
254                 break;
255         }
256
257         percent = from + ((to - from) * percent / 100);
258
259         fota_gui_update_progress(percent);      /* update progress bar and text */
260
261         LOGL(LOG_FUNCS|LOG_GUI, "-- uPercent=%lu, Print Percent(%d%%)\n", uPercent, percent);
262 }
263
264 /*-----------------------------------------------------------------------------
265   verify_Delta_FS
266  ----------------------------------------------------------------------------*/
267 int verify_Delta_FS()
268 {
269         int ret = SUCCESS;
270         ua_dataSS_t ua_dataSS;
271         ua_part_info_t *ua_part_info = &s_part_info;
272         ua_update_cfg_t *ua_update_cfg = &s_update_cfg;
273         ua_update_data_t *ua_update_data = &s_update_data;
274         ua_delta_info_t *ua_delta_info = &s_delta_info;
275         tar_info *ua_tar_data = &s_tar_data;
276         ua_dataSS.parti_info = ua_part_info;
277         ua_dataSS.update_cfg = ua_update_cfg;
278         ua_dataSS.update_data = ua_update_data;
279         ua_dataSS.update_delta = ua_delta_info;
280         ua_dataSS.ua_operation = UI_OP_SCOUT;
281         ua_dataSS.tar_data = ua_tar_data;
282         ua_dataSS.ui_progress = fota_gui_progress;
283
284         if (ua_update_data->ua_delta_path != NULL) {
285                 LOG("Verifying %s \n", ua_dataSS.parti_info->ua_parti_name);
286                 ret = SS_FSVerifyPartition(&ua_dataSS);
287         }
288
289         return ret;
290 }
291
292 /*-----------------------------------------------------------------------------
293   update_Delta_FS
294  ----------------------------------------------------------------------------*/
295 int update_Delta_FS(unsigned long ui32Operation)
296 {
297         int ret = SUCCESS;
298         ua_dataSS_t ua_dataSS;
299         ua_part_info_t *ua_part_info = &s_part_info;
300         ua_update_cfg_t *ua_update_cfg = &s_update_cfg;
301         ua_update_data_t *ua_update_data = &s_update_data;
302         ua_delta_info_t *ua_delta_info = &s_delta_info;
303         tar_info *ua_tar_data = &s_tar_data;
304         ua_dataSS.parti_info = ua_part_info;
305         ua_dataSS.update_cfg = ua_update_cfg;
306         ua_dataSS.update_data = ua_update_data;
307         ua_dataSS.update_delta = ua_delta_info;
308         ua_dataSS.ua_operation = ui32Operation;
309         ua_dataSS.tar_data = ua_tar_data;
310         ua_dataSS.ui_progress = fota_gui_progress;
311
312         if (ua_update_data->ua_delta_path != NULL)
313                 ret = SS_FSUpdatemain(&ua_dataSS);
314
315         return ret;
316 }
317
318 /*-----------------------------------------------------------------------------
319   set_data_weight
320  ----------------------------------------------------------------------------*/
321 /* set data weight using data size minimum:1 total: 100 */
322 // TODO - remove
323 static void set_data_weight(unsigned int total_data_size)
324 {
325         LOG("%s entered, total_data_size=%u\n", __func__, total_data_size);
326         s_update_data.weight = 100;
327         LOG("%s leaved\n", __func__);
328 }
329
330 /*-----------------------------------------------------------------------------
331   set_data_weight_offset
332  ----------------------------------------------------------------------------*/
333  // TODO - remove
334 static void set_data_weight_offset(void)
335 {
336         LOG("%s entered\n", __func__);
337         s_update_data.weight_offset = 0; // not sure what it does, keep it like this for now
338     LOG("s_update_data.weight_offset=%u\n", s_update_data.weight_offset);
339         LOG("%s leaved\n", __func__);
340 }
341
342 /*-----------------------------------------------------------------------------
343   get_time_stamp
344  ----------------------------------------------------------------------------*/
345 static char ts[256];
346 static void get_time_stamp(void)
347 {
348         struct timeval tv;
349         int sec, msec;
350
351         gettimeofday(&tv, NULL);
352         sec = (int) tv.tv_sec;
353         msec = (int) (tv.tv_usec / 1000);
354         snprintf(ts, sizeof(ts), "%06d.%03d", sec % 100000, msec);
355 }
356
357 /*-----------------------------------------------------------------------------
358   remove_cfg_file_files
359  ----------------------------------------------------------------------------*/
360 void remove_extracted_files(void)
361 {
362         for (int i = 0; i < NO_OF_TEXT_FILES; i++)
363         {
364                 if (s_tar_data.text_files_info[i].size > 0) {
365                         if (unlink(s_tar_data.text_files_info[i].extracted_name) < 0) {
366                                 LOGE("unlink error!\n");
367                         }
368                 }
369         }
370 }
371
372 /*-----------------------------------------------------------------------------
373   update_all
374  ----------------------------------------------------------------------------*/
375 int update_all()
376 {
377         int ret = OK;
378         int cause = 0;
379         unsigned long ui32Operation = UI_OP_SCOUT;
380         char * org_dir = getcwd(NULL, 0);
381
382         if ((ret = chdir(mnt_point)) < 0) {
383                 cause = ret;
384                 goto CleanUp;
385         }
386         if (tar_get_cfg_data(&s_tar_data) < 0) {
387                 LOGE("Delta read error!\n");
388                 ret = UPI_DELTACOUNT_ERROR;
389                 goto CleanUp;
390         }
391         if (s_tar_data.text_files_info[PATCHLIST_FILE].size <= 0) {
392                 LOGE("Patchlist file not present in delta -> aborting!\n");
393                 ret = UPI_DELTACOUNT_ERROR;
394                 goto CleanUp;
395         }
396
397         s_update_data.data_size = s_tar_data.uncompressed_folder_size;
398     LOGL(LOG_DEBUG, "s_update_data.data_size=%lu, ua_delta_path=%s, "
399                 "ua_subject_name=%s\n",
400                 (long unsigned int)s_update_data.data_size,
401                 s_update_data.ua_delta_path,
402                 s_part_info.ua_subject_name);
403
404         if (s_update_data.data_size <= 0) {
405                 ret = UPI_DELTACOUNT_ERROR;
406                 sleep(3);
407
408                 goto CleanUp;
409         }
410
411         LOG(" set weight to draw progressive bar.....\n");
412         set_data_weight(s_update_data.data_size);
413         set_data_weight_offset();
414
415         LOG("s_part_info.ua_parti_name = %s ua_delta_path = %s ua_subject_name=%s\n",
416                 s_part_info.ua_parti_name,
417                 s_update_data.ua_delta_path,
418                 s_part_info.ua_subject_name);
419
420         if (s_update_data.data_size > 0) {
421                 get_time_stamp();
422                 LOG("[%s] Verify %s ..............................................................\n", ts,
423                         s_part_info.ua_parti_name);
424
425                 ret = verify_Delta_FS();
426                 LOG("return form verify : %d\n", ret);
427                 if (ret != OK) {
428                         cause = ret;
429                         ret = UPI_VERIFY_ERROR;
430                         LOG("%s verify fail\n", s_part_info.ua_parti_name);
431                         goto CleanUp;
432                 }
433         }
434
435         get_time_stamp();
436         LOG("[%s] Verify End ..............................................................\n", ts);
437
438         /* Update */
439         ui32Operation = UI_OP_SCOUT_UPDATE;
440
441
442         if (s_update_data.data_size > 0) {
443                 get_time_stamp();
444                 LOG("[%s] Update %s ..............................................................\n", ts,
445                         s_part_info.ua_parti_name);
446
447                 ret = update_Delta_FS(ui32Operation);
448                 LOG("return form update : %d\n", ret);
449                 if (ret != OK) {
450                         cause = ret;
451                         ret = UPI_UPDATE_ERROR;
452                         LOG("%s update fail\n", s_part_info.ua_parti_name);
453                         goto CleanUp;
454                 }
455         }
456
457         if ((ret = chdir(org_dir)) < 0) {
458                 cause = ret;
459                 goto CleanUp;
460         }
461
462         get_time_stamp();
463         LOG("[%s] Update End ..............................................................\n", ts);
464
465  CleanUp:
466         if (ret != OK)
467                 save_cause(cause);
468
469         remove_extracted_files();
470         free(org_dir);
471         return ret;
472 }
473
474 /*-----------------------------------------------------------------------------
475   log_init
476  ----------------------------------------------------------------------------*/
477 void log_init(void)
478 {
479         snprintf(log_path, sizeof(log_path), "%s", LOG_FILE_PATH);
480
481         __log_out_file__ = fopen(log_path, "w");
482         if (__log_out_file__ == NULL) {
483                 perror("file open error\n");
484                 return;
485         }
486
487         get_time_stamp();
488         LOG("===== log start [%s] =====\n", ts);
489 }
490
491 /*-----------------------------------------------------------------------------
492   log_deinit
493  ----------------------------------------------------------------------------*/
494 void log_deinit(void)
495 {
496         get_time_stamp();
497         LOG("===== log end [%s] =====\n", ts);
498
499         if (__log_out_file__) {
500                 fclose(__log_out_file__);
501                 __log_out_file__ = NULL;
502         }
503
504         sync();
505 }
506
507 /*-----------------------------------------------------------------------------
508   print_error_cause
509  ----------------------------------------------------------------------------*/
510 static void print_error_cause(int error)
511 {
512         switch (error) {
513         case E_SS_FSBADDELTA:
514                 LOG("Corrupted firmware update package, did not store correctly.  Detected, for example, by mismatched CRCs between actual and expected.\n");
515                 break;
516         case E_SS_BAD_PARAMS:
517                 LOG("Wrong Firmware Update Package delivered to device based on current device characteristics\n");
518                 break;
519         case E_SS_MALLOC_ERROR:
520                 LOG("The update fails because there isn't sufficient memory to update the device.\n");
521                 break;
522         case E_SS_FSSRCBACKUPFAILED:
523         case E_SS_WRITE_ERROR:
524         case E_SS_FSFAILEDTOBACKUPPATCHINFO:
525         case E_SS_FSBADATTRIBUTES:
526                 LOG("The update failed because writing data to the device was unsuccessful.\n");
527                 break;
528         case E_SS_FSSRCCURRUPTED:
529         case E_SS_FSSHA_MISMATCH:
530         case E_SS_FSFAILEDTOPARSEDELTACNT:
531         case E_SS_FSFAILEDTOOPENPATCHINFO:
532         case E_SS_FSFAILEDTOPARSEDELTAINFO:
533                 LOG("The update failed because data was corrupted during update of device.\n");
534                 break;
535         default:
536                 LOG("another error\n");
537                 break;
538         }
539 }
540
541 /*
542 <Corrupted Firmware Update Package>
543 Corrupted firmware update package, did not store correctly.  Detected, for example, by mismatched CRCs between actual and expected.
544 E_RB_PKG_CORRUPTED(0x8000000D)
545 E_RB_PKG_NOT_AUTHORIZED(0x8000000E): not used
546
547 <Firmware Update Package-Device Mismatch>
548 Wrong Firmware Update Package delivered to device based on current device characteristics
549 E_RB_BAD_PARAMS(0x800000002)
550 E_RB_WRONG_UPI_VER(0x80000011):not used
551 E_RB_WRONG_UPI_UPDATE(0x80000012): not used
552 E_RB_UPDATE_SECTOR_SIG(0x80000013): not used
553
554 <Failed Firmware Update Package Validation>
555 Failure to positively validate digital signature of firmware update package
556 E_RB_NON_DP_FORMAT_NOT_SUPPORTED(0x8001001A)
557 E_RB_INVALID_DP_HEADER(0x80010025)
558 E_RB_INVALID_DP_WRONG_SIGNATURE(0x80010026)
559 E_RB_INVALID_DP(0x80010027)
560
561 <Firmware Update Package Not Acceptable>
562 Firmware Update Package is Not Acceptable
563 E_RB_PKG_TOO_SHORT(0x8000000B) not used
564 E_RB_PKG_TOO_LONG(0x8000000C) not used
565 E_RB_PKG_NOT_AUTHORIZED(0x8000000F)
566
567 <Firmware update fails due to device out of memory>
568 The update fails because there isn\A1\AFt sufficient memory to update the device.
569 E_RB_NOT_ENOUGH_RAM(0x8000001E)
570 */
571
572 /*-----------------------------------------------------------------------------
573   save_cause
574  ----------------------------------------------------------------------------*/
575 void save_cause(int cause)
576 {
577         char return_char[20];
578         FILE *result_fp;
579
580         LOG("%s entered, 0x%x\n", __func__, cause);
581
582         print_error_cause(cause);
583
584         if ((result_fp = fopen(fota_cause, "w")) == NULL) {
585                 LOG("cause file open fail\n");
586                 return;
587         }
588
589         snprintf(return_char, sizeof(return_char), "%x", cause);
590         fwrite(return_char, strlen(return_char), 1, result_fp);
591         fclose(result_fp);
592
593         LOG("%s leaved!\n", __func__);
594 }
595
596 /*-----------------------------------------------------------------------------
597   save_result
598  ----------------------------------------------------------------------------*/
599 void save_result(int result)
600 {
601         char return_char[20];
602         FILE *result_fp;
603
604         LOG("%s entered, result=0x%x\n", __func__, result);
605
606         if ((result_fp = fopen(fota_result, "w")) == NULL) {
607                 LOG("result file open fail\n");
608                 return;
609         }
610
611         snprintf(return_char, sizeof(return_char), "%x", result);
612         fwrite(return_char, strlen(return_char), 1, result_fp);
613         fclose(result_fp);
614
615         LOG("%s leaved!\n", __func__);
616
617         return;
618 }
619
620 /*-----------------------------------------------------------------------------
621   check_dm_verity_status
622  ----------------------------------------------------------------------------*/
623 int check_dm_verity_status(void)
624 {
625         int ret = 0;
626
627         ret = access("/usr/bin/verityctl", F_OK);
628         if (ret == -1) {
629                 if (errno == ENOENT) {
630                         LOG("dm-verity status : disabled\n");
631                         dm_verity_status = DM_VERITY_DISABLED;
632                         return 0;
633                 } else {
634                         LOG("access failed with errno: %d\n", errno);
635                         return -errno;
636                 }
637         }
638
639         LOG("dm-verity status : enabled\n");
640         dm_verity_status = DM_VERITY_ENABLED;
641         return 0;
642 }
643
644 /*-----------------------------------------------------------------------------
645   set_delta_folder
646  ----------------------------------------------------------------------------*/
647 int set_delta_folder(void)
648 {
649         char *pos = strrchr(delta_path, '/');
650         if (pos == NULL) {
651                 snprintf(delta_folder, MAX_FOLDER_PATH, ".", delta_path);       // if no "/" in delta path, assume current directory as delta folder
652                 return 0;
653         }
654         if ((pos - delta_path + 1) == strlen(delta_path)) {
655                 print_usage("Invalid delta path");
656                 return -1;
657         }
658         snprintf(delta_folder, (pos - delta_path) + 1, "%s", delta_path);
659         return 0;
660 }
661 /*-----------------------------------------------------------------------------
662   set_tar_info
663  ----------------------------------------------------------------------------*/
664 void set_tar_info(TAR *tar)
665 {
666         s_tar_data.subject_name = strdup(s_part_info.ua_subject_name);
667         s_tar_data.tar = tar;
668         s_tar_data.subject_offset = 0;
669         s_tar_data.uncompressed_folder_size = 0;
670
671         s_new_files_info.offset = 0;
672         snprintf(s_new_files_info.item_name,  MAX_FILE_PATH, "%s%s",  s_tar_data.subject_name, SS_NEW_COMPRESSED_FILE);
673         snprintf(s_new_files_info.extracted_name, MAX_FILE_PATH, "%s/%s",  s_update_data.ua_delta_folder, SS_NEW_COMPRESSED_FILE);
674
675         s_text_files_info[PATCHLIST_FILE].size = 0;
676         s_text_files_info[ATTR_FILE].size = 0;
677
678         snprintf(s_text_files_info[PATCHLIST_FILE].item_name, MAX_FILE_PATH, "%s%s%s", s_tar_data.subject_name, s_part_info.ua_parti_name, SS_PATCHLISTFORMAT);
679         snprintf(s_text_files_info[PATCHLIST_FILE].extracted_name, MAX_FILE_PATH, "%s/%s%s", s_update_data.ua_delta_folder, s_part_info.ua_parti_name, SS_PATCHLISTFORMAT);
680
681         snprintf(s_text_files_info[ATTR_FILE].item_name, MAX_FILE_PATH, "%s%s%s", s_tar_data.subject_name, s_part_info.ua_parti_name, SS_PATCH_ATTR_FORMAT);
682         snprintf(s_text_files_info[ATTR_FILE].extracted_name, MAX_FILE_PATH, "%s/%s%s", s_update_data.ua_delta_folder, s_part_info.ua_parti_name, SS_PATCH_ATTR_FORMAT);
683
684         s_tar_data.text_files_info[PATCHLIST_FILE] = s_text_files_info[PATCHLIST_FILE];
685         s_tar_data.text_files_info[ATTR_FILE] = s_text_files_info[ATTR_FILE];
686         s_tar_data.new_files_info = s_new_files_info;
687 }
688 /*-----------------------------------------------------------------------------
689   arg_parse
690  ----------------------------------------------------------------------------*/
691 int arg_parse(int argc, char ** argv, temp_opt *my_opt)
692 {
693         if (argc != 7) {
694                 print_usage("Invalid parameter count");
695                 return -1;
696         }
697         char * archive = NULL;
698         char * archive_file = NULL;
699         char * dest = NULL;
700         const struct option long_options[] = {
701                 {"archive",      required_argument, NULL, 0  },
702                 {"dest",         required_argument, NULL, 1  },
703                 {"archive-file", required_argument, NULL, 2  },
704                 {0}
705         };
706         while (1) {
707                 int option = getopt_long(argc, argv, "", long_options, NULL);
708                 if (option < 0)
709                         break;
710                 switch (option) {
711                 case 0:
712                         if (archive != NULL) {
713                                 print_usage("Parameters repeated");
714                                 return -1;
715                         }
716                         archive = optarg;
717                         break;
718                 case 1:
719                         if (dest != NULL) {
720                                 print_usage("Parameters repeated");
721                                 return -1;
722                         }
723                         dest = optarg;
724                         break;
725                 case 2:
726                         if (archive_file != NULL) {
727                                 print_usage("Parameters repeated");
728                                 return -1;
729                         }
730                         archive_file = optarg;
731                         break;
732                 default:
733                         print_usage("Invalid parameters");
734                         return -1;
735                 }
736         }
737         if (archive_file == NULL || dest == NULL || archive == NULL) {
738                 print_usage("Wrong parameters");
739                 return -1;
740         }
741         (*my_opt).archive = archive;
742         (*my_opt).dest = dest;
743         (*my_opt).archive_file = archive_file;
744
745         return 0;
746 }
747
748 /*-----------------------------------------------------------------------------
749   main
750  ----------------------------------------------------------------------------*/
751 int main(int argc, char **argv)
752 {
753         char ver_str[MAX_PATH];
754         int ret = FAIL;
755         char *dot_pos;
756         int len;
757         temp_opt my_opt;
758         tartype_t *type;
759         TAR *tar;
760         log_init();
761         if (arg_parse(argc, argv, &my_opt) < 0) {
762                 ret = UPI_INVALID_PARAM_ERROR;
763                 goto Results;
764         }
765
766 #if defined(FEATURE_SUPPORT_CAPABILITY)
767         SS_set_feature_support_capability(1);
768 #endif
769
770         snprintf(delta_path, sizeof(delta_folder)-1, "%s", my_opt.archive);
771         if (set_delta_folder() < 0) {
772                 ret = UPI_INVALID_PARAM_ERROR;
773                 goto Results;
774         }
775         s_update_data.ua_delta_folder = strdup(delta_folder);
776         s_update_data.ua_delta_path = strdup(delta_path);
777         snprintf(mnt_point, sizeof(mnt_point)-1, "%s", my_opt.dest);
778         snprintf(temp_folder, sizeof(temp_folder)-1, "%s", TEMP_FOLDER);
779         snprintf(log_folder, sizeof(log_folder)-1, "%s", SYSTEM_LOG_DIR);
780         snprintf(fota_result, sizeof(fota_result), "%s/%s", result_folder, "result");
781
782
783         if (check_dm_verity_status() < 0) { // to be removed
784                 LOG("check_dm_verity_status fail\n");
785                 ret = UPI_CONFIG_ERROR;
786                 goto Results;
787         }
788
789         dot_pos = strchr(my_opt.archive_file, '.');
790         len = (dot_pos - my_opt.archive_file);
791         s_part_info.ua_parti_name = (char*)malloc(sizeof(char) * (len + 1));
792         strncpy(s_part_info.ua_parti_name, my_opt.archive_file, len);
793         s_part_info.ua_parti_name[len] = '\0';
794
795         s_part_info.ua_subject_name = my_opt.archive_file;
796         s_update_cfg.source_img_size = 0; // TODO lets see if 0 works
797
798         if (tar_get_tartype(s_update_data.ua_delta_path, &type) < 0) {
799                 ret = UPI_CONFIG_ERROR;
800                 goto Results;
801         }
802
803         if (tar_init_with_type(&tar, s_update_data.ua_delta_path, type) < 0) {
804                 ret = UPI_CONFIG_ERROR;
805                 goto Results;
806         }
807
808         set_tar_info(tar);
809
810
811
812         LOG("<<<<<<<<<<< log_init >>>>>>>>>>>>\n");
813
814         /* UPI version check */
815         if (S_SS_SUCCESS == SS_GetUPIVersion((unsigned char*)ver_str)) {
816                 LOG("<<<<<<<<< TOTA Update Agent %s >>>>>>>>>>>>\n", ver_str);
817         } else {
818                 LOG("[SS_GetUPIVersion fail] \n");
819                 ret = UPI_VERSION_ERROR;
820                 goto Results;
821         }
822         /* Main Update Routine : Scout & Update */
823         ret = update_all();
824         LOG("[update_all ret=%d]\n", ret);
825
826  Results:
827         LOG("Result=%d\n", ret);
828         save_result(ret);
829         if (ret != SUCCESS)
830                 print_error_code(ret);
831         switch (ret) {
832         /* Before initialize fota path */
833         case UPI_INVALID_PARAM_ERROR:
834         case UPI_DELTA_PATH_ERROR:
835         case UPI_CONFIG_ERROR:
836         case UPI_PARTINFO_ERROR:
837         case UPI_DELTA_PATH_LENGTH_ERROR:
838                 log_deinit();
839                 _exit_stdio();
840                 return -1;
841         /* After initialize fota path */
842         case UPI_VERSION_ERROR:
843         case UPI_DELTACOUNT_ERROR:
844         case UPI_VERIFY_ERROR:
845         case UPI_UPDATE_ERROR:
846                 log_deinit();
847                 if(s_tar_data.tar)
848                         tar_close(s_tar_data.tar);
849                 _exit_stdio();
850                 return -1;
851         case SUCCESS:
852                 log_deinit();
853                 /* Preserve log file for debugging */
854                 if(s_tar_data.tar)
855                         tar_close(s_tar_data.tar);
856                 _exit_stdio();
857                 return 0;
858         default:
859                 LOG("!!! Not expected ret (= %d)\n", ret);
860         }
861
862         if(s_part_info.ua_parti_name)   free(s_part_info.ua_parti_name);
863         if(s_part_info.ua_subject_name) free(s_part_info.ua_subject_name);
864
865         _exit_stdio();
866         return -1;
867 }