LCOV - code coverage report
Current view: top level - src - ft_archive.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 72 0
Test Date: 2025-10-15 21:43:52 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /**
       2              :  * @file ft_archive.c
       3              :  * @brief Archive handling functions for extracting files from archives.
       4              :  * @ingroup Archive
       5              :  */
       6              : /*
       7              :  * Copyright (C) 2007 François Pesce : francois.pesce (at) gmail (dot) com
       8              :  *
       9              :  * Licensed under the Apache License, Version 2.0 (the "License");
      10              :  * you may not use this file except in compliance with the License.
      11              :  * You may obtain a copy of the License at
      12              :  *
      13              :  *      http://www.apache.org/licenses/LICENSE-2.0
      14              :  *
      15              :  * Unless required by applicable law or agreed to in writing, software
      16              :  * distributed under the License is distributed on an "AS IS" BASIS,
      17              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      18              :  * See the License for the specific language governing permissions and
      19              :  * limitations under the License.
      20              :  */
      21              : 
      22              : #include "ft_archive.h"
      23              : 
      24              : #include <sys/stat.h>
      25              : #include <unistd.h>
      26              : 
      27              : #include <apr_file_io.h>
      28              : #include <apr_strings.h>
      29              : 
      30              : #include "config.h"
      31              : #include "debug.h"
      32              : 
      33              : #include <archive.h>
      34              : #include <archive_entry.h>
      35              : 
      36              : /**
      37              :  * @brief The block size for archive operations.
      38              :  *
      39              :  * This constant defines the block size (in bytes) used for reading from
      40              :  * and writing to archives.
      41              :  */
      42              : static const size_t ARCHIVE_BLOCK_SIZE = 10240;
      43              : 
      44            0 : static int copy_data(struct archive *archive_read, struct archive *archive_write)
      45              : {
      46            0 :     const void *buff = NULL;
      47            0 :     off_t offset = 0;
      48            0 :     size_t size = 0;
      49              : 
      50            0 :     for (;;) {
      51            0 :         int result_value = archive_read_data_block(archive_read, &buff, &size, &offset);
      52            0 :         if (result_value == ARCHIVE_EOF) {
      53            0 :             return ARCHIVE_OK;
      54              :         }
      55            0 :         if (result_value != ARCHIVE_OK) {
      56            0 :             DEBUG_ERR("error calling archive_read_data_block(): %s", archive_error_string(archive_read));
      57            0 :             return result_value;
      58              :         }
      59            0 :         result_value = (int) archive_write_data_block(archive_write, buff, size, offset);
      60            0 :         if (result_value != ARCHIVE_OK) {
      61            0 :             DEBUG_ERR("error calling archive_write_data_block(): %s", archive_error_string(archive_write));
      62            0 :             return result_value;
      63              :         }
      64              :     }
      65              : }
      66              : 
      67            0 : char *ft_archive_untar_file(ft_file_t *file, apr_pool_t *pool)
      68              : {
      69            0 :     struct archive *archive_handle = NULL;
      70            0 :     struct archive *ext = NULL;
      71            0 :     struct archive_entry *entry = NULL;
      72            0 :     char *tmpfile = NULL;
      73            0 :     int result_value = 0;
      74              : 
      75            0 :     archive_handle = archive_read_new();
      76            0 :     if (NULL == archive_handle) {
      77            0 :         DEBUG_ERR("error calling archive_read_new()");
      78            0 :         return NULL;
      79              :     }
      80            0 :     result_value = archive_read_support_filter_all(archive_handle);
      81            0 :     if (0 != result_value) {
      82            0 :         DEBUG_ERR("error calling archive_read_support_filter_all(): %s", archive_error_string(archive_handle));
      83            0 :         return NULL;
      84              :     }
      85            0 :     result_value = archive_read_support_format_all(archive_handle);
      86            0 :     if (0 != result_value) {
      87            0 :         DEBUG_ERR("error calling archive_read_support_format_all(): %s", archive_error_string(archive_handle));
      88            0 :         return NULL;
      89              :     }
      90            0 :     result_value = archive_read_open_filename(archive_handle, file->path, ARCHIVE_BLOCK_SIZE);
      91            0 :     if (0 != result_value) {
      92            0 :         DEBUG_ERR("error calling archive_read_open_filename(%s): %s", file->path, archive_error_string(archive_handle));
      93            0 :         return NULL;
      94              :     }
      95              : 
      96            0 :     ext = archive_write_disk_new();
      97            0 :     if (NULL == ext) {
      98            0 :         DEBUG_ERR("error calling archive_write_disk_new()");
      99            0 :         return NULL;
     100              :     }
     101              : 
     102              :     for (;;) {
     103            0 :         result_value = archive_read_next_header(archive_handle, &entry);
     104            0 :         if (result_value == ARCHIVE_EOF) {
     105            0 :             DEBUG_ERR("subpath [%s] not found in archive [%s]", file->subpath, file->path);
     106            0 :             return NULL;
     107              :         }
     108            0 :         if (result_value != ARCHIVE_OK) {
     109            0 :             DEBUG_ERR("error in archive (%s): %s", file->path, archive_error_string(archive_handle));
     110            0 :             return NULL;
     111              :         }
     112              : 
     113            0 :         if (!strcmp(file->subpath, archive_entry_pathname(entry))) {
     114            0 :             mode_t current_mode = umask(S_IRWXG | S_IRWXO);
     115              : 
     116              :             /*
     117              :              * All I want is only a temporary filename, but gcc outputs me an
     118              :              * ugly warning if I use tempnam...
     119              :              * tmpfile = tempnam("/tmp/", "ftwin");
     120              :              */
     121            0 :             tmpfile = apr_pstrdup(pool, "/tmp/ftwinXXXXXX");
     122            0 :             result_value = mkstemp(tmpfile);
     123            0 :             if (result_value < 0) {
     124            0 :                 DEBUG_ERR("error creating tmpfile %s", tmpfile);
     125            0 :                 return NULL;
     126              :             }
     127            0 :             umask(current_mode);
     128            0 :             close(result_value);
     129              : 
     130            0 :             archive_entry_copy_pathname(entry, tmpfile);
     131              : 
     132            0 :             result_value = archive_write_header(ext, entry);
     133            0 :             if (result_value == ARCHIVE_OK) {
     134            0 :                 result_value = copy_data(archive_handle, ext);
     135            0 :                 if (result_value != ARCHIVE_OK) {
     136            0 :                     DEBUG_ERR("error while copying data from archive (%s)", file->path);
     137            0 :                     (void) apr_file_remove(tmpfile, pool);
     138            0 :                     return NULL;
     139              :                 }
     140              :             }
     141              :             else {
     142            0 :                 DEBUG_ERR("error in archive (%s): %s", file->path, archive_error_string(archive_handle));
     143            0 :                 (void) apr_file_remove(tmpfile, pool);
     144            0 :                 return NULL;
     145              :             }
     146              : 
     147            0 :             break;
     148              :         }
     149              :     }
     150              : 
     151            0 :     archive_write_free(ext);
     152            0 :     archive_read_free(archive_handle);
     153              : 
     154            0 :     return tmpfile;
     155              : }
        

Generated by: LCOV version 2.0-1