1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
/*********************************************************************************************************************
*
* Copyright (C) 2012 Continental Automotive Systems, Inc.
*
* Author: Ionut.Ieremie@continental-corporation.com
*
* Implementation of funtions declaredin ssw_pers_admin_common.h
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Date Author Reason
* 2013.03.20 uidu0250 CSP_WZ#2250: Provide compress/uncompress functionality
* 2013.02.07 uidu0250 CSP_WZ#2220: Removed Helplibs dependency (CRC16 checksum calculation)
* 2013.01.22 uidn3591 CSP_WZ#2060: Implemented wrappers over libarchive to compress/uncompress files into/from an archive
* 2013.01.04 uidu0250 CSP_WZ#2060: Switched get_hash_for_file implementation from using CRC32 to using CRC16 provided by HelpLibs
* 2012.11.15 uidl9757 CSP_WZ#1280: Use protected interface pers_data_organization_if.h
* 2012.11.16 uidn3565 CSP_WZ#1280: Added implementation for
- persadmin_list_application_folders
- persadmin_list_application_folders_get_size
* 2012.11.15 uidl9757 CSP_WZ#1280: Created
*
**********************************************************************************************************************/
/* ---------------------- include files --------------------------------- */
#include "persComTypes.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
/* compress/uncompress */
#include <archive.h>
#include <archive_entry.h>
#include "malloc.h"
#include "ssw_pers_admin_common.h"
#include "ssw_pers_admin_files_helper.h"
#include "persComDataOrg.h"
#include "persistence_admin_service.h"
/* ---------------------- local definitions -------------------------------- */
#define READ_BUFFER_LENGTH (16384)
#define COPY_BUFFER_LENGTH (128)
#define PATH_ABS_MAX_SIZE ( 512)
#define PERSADMIN_POLICY_MARKER_CACHED PERS_ORG_CACHE_FOLDER_NAME
#define PERSADMIN_POLICY_MARKER_WT PERS_ORG_WT_FOLDER_NAME
#define CRC16_FILE_CHUNK_SIZE (10 * 1024)
/* TO DO : This should be published in a protected interface */
#define PERSADMIN_LINKS_INFO_FILENAME "linksInfo.lnk"
#define GetApplicationRootPath( RootPath, FullPath ) \
int pathLength = strlen( RootPath ); \
char FullPath[ strlen( gLocalCachePath ) + pathLength + sizeof( StringTerminator ) ]; \
snprintf( FullPath, sizeof( FullPath ), "%s", RootPath ); \
snprintf( FullPath + pathLength, sizeof( FullPath ) - pathLength, gLocalCachePath, "", "" )
/* ---------------------- local types -------------------------------------- */
/* ---------------------- local functions ---------------------------------- */
static sint_t persadmin_common_extract_group_id(pstr_t linkName) ;
static void persadmin_common_remove_endofline(pstr_t line) ;
static bool_t persadmin_is_shared_folder( pconststr_t name, int length );
static sint_t persadmin_copy_data(struct archive *ar, struct archive *aw);
/* ---------------------- local variables ---------------------------------- */
//moved to "ssw_pers_admin_common.h"
//extern const char StringTerminator;
/*
* export the application's information about links (to groups and public data)
* returns the number of exported links, or a negative value in case of error
*/
sint_t persadmin_export_links(pstr_t absPathApplicationFolder, pstr_t absPathExportFolder)
{
pstr_t FuncName = "persadmin_export_links:" ;
bool_t bEverythingOK = true ;
pstr_t buffer = NIL ;
bool_t bNothingToExport = false ;
sint_t exportedLinks = 0 ;
sint_t neededBufferSize = 0 ;
FILE * fileExport = NIL ;
if( (NIL == absPathApplicationFolder) || (NIL == absPathExportFolder))
{
bEverythingOK = false ;
printf("\n%s NIL param \n", FuncName) ;
}
else
{
if(0 != persadmin_check_if_file_exists(absPathApplicationFolder, true))
{
bEverythingOK = false ;
printf("\n%s folder does not exist (%s) \n", FuncName, absPathApplicationFolder) ;
}
else
{
if(0 != persadmin_check_if_file_exists(absPathExportFolder, true))
{
bEverythingOK = false ;
printf("\n%s folder does not exist (%s) \n", FuncName, absPathExportFolder) ;
}
}
}
if(bEverythingOK)
{
neededBufferSize = persadmin_list_folder_get_size(absPathApplicationFolder, PersadminFilterFilesLink, false) ;
if(neededBufferSize > 0)
{
buffer = (pstr_t)malloc(neededBufferSize*sizeof(str_t)) ;
if(NIL == buffer)
{
bEverythingOK = false ;
}
else
{
sint_t listingSize = persadmin_list_folder(absPathApplicationFolder, buffer, neededBufferSize, PersadminFilterFilesLink, false) ;
if(neededBufferSize != listingSize)
{
bEverythingOK = false ;
printf("\n%s persadmin_list_folder(%s) returned %d (expected %d) \n", FuncName, absPathApplicationFolder, listingSize, neededBufferSize) ;
}
}
}
else
{
if(0 == neededBufferSize)
{
/* no links to export */
bNothingToExport = true ;
}
else
{
bEverythingOK = false ;
printf("\n%s persadmin_list_folder_get_size(<%s>, FilterFilesLink, false) failed\n", FuncName, absPathApplicationFolder) ;
}
}
}
if(bEverythingOK && (! bNothingToExport))
{
/* create the export file */
str_t completePath[PERSADMIN_MAX_PATH_LENGHT] ;
sint_t lenPathExport = strlen(absPathExportFolder) ;
sint_t lenLinkFilename = strlen(PERSADMIN_LINKS_INFO_FILENAME) ;
if( (lenPathExport + 1 + lenLinkFilename) < PERSADMIN_MAX_PATH_LENGHT )
{
strncpy(completePath, absPathExportFolder, sizeof(completePath)) ;
if('/' != completePath[lenPathExport -1])
{
strncat(completePath, "/", sizeof(completePath)) ;
}
strncat(completePath, PERSADMIN_LINKS_INFO_FILENAME, sizeof(completePath)) ;
fileExport = fopen(completePath, "w") ;
if(NIL == fileExport)
{
bEverythingOK = false ;
printf("\n%s fopen(<%s>, w) errno = %s\n", FuncName, completePath, strerror(errno)) ;
}
}
else
{
bEverythingOK = false ;
printf("\n%s path too long (%s/%s)\n", FuncName, absPathExportFolder, PERSADMIN_LINKS_INFO_FILENAME) ;
}
}
if(bEverythingOK && (! bNothingToExport))
{
/* for each link file in buffer, create an entry (line) in the export file
* for links to group - only the number of the group (i.e. a hex value in 0x00 - 0xFF domain) is stored
* for links to public data - the word "public" is stored
**/
sint_t posInBuffer = 0 ;
while((posInBuffer < neededBufferSize) && bEverythingOK)
{
sint_t lenCurrentLink = strlen(buffer+posInBuffer) ;
if(0 == strcmp(buffer+posInBuffer, PERS_ORG_SHARED_PUBLIC_SYMLINK_NAME))
{
/* it is the link to the public data */
if(0 > fputs("public\n", fileExport))
{
bEverythingOK = false ;
printf("\n%s fputs(public) errno=%s\n", FuncName, strerror(errno)) ;
}
else
{
exportedLinks++ ;
}
}
else
{
sint_t groupID = persadmin_common_extract_group_id(buffer+posInBuffer) ;
if(groupID >= 0)
{
str_t line[PERSADMIN_MAX_PATH_LENGHT] ;
printf("\n%s groupID(%s)=0x%02X\n", FuncName, buffer+posInBuffer, groupID) ;
snprintf(line, sizeof(line), "%02X\n", groupID) ;
if(0 > fputs(line, fileExport))
{
bEverythingOK = false ;
printf("\n%s fputs(%02X) errno=%s\n", FuncName, groupID, strerror(errno)) ;
}
else
{
exportedLinks++ ;
}
}
else
{
printf("\n%s unable to extract group ID from (%s). Ignore it\n", FuncName, buffer+posInBuffer) ;
}
}
posInBuffer += (lenCurrentLink + 1) ;
}
}
if(NIL != buffer)
{
free(buffer) ;
}
if(NIL != fileExport)
{
fclose(fileExport) ;
}
return bEverythingOK ? exportedLinks : PAS_FAILURE;
}
/*
* install links (to groups and public data) into the application folder(indicated by absPathApplicationFolder)
* based on information available inside the import folder (indicated by absPathImportFolder)
* returns the number of installed links, or a negative value in case of error
*/
sint_t persadmin_import_links(pstr_t absPathImportFolder, pstr_t absPathApplicationFolder)
{
pstr_t FuncName = "persadmin_import_links:" ;
bool_t bEverythingOK = true ;
bool_t bNothingToImport = false ;
sint_t importedLinks = 0 ;
FILE * fileImport = NIL ;
bool_t bImportInCachedPath = true ;
if( (NIL == absPathImportFolder) || (NIL == absPathApplicationFolder))
{
bEverythingOK = false ;
printf("\n%s NIL param \n", FuncName) ;
}
else
{
if(0 != persadmin_check_if_file_exists(absPathImportFolder, true))
{
bEverythingOK = false ;
printf("\n%s folder does not exist (%s) \n", FuncName, absPathImportFolder) ;
}
else
{
if(0 != persadmin_check_if_file_exists(absPathApplicationFolder, true))
{
bEverythingOK = false ;
printf("\n%s folder does not exist (%s) \n", FuncName, absPathApplicationFolder) ;
}
}
}
if(bEverythingOK)
{
/* check if the absPathApplicationFolder is a cached or write-through path */
if(NIL != strstr(absPathApplicationFolder, PERSADMIN_POLICY_MARKER_CACHED))
{
/* cached path */
bImportInCachedPath = true ;
}
else
{
/* not a cached path, so it ahould be a write-through path */
if(NIL != strstr(absPathApplicationFolder, PERSADMIN_POLICY_MARKER_WT))
{
/* write-through */
bImportInCachedPath = false ;
}
else
{
bEverythingOK = false ;
printf("\n%s no cached or wt path (%s) \n", FuncName, absPathApplicationFolder) ;
}
}
}
if(bEverythingOK)
{
/* open the source file */
str_t completePath[PERSADMIN_MAX_PATH_LENGHT] ;
sint_t lenPathImport = strlen(absPathImportFolder) ;
sint_t lenLinkFilename = strlen(PERSADMIN_LINKS_INFO_FILENAME) ;
if( (lenPathImport + 1 + lenLinkFilename) < PERSADMIN_MAX_PATH_LENGHT )
{
strncpy(completePath, absPathImportFolder, sizeof(completePath)) ;
if('/' != completePath[lenPathImport -1])
{
strncat(completePath, "/", sizeof(completePath)) ;
}
strncat(completePath, PERSADMIN_LINKS_INFO_FILENAME, sizeof(completePath)) ;
fileImport = fopen(completePath, "r") ;
if(NIL == fileImport)
{
/* nothing to import */
bNothingToImport = true ;
printf("\n%s fopen(<%s>, r) errno = %s\n", FuncName, completePath, strerror(errno)) ;
}
}
else
{
bEverythingOK = false ;
printf("\n%s path too long (%s/%s)\n", FuncName, absPathImportFolder, PERSADMIN_LINKS_INFO_FILENAME) ;
}
}
if(bEverythingOK && (! bNothingToImport))
{
bool_t bEndOfFileReached = false ;
str_t appFolderPath[PERSADMIN_MAX_PATH_LENGHT] ;
sint_t lenAppFolder = strlen(absPathApplicationFolder) ;
if(lenAppFolder + 1 < PERSADMIN_MAX_PATH_LENGHT)
{
strncpy(appFolderPath, absPathApplicationFolder, sizeof(appFolderPath)) ;
if('/' != appFolderPath[lenAppFolder-1])
{
strncat(appFolderPath, "/", sizeof(appFolderPath)) ;
lenAppFolder += 1 ;
}
}
else
{
bEverythingOK = false ;
printf("\n%s path too long (%s)\n", FuncName, absPathImportFolder) ;
}
while((! bEndOfFileReached) && bEverythingOK)
{
str_t line[256] ;
pstr_t pResult = fgets(line, sizeof(line), fileImport) ;
if(NIL == pResult)
{
/* end of file */
bEndOfFileReached = true ;
}
else
{
if(strlen(line) > (sizeof(line) - 3)) /* 3 <=> \n \r \0 */
{
bEverythingOK = false ;
printf("%s - unexpected line too long \n", FuncName) ;
}
else
{
str_t linkTarget[256] ;
str_t linkPathname[256] ;
bool_t bIgnoreLine = false ;
persadmin_common_remove_endofline(line) ;
if(0 == strcmp(line, "public"))
{
snprintf(linkTarget, sizeof(linkTarget), "%s",
bImportInCachedPath ? PERS_ORG_SHARED_PUBLIC_CACHE_PATH_ : PERS_ORG_SHARED_PUBLIC_WT_PATH_) ;
if((sizeof(linkPathname)-1) < snprintf(linkPathname, sizeof(linkPathname), "%s%s",
appFolderPath, PERS_ORG_SHARED_PUBLIC_SYMLINK_NAME))
{
/* hard to believe, but anyway */
bIgnoreLine = true ;
printf("%s - unexpected linkPathname too long (%s%s) \n", FuncName, appFolderPath, PERS_ORG_SHARED_PUBLIC_SYMLINK_NAME) ;
}
}
else
{
sint_t groupID ;
sint_t result = sscanf(line, "%X", &groupID) ;
if(1 == result)
{
snprintf(linkTarget, sizeof(linkTarget), "%s%02X",
(bImportInCachedPath ? PERS_ORG_SHARED_GROUP_CACHE_PATH_ : PERS_ORG_SHARED_GROUP_WT_PATH_), groupID) ;
if((sizeof(linkPathname)-1) < snprintf(linkPathname, sizeof(linkPathname), "%s%s%02X", appFolderPath, PERS_ORG_SHARED_GROUP_SYMLINK_PREFIX, groupID))
{
/* hard to believe, but anyway */
bIgnoreLine = true ;
printf("%s - unexpected linkPathname too long (%s%s%02X) \n", FuncName, appFolderPath, PERS_ORG_SHARED_GROUP_SYMLINK_PREFIX, groupID) ;
}
}
else
{
bIgnoreLine = true ;
printf("%s - unable to extract group ID from (%s) - ignore it \n", FuncName, line) ;
}
}
if( ! bIgnoreLine)
{
if(0 <= persadmin_check_if_file_exists(linkPathname, false))
{
if(0 > persadmin_delete_file(linkPathname))
{
bEverythingOK = false ;
printf("%s - unable to delete existing link (%s) \n", FuncName, linkPathname) ;
}
}
if(bEverythingOK)
{
if(0 == persadmin_create_symbolic_link(linkPathname, linkTarget))
{
importedLinks++ ;
}
else
{
bEverythingOK = false ;
printf("%s - persadmin_create_symbolic_link(<%s>, <%s>) failed \n", FuncName, linkPathname, linkTarget) ;
}
}
}
}
}
}
}
if(NIL != fileImport)
{
fclose(fileImport) ;
}
return bEverythingOK ? importedLinks : PAS_FAILURE;
}
/*
* linkName is not checked against NIL
* return group ID, or negative value for error
* it is assumed that lenght of linkName < PERSADMIN_MAX_PATH_LENGHT
**/
static sint_t persadmin_common_extract_group_id(pstr_t linkName)
{
sint_t groupID = -1 ;
sint_t lenPrefix = strlen(PERS_ORG_SHARED_GROUP_SYMLINK_PREFIX) ;
if(strlen(linkName) > lenPrefix)
{
if(0 == strncmp(linkName, PERS_ORG_SHARED_GROUP_SYMLINK_PREFIX, lenPrefix))
{
if(1 != sscanf(linkName+lenPrefix, "%X", &groupID))
{
groupID = -1 ;
}
}
}
return groupID ;
}
/*
* line is not checked against NIL
* the content of line is changed
**/
static void persadmin_common_remove_endofline(pstr_t line)
{
sint_t len = strlen(line) ;
if((len > 0) && (('\r' == line[len-1]) || ('\n' == line[len-1])))
{
line[len-1] = '\0' ;
}
if((len > 1) && (('\r' == line[len-2]) || ('\n' == line[len-2])))
{
line[len-2] = '\0' ;
}
}
sint_t persadmin_list_application_folders( pconststr_t rootPath, pstr_t list, sint_t listSize ) {
sint_t result = PAS_FAILURE;
if ( ( rootPath != 0 ) && ( list != 0 ) && ( listSize > 0 ) ) {
GetApplicationRootPath( rootPath, completeRootPath );
// Clear the output buffer before retrieving the actual list
memset( list, 0, listSize );
result = persadmin_list_folder( completeRootPath, list, listSize, PersadminFilterFolders, false );
if ( result >= 0 ) {
char * crtName = list;
bool_t done = false;
result += sizeof( StringTerminator );
while ( ( ( * crtName ) != 0 ) && ( done == false ) ) {
int length = strlen( crtName );
if ( persadmin_is_shared_folder( crtName, length ) == true ) {
result -= length + sizeof( StringTerminator );
memmove( crtName, crtName + length + sizeof( StringTerminator ), listSize - ( crtName - list ) - length - sizeof( StringTerminator ) );
done = true;
}
else {
crtName += length + sizeof( StringTerminator );
}
}
}
}
return result;
}
sint_t persadmin_list_application_folders_get_size( pconststr_t rootPath ) {
sint_t result = PAS_FAILURE;
GetApplicationRootPath( rootPath, completeRootPath );
result = persadmin_list_folder_get_size( completeRootPath, PersadminFilterFolders, false );
if ( result > 0 ) {
// Add space for doubling the final '\0' - this is not done inside persadmin_list_folder_get_size()
result += sizeof( StringTerminator );
}
return result;
}
bool_t persadmin_is_shared_folder( pconststr_t name, int length ) {
bool_t result = false;
int compLen = strlen( gSharedPathName );
if ( ( name != 0 ) && ( length == compLen ) ) {
int i = 0;
result = true;
for ( ; ( ( i < compLen ) && ( result == true ) ); ++i ) {
if ( gSharedPathName[ i ] != name[ i ] ) {
result = false;
}
}
}
return result;
}
/**
* @brief Saves files together into a single archive.
* @usage persadmin_compress("/path/to/compress/to/archive_name.tgz", "/path/from/where/to/compress")
* @return 0 for success, negative value otherwise.
*/
sint_t persadmin_compress(pstr_t compressTo, pstr_t compressFrom)
{
uint8_t buffer [READ_BUFFER_LENGTH];
str_t pchParentPath [PATH_ABS_MAX_SIZE];
pstr_t pchStrPos = NIL;
struct archive *psArchive = NIL;
struct archive *psDisk = NIL;
struct archive_entry *psEntry = NIL;
sint_t s32Result = ARCHIVE_OK;
sint_t s32Length = 0;
sint_t fd;
sint_t s32ParentPathLength = 0;
if( (NIL == compressTo) ||
(NIL == compressFrom) )
{
s32Result = ARCHIVE_FAILED;
printf("persadmin_compress - invalid parameters \n");
}
if( ARCHIVE_OK == s32Result )
{
printf("persadmin_compress - create <%s> from <%s>\n", compressTo, compressFrom);
psArchive = archive_write_new();
if( NIL == psArchive )
{
s32Result = ARCHIVE_FAILED;
printf("persadmin_compress - archive_write_new ERR\n");
}
}
if( ARCHIVE_OK == s32Result )
{
/* this in turn calls archive_write_add_filter_gzip; */
s32Result = archive_write_set_compression_gzip(psArchive);
if( ARCHIVE_OK != s32Result )
{
printf("persadmin_compress - archive_write_set_compression_gzip ERR %d\n", s32Result);
}
}
if( ARCHIVE_OK == s32Result )
{
/* portable archive exchange; */
archive_write_set_format_pax(psArchive);
compressTo = (strcmp(compressTo, "-") == 0) ? NIL : compressTo;
s32Result = archive_write_open_filename(psArchive, compressTo);
if( ARCHIVE_OK != s32Result )
{
printf("persadmin_compress - archive_write_open_filename ERR %d\n", s32Result);
}
}
if( ARCHIVE_OK == s32Result )
{
psDisk = archive_read_disk_new();
if( NIL == psDisk )
{
s32Result = ARCHIVE_FAILED;
printf("persadmin_compress - archive_read_disk_new ERR\n");
}
}
if( ARCHIVE_OK == s32Result )
{
archive_read_disk_set_standard_lookup(psDisk);
s32Result = archive_read_disk_open(psDisk, compressFrom);
if( ARCHIVE_OK != s32Result )
{
printf("persadmin_compress - archive_read_disk_new ERR %s\n", archive_error_string(psDisk));
}
}
memset(pchParentPath, 0, sizeof(pchParentPath));
snprintf(pchParentPath, sizeof(pchParentPath), compressFrom);
pchStrPos = strrchr(pchParentPath, '/');
if(NIL != pchStrPos)
{
*pchStrPos = '\0';
}
s32ParentPathLength = strlen(pchParentPath);
while( ARCHIVE_OK == s32Result )
{
psEntry = archive_entry_new();
s32Result = archive_read_next_header2(psDisk, psEntry);
switch( s32Result )
{
case ARCHIVE_EOF:
{
/* nothing else to do; */
break;
}
case ARCHIVE_OK:
{
str_t pstrTemp[PATH_ABS_MAX_SIZE];
pstr_t p = (pstr_t)archive_entry_pathname(psEntry);
if(NIL != p)
{
/* remove parent section and save relative pathnames */
memset(pstrTemp, 0, sizeof(pstrTemp));
snprintf(pstrTemp, sizeof(pstrTemp), "%s", p + (s32ParentPathLength + 1));
archive_entry_copy_pathname(psEntry, pstrTemp);
}
archive_read_disk_descend(psDisk);
s32Result = archive_write_header(psArchive, psEntry);
if( ARCHIVE_OK > s32Result)
{
printf("persadmin_compress - archive_write_header ERR %s\n", archive_error_string(psArchive));
}
if( ARCHIVE_FATAL == s32Result )
{
/* exit; */
printf("persadmin_compress - archive_write_header ERR FATAL\n");
}
if( ARCHIVE_FAILED < s32Result )
{
#if 0
/* Ideally, we would be able to use
* the same code to copy a body from
* an archive_read_disk to an
* archive_write that we use for
* copying data from an archive_read
* to an archive_write_disk.
* Unfortunately, this doesn't quite
* work yet. */
persadmin_copy_data(psDisk, psArchive);
#else
/* For now, we use a simpler loop to copy data
* into the target archive. */
fd = open(archive_entry_sourcepath(psEntry), O_RDONLY);
s32Length = read(fd, buffer, READ_BUFFER_LENGTH);
while( s32Length > 0 )
{
archive_write_data(psArchive, buffer, s32Length);
s32Length = read(fd, buffer, READ_BUFFER_LENGTH);
}
close(fd);
#endif
}
break;
}
default:
{
printf("persadmin_compress - archive_read_next_header2 ERR %s\n", archive_error_string(psDisk));
/* exit; */
break;
}
}
if( NIL != psEntry )
{
archive_entry_free(psEntry);
}
}
/* perform cleaning operations; */
if( NIL != psDisk )
{
archive_read_close(psDisk);
archive_read_free(psDisk);
}
if( NIL != psArchive )
{
archive_write_close(psArchive);
archive_write_free(psArchive);
}
/* overwrite result; */
s32Result = (s32Result == ARCHIVE_EOF) ? ARCHIVE_OK : s32Result;
/* return result; */
return s32Result;
} /* persadmin_compress() */
/**
* @brief Restore files from an archive.
* @usage persadmin_uncompress("/path/from/where/to/extract/archive_name.tgz", "/path/where/to/extract/") - extract to specified folder
* @usage persadmin_uncompress("/path/from/where/to/extract/archive_name.tgz", "") - extract to local folder
* @return 0 for success, negative value otherwise.
*/
sint_t persadmin_uncompress(pstr_t extractFrom, pstr_t extractTo)
{
struct archive *psArchive = NIL;
struct archive *psExtract = NIL;
struct archive_entry *psEntry = NIL;
sint_t s32Result = ARCHIVE_OK;
sint_t s32Flags = ARCHIVE_EXTRACT_TIME;
/* select which attributes to restore; */
s32Flags |= ARCHIVE_EXTRACT_PERM;
s32Flags |= ARCHIVE_EXTRACT_ACL;
s32Flags |= ARCHIVE_EXTRACT_FFLAGS;
if( (NIL == extractFrom) ||
(NIL == extractTo) )
{
s32Result = ARCHIVE_FAILED;
printf("persadmin_uncompress - invalid parameters\n");
}
if( ARCHIVE_OK == s32Result )
{
psArchive = archive_read_new();
if( NIL == psArchive )
{
s32Result = ARCHIVE_FAILED;
printf("persadmin_uncompress - archive_read_new ERR\n");
}
}
if( ARCHIVE_OK == s32Result )
{
archive_read_support_format_all(psArchive);
archive_read_support_compression_all(psArchive);
psExtract = archive_write_disk_new();
s32Result = ((NIL == psExtract) ? ARCHIVE_FAILED : s32Result);
archive_write_disk_set_options(psExtract, s32Flags);
archive_write_disk_set_standard_lookup(psExtract);
}
if( ARCHIVE_OK == s32Result )
{
s32Result = archive_read_open_filename(psArchive, extractFrom, 10240);
/* exit if s32Result != ARCHIVE_OK; */
}
while( ARCHIVE_OK == s32Result )
{
s32Result = archive_read_next_header(psArchive, &psEntry);
switch( s32Result )
{
case ARCHIVE_EOF:
{
/* nothing else to do; */
break;
}
case ARCHIVE_OK:
{
/* modify entry here to extract to the needed location; */
str_t pstrTemp[PATH_ABS_MAX_SIZE];
memset(pstrTemp, 0, sizeof(pstrTemp));
snprintf(pstrTemp, sizeof(pstrTemp), "%s%s", extractTo, archive_entry_pathname(psEntry));
printf("persadmin_uncompress - archive_entry_pathname %s\n", pstrTemp);
archive_entry_copy_pathname(psEntry, pstrTemp);
s32Result = archive_write_header(psExtract, psEntry);
if( ARCHIVE_OK == s32Result )
{
if( archive_entry_size(psEntry) > 0 )
{
s32Result = persadmin_copy_data(psArchive, psExtract);
if( ARCHIVE_OK != s32Result )
{
printf("persadmin_uncompress - copy_data ERR %s\n", archive_error_string(psExtract));
}
/* if( ARCHIVE_WARN > s32Result ) exit; */
}
if( ARCHIVE_OK == s32Result )
{
s32Result = archive_write_finish_entry(psExtract);
if( ARCHIVE_OK != s32Result )
{
printf("persadmin_uncompress - archive_write_finish_entry ERR %s\n", archive_error_string(psExtract));
}
/* if( ARCHIVE_WARN > s32Result ) exit; */
}
}
else
{
printf("persadmin_uncompress - archive_write_header ERR %s\n", archive_error_string(psExtract));
}
break;
}
default:
{
printf("persadmin_uncompress - archive_read_next_header ERR %d\n", s32Result);
break;
}
}
}
/* perform cleaning operations; */
if( NIL != psArchive )
{
archive_read_close(psArchive);
archive_read_free(psArchive);
}
if( NIL != psExtract )
{
archive_write_close(psExtract);
archive_write_free(psExtract);
}
/* overwrite result; */
s32Result = (s32Result == ARCHIVE_EOF) ? ARCHIVE_OK : s32Result;
/* return result; */
return s32Result;
} /* persadmin_uncompress() */
static sint_t persadmin_copy_data(struct archive *ar, struct archive *aw)
{
sint_t s32Result = ARCHIVE_OK;
sint_t s32Size = 0;
uint8_t buffer[COPY_BUFFER_LENGTH];
while( ARCHIVE_OK == s32Result )
{
s32Size = archive_read_data(ar, buffer, COPY_BUFFER_LENGTH);
if( 0 > s32Size )
{
printf("persadmin_copy_data - archive_read_data ERR\n");
s32Result = ARCHIVE_FAILED;
}
else
{
if( 0 < s32Size )
{
s32Size = archive_write_data(aw, buffer, COPY_BUFFER_LENGTH);
if( 0 > s32Size )
{
printf("persadmin_copy_data - archive_write_data ERR\n");
s32Result = ARCHIVE_FAILED;
}
}
else
{
/* nothing to copy; */
break;
}
}
}
/* return result; */
return s32Result;
} /* persadmin_copy_data() */
|