Rename delta-ua directory to upgrade-apply-deltafs and delta.ua binary to upgrade...
[platform/core/system/upgrade.git] / src / upgrade-apply-deltafs / engine / fota_tar.c
1 /*
2  * upgrade-apply-deltafs
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 <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include "SS_Engine_Errors.h"
28 #include "SS_FSUpdate.h"
29 #include "fota_common.h"
30 #include "fota_tar.h"
31 #include "ua_types.h"
32
33 /* tar Header Block, from POSIX 1003.1-1990. for reference */
34 #if 0
35                 /* POSIX header.  */
36
37 struct posix_header {              /* byte offset */
38         char name[100];                  /*   0 */
39         char mode[8];                      /* 100 */
40         char uid[8];                            /* 108 */
41         char gid[8];                            /* 116 */
42         char size[12];                    /* 124 */
43         char mtime[12];                  /* 136 */
44         char chksum[8];                  /* 148 */
45         char typeflag;                    /* 156 */
46         char linkname[100];              /* 157 */
47         char magic[6];                    /* 257 */
48         char version[2];                        /* 263 */
49         char uname[32];                  /* 265 */
50         char gname[32];                  /* 297 */
51         char devmajor[8];                  /* 329 */
52         char devminor[8];                  /* 337 */
53         char prefix[155];                  /* 345 */
54         /* 500 */
55 };
56 #endif
57
58 #define MAX_ITEM_SIZE                           0x7FFFFFFF
59 #define TAR_ITEM_SIZE_POSITION  124
60 #define TAR_SIZE_OF_ITEM_SIZE           8
61 #define TAR_SIZE_OF_HEADER              12
62 #define TAR_BLOCK_SIZE                          512
63 #define TAR_ITEM_NAME_SIZE              100
64 #define TAR_LONG_NAME_SIZE              256
65 #define TAR_ITEM_TYPE_FLAG_POS  156
66 /*** The byte that indicates whether the prefix is present or not */
67 #define PREFIX_INDICATOR_BYTE 345
68 #define PREFIX_LEN 155
69
70 /** the rest heavily based on (ie mostly) untgz.c from zlib **/
71
72 /* Values used in typeflag field.  */
73
74 #define REGTYPE  '0'                    /* regular file */
75 #define AREGTYPE '\0'              /* regular file */
76 #define LNKTYPE  '1'                    /* link */
77 #define SYMTYPE  '2'                    /* reserved */
78 #define CHRTYPE  '3'                    /* character special */
79 #define BLKTYPE  '4'                    /* block special */
80 #define DIRTYPE  '5'                    /* directory */
81 #define FIFOTYPE '6'                    /* FIFO special */
82 #define CONTTYPE '7'                    /* reserved, for compatibility with gnu tar,
83                                                                    treat as regular file, where it represents
84                                                                    a regular file, but saved contiguously on disk */
85
86 /* GNU tar extensions */
87
88 #define GNUTYPE_DUMPDIR  'D'    /* file names from dumped directory */
89 #define GNUTYPE_LONGLINK 'K'    /* long link name */
90 #define GNUTYPE_LONGNAME 'L'    /* long file name */
91 #define GNUTYPE_MULTIVOL 'M'    /* continuation of file from another volume */
92 #define GNUTYPE_NAMES   'N'     /* file name that does not fit into main hdr */
93 #define GNUTYPE_SPARSE   'S'    /* sparse file */
94 #define GNUTYPE_VOLHDR   'V'    /* tape/volume header */
95
96 extern void *SS_Malloc(SS_UINT32 size);
97
98 int gTarFd = -1;                                // Currenlty this logic supports only one tar file
99
100 void create_dir(char *pathname, int mode)
101 {
102         char *p;
103         int r;
104
105         /* Strip trailing '/' */
106         if (pathname[strlen(pathname) - 1] == '/')
107                 pathname[strlen(pathname) - 1] = '\0';
108
109         /* Try creating the directory. */
110         r = mkdir(pathname, mode);
111
112         if (r != 0) {
113                 /* On failure, try creating parent directory. */
114                 p = strrchr(pathname, '/');
115                 if (p != NULL) {
116                         *p = '\0';
117                         create_dir(pathname, 0755);
118                         *p = '/';
119                         r = mkdir(pathname, mode);
120                 }
121         }
122         if (r != 0) {
123                 if (r != EEXIST && r != -1)
124                         LOG("Could not create directory [%s] Error[%d]\n", pathname, r);
125         }
126 }
127
128 /*-----------------------------------------------------------------------------
129   tar_get_item_offset
130  ----------------------------------------------------------------------------*/
131 int tar_get_item_offset(char *tar, char *item)
132 {
133         int ret = -1;
134         int fd = -1;
135         char header[TAR_BLOCK_SIZE] = { 0, };
136         char uExtendedName[MAX_FILE_PATH + 1] = { 0, };
137         char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
138         unsigned long size_dec = 0;
139         int blknum = 0;
140         off_t pos = 0;
141         off_t tar_len = 0;
142         ssize_t rdcnt = 0;
143
144         if (!item || !tar){
145                 LOG("Invalid params\n");
146                 return -1;
147         };
148         //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it
149         if (gTarFd >= 0)
150                 fd = gTarFd;
151         else {
152                 fd = open(tar, O_RDONLY);
153                 if (fd < 0) {
154                         LOGE("can't open file(%s).\n", tar);
155                         return -1;
156                 }
157         }
158
159         tar_len = lseek(fd, 0, SEEK_END);
160         if (tar_len < 0) {
161                 LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
162                 goto Cleanup;
163         }
164         pos = lseek(fd, 0, SEEK_SET);
165         if (pos < 0) {
166                 LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
167                 goto Cleanup;
168         }
169         while (pos < tar_len) {
170                 /* read file header */
171                 rdcnt = read(fd, header, sizeof(header));
172                 if (rdcnt <= 0) {
173                         LOG("read failed. (rdcnt=%d)\n", rdcnt);
174                         break;
175                 }
176
177                 /* get file name and file size */
178                 if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) {
179                         //rdcnt = read(fd, header, sizeof(header));
180                         memset(uExtendedName, 0, sizeof(uExtendedName));
181                         rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1);
182                         if (rdcnt <= 0) {
183                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
184                                 break;
185                         }
186                         rdcnt = read(fd, header, sizeof(header));
187                         if (rdcnt <= 0) {
188                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
189                                 break;
190                         }
191                 } else {
192                         memset(uExtendedName, 0, sizeof(uExtendedName));
193                         memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE);
194                 }
195                 memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
196                 size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
197                 if (size_dec > MAX_ITEM_SIZE) {
198                         LOG("ITEM : [%s]\n", item);
199                         LOG("size too big. (size_dec=0x%08X)\n", size_dec);
200                         break;
201                 }
202
203                 /* check if the file is what we are looking for */
204                 if (strncmp(uExtendedName, item, sizeof(uExtendedName) - 1) == 0) {
205                         ret = (int)lseek(fd, 0, SEEK_CUR);
206                         break;
207                 }
208
209                 /* move file pointer to next file header */
210                 blknum = size_dec / TAR_BLOCK_SIZE;
211                 if (size_dec % TAR_BLOCK_SIZE)
212                         blknum++;
213
214                 pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
215                 if (pos < 0) {
216                         LOGE("can't read next block (%s).\n", tar);
217                         close(fd);
218                         return -1;
219                 }
220         }
221
222  Cleanup:
223         if (gTarFd < 0)
224                 close(fd);
225
226         return ret;
227 }
228
229 /*-----------------------------------------------------------------------------
230   tar_get_item_size
231  ----------------------------------------------------------------------------*/
232 int tar_get_item_size(char *tar, char *item)
233 {
234         int ret = -1;
235         int fd = -1;
236         char header[TAR_BLOCK_SIZE] = { 0, };
237         char uExtendedName[MAX_FILE_PATH + 1] = { 0, };
238         char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
239         unsigned long size_dec = 0;
240         int blknum = 0;
241         off_t pos = 0;
242         off_t tar_len = 0;
243         ssize_t rdcnt = 0;
244
245         if (!item || !tar){
246                 LOG("Invalid params\n");
247                 return -1;
248         }
249         LOGL(LOG_SSENGINE, "Tar file Looking for (%s)\n", item);
250         fd = open(tar, O_RDONLY);
251         if (fd < 0) {
252                 LOG("can't open file(%s).\n", tar);
253                 return -1;
254         }
255
256         tar_len = lseek(fd, 0, SEEK_END);
257         if (tar_len < 0) {
258                 LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
259                 goto Cleanup;
260         }
261         pos = lseek(fd, 0, SEEK_SET);
262         if (pos < 0) {
263                 LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
264                 goto Cleanup;
265         }
266
267         while (pos < tar_len) {
268                 /* read file header */
269                 rdcnt = read(fd, header, sizeof(header));
270                 if (rdcnt <= 0) {
271                         LOG("read failed. (rdcnt=%d)\n", rdcnt);
272                         break;
273                 }
274
275                 /* get file name and file size */
276                 if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) {
277                         //rdcnt = read(fd, header, sizeof(header));
278                         memset(uExtendedName, 0, sizeof(uExtendedName));
279                         rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1);
280                         if (rdcnt <= 0) {
281                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
282                                 break;
283                         }
284                         rdcnt = read(fd, header, sizeof(header));
285                         if (rdcnt <= 0) {
286                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
287                                 break;
288                         }
289                 } else {
290                         memset(uExtendedName, 0, sizeof(uExtendedName));
291                         memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE);
292                 }
293                 memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
294                 size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
295                 if (size_dec > MAX_ITEM_SIZE) {
296                         LOG("ITEM : [%s]\n", item);
297                         LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
298                         break;
299                 }
300
301                 /* check if the file is what we are looking for */
302                 if (strncmp(uExtendedName, item, sizeof(uExtendedName) - 1) == 0) {
303                         ret = (int)size_dec;
304                         if ((ret == 0) && (header[TAR_ITEM_TYPE_FLAG_POS] == DIRTYPE))
305                                 ret = tar_get_folder_size(tar, item);
306                         break;
307                 }
308                 /* move file pointer to next file header */
309                 //LOGL(LOG_SSENGINE,"Item in Tar (%s)\n", uExtendedName);
310                 blknum = size_dec / TAR_BLOCK_SIZE;
311                 if (size_dec % TAR_BLOCK_SIZE)
312                         blknum++;
313
314                 pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
315                 if (pos < 0) {
316                         LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
317                         close(fd);
318                         return -1;
319                 }
320         }
321
322  Cleanup:
323         close(fd);
324
325         return ret;
326 }
327
328 /*-----------------------------------------------------------------------------
329   tar_get_cfg_data
330  ----------------------------------------------------------------------------*/
331 int tar_get_cfg_data(char *tar, char *item, char *buf, int buflen)
332 {
333         int fd = -1;
334         int data_size = -1;
335         int data_offset = -1;
336         off_t pos = 0;
337         ssize_t rdcnt = 0;
338
339         if (!buf){
340                 LOG("Invalid params\n");
341                 return -1;
342         }
343         data_size = tar_get_item_size(tar, item);
344         if (data_size <= 0)
345                 return -1;
346
347         if (data_size > buflen)
348                 data_size = buflen;
349
350         data_offset = tar_get_item_offset(tar, item);
351         if (data_offset < 0)
352                 return -1;
353
354         fd = open(tar, O_RDONLY);
355         if (fd < 0) {
356                 LOG("can't open file(%s).\n", tar);
357                 return -1;
358         }
359
360         pos = lseek(fd, data_offset, SEEK_SET);
361         if (pos < 0) {
362                 LOG("lseek fail (%s offset %d).\n", tar, data_offset);
363                 close(fd);
364                 return -1;
365         }
366
367         rdcnt = read(fd, buf, data_size);
368         if (rdcnt != (ssize_t) data_size) {
369                 LOG("read fail(%s from %s).\n", item, tar);
370                 close(fd);
371                 return -1;
372         }
373
374         close(fd);
375
376         return rdcnt;
377 }
378
379 tar_Data_t *tar_build_cfg_table(char *tar)
380 {
381
382         int fd = -1;
383         int ret = 0;
384         char header[TAR_BLOCK_SIZE] = { 0, };
385         char uExtendedName[MAX_FILE_PATH + 1] = { 0, };
386         char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
387         unsigned long size_dec = 0;
388         int blknum = 0;
389         off_t pos = 0;
390         off_t tar_len = 0;
391         ssize_t rdcnt = 0;
392
393         int itemSize;
394         int itemOffset;
395         tar_Data_t *headparam = NULL, *tailparam = NULL, *newnode = NULL;
396         tar_Data_t *local_temp = NULL;
397         tar_Data_t *local_next = NULL;
398         if (!tar) {
399                 LOGE("Bad param tar\n");
400                 return NULL;
401         }
402         //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it
403         if (gTarFd >= 0)
404                 fd = gTarFd;
405         else {
406                 fd = open(tar, O_RDONLY);
407                 if (fd < 0) {
408                         LOG("can't open file(%s).\n", tar);
409                         return NULL;
410                 }
411         }
412
413         tar_len = lseek(fd, 0, SEEK_END);
414         if (tar_len < 0) {
415                 LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
416                 goto Cleanup;
417         }
418         pos = lseek(fd, 0, SEEK_SET);
419         if (pos < 0) {
420                 LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
421                 goto Cleanup;
422         }
423         while (pos < tar_len) {
424                 /* read file header */
425                 rdcnt = read(fd, header, sizeof(header));
426                 if (rdcnt <= 0) {
427                         LOG("read failed. (rdcnt=%d)\n", rdcnt);
428                         ret = -1;
429                         break;
430                 }
431                 /* get file name and file size */
432                 if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) {
433                         //rdcnt = read(fd, header, sizeof(header));
434                         memset(uExtendedName, 0, sizeof(uExtendedName));
435                         rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1);
436                         if (rdcnt <= 0) {
437                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
438                                 ret = -1;
439                                 break;
440                         }
441                         rdcnt = read(fd, header, sizeof(header));
442                         if (rdcnt <= 0) {
443                                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
444                                 ret = -1;
445                                 break;
446                         }
447                 } else {
448                         memset(uExtendedName, 0, sizeof(uExtendedName));
449                         memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE);
450                 }
451                 memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
452                 size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
453                 if (size_dec > MAX_ITEM_SIZE) {
454                         LOG("uExtendedName is : [%s]\n", uExtendedName);
455                         LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
456                         ret = -1;
457                         break;
458                 }
459                 //fix WGID : 51254 , size_dec comparison is not required
460                 if ((strstr(uExtendedName, "/diff") != NULL)) { //add only delta files from rootfs and csc, hardcoding shd b removed..
461
462                         /* check if the file is what we are looking for */
463                         //strncpy(itemName, name,100);
464                         itemSize = (int)size_dec;
465                         itemOffset = (int)lseek(fd, 0, SEEK_CUR);
466                         newnode = (tar_Data_t *) SS_Malloc(sizeof(tar_Data_t));
467                         if (!newnode) {
468                                 ret = -1;
469                                 break;
470                         }
471                         memset(newnode->itemName, 0, sizeof(newnode->itemName));
472                         strncpy((char *)newnode->itemName, uExtendedName, sizeof(newnode->itemName) - 1);
473                         newnode->itemOffset = itemOffset;
474                         newnode->itemSize = itemSize;
475                         newnode->nextnode = NULL;
476                         if (headparam == NULL) {
477                                 headparam = newnode;
478                                 tailparam = newnode;
479                         } else {
480                                 (tailparam)->nextnode = newnode;
481                                 (tailparam) = (tailparam)->nextnode;
482                         }
483                 }
484
485                 /* move file pointer to next file header */
486                 blknum = size_dec / TAR_BLOCK_SIZE;
487                 if (size_dec % TAR_BLOCK_SIZE)
488                         blknum++;
489
490                 pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
491                 if (pos < 0) {
492                         LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
493                         ret = -1;
494                         break;
495                 }
496         }
497  Cleanup:
498         //if gTarFd was opened by tar_open during SS_FSUpdateFile we do not close it
499         if (gTarFd < 0)
500                 close(fd);
501         if (ret != -1)
502                 return headparam;
503         else {
504                 if (headparam != newnode && newnode)
505                         SS_Free(newnode);
506                 if (headparam) {
507                         local_temp = headparam;
508                         while (local_temp) {
509                                 local_next = local_temp->nextnode;
510                                 SS_Free(local_temp);
511                                 local_temp = local_next;
512                         }
513                 }
514                 return NULL;
515         }
516 }
517
518 void tar_free_cfg_table(tar_Data_t ** delta_tar)
519 {
520         tar_Data_t *local_temp = NULL;
521         tar_Data_t *local_next = NULL;
522         LOGL(LOG_SSENGINE, "Free TAR CFG TABLE\n");
523         if (*delta_tar) {
524                 local_temp = *delta_tar;
525                 while (local_temp) {
526                         local_next = local_temp->nextnode;
527                         //LOGL(LOG_SSENGINE,"freeing [%s]\n",local_temp->itemName);
528                         SS_Free(local_temp);
529                         local_temp = local_next;
530                 }
531         }
532 }
533
534 void deleteNode(tar_Data_t * head, tar_Data_t * n)
535 {
536         tar_Data_t *prev = head;
537         if (head == n) {
538                 if (head->nextnode == NULL) {
539                         LOG("There is only one node. The list can't be made empty\n");
540                         return;
541                 }
542                 strncpy((char *)head->itemName, (const char *)head->nextnode->itemName, TAR_ITEM_NAME_SIZE);    //head->itemName = head->nextnode->itemName;
543                 head->itemSize = head->nextnode->itemSize;
544                 head->itemOffset = head->nextnode->itemOffset;
545                 n = head->nextnode;
546                 head->nextnode = head->nextnode->nextnode;
547                 SS_Free(n);
548                 return;
549         }
550         while (prev->nextnode != NULL && prev->nextnode != n)
551                 prev = prev->nextnode;
552         if (prev->nextnode == NULL) {
553                 LOG("Given node is not present in Linked List\n");
554                 return;
555         }
556         prev->nextnode = prev->nextnode->nextnode;
557         SS_Free(n);
558         return;
559 }
560
561 int tar_get_item_size_from_struct(tar_Data_t ** delta_tar, const char *patchname, int *data_size, int *data_offset)
562 {
563         tar_Data_t *head = *delta_tar;
564         tar_Data_t *base = *delta_tar;
565         if (head == NULL)
566                 return 1;
567         else {
568                 //LOG("fast_tar_get_item_size- looking for [%s] [%s]\n",patchname,head->itemName);
569                 while (1) {
570                         if (strstr((const char *)head->itemName, patchname) != 0) {
571                                 //LOG("fast_tar_get_item_size found [%s]  in [%s]\n",patchname, head->itemName);
572                                 *data_size = head->itemSize;
573                                 *data_offset = head->itemOffset;
574                                 deleteNode(base, head);
575                                 return 0;
576
577                         } else if (head->nextnode != NULL) {
578                                 head = head->nextnode;
579                                 //LOG("fast_tar_get_item_size current node [%s] \n",head->itemName);
580                         } else {
581                                 LOGE("fast_tar_get_item_size FAILED TO GET [%s]  in [%s]\n", patchname, (char *)head->itemName);
582                                 break;
583                         }
584                 }
585                 return 1;
586         }
587 }
588
589 int tar_open(char *tar)
590 {
591         if (gTarFd >= 0)
592                 close(gTarFd);
593         gTarFd = open(tar, O_RDONLY);
594         if (gTarFd < 0) {
595                 LOG("can't open TAR file(%s).\n", tar);
596                 return -1;
597         }
598         return 0;
599 }
600
601 int tar_close()
602 {
603         if (gTarFd >= 0)
604                 close(gTarFd);
605         gTarFd = -1;
606         return 0;
607 }
608
609 int tar_get_folder_size(char *tar, char *item)
610 {
611         int ret = -1;
612         int fd = -1;
613         char header[TAR_BLOCK_SIZE] = { 0, };
614         char name[TAR_LONG_NAME_SIZE + 1] = { 0, };
615         char *lastfolder = NULL;
616         int folderpathlen = 0;
617         char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
618         unsigned long size_dec = 0;
619         int blknum = 0;
620         off_t pos = 0;
621         off_t tar_len = 0;
622         ssize_t rdcnt = 0;
623
624         if (!item || !tar){
625                 LOG("Invalid params\n");
626                 return -1;
627         }
628         LOG("Tar folder Looking for (%s)\n", item);
629         fd = open(tar, O_RDONLY);
630         if (fd < 0) {
631                 LOG("can't open file(%s).\n", tar);
632                 return -1;
633         }
634
635         tar_len = lseek(fd, 0, SEEK_END);
636         if (tar_len < 0) {
637                 LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
638                 goto Cleanup;
639         }
640         pos = lseek(fd, 0, SEEK_SET);
641         if (pos < 0) {
642                 LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
643                 goto Cleanup;
644         }
645
646         while (pos < tar_len) {
647                 /* read file header */
648                 rdcnt = read(fd, header, sizeof(header));
649                 if (rdcnt <= 0) {
650                         LOG("read failed. (rdcnt=%d)\n", rdcnt);
651                         ret = -1;
652                         break;
653                 }
654
655                 /* get file name and file size */
656                 memcpy(name, header, sizeof(name) - 1);
657                 memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
658                 errno = 0;
659                 size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
660                 if (errno != 0) {
661                         LOG("strtoul failed. (errno=%d)\n", errno);
662                         ret = -1;
663                         break;
664                 } else if (size_dec > MAX_ITEM_SIZE) {
665                         LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
666                         ret = -1;
667                         break;
668                 }
669
670                 /* check if the file is what we are looking for */
671                 //Get until folder name
672
673                 lastfolder = strrchr(name, '/');
674                 if (lastfolder)
675                         folderpathlen = strlen(name) - strlen(lastfolder);
676
677                 if (strncmp(name, item, folderpathlen) == 0) {
678                         ret += (int)size_dec;
679                         //LOG("Tar Files under folder [%s]\n", name);
680                         //break;
681                 }
682
683                 /* move file pointer to next file header */
684                 blknum = size_dec / TAR_BLOCK_SIZE;
685                 if (size_dec % TAR_BLOCK_SIZE)
686                         blknum++;
687
688                 pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
689                 if (pos < 0) {
690                         LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
691                         close(fd);
692                         return -1;
693                 }
694         }
695
696  Cleanup:
697         close(fd);
698         LOG("ret=%d\n", ret);
699
700         return ret;                              //Should return +1?? or Ignore??
701 }
702
703 int fast_tar_extract_file(char *tar, char *item, char *pathname, int size, int offset)
704 {
705         int fd = -1;
706         int data_size = size;
707         int data_offset = offset;
708         off_t pos = 0;
709         ssize_t rdcnt = 0;
710         ssize_t writeCount = 0;
711         char *buf = NULL;
712         char err_buf[256];
713         int fd2;
714
715         if (!item || !tar || !pathname){
716                 LOG("Invalid params\n");
717                 return -1;
718         }
719         if (gTarFd >= 0)
720                 fd = gTarFd;
721         else {
722                 fd = open(tar, O_RDONLY);
723                 if (fd < 0) {
724                         LOG("can't open file(%s).\n", tar);
725                         return -1;
726                 }
727         }
728
729         pos = lseek(fd, data_offset, SEEK_SET);
730         if (pos < 0) {
731                 LOG("lseek fail (%s offset %d).\n", tar, data_offset);
732                 close(fd);
733                 return -1;
734         }
735         buf = SS_Malloc(data_size + 1);
736         if (buf == NULL) {
737                 close(fd);
738                 LOGE("Failed to Allocate Memory\n");
739                 return -1;
740         }
741         rdcnt = read(fd, buf, data_size);
742         if (rdcnt != (ssize_t) data_size) {
743                 LOG(" rdcnt read fail(%s from %s).\n", item, tar);
744                 SS_Free(buf);
745                 close(fd);
746                 return -1;
747         }
748         fd2 = open(pathname, O_CREAT | O_WRONLY, S_IRWXU);       // Directory where file is required should be created already.
749         if (fd2 < 0) {
750                 LOG("can't open file(%s).\n", pathname);
751                 SS_Free(buf);
752                 close(fd);
753                 return -1;
754         }
755         writeCount = write(fd2, buf, rdcnt);
756         if (writeCount != rdcnt) {
757                 LOG("writeCount write fail(%s from %s).\n", item, tar);
758                 strerror_r(errno, err_buf, sizeof(err_buf));
759                 LOG("Oh  dear, something went wrong with read()! %s\n", err_buf);
760                 close(fd);
761                 close(fd2);
762                 SS_Free(buf);
763                 return -1;
764         }
765         SS_Free(buf);
766         if (gTarFd < 0)
767                 close(fd);
768         fsync(fd2);
769         close(fd2);
770         return rdcnt;                      // or jus return success?
771 }
772
773 int tar_extract_file(char *tar, char *item, char *pathname)
774 {
775         int fd = -1;
776         int data_size = -1;
777         int data_offset = -1;
778         off_t pos = 0;
779         ssize_t rdcnt = 0;
780         ssize_t writeCount = 0;
781         char *buf = NULL;
782         char err_buf[256];
783         int fd2;
784
785         if (!item || !tar || !pathname){
786                 LOG("Invalid params\n");
787                 return -1;
788         }
789         data_size = tar_get_item_size(tar, item);
790         data_offset = tar_get_item_offset(tar, item);
791
792         if (data_size <= 0 || data_offset < 0) {
793                 LOGE("Error Not a file , size is [%d], offset [%d] for item [%s]\n", data_size, data_offset, item);
794                 return -1;
795         } else
796                 LOGL(LOG_SSENGINE, "extracting file [%s] size [%d]\n", item, data_size);
797         fd = open(tar, O_RDONLY);
798         if (fd < 0) {
799                 LOG("can't open file(%s).\n", tar);
800                 return -1;
801         }
802         pos = lseek(fd, data_offset, SEEK_SET);
803         if (pos < 0) {
804                 LOG("lseek fail (%s offset %d).\n", tar, data_offset);
805                 close(fd);
806                 return -1;
807         }
808         buf = SS_Malloc(data_size + 1);
809         if (buf == NULL) {
810                 close(fd);
811                 LOGE("Failed to Allocate Memory\n");
812                 return -1;
813         }
814         rdcnt = read(fd, buf, data_size);
815         if (rdcnt != (ssize_t) data_size) {
816                 LOG(" rdcnt read fail(%s from %s).\n", item, tar);
817                 SS_Free(buf);
818                 close(fd);
819                 return -1;
820         }
821         fd2 = open(pathname, O_CREAT | O_WRONLY, S_IRWXU);       // Directory where file is required should be created already.
822         if (fd2 < 0) {
823                 LOG("can't open file(%s).\n", pathname);
824                 SS_Free(buf);
825                 close(fd);
826                 return -1;
827         }
828         writeCount = write(fd2, buf, rdcnt);
829         if (writeCount != rdcnt) {
830                 LOG("writeCount write fail(%s from %s).\n", item, tar);
831                 strerror_r(errno, err_buf, sizeof(err_buf));
832                 LOG("Oh  dear, something went wrong with read()! %s\n", err_buf);
833                 close(fd);
834                 close(fd2);
835                 SS_Free(buf);
836                 return -1;
837         }
838         SS_Free(buf);
839         close(fd);
840         fsync(fd2);
841         close(fd2);
842         return rdcnt;                      // or jus return success?
843 }