Coverage Report

Created: 2025-11-24 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/include/optutils.h
Line
Count
Source
1
/*
2
 * No copyright is claimed.  This code is in the public domain; do with
3
 * it what you wish.
4
 */
5
#ifndef UTIL_LINUX_OPTUTILS_H
6
#define UTIL_LINUX_OPTUTILS_H
7
8
#include <assert.h>
9
10
#include "c.h"
11
#include "nls.h"
12
#include "cctype.h"
13
14
/*
15
 * Converts the short option @c to the corresponding long option from @opts, or
16
 * returns NULL.
17
 */
18
static inline const char *ul_get_longopt(const struct option *opts, int c)
19
0
{
20
0
  const struct option *o;
21
0
22
0
  assert(!(opts == NULL));
23
0
  for (o = opts; o->name; o++)
24
0
    if (o->val == c)
25
0
      return o->name;
26
0
  return NULL;
27
0
}
28
29
/*
30
 * Converts the short options @c to "%c" or "0x<hex>" if not printable.
31
 */
32
static inline const char *ul_get_shortopt(char *buf, size_t bufsz, int c)
33
0
{
34
0
  if (c_isgraph(c))
35
0
    snprintf(buf, bufsz, "%c", c);
36
0
  else
37
0
    snprintf(buf, bufsz, "<0x%02x>", c);  /* should not happen */
38
0
39
0
  return buf;
40
0
}
41
42
#ifndef OPTUTILS_EXIT_CODE
43
# define OPTUTILS_EXIT_CODE EXIT_FAILURE
44
#endif
45
46
/*
47
 * Check collisions between options.
48
 *
49
 * The conflicts between options are described in ul_excl_t array. The
50
 * array contains groups of mutually exclusive options. For example
51
 *
52
 *  static const ul_excl_t excl[] = {
53
 *    { 'Z','b','c' },    // first group
54
 *    { 'b','x' },      // second group
55
 *    { 0 }
56
 *  };
57
 *
58
 *  int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
59
 *
60
 *  while ((c = getopt_long(argc, argv, "Zbcx", longopts, NULL)) != -1) {
61
 *
62
 *    err_exclusive_options(c, longopts, excl, excl_st);
63
 *
64
 *    switch (c) {
65
 *    case 'Z':
66
 *       ....
67
 *    }
68
 *  }
69
 *
70
 * The array excl[] defines two groups of the mutually exclusive options. The
71
 * option '-b' is in the both groups.
72
 *
73
 * Note that the options in the group have to be in ASCII order (ABC..abc..) and
74
 * groups have to be also in ASCII order.
75
 *
76
 * The maximal number of the options in the group is 15 (size of the array is
77
 * 16, last is zero).
78
 *
79
 * The current status of options is stored in excl_st array. The size of the array
80
 * must be the same as number of the groups in the ul_excl_t array.
81
 *
82
 * If you're unsure then see sys-utils/mount.c or misc-utils/findmnt.c.
83
 */
84
#define UL_EXCL_STATUS_INIT { 0 }
85
typedef int ul_excl_t[16];
86
87
static inline void err_exclusive_options(
88
      int c,
89
      const struct option *opts,
90
      const ul_excl_t *excl,
91
      int *status)
92
0
{
93
0
  int e;
94
0
95
0
  for (e = 0; excl[e][0] && excl[e][0] <= c; e++) {
96
0
    const int *op = excl[e];
97
0
98
0
    for (; *op && *op <= c; op++) {
99
0
      if (*op != c)
100
0
        continue;
101
0
      if (status[e] == 0)
102
0
        status[e] = c;
103
0
      else if (status[e] != c) {
104
0
        const char *a = ul_get_longopt(opts, status[e]);
105
0
        const char *b = ul_get_longopt(opts, c);
106
0
        char buf[16]; /* short option in hex */
107
0
108
0
        errx(OPTUTILS_EXIT_CODE,
109
0
          _("options %s%s and %s%s cannot be combined"),
110
0
          a ? "--" : "-",
111
0
          a ? a : ul_get_shortopt(buf, sizeof(buf), status[e]),
112
0
          b ? "--" : "-",
113
0
          b ? b : ul_get_shortopt(buf, sizeof(buf), c));
114
0
      }
115
0
      break;
116
0
    }
117
0
  }
118
0
}
119
120
#endif