Initial codes of libtota
[platform/core/system/libtota.git] / ss_engine / fota_tar.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 <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 "SS_Engine_Update.h"
27 #include "SS_Engine_Errors.h"
28 #include "fota_common.h"
29 #include "fota_tar.h"
30 #include "ua.h"
31
32 /* tar Header Block, from POSIX 1003.1-1990. for reference */
33 #if 0
34         /* POSIX header.  */
35
36 struct posix_header {           /* byte offset */
37     char name[100];             /*   0 */
38     char mode[8];               /* 100 */
39     char uid[8];                /* 108 */
40     char gid[8];                /* 116 */
41     char size[12];              /* 124 */
42     char mtime[12];             /* 136 */
43     char chksum[8];             /* 148 */
44     char typeflag;              /* 156 */
45     char linkname[100];         /* 157 */
46     char magic[6];              /* 257 */
47     char version[2];            /* 263 */
48     char uname[32];             /* 265 */
49     char gname[32];             /* 297 */
50     char devmajor[8];           /* 329 */
51     char devminor[8];           /* 337 */
52     char prefix[155];           /* 345 */
53     /* 500 */
54 };
55 #endif
56
57 #define MAX_ITEM_SIZE                           0x0FFFFFFF
58 #define TAR_ITEM_SIZE_POSITION  124
59 #define TAR_SIZE_OF_ITEM_SIZE           8
60 #define TAR_SIZE_OF_HEADER              12
61 #define TAR_BLOCK_SIZE                          512
62 #define TAR_ITEM_NAME_SIZE              100
63 #define TAR_LONG_NAME_SIZE              256
64 #define TAR_ITEM_TYPE_FLAG_POS  156
65
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 /* Parse an octal number, ignoring leading and trailing nonsense. */
101 static int parseoct(const char *p, size_t n)
102 {
103     int i = 0;
104
105     while (*p < '0' || *p > '7') {
106         ++p;
107         --n;
108     }
109     while (*p >= '0' && *p <= '7' && n > 0) {
110         i *= 8;
111         i += *p - '0';
112         ++p;
113         --n;
114     }
115     return (i);
116 }
117
118 /* Verify the tar checksum. */
119 static int verify_checksum(const char *p)
120 {
121     int n, u = 0;
122     for (n = 0; n < 512; ++n) {
123         if (n < 148 || n > 155)
124             /* Standard tar checksum adds unsigned bytes. */
125             u += ((unsigned char *)p)[n];
126         else
127             u += 0x20;
128
129     }
130     return (u == parseoct(p + 148, 8));
131 }
132
133 static int is_end_of_archive(const char *p)
134 {
135     int n;
136     for (n = 511; n >= 0; --n)
137         if (p[n] != '\0')
138             return (0);
139     return (1);
140 }
141
142 void create_dir(char *pathname, int mode)
143 {
144     char *p;
145     int r;
146
147     /* Strip trailing '/' */
148     if (pathname[strlen(pathname) - 1] == '/')
149         pathname[strlen(pathname) - 1] = '\0';
150
151     /* Try creating the directory. */
152     r = mkdir(pathname, mode);
153
154     if (r != 0) {
155         /* On failure, try creating parent directory. */
156         p = strrchr(pathname, '/');
157         if (p != NULL) {
158             *p = '\0';
159             create_dir(pathname, 0755);
160             *p = '/';
161             r = mkdir(pathname, mode);
162         }
163     }
164     if (r != 0) {
165         if (r != EEXIST && r != -1)
166             LOG("Could not create directory [%s] Error[%d]\n", pathname, r);
167     }
168 }
169
170 /* Create a file, including parent directory as necessary. */
171 static FILE *create_file(char *pathname, int mode)
172 {
173     FILE *f;
174     f = fopen(pathname, "w+");
175     if (f == NULL) {
176         /* Try creating parent dir and then creating file. */
177         char *p = strrchr(pathname, '/');
178         if (p != NULL) {
179             *p = '\0';
180             create_dir(pathname, 0755);
181             *p = '/';
182             f = fopen(pathname, "w+");
183         }
184     }
185     return (f);
186 }
187
188 /*-----------------------------------------------------------------------------
189   tar_get_item_offset
190  ----------------------------------------------------------------------------*/
191 int tar_get_item_offset(char *tar, char *item)
192 {
193     int ret = -1;
194     int fd = -1;
195     char header[TAR_BLOCK_SIZE] = { 0, };
196     char name[TAR_ITEM_NAME_SIZE + 1] = { 0, };
197     char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
198     int size_dec = 0;
199     int blknum = 0;
200     off_t pos = 0;
201     off_t tar_len = 0;
202     ssize_t rdcnt = 0;
203
204     //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it
205     if (gTarFd > 0)
206         fd = gTarFd;
207     if (fd < 0) {
208         fd = open(tar, O_RDONLY);
209         if (fd < 0) {
210             LOGE("can't open file(%s).\n", tar);
211             return -1;
212         }
213     }
214
215     tar_len = lseek(fd, 0, SEEK_END);
216     if (tar_len < 0) {
217         LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
218         goto Cleanup;
219     }
220     pos = lseek(fd, 0, SEEK_SET);
221     if (pos < 0) {
222         LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
223         goto Cleanup;
224     }
225     while (pos < tar_len) {
226         /* read file header */
227         rdcnt = read(fd, header, sizeof(header));
228         if (rdcnt <= 0) {
229             LOG("read failed. (rdcnt=%d)\n", rdcnt);
230             break;
231         }
232
233         /* get file name and file size */
234         memcpy(name, header, sizeof(name) - 1);//wgid: 24572
235         memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
236         size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
237         if (size_dec > MAX_ITEM_SIZE) {
238             LOG("size too big. (size_dec=0x%08X)\n", size_dec);
239             break;
240         }
241
242         /* check if the file is what we are looking for */
243         if (strncmp(name, item, TAR_ITEM_NAME_SIZE) == 0) {
244             ret = (int)lseek(fd, 0, SEEK_CUR);
245             break;
246         }
247
248         /* move file pointer to next file header */
249         blknum = size_dec / TAR_BLOCK_SIZE;
250         if (size_dec % TAR_BLOCK_SIZE)
251             blknum++;
252
253         pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
254         if (pos < 0) {
255             LOGE("can't read next block (%s).\n", tar);
256             close(fd);
257             return -1;
258         }
259     }
260
261  Cleanup:
262     if (gTarFd < 0)
263         close(fd);
264
265     return ret;
266 }
267
268 /*-----------------------------------------------------------------------------
269   tar_get_item_size
270  ----------------------------------------------------------------------------*/
271 int tar_get_item_size(char *tar, char *item)
272 {
273     int ret = -1;
274     int fd = -1;
275     char header[TAR_BLOCK_SIZE] = { 0, };
276     char uExtendedName[MAX_FILE_PATH] = { 0, };
277     char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
278     unsigned long size_dec = 0;
279     int blknum = 0;
280     off_t pos = 0;
281     off_t tar_len = 0;
282     ssize_t rdcnt = 0;
283     LOGL(LOG_SSENGINE, "Tar file Looking for (%s)\n", item);
284     fd = open(tar, O_RDONLY);
285     if (fd < 0) {
286         LOG("can't open file(%s).\n", tar);
287         return -1;
288     }
289
290     tar_len = lseek(fd, 0, SEEK_END);
291     if (tar_len < 0) {
292         LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
293         goto Cleanup;
294     }
295     pos = lseek(fd, 0, SEEK_SET);
296     if (pos < 0) {
297         LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
298         goto Cleanup;
299     }
300
301     while (pos < tar_len) {
302         /* read file header */
303         rdcnt = read(fd, header, sizeof(header));
304         if (rdcnt <= 0) {
305             LOG("read failed. (rdcnt=%d)\n", rdcnt);
306             break;
307         }
308
309         /* get file name and file size */
310         if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) {
311             //rdcnt = read(fd, header, sizeof(header));
312             memset(uExtendedName, 0, sizeof(uExtendedName));
313             rdcnt = read(fd, uExtendedName, sizeof(uExtendedName));
314             if (rdcnt <= 0) {
315                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
316                 break;
317             }
318             rdcnt = read(fd, header, sizeof(header));
319             if (rdcnt <= 0) {
320                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
321                 break;
322             }
323         } else {
324             memset(uExtendedName, 0, sizeof(uExtendedName));
325             memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE);
326         }
327         //memcpy(name, header, sizeof(name));
328         memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
329         size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
330         if (size_dec > MAX_ITEM_SIZE) {
331             LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
332             break;
333         }
334
335         /* check if the file is what we are looking for */
336         if (strcmp(uExtendedName, item) == 0) {
337             ret = (int)size_dec;
338             if ((ret == 0) && (header[TAR_ITEM_TYPE_FLAG_POS] == DIRTYPE))
339                 ret = tar_get_folder_size(tar, item);
340             break;
341         }
342         /* move file pointer to next file header */
343         //LOGL(LOG_SSENGINE,"Item in Tar (%s)\n", uExtendedName);
344         blknum = size_dec / TAR_BLOCK_SIZE;
345         if (size_dec % TAR_BLOCK_SIZE)
346             blknum++;
347
348         pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
349         if (pos < 0) {
350             LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
351             close(fd);
352             return -1;
353         }
354     }
355
356  Cleanup:
357     close(fd);
358
359     return ret;
360 }
361
362 /*-----------------------------------------------------------------------------
363   tar_get_item_tye. (Dir/file/link etc)
364  ----------------------------------------------------------------------------*/
365
366 char tar_get_item_type(char *tar, char *item)
367 {
368     char ret = '0';
369     int fd = -1;
370     char header[TAR_BLOCK_SIZE] = { 0, };
371     char name[TAR_ITEM_NAME_SIZE + 1] = { 0, };
372     char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
373     unsigned long size_dec = 0;
374     int blknum = 0;
375     off_t pos = 0;
376     off_t tar_len = 0;
377     ssize_t rdcnt = 0;
378     //LOG("Tar file Looking for (%s)\n", item);
379     fd = open(tar, O_RDONLY);
380     if (fd < 0) {
381         LOG("can't open file(%s).\n", tar);
382         return -1;
383     }
384
385     tar_len = lseek(fd, 0, SEEK_END);
386     if (tar_len < 0) {
387         LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
388         goto Cleanup;
389     }
390     pos = lseek(fd, 0, SEEK_SET);
391     if (pos < 0) {
392         LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
393         goto Cleanup;
394     }
395
396     while (pos < tar_len) {
397         /* read file header */
398         rdcnt = read(fd, header, sizeof(header));
399         if (rdcnt <= 0) {
400             LOG("read failed. (rdcnt=%d)\n", rdcnt);
401             ret = -1;
402             break;
403         }
404
405         /* get file name and file size */
406         memcpy(name, header, sizeof(name) - 1);//wgid: 24573
407         memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
408         size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
409         if (size_dec > MAX_ITEM_SIZE) {
410             LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
411             ret = -1;
412             break;
413         }
414
415         /* check if the file is what we are looking for */
416         if (strncmp(name, item, TAR_ITEM_NAME_SIZE) == 0) {
417             ret = header[TAR_ITEM_TYPE_FLAG_POS];
418             break;
419         }
420
421         /* move file pointer to next file header */
422         blknum = size_dec / TAR_BLOCK_SIZE;
423         if (size_dec % TAR_BLOCK_SIZE)
424             blknum++;
425
426         pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
427         if (pos < 0) {
428             LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
429             close(fd);
430             return -1;
431         }
432     }
433
434  Cleanup:
435     close(fd);
436
437     return ret;
438 }
439
440 /*-----------------------------------------------------------------------------
441   tar_get_cfg_data
442  ----------------------------------------------------------------------------*/
443 int tar_get_cfg_data(char *tar, char *item, char *buf, int buflen)
444 {
445     int fd = -1;
446     int data_size = -1;
447     int data_offset = -1;
448     off_t pos = 0;
449     ssize_t rdcnt = 0;
450
451     data_size = tar_get_item_size(tar, item);
452     if (data_size <= 0) {
453         return -1;
454     }
455
456     if (data_size > buflen) {
457         data_size = buflen;
458     }
459
460     data_offset = tar_get_item_offset(tar, item);
461     if (data_offset < 0) {
462         return -1;
463     }
464
465     fd = open(tar, O_RDONLY);
466     if (fd < 0) {
467         LOG("can't open file(%s).\n", tar);
468         return -1;
469     }
470
471     pos = lseek(fd, data_offset, SEEK_SET);
472     if (pos < 0) {
473         LOG("lseek fail (%s offset %d).\n", tar, data_offset);
474         close(fd);
475         return -1;
476     }
477
478     rdcnt = read(fd, buf, data_size);
479     if (rdcnt != (ssize_t) data_size) {
480         LOG("read fail(%s from %s).\n", item, tar);
481         close(fd);
482         return -1;
483     }
484
485     close(fd);
486
487     return rdcnt;
488 }
489
490 tar_Data_t *tar_build_cfg_table(char *tar)
491 {
492
493     int fd = -1;
494     int ret = 0;
495     char header[TAR_BLOCK_SIZE] = { 0, };
496     char uExtendedName[MAX_FILE_PATH] = { 0, };
497     char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
498     unsigned long size_dec = 0;
499     int blknum = 0;
500     off_t pos = 0;
501     off_t tar_len = 0;
502     ssize_t rdcnt = 0;
503
504     int itemSize;
505     int itemOffset;
506     tar_Data_t *headparam = NULL, *tailparam = NULL, *newnode = NULL;
507     tar_Data_t *local_temp = NULL;
508     tar_Data_t *local_next = NULL;
509     if (!tar) {
510         LOGE("Bad param tar\n");
511         return NULL;
512     }
513     //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it
514     if (gTarFd > 0)
515         fd = gTarFd;
516     if (fd < 0) {
517         fd = open(tar, O_RDONLY);
518         if (fd < 0) {
519             LOG("can't open file(%s).\n", tar);
520             return NULL;
521         }
522     }
523     tar_len = lseek(fd, 0, SEEK_END);
524     if (tar_len < 0) {
525         LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
526         goto Cleanup;
527     }
528     pos = lseek(fd, 0, SEEK_SET);
529     if (pos < 0) {
530         LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
531         goto Cleanup;
532     }
533     while (pos < tar_len) {
534         /* read file header */
535         rdcnt = read(fd, header, sizeof(header));
536         if (rdcnt <= 0) {
537             LOG("read failed. (rdcnt=%d)\n", rdcnt);
538             ret = -1;
539             break;
540         }
541         /* get file name and file size */
542         //memcpy(name, header, sizeof(name));
543         if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) {
544             //rdcnt = read(fd, header, sizeof(header));
545             memset(uExtendedName, 0, sizeof(uExtendedName));
546             rdcnt = read(fd, uExtendedName, sizeof(uExtendedName));
547             if (rdcnt <= 0) {
548                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
549                 ret = -1;
550                 break;
551             }
552             rdcnt = read(fd, header, sizeof(header));
553             if (rdcnt <= 0) {
554                 LOG("read failed. (rdcnt=%d)\n", rdcnt);
555                 ret = -1;
556                 break;
557             }
558         } else {
559             memset(uExtendedName, 0, sizeof(uExtendedName));
560             memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE);
561         }
562         memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
563         size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
564         if (size_dec > MAX_ITEM_SIZE) {
565             LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
566             ret = -1;
567             break;
568         }
569         //fix WGID : 51254 , size_dec comparison is not required
570         if ((strstr(uExtendedName, "/diff") != NULL)) //add only delta files from rootfs and csc, hardcoding shd b removed..
571         {
572
573             /* check if the file is what we are looking for */
574             //strncpy(itemName, name,100);
575             itemSize = (int)size_dec;
576             itemOffset = (int)lseek(fd, 0, SEEK_CUR);
577             newnode = (tar_Data_t *) SS_Malloc(sizeof(tar_Data_t));
578             if (!newnode) {
579                 ret = -1;
580                 break;
581             }
582             strncpy((char *)newnode->itemName, uExtendedName, sizeof(newnode->itemName));
583             newnode->itemOffset = itemOffset;
584             newnode->itemSize = itemSize;
585             newnode->nextnode = NULL;
586             if (headparam == NULL) {
587                 headparam = newnode;
588                 tailparam = newnode;
589             } else {
590                 (tailparam)->nextnode = newnode;
591                 (tailparam) = (tailparam)->nextnode;
592             }
593         }
594
595         /* move file pointer to next file header */
596         blknum = size_dec / TAR_BLOCK_SIZE;
597         if (size_dec % TAR_BLOCK_SIZE)
598             blknum++;
599
600         pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
601         if (pos < 0) {
602             LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
603             ret = -1;
604             break;
605         }
606     }
607  Cleanup:
608     //if gTarFd was opened by tar_open during SS_FSUpdateFile we do not close it
609     if (gTarFd < 0)
610         close(fd);
611     if (ret != -1)
612         return headparam;
613     else {
614         if (newnode)
615             SS_Free(newnode);
616         if (headparam) {
617             local_temp = headparam;
618             while (local_temp) {
619                 local_next = local_temp->nextnode;
620                 SS_Free(local_temp);
621                 local_temp = local_next;
622             }
623         }
624         return NULL;
625     }
626 }
627
628 void tar_free_cfg_table(tar_Data_t ** delta_tar)
629 {
630     tar_Data_t *local_temp = NULL;
631     tar_Data_t *local_next = NULL;
632     LOGL(LOG_SSENGINE, "Free TAR CFG TABLE\n");
633     if (*delta_tar) {
634         local_temp = *delta_tar;
635         while (local_temp) {
636             local_next = local_temp->nextnode;
637             //LOGL(LOG_SSENGINE,"freeing [%s]\n",local_temp->itemName);
638             SS_Free(local_temp);
639             local_temp = local_next;
640         }
641     }
642 }
643
644 void deleteNode(tar_Data_t * head, tar_Data_t * n)
645 {
646     tar_Data_t *prev = head;
647     if (head == n) {
648         if (head->nextnode == NULL) {
649             LOG("There is only one node. The list can't be made empty ");
650             return;
651         }
652         strncpy((char *)head->itemName, (const char *)head->nextnode->itemName, TAR_ITEM_NAME_SIZE);    //head->itemName = head->nextnode->itemName;
653         head->itemSize = head->nextnode->itemSize;
654         head->itemOffset = head->nextnode->itemOffset;
655         n = head->nextnode;
656         head->nextnode = head->nextnode->nextnode;
657         SS_Free(n);
658         return;
659     }
660     while (prev->nextnode != NULL && prev->nextnode != n)
661         prev = prev->nextnode;
662     if (prev->nextnode == NULL) {
663         LOG("\n Given node is not present in Linked List");
664         return;
665     }
666     prev->nextnode = prev->nextnode->nextnode;
667     SS_Free(n);
668     return;
669 }
670
671 int tar_get_item_size_from_struct(tar_Data_t ** delta_tar, const char *patchname, int *data_size, int *data_offset)
672 {
673     tar_Data_t *head = *delta_tar;
674     tar_Data_t *base = *delta_tar;
675     if (head == NULL)
676         return 1;
677     else {
678         //LOG("fast_tar_get_item_size- looking for [%s] [%s]\n",patchname,head->itemName);
679         while (1) {
680             if (strstr((const char *)head->itemName, patchname) != 0) {
681                 //LOG("fast_tar_get_item_size found [%s]  in [%s]\n",patchname, head->itemName);
682                 *data_size = head->itemSize;
683                 *data_offset = head->itemOffset;
684                 deleteNode(base, head);
685                 return 0;
686
687             } else if (head->nextnode != NULL) {
688                 head = head->nextnode;
689                 //LOG("fast_tar_get_item_size current node [%s] \n",head->itemName);
690             } else {
691                 LOGE("fast_tar_get_item_size FAILED TO GET [%s]  in [%s]\n", patchname, (char *)head->itemName);
692                 break;
693             }
694         }
695         return 1;
696     }
697 }
698
699 tar_Data_t *tar_cfg_clear_nodes(tar_Data_t * head)
700 {
701     tar_Data_t *local_temp = NULL;
702     while (head) {
703         LOGL(LOG_SSENGINE, "tar_cfg_delete_node [%s]", (char *)head->itemName);
704         local_temp = head->nextnode;
705         SS_Free(head);
706         head = local_temp;
707     }
708     return 0;
709 }
710
711 int tar_open(char *tar)
712 {
713     if (gTarFd)
714         close(gTarFd);
715     gTarFd = open(tar, O_RDONLY);
716     if (gTarFd < 0) {
717         LOG("can't open TAR file(%s).\n", tar);
718         return -1;
719     }
720     return 0;
721 }
722
723 int tar_close()
724 {
725     if (gTarFd)
726         close(gTarFd);
727     gTarFd = -1;
728     return 0;
729 }
730
731 int tar_get_folder_size(char *tar, char *item)
732 {
733     int ret = -1;
734     int fd = -1;
735     char header[TAR_BLOCK_SIZE] = { 0, };
736     char name[TAR_LONG_NAME_SIZE + 1] = { 0, };
737     char *lastfolder = NULL;
738     int folderpathlen = 0;
739     char size_oct[TAR_SIZE_OF_HEADER] = { 0, };
740     unsigned long size_dec = 0;
741     int blknum = 0;
742     off_t pos = 0;
743     off_t tar_len = 0;
744     ssize_t rdcnt = 0;
745     LOG("Tar folder Looking for (%s)\n", item);
746     fd = open(tar, O_RDONLY);
747     if (fd < 0) {
748         LOG("can't open file(%s).\n", tar);
749         return -1;
750     }
751
752     tar_len = lseek(fd, 0, SEEK_END);
753     if (tar_len < 0) {
754         LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar);
755         goto Cleanup;
756     }
757     pos = lseek(fd, 0, SEEK_SET);
758     if (pos < 0) {
759         LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar);
760         goto Cleanup;
761     }
762
763     while (pos < tar_len) {
764         /* read file header */
765         rdcnt = read(fd, header, sizeof(header));
766         if (rdcnt <= 0) {
767             LOG("read failed. (rdcnt=%d)\n", rdcnt);
768             ret = -1;
769             break;
770         }
771
772         /* get file name and file size */
773         memcpy(name, header, sizeof(name) - 1);//wgid: 24574
774         memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct));
775         size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE);
776         if (size_dec > MAX_ITEM_SIZE) {
777             LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec);
778             ret = -1;
779             break;
780         }
781
782         /* check if the file is what we are looking for */
783         //Get until folder name
784
785         lastfolder = strrchr(name, '/');
786         if (lastfolder)
787             folderpathlen = strlen(name) - strlen(lastfolder);
788
789         if (strncmp(name, item, folderpathlen) == 0) {
790             ret += (int)size_dec;
791             //LOG("Tar Files under folder [%s]\n", name);
792             //break;
793         }
794
795         /* move file pointer to next file header */
796         blknum = size_dec / TAR_BLOCK_SIZE;
797         if (size_dec % TAR_BLOCK_SIZE)
798             blknum++;
799
800         pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR);
801         if (pos < 0) {
802             LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar);
803             close(fd);
804             return -1;
805         }
806     }
807
808  Cleanup:
809     close(fd);
810     LOG("ret=%d\n", ret);
811
812     return ret;                 //Should return +1?? or Ignore??
813 }
814
815 /*Extract Specific Folder from tar, Taken from Untar.c */
816 int tar_extract_folder(char *tar, char *item, char *path)
817 {
818     char buff[MAX_FILE_PATH];
819     FILE *f = NULL;
820     size_t bytes_read;
821     int filesize;
822     int data_offset = -1;
823     int fd = -1;
824     char name[512] = { 0, };
825     int folderpathlen = 0;
826     char dirPath[512] = { 0 };
827     int getheader = 1;          // Asuming initial header is TAR header
828     char fullname[512] = { 0 };
829     LOG("Extracting Folder from %s %s to %s\n", tar, item, path);
830
831     data_offset = tar_get_item_offset(tar, item);
832     if (data_offset < 0) {
833         LOGE("data offset for [%s] is [%d]\n", item, data_offset);
834         return -1;
835     }
836
837     fd = open(tar, O_RDONLY);
838     if (fd < 0) {
839         LOGE("can't open file(%s).\n", tar);
840         return -1;
841     }
842
843     folderpathlen = strlen(item);
844
845     for (;;) {
846         bytes_read = read(fd, buff, sizeof(buff));
847         if (bytes_read < 512) {
848             LOGE("Short read on %s: expected 512, got %d\n", tar, bytes_read);
849             close(fd);
850             return -1;
851         }
852         if (is_end_of_archive(buff)) {
853             close(fd);
854             LOG("End of %s\n", tar);    //Can stop at end of folder.
855             return S_SS_SUCCESS;
856         }
857         if (!verify_checksum(buff)) {
858             close(fd);
859             LOGE("Checksum failure\n");
860             return -1;
861         }
862         filesize = parseoct(buff + 124, 12);
863         if (getheader == 2) {
864             getheader = 1;
865             //LOG(" Working on LONG FILE NAME CASE [%s]\n", fullname);
866         } else {
867             memset(fullname, 0, sizeof(fullname));
868             strncpy(fullname, buff, 100);
869             //LOG(" Working on Normal FILE NAME CASE [%s]\n", fullname);
870         }
871
872         switch (buff[156]) {
873         case '1':
874             LOG(" Ignoring hardlink %s\n", fullname);
875             break;
876         case '2':
877
878             //LOG(" Creating symlink %s\n", buff);
879             if (strncmp(fullname, item, folderpathlen) == 0) {
880                 //LOG("Printing Buffer \n");
881                 //for(i=157; buff[i] !='\0' ;i++)
882                 //{
883                 //LOG("%c", buff[i])    ;
884                 //}
885                 //LOG("\nEnd buffer\n");
886                 memset(name, 0, sizeof(name));
887                 strncpy(name, buff + 157, 100); //157, target link name will be present
888                 memset(dirPath, 0, sizeof(dirPath));
889                 sprintf(dirPath, "%s/%s", path, fullname + folderpathlen);
890                 LOG(" Creating Symlink [%s][%s]\n", name, dirPath);
891                 symlink(name, dirPath); // use ss_link
892             }
893             break;
894         case '3':
895             LOG(" Ignoring character device %s\n", fullname);
896             break;
897         case '4':
898             LOG(" Ignoring block device %s\n", fullname);
899             break;
900         case '5':
901             //break;//delete
902             //LOG(" Dir [%s] Item [%s] Length [%d]\n", fullname, item, folderpathlen);
903             if (strncmp(fullname, item, folderpathlen) == 0) {
904                 //LOG(" Extracting dir %s\n", fullname);
905                 memset(dirPath, 0, sizeof(dirPath));
906                 sprintf(dirPath, "%s/%s", path, fullname + folderpathlen);
907                 create_dir(dirPath, parseoct(fullname + 100, 8));
908             }
909
910             filesize = 0;
911             break;
912         case '6':
913             LOG(" Ignoring FIFO %s\n", fullname);
914             break;
915         case GNUTYPE_LONGLINK:
916         case GNUTYPE_LONGNAME:
917             {
918                 getheader = 2;
919                 memset(fullname, 0, sizeof(fullname));
920                 bytes_read = read(fd, fullname, sizeof(fullname));
921                 if (bytes_read < 512) {
922                     LOGE("Short read on %s: expected 512, got %d\n", tar, bytes_read);
923                     close(fd);
924                     return -1;
925                 }
926                 filesize = 0;
927                 //LOG("Entered LONG FILE NAME CASE  new NAME is [%s]\n", fullname);
928                 break;
929             }
930
931         default:
932             //break;
933             //LOG(" File [%s] Item [%s] Length [%d]\n", fullname, item, folderpathlen);
934             if (strncmp(fullname, item, folderpathlen) == 0) {
935                 if (buff[PREFIX_INDICATOR_BYTE] != 0) {
936                     memset(name, 0, sizeof(name));
937                     memset(dirPath, 0, sizeof(dirPath));
938                     strncpy(name, buff, 100);
939                     strcat(name, buff + PREFIX_INDICATOR_BYTE);
940                     sprintf(dirPath, "%s/%s", path, name + folderpathlen);
941                     LOG(" File Name is longer than 100 bytes -Remaining Str [%s]\n Full Str[%s]", dirPath);
942                 } else {
943                     //LOG(" Extracting file %s\n", fullname);
944                     memset(dirPath, 0, sizeof(dirPath));
945                     sprintf(dirPath, "%s/%s", path, fullname + folderpathlen);
946                     f = create_file(dirPath, parseoct(fullname + 100, 8));
947                 }
948             }
949
950             break;
951         }
952
953         while (filesize > 0) {
954             bytes_read = read(fd, buff, sizeof(buff));
955             if (bytes_read < 512) {
956                 LOGE("Short read on %s: Expected 512, got %d\n", tar, bytes_read);
957                 close(fd);
958                 if(f){
959                     fclose(f);//wgid: 16892
960                     f = NULL;
961                 }
962                 return -1;
963             }
964             if (filesize < 512)
965                 bytes_read = filesize;
966             if (f != NULL) {
967                 if (fwrite(buff, 1, bytes_read, f)
968                     != bytes_read) {
969                     LOG("Failed write\n");
970                     fclose(f);
971                     f = NULL;
972                     close(fd);//wgid: 59268
973                     return -1;//wgid: 16892
974                 }
975             }
976             filesize -= bytes_read;
977         }
978         if (f != NULL) {
979             fclose(f);
980             f = NULL;
981         }
982
983     }
984     close(fd);
985     return S_SS_SUCCESS;
986 }
987
988 int fast_tar_extract_file(char *tar, char *item, char *pathname, int size, int offset)
989 {
990     int fd = -1;
991     int data_size = size;
992     int data_offset = offset;
993     off_t pos = 0;
994     ssize_t rdcnt = 0;
995     ssize_t writeCount = 0;
996     char *buf = NULL;
997     int fd2;
998
999     if (gTarFd > 0)
1000         fd = gTarFd;
1001     if (fd < 0) {
1002         fd = open(tar, O_RDONLY);
1003         if (fd < 0) {
1004             LOG("can't open file(%s).\n", tar);
1005             return -1;
1006         }
1007     }
1008     pos = lseek(fd, data_offset, SEEK_SET);
1009     if (pos < 0) {
1010         LOG("lseek fail (%s offset %d).\n", tar, data_offset);
1011         close(fd);
1012         return -1;
1013     }
1014     buf = SS_Malloc(data_size + 1);
1015     if (buf == NULL) {
1016         close(fd);
1017         LOGE("Failed to Allocate Memory\n");
1018         return -1;
1019     }
1020     rdcnt = read(fd, buf, data_size);
1021     if (rdcnt != (ssize_t) data_size) {
1022         LOG(" rdcnt read fail(%s from %s).\n", item, tar);
1023         SS_Free(buf);
1024         close(fd);
1025         return -1;
1026     }
1027     fd2 = open(pathname, O_CREAT | O_WRONLY, 0777);     // Directory where file is required should be created already.
1028     if (fd2 < 0) {
1029         LOG("can't open file(%s).\n", pathname);
1030         SS_Free(buf);
1031         close(fd);
1032         return -1;
1033     }
1034     writeCount = write(fd2, buf, rdcnt);
1035     if (writeCount != rdcnt) {
1036         LOG("writeCount write fail(%s from %s).\n", item, tar);
1037         LOG("Oh  dear, something went wrong with read()! %s\n", strerror(errno));
1038         close(fd);
1039         close(fd2);
1040         SS_Free(buf);
1041         return -1;
1042     }
1043     SS_Free(buf);
1044     if (gTarFd < 0)
1045         close(fd);
1046     fsync(fd2);
1047     close(fd2);
1048     return rdcnt;               // or jus return success?
1049 }
1050
1051 int tar_extract_file(char *tar, char *item, char *pathname)
1052 {
1053     int fd = -1;
1054     int data_size = -1;
1055     int data_offset = -1;
1056     off_t pos = 0;
1057     ssize_t rdcnt = 0;
1058     ssize_t writeCount = 0;
1059     char *buf = NULL;
1060     int fd2;
1061     data_size = tar_get_item_size(tar, item);
1062     data_offset = tar_get_item_offset(tar, item);
1063
1064     if (data_size <= 0 || data_offset < 0) {
1065         LOGE("Error Not a file , size is [%d], offset [%d] for item [%s]\n", data_size, data_offset, item);
1066         return -1;
1067     } else
1068         LOGL(LOG_SSENGINE, "extracting file [%s] size [%d]\n", item, data_size);
1069     fd = open(tar, O_RDONLY);
1070     if (fd < 0) {
1071         LOG("can't open file(%s).\n", tar);
1072         return -1;
1073     }
1074     pos = lseek(fd, data_offset, SEEK_SET);
1075     if (pos < 0) {
1076         LOG("lseek fail (%s offset %d).\n", tar, data_offset);
1077         close(fd);
1078         return -1;
1079     }
1080     buf = SS_Malloc(data_size + 1);
1081     if (buf == NULL) {
1082         close(fd);
1083         LOGE("Failed to Allocate Memory\n");
1084         return -1;
1085     }
1086     rdcnt = read(fd, buf, data_size);
1087     if (rdcnt != (ssize_t) data_size) {
1088         LOG(" rdcnt read fail(%s from %s).\n", item, tar);
1089         SS_Free(buf);
1090         close(fd);
1091         return -1;
1092     }
1093     fd2 = open(pathname, O_CREAT | O_WRONLY, 0777);     // Directory where file is required should be created already.
1094     if (fd2 < 0) {
1095         LOG("can't open file(%s).\n", pathname);
1096         SS_Free(buf);
1097         close(fd);
1098         return -1;
1099     }
1100     writeCount = write(fd2, buf, rdcnt);
1101     if (writeCount != rdcnt) {
1102         LOG("writeCount write fail(%s from %s).\n", item, tar);
1103         LOG("Oh  dear, something went wrong with read()! %s\n", strerror(errno));
1104         close(fd);
1105         close(fd2);
1106         SS_Free(buf);
1107         return -1;
1108     }
1109     SS_Free(buf);
1110     close(fd);
1111     fsync(fd2);
1112     close(fd2);
1113     return rdcnt;               // or jus return success?
1114 }