Coverage Report

Created: 2026-09-04 06:51

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.06k
#define minix_swab16(doit, num) ((uint16_t) (doit ? swab16(num) : num))
17
353
#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.22k
{
21
1.22k
  const struct minix_super_block *sb = (const struct minix_super_block *) data;
22
1.22k
  const struct minix3_super_block *sb3 = (const struct minix3_super_block *) data;
23
1.22k
  int version = 0;
24
1.22k
  char *endian;
25
26
1.22k
  *other_endian = 0;
27
28
1.22k
  switch (sb->s_magic) {
29
259
  case MINIX_SUPER_MAGIC:
30
404
  case MINIX_SUPER_MAGIC2:
31
404
    version = 1;
32
404
    break;
33
103
  case MINIX2_SUPER_MAGIC:
34
170
  case MINIX2_SUPER_MAGIC2:
35
170
    version = 2;
36
170
    break;
37
653
  default:
38
653
    if (sb3->s_magic == MINIX3_SUPER_MAGIC)
39
117
      version = 3;
40
653
    break;
41
1.22k
  }
42
43
1.22k
  if (!version) {
44
536
    *other_endian = 1;
45
46
536
    switch (swab16(sb->s_magic)) {
47
177
    case MINIX_SUPER_MAGIC:
48
295
    case MINIX_SUPER_MAGIC2:
49
295
      version = 1;
50
295
      break;
51
4
    case MINIX2_SUPER_MAGIC:
52
150
    case MINIX2_SUPER_MAGIC2:
53
150
      version = 2;
54
150
      break;
55
91
    default:
56
91
      if (sb3->s_magic == MINIX3_SUPER_MAGIC)
57
0
        version = 3;
58
91
      break;
59
536
    }
60
536
  }
61
1.22k
  if (!version)
62
91
    return -1;
63
64
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
65
  endian = *other_endian ? "LE" : "BE";
66
#else
67
1.13k
  endian = *other_endian ? "BE" : "LE";
68
1.13k
#endif
69
1.13k
  DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version,
70
1.13k
             endian));
71
1.13k
  return version;
72
1.22k
}
73
74
static int probe_minix(blkid_probe pr,
75
    const struct blkid_idmag *mag __attribute__((__unused__)))
76
1.22k
{
77
1.22k
  const unsigned char *ext;
78
1.22k
  const unsigned char *erofs;
79
1.22k
  const unsigned char *data;
80
1.22k
  int version = 0, swabme = 0;
81
1.22k
  unsigned long zones, ninodes, imaps, zmaps;
82
1.22k
  off_t firstz;
83
1.22k
  size_t zone_size;
84
1.22k
  unsigned block_size;
85
86
1.22k
  data = blkid_probe_get_buffer(pr, 1024,
87
1.22k
      max(sizeof(struct minix_super_block),
88
1.22k
          sizeof(struct minix3_super_block)));
89
1.22k
  if (!data)
90
0
    return errno ? -errno : 1;
91
1.22k
  version = get_minix_version(data, &swabme);
92
1.22k
  switch (version) {
93
699
  case 1:
94
1.01k
  case 2: {
95
1.01k
    const struct minix_super_block *sb = (const struct minix_super_block *) data;
96
97
1.01k
    uint16_t state = minix_swab16(swabme, sb->s_state);
98
1.01k
    if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
99
569
      return 1;
100
101
450
    zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
102
450
               minix_swab16(swabme, sb->s_nzones);
103
450
    ninodes = minix_swab16(swabme, sb->s_ninodes);
104
450
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
105
450
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
106
450
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
107
450
    zone_size = sb->s_log_zone_size;
108
450
    block_size = 1024;
109
450
    break;
110
1.01k
  }
111
117
  case 3: {
112
117
    const struct minix3_super_block *sb = (const struct minix3_super_block *) data;
113
114
117
    zones = minix_swab32(swabme, sb->s_zones);
115
117
    ninodes = minix_swab32(swabme, sb->s_ninodes);
116
117
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
117
117
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
118
117
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
119
117
    zone_size = sb->s_log_zone_size;
120
117
    block_size = minix_swab16(swabme, sb->s_blocksize);
121
122
117
    break;
123
1.01k
  }
124
91
  default:
125
91
    return 1;
126
1.22k
  }
127
128
  /* sanity checks to be sure that the FS is really minix.
129
   * see disk-utils/fsck.minix.c read_superblock
130
   */
131
567
  if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX)
132
214
    return 1;
133
353
  if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
134
214
    return 1;
135
139
  if (firstz > (off_t) zones)
136
28
    return 1;
137
111
  if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
138
60
    return 1;
139
140
  /* unfortunately, some parts of ext3 is sometimes possible to
141
   * interpreted as minix superblock. So check for extN magic
142
   * string. (For extN magic string and offsets see ext.c.)
143
   */
144
51
  ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
145
51
  if (!ext)
146
0
    return errno ? -errno : 1;
147
148
51
  if (memcmp(ext, "\123\357", 2) == 0)
149
26
    return 1;
150
151
  /* erofs superblock starts at 0x400 too, and its inode count field
152
   * overlaps the minix magic offset, so an erofs image can be
153
   * misinterpreted as minix. (For erofs magic and offsets see erofs.c.)
154
   */
155
25
  erofs = blkid_probe_get_buffer(pr, 0x400, 4);
156
25
  if (!erofs)
157
0
    return errno ? -errno : 1;
158
159
25
  if (memcmp(erofs, "\xe2\xe1\xf5\xe0", 4) == 0)
160
7
    return 1;
161
162
18
  blkid_probe_sprintf_version(pr, "%d", version);
163
18
  blkid_probe_set_fsblocksize(pr, block_size);
164
18
  blkid_probe_set_block_size(pr, block_size);
165
18
  blkid_probe_set_fsendianness(pr, !swabme ?
166
10
      BLKID_ENDIANNESS_NATIVE : BLKID_ENDIANNESS_OTHER);
167
18
  return 0;
168
25
}
169
170
const struct blkid_idinfo minix_idinfo =
171
{
172
  .name   = "minix",
173
  .usage    = BLKID_USAGE_FILESYSTEM,
174
  .probefunc  = probe_minix,
175
  .magics   =
176
  {
177
    /* version 1 - LE */
178
    { .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
179
    { .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
180
181
    /* version 1 - BE */
182
    { .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 },
183
    { .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 },
184
185
    /* version 2 - LE */
186
    { .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
187
    { .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
188
189
    /* version 2 - BE */
190
    { .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 },
191
    { .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 },
192
193
    /* version 3 - LE */
194
    { .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
195
196
    /* version 3 - BE */
197
    { .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 },
198
199
    { NULL }
200
  }
201
};
202