LCOV - code coverage report
Current view: top level - config - path.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 87 87 100.0 %
Date: 2020-09-01 11:23:34 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  * Type representing a path
       4             :  *
       5             :  * @authors
       6             :  * Copyright (C) 2020 Richard Russon <rich@flatcap.org>
       7             :  *
       8             :  * @copyright
       9             :  * This program is free software: you can redistribute it and/or modify it under
      10             :  * the terms of the GNU General Public License as published by the Free Software
      11             :  * Foundation, either version 2 of the License, or (at your option) any later
      12             :  * version.
      13             :  *
      14             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      15             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      16             :  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
      17             :  * details.
      18             :  *
      19             :  * You should have received a copy of the GNU General Public License along with
      20             :  * this program.  If not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : /**
      24             :  * @page config_path Type: Path
      25             :  *
      26             :  * Config type representing a path.
      27             :  *
      28             :  * - Backed by `char *`
      29             :  * - Empty path is stored as `NULL`
      30             :  * - Validator is passed `char *`, which may be `NULL`
      31             :  * - Data is freed when `ConfigSet` is freed
      32             :  */
      33             : 
      34             : #include "config.h"
      35             : #include <stddef.h>
      36             : #include <limits.h>
      37             : #include <stdbool.h>
      38             : #include <stdint.h>
      39             : #include "mutt/lib.h"
      40             : #include "set.h"
      41             : #include "types.h"
      42             : 
      43             : extern char *HomeDir;
      44             : 
      45             : /**
      46             :  * path_tidy - Tidy a path for storage
      47             :  * @param path   Path to be tidied
      48             :  * @param is_dir Is the path a directory?
      49             :  * @retval ptr Tidy path
      50             :  *
      51             :  * Expand `~` and remove junk like `/./`
      52             :  *
      53             :  * @note The caller must free the returned string
      54             :  */
      55         128 : static char *path_tidy(const char *path, bool is_dir)
      56             : {
      57         128 :   if (!path || (*path == '\0'))
      58          31 :     return NULL;
      59             : 
      60          97 :   char buf[PATH_MAX] = { 0 };
      61          97 :   mutt_str_copy(buf, path, sizeof(buf));
      62             : 
      63          97 :   mutt_path_tilde(buf, sizeof(buf), HomeDir);
      64          97 :   mutt_path_tidy(buf, is_dir);
      65             : 
      66          97 :   return mutt_str_dup(buf);
      67             : }
      68             : 
      69             : /**
      70             :  * path_destroy - Destroy a Path - Implements ConfigSetType::destroy()
      71             :  */
      72         172 : static void path_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
      73             : {
      74         172 :   const char **str = (const char **) var;
      75         172 :   if (!*str)
      76          79 :     return;
      77             : 
      78          93 :   FREE(var);
      79             : }
      80             : 
      81             : /**
      82             :  * path_string_set - Set a Path by string - Implements ConfigSetType::string_set()
      83             :  */
      84          61 : static int path_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
      85             :                            const char *value, struct Buffer *err)
      86             : {
      87             :   /* Store empty paths as NULL */
      88          61 :   if (value && (value[0] == '\0'))
      89           6 :     value = NULL;
      90             : 
      91          61 :   if (!value && (cdef->type & DT_NOT_EMPTY))
      92             :   {
      93           2 :     mutt_buffer_printf(err, _("Option %s may not be empty"), cdef->name);
      94           2 :     return CSR_ERR_INVALID | CSR_INV_VALIDATOR;
      95             :   }
      96             : 
      97          59 :   int rc = CSR_SUCCESS;
      98             : 
      99          59 :   if (var)
     100             :   {
     101          53 :     if (mutt_str_equal(value, (*(char **) var)))
     102          10 :       return CSR_SUCCESS | CSR_SUC_NO_CHANGE;
     103             : 
     104          43 :     if (cdef->validator)
     105             :     {
     106           8 :       rc = cdef->validator(cs, cdef, (intptr_t) value, err);
     107             : 
     108           8 :       if (CSR_RESULT(rc) != CSR_SUCCESS)
     109           2 :         return rc | CSR_INV_VALIDATOR;
     110             :     }
     111             : 
     112          41 :     path_destroy(cs, var, cdef);
     113             : 
     114          41 :     char *str = path_tidy(value, cdef->type & DT_PATH_DIR);
     115          41 :     if (!str)
     116           6 :       rc |= CSR_SUC_EMPTY;
     117             : 
     118          41 :     *(char **) var = str;
     119             :   }
     120             :   else
     121             :   {
     122           6 :     if (cdef->type & DT_INITIAL_SET)
     123           4 :       FREE(&cdef->initial);
     124             : 
     125           6 :     cdef->type |= DT_INITIAL_SET;
     126           6 :     cdef->initial = IP mutt_str_dup(value);
     127             :   }
     128             : 
     129          47 :   return rc;
     130             : }
     131             : 
     132             : /**
     133             :  * path_string_get - Get a Path as a string - Implements ConfigSetType::string_get()
     134             :  */
     135          72 : static int path_string_get(const struct ConfigSet *cs, void *var,
     136             :                            const struct ConfigDef *cdef, struct Buffer *result)
     137             : {
     138          72 :   const char *str = NULL;
     139             : 
     140          72 :   if (var)
     141          62 :     str = *(const char **) var;
     142             :   else
     143          10 :     str = (char *) cdef->initial;
     144             : 
     145          72 :   if (!str)
     146          14 :     return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty path */
     147             : 
     148          58 :   mutt_buffer_addstr(result, str);
     149          58 :   return CSR_SUCCESS;
     150             : }
     151             : 
     152             : /**
     153             :  * path_native_set - Set a Path config item by string - Implements ConfigSetType::native_set()
     154             :  */
     155          28 : static int path_native_set(const struct ConfigSet *cs, void *var,
     156             :                            const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
     157             : {
     158          28 :   char *str = (char *) value;
     159             : 
     160             :   /* Store empty paths as NULL */
     161          28 :   if (str && (str[0] == '\0'))
     162           6 :     value = 0;
     163             : 
     164          28 :   if ((value == 0) && (cdef->type & DT_NOT_EMPTY))
     165             :   {
     166           2 :     mutt_buffer_printf(err, _("Option %s may not be empty"), cdef->name);
     167           2 :     return CSR_ERR_INVALID | CSR_INV_VALIDATOR;
     168             :   }
     169             : 
     170          26 :   if (mutt_str_equal((const char *) value, (*(char **) var)))
     171           8 :     return CSR_SUCCESS | CSR_SUC_NO_CHANGE;
     172             : 
     173             :   int rc;
     174             : 
     175          18 :   if (cdef->validator)
     176             :   {
     177           6 :     rc = cdef->validator(cs, cdef, value, err);
     178             : 
     179           6 :     if (CSR_RESULT(rc) != CSR_SUCCESS)
     180           2 :       return rc | CSR_INV_VALIDATOR;
     181             :   }
     182             : 
     183          16 :   path_destroy(cs, var, cdef);
     184             : 
     185          16 :   str = path_tidy(str, cdef->type & DT_PATH_DIR);
     186          16 :   rc = CSR_SUCCESS;
     187          16 :   if (!str)
     188           4 :     rc |= CSR_SUC_EMPTY;
     189             : 
     190          16 :   *(const char **) var = str;
     191          16 :   return rc;
     192             : }
     193             : 
     194             : /**
     195             :  * path_native_get - Get a string from a Path config item - Implements ConfigSetType::native_get()
     196             :  */
     197          20 : static intptr_t path_native_get(const struct ConfigSet *cs, void *var,
     198             :                                 const struct ConfigDef *cdef, struct Buffer *err)
     199             : {
     200          20 :   const char *str = *(const char **) var;
     201             : 
     202          20 :   return (intptr_t) str;
     203             : }
     204             : 
     205             : /**
     206             :  * path_reset - Reset a Path to its initial value - Implements ConfigSetType::reset()
     207             :  */
     208          71 : static int path_reset(const struct ConfigSet *cs, void *var,
     209             :                       const struct ConfigDef *cdef, struct Buffer *err)
     210             : {
     211          71 :   int rc = CSR_SUCCESS;
     212             : 
     213          71 :   const char *str = path_tidy((const char *) cdef->initial, cdef->type & DT_PATH_DIR);
     214          71 :   if (!str)
     215          21 :     rc |= CSR_SUC_EMPTY;
     216             : 
     217          71 :   if (mutt_str_equal(str, (*(char **) var)))
     218             :   {
     219          21 :     FREE(&str);
     220          21 :     return rc | CSR_SUC_NO_CHANGE;
     221             :   }
     222             : 
     223          50 :   if (cdef->validator)
     224             :   {
     225          10 :     rc = cdef->validator(cs, cdef, cdef->initial, err);
     226             : 
     227          10 :     if (CSR_RESULT(rc) != CSR_SUCCESS)
     228             :     {
     229           2 :       FREE(&str);
     230           2 :       return rc | CSR_INV_VALIDATOR;
     231             :     }
     232             :   }
     233             : 
     234          48 :   path_destroy(cs, var, cdef);
     235             : 
     236          48 :   if (!str)
     237           2 :     rc |= CSR_SUC_EMPTY;
     238             : 
     239          48 :   *(const char **) var = str;
     240          48 :   return rc;
     241             : }
     242             : 
     243             : /**
     244             :  * cst_path - Config type representing a path
     245             :  */
     246             : const struct ConfigSetType cst_path = {
     247             :   DT_PATH,
     248             :   "path",
     249             :   path_string_set,
     250             :   path_string_get,
     251             :   path_native_set,
     252             :   path_native_get,
     253             :   NULL, // string_plus_equals
     254             :   NULL, // string_minus_equals
     255             :   path_reset,
     256             :   path_destroy,
     257             : };

Generated by: LCOV version 1.15