LCOV - code coverage report
Current view: top level - src - ftwin.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 43.5 % 62 27
Test Date: 2025-10-15 21:43:52 Functions: 100.0 % 3 3

            Line data    Source code
       1              : /**
       2              :  * @file ftwin.c
       3              :  * @brief Main application logic for ftwin, including argument parsing, file traversal, and duplicate reporting.
       4              :  * @ingroup CoreLogic
       5              :  */
       6              : /*
       7              :  *
       8              :  * Copyright (C) 2007 François Pesce : francois.pesce (at) gmail (dot) com
       9              :  *
      10              :  * Licensed under the Apache License, Version 2.0 (the "License");
      11              :  * you may not use this file except in compliance with the License.
      12              :  * You may obtain a copy of the License at
      13              :  *
      14              :  *      http://www.apache.org/licenses/LICENSE-2.0
      15              :  *
      16              :  * Unless required by applicable law or agreed to in writing, software
      17              :  * distributed under the License is distributed on an "AS IS" BASIS,
      18              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      19              :  * See the License for the specific language governing permissions and
      20              :  * limitations under the License.
      21              :  */
      22              : 
      23              : #include <unistd.h>               /* getegid */
      24              : #include <stdio.h>                /* fgetgrent */
      25              : #include <sys/stat.h>             /* umask */
      26              : #include <grp.h>          /* fgetgrent */
      27              : 
      28              : #include <apr_file_io.h>
      29              : #include <apr_strings.h>
      30              : #include <apr_user.h>
      31              : 
      32              : #include "config.h"
      33              : 
      34              : #include "debug.h"
      35              : #include "ft_file.h"
      36              : #include "ft_system.h"
      37              : #include "human_size.h"
      38              : #include "napr_threadpool.h"
      39              : #include "ft_types.h"
      40              : #include "ft_config.h"
      41              : #include "ft_traverse.h"
      42              : #include "ft_process.h"
      43              : #include "ft_archive.h"
      44              : #include "ft_report.h"
      45              : #include "ft_report_json.h"
      46              : #include "ft_image.h"
      47              : #include "key_hash.h"
      48              : 
      49              : int ft_file_cmp(const void *param1, const void *param2);
      50              : 
      51          224 : const void *ft_fsize_get_key(const void *opaque)
      52              : {
      53          224 :     const ft_fsize_t *fsize = opaque;
      54              : 
      55          224 :     return &(fsize->val);
      56              : }
      57              : 
      58           17 : const void *ft_gids_get_key(const void *opaque)
      59              : {
      60           17 :     const ft_gid_t *gid = opaque;
      61              : 
      62           17 :     return &(gid->val);
      63              : }
      64              : 
      65           17 : int ftwin_main(int argc, const char **argv)
      66              : {
      67              :     char errbuf[128];
      68              :     ft_conf_t *conf;
      69              :     apr_pool_t *pool, *gc_pool;
      70              :     int i, first_arg_index;
      71              :     apr_status_t status;
      72              : 
      73           17 :     if (APR_SUCCESS != (status = apr_initialize())) {
      74            0 :         DEBUG_ERR("error calling apr_initialize: %s", apr_strerror(status, errbuf, 128));
      75            0 :         return -1;
      76              :     }
      77              : 
      78           17 :     if (APR_SUCCESS != (status = apr_pool_create(&pool, NULL))) {
      79            0 :         DEBUG_ERR("error calling apr_pool_create: %s", apr_strerror(status, errbuf, 128));
      80            0 :         apr_terminate();
      81            0 :         return -1;
      82              :     }
      83              : 
      84           17 :     conf = ft_config_create(pool);
      85           17 :     if (APR_SUCCESS != (status = ft_config_parse_args(conf, argc, argv, &first_arg_index))) {
      86              :         /* Error message is printed inside the function */
      87            0 :         apr_terminate();
      88            0 :         return -1;
      89              :     }
      90              : 
      91              :     /* Step 1 : Browse the file */
      92           17 :     if (APR_SUCCESS != (status = apr_pool_create(&gc_pool, pool))) {
      93            0 :         DEBUG_ERR("error calling apr_pool_create: %s", apr_strerror(status, errbuf, 128));
      94            0 :         apr_terminate();
      95            0 :         return -1;
      96              :     }
      97           40 :     for (i = first_arg_index; i < argc; i++) {
      98           23 :         const char *current_arg = argv[i];
      99           23 :         char *resolved_path = (char *) current_arg;
     100              : 
     101              :         // Requirement: JSON output must contain absolute paths.
     102           23 :         if (is_option_set(conf->mask, OPTION_JSON)) {
     103              :             // Use apr_filepath_merge with NULL rootpath to resolve the absolute path.
     104            3 :             status = apr_filepath_merge(&resolved_path, NULL, current_arg, APR_FILEPATH_TRUENAME, gc_pool);
     105            3 :             if (APR_SUCCESS != status) {
     106            0 :                 DEBUG_ERR("Error resolving absolute path for argument %s: %s.", current_arg,
     107              :                           apr_strerror(status, errbuf, 128));
     108            0 :                 apr_terminate();
     109            0 :                 return -1;      // Fail if path resolution fails for JSON mode
     110              :             }
     111              :         }
     112              : 
     113           23 :         if (APR_SUCCESS != (status = ft_traverse_path(conf, resolved_path))) {
     114            0 :             DEBUG_ERR("error calling ft_traverse_path: %s", apr_strerror(status, errbuf, 128));
     115            0 :             apr_terminate();
     116            0 :             return -1;
     117              :         }
     118              :     }
     119              : 
     120           17 :     if (0 < napr_heap_size(conf->heap)) {
     121           17 :         if (is_option_set(conf->mask, OPTION_PUZZL)) {
     122              : #if HAVE_JANSSON
     123            0 :             if (is_option_set(conf->mask, OPTION_JSON)) {
     124            0 :                 fprintf(stderr, "Error: JSON output is currently not supported in image comparison mode (-I).\n");
     125            0 :                 apr_terminate();
     126            0 :                 return -1;
     127              :             }
     128              : #endif
     129              :             /* Step 2: Report the image twins */
     130            0 :             if (APR_SUCCESS != (status = ft_image_twin_report(conf))) {
     131            0 :                 DEBUG_ERR("error calling ft_image_twin_report: %s", apr_strerror(status, errbuf, 128));
     132            0 :                 apr_terminate();
     133            0 :                 return status;
     134              :             }
     135              :         }
     136              :         else {
     137              :             /* Step 2: Process the sizes set */
     138           17 :             if (APR_SUCCESS != (status = ft_process_files(conf))) {
     139            0 :                 DEBUG_ERR("error calling ft_process_files: %s", apr_strerror(status, errbuf, 128));
     140            0 :                 apr_terminate();
     141            0 :                 return -1;
     142              :             }
     143              : 
     144              : #if HAVE_JANSSON
     145           17 :             if (is_option_set(conf->mask, OPTION_JSON)) {
     146            1 :                 if (APR_SUCCESS != (status = ft_report_json(conf))) {
     147            0 :                     DEBUG_ERR("error calling ft_report_json: %s", apr_strerror(status, errbuf, 128));
     148            0 :                     apr_terminate();
     149            0 :                     return status;
     150              :                 }
     151              :             }
     152              :             else {
     153              : #endif
     154           16 :                 if (APR_SUCCESS != (status = ft_report_duplicates(conf))) {
     155            0 :                     DEBUG_ERR("error calling ft_report_duplicates: %s", apr_strerror(status, errbuf, 128));
     156            0 :                     apr_terminate();
     157            0 :                     return status;
     158              :                 }
     159              : #if HAVE_JANSSON
     160              :             }
     161              : #endif
     162              :         }
     163              :     }
     164              :     else {
     165            0 :         fprintf(stderr, "Please submit at least two files...\n");
     166            0 :         return -1;
     167              :     }
     168              : 
     169           17 :     apr_terminate();
     170              : 
     171           17 :     return 0;
     172              : }
     173              : 
     174              : #ifndef FTWIN_TEST_BUILD
     175              : int main(int argc, const char **argv)
     176              : {
     177              :     return ftwin_main(argc, argv);
     178              : }
     179              : #endif
        

Generated by: LCOV version 2.0-1