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