Coverage Report

Created: 2025-11-11 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/superblocks/minix.c
Line
Count
Source
1
/*
2
 * Copyright (C) 1999 by Andries Brouwer
3
 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4
 * Copyright (C) 2001 by Andreas Dilger
5
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6
 * Copyright (C) 2008-2013 Karel Zak <kzak@redhat.com>
7
 *
8
 * This file may be redistributed under the terms of the
9
 * GNU Lesser General Public License.
10
 */
11
12
#include <string.h>
13
#include "superblocks.h"
14
#include "minix.h"
15
16
4.25k
#define minix_swab16(doit, num) ((uint16_t) (doit ? swab16(num) : num))
17
321
#define minix_swab32(doit, num) ((uint32_t) (doit ? swab32(num) : num))
18
19
static int get_minix_version(const unsigned char *data, int *other_endian)
20
1.77k
{
21
1.77k
  const struct minix_super_block *sb = (const struct minix_super_block *) data;
22
1.77k
  const struct minix3_super_block *sb3 = (const struct minix3_super_block *) data;
23
1.77k
  int version = 0;
24
1.77k
  char *endian;
25
26
1.77k
  *other_endian = 0;
27
28
1.77k
  switch (sb->s_magic) {
29
295
  case MINIX_SUPER_MAGIC:
30
551
  case MINIX_SUPER_MAGIC2:
31
551
    version = 1;
32
551
    break;
33
271
  case MINIX2_SUPER_MAGIC:
34
351
  case MINIX2_SUPER_MAGIC2:
35
351
    version = 2;
36
351
    break;
37
873
  default:
38
873
    if (sb3->s_magic == MINIX3_SUPER_MAGIC)
39
94
      version = 3;
40
873
    break;
41
1.77k
  }
42
43
1.77k
  if (!version) {
44
779
    *other_endian = 1;
45
46
779
    switch (swab16(sb->s_magic)) {
47
106
    case MINIX_SUPER_MAGIC:
48
371
    case MINIX_SUPER_MAGIC2:
49
371
      version = 1;
50
371
      break;
51
12
    case MINIX2_SUPER_MAGIC:
52
295
    case MINIX2_SUPER_MAGIC2:
53
295
      version = 2;
54
295
      break;
55
113
    default:
56
113
      if (sb3->s_magic == MINIX3_SUPER_MAGIC)
57
0
        version = 3;
58
113
      break;
59
779
    }
60
779
  }
61
1.77k
  if (!version)
62
113
    return -1;
63
64
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
65
  endian = *other_endian ? "LE" : "BE";
66
#else
67
1.66k
  endian = *other_endian ? "BE" : "LE";
68
1.66k
#endif
69
1.66k
  DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version,
70
1.66k
             endian));
71
1.66k
  return version;
72
1.77k
}
73
74
static int probe_minix(blkid_probe pr,
75
    const struct blkid_idmag *mag __attribute__((__unused__)))
76
1.77k
{
77
1.77k
  const unsigned char *ext;
78
1.77k
  const unsigned char *data;
79
1.77k
  int version = 0, swabme = 0;
80
1.77k
  unsigned long zones, ninodes, imaps, zmaps;
81
1.77k
  off_t firstz;
82
1.77k
  size_t zone_size;
83
1.77k
  unsigned block_size;
84
85
1.77k
  data = blkid_probe_get_buffer(pr, 1024,
86
1.77k
      max(sizeof(struct minix_super_block),
87
1.77k
          sizeof(struct minix3_super_block)));
88
1.77k
  if (!data)
89
0
    return errno ? -errno : 1;
90
1.77k
  version = get_minix_version(data, &swabme);
91
1.77k
  switch (version) {
92
922
  case 1:
93
1.56k
  case 2: {
94
1.56k
    const struct minix_super_block *sb = (const struct minix_super_block *) data;
95
96
1.56k
    uint16_t state = minix_swab16(swabme, sb->s_state);
97
1.56k
    if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
98
1.16k
      return 1;
99
100
408
    zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
101
408
               minix_swab16(swabme, sb->s_nzones);
102
408
    ninodes = minix_swab16(swabme, sb->s_ninodes);
103
408
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
104
408
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
105
408
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
106
408
    zone_size = sb->s_log_zone_size;
107
408
    block_size = 1024;
108
408
    break;
109
1.56k
  }
110
94
  case 3: {
111
94
    const struct minix3_super_block *sb = (const struct minix3_super_block *) data;
112
113
94
    zones = minix_swab32(swabme, sb->s_zones);
114
94
    ninodes = minix_swab32(swabme, sb->s_ninodes);
115
94
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
116
94
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
117
94
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
118
94
    zone_size = sb->s_log_zone_size;
119
94
    block_size = minix_swab16(swabme, sb->s_blocksize);
120
121
94
    break;
122
1.56k
  }
123
113
  default:
124
113
    return 1;
125
1.77k
  }
126
127
  /* sanity checks to be sure that the FS is really minix.
128
   * see disk-utils/fsck.minix.c read_superblock
129
   */
130
502
  if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX)
131
219
    return 1;
132
283
  if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
133
135
    return 1;
134
148
  if (firstz > (off_t) zones)
135
18
    return 1;
136
130
  if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
137
86
    return 1;
138
139
  /* unfortunately, some parts of ext3 is sometimes possible to
140
   * interpreted as minix superblock. So check for extN magic
141
   * string. (For extN magic string and offsets see ext.c.)
142
   */
143
44
  ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
144
44
  if (!ext)
145
0
    return errno ? -errno : 1;
146
147
44
  if (memcmp(ext, "\123\357", 2) == 0)
148
7
    return 1;
149
150
37
  blkid_probe_sprintf_version(pr, "%d", version);
151
37
  blkid_probe_set_fsblocksize(pr, block_size);
152
37
  blkid_probe_set_block_size(pr, block_size);
153
37
  blkid_probe_set_fsendianness(pr, !swabme ?
154
30
      BLKID_ENDIANNESS_NATIVE : BLKID_ENDIANNESS_OTHER);
155
37
  return 0;
156
44
}
157
158
const struct blkid_idinfo minix_idinfo =
159
{
160
  .name   = "minix",
161
  .usage    = BLKID_USAGE_FILESYSTEM,
162
  .probefunc  = probe_minix,
163
  .magics   =
164
  {
165
    /* version 1 - LE */
166
    { .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
167
    { .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
168
169
    /* version 1 - BE */
170
    { .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 },
171
    { .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 },
172
173
    /* version 2 - LE */
174
    { .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
175
    { .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
176
177
    /* version 2 - BE */
178
    { .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 },
179
    { .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 },
180
181
    /* version 3 - LE */
182
    { .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
183
184
    /* version 3 - BE */
185
    { .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 },
186
187
    { NULL }
188
  }
189
};
190