Coverage Report

Created: 2026-02-22 06:11

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
3.61k
#define minix_swab16(doit, num) ((uint16_t) (doit ? swab16(num) : num))
17
262
#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.68k
{
21
1.68k
  const struct minix_super_block *sb = (const struct minix_super_block *) data;
22
1.68k
  const struct minix3_super_block *sb3 = (const struct minix3_super_block *) data;
23
1.68k
  int version = 0;
24
1.68k
  char *endian;
25
26
1.68k
  *other_endian = 0;
27
28
1.68k
  switch (sb->s_magic) {
29
294
  case MINIX_SUPER_MAGIC:
30
617
  case MINIX_SUPER_MAGIC2:
31
617
    version = 1;
32
617
    break;
33
226
  case MINIX2_SUPER_MAGIC:
34
400
  case MINIX2_SUPER_MAGIC2:
35
400
    version = 2;
36
400
    break;
37
666
  default:
38
666
    if (sb3->s_magic == MINIX3_SUPER_MAGIC)
39
83
      version = 3;
40
666
    break;
41
1.68k
  }
42
43
1.68k
  if (!version) {
44
583
    *other_endian = 1;
45
46
583
    switch (swab16(sb->s_magic)) {
47
69
    case MINIX_SUPER_MAGIC:
48
302
    case MINIX_SUPER_MAGIC2:
49
302
      version = 1;
50
302
      break;
51
4
    case MINIX2_SUPER_MAGIC:
52
178
    case MINIX2_SUPER_MAGIC2:
53
178
      version = 2;
54
178
      break;
55
103
    default:
56
103
      if (sb3->s_magic == MINIX3_SUPER_MAGIC)
57
0
        version = 3;
58
103
      break;
59
583
    }
60
583
  }
61
1.68k
  if (!version)
62
103
    return -1;
63
64
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
65
  endian = *other_endian ? "LE" : "BE";
66
#else
67
1.58k
  endian = *other_endian ? "BE" : "LE";
68
1.58k
#endif
69
1.58k
  DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version,
70
1.58k
             endian));
71
1.58k
  return version;
72
1.68k
}
73
74
static int probe_minix(blkid_probe pr,
75
    const struct blkid_idmag *mag __attribute__((__unused__)))
76
1.68k
{
77
1.68k
  const unsigned char *ext;
78
1.68k
  const unsigned char *data;
79
1.68k
  int version = 0, swabme = 0;
80
1.68k
  unsigned long zones, ninodes, imaps, zmaps;
81
1.68k
  off_t firstz;
82
1.68k
  size_t zone_size;
83
1.68k
  unsigned block_size;
84
85
1.68k
  data = blkid_probe_get_buffer(pr, 1024,
86
1.68k
      max(sizeof(struct minix_super_block),
87
1.68k
          sizeof(struct minix3_super_block)));
88
1.68k
  if (!data)
89
0
    return errno ? -errno : 1;
90
1.68k
  version = get_minix_version(data, &swabme);
91
1.68k
  switch (version) {
92
919
  case 1:
93
1.49k
  case 2: {
94
1.49k
    const struct minix_super_block *sb = (const struct minix_super_block *) data;
95
96
1.49k
    uint16_t state = minix_swab16(swabme, sb->s_state);
97
1.49k
    if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
98
1.18k
      return 1;
99
100
314
    zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
101
314
               minix_swab16(swabme, sb->s_nzones);
102
314
    ninodes = minix_swab16(swabme, sb->s_ninodes);
103
314
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
104
314
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
105
314
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
106
314
    zone_size = sb->s_log_zone_size;
107
314
    block_size = 1024;
108
314
    break;
109
1.49k
  }
110
83
  case 3: {
111
83
    const struct minix3_super_block *sb = (const struct minix3_super_block *) data;
112
113
83
    zones = minix_swab32(swabme, sb->s_zones);
114
83
    ninodes = minix_swab32(swabme, sb->s_ninodes);
115
83
    imaps   = minix_swab16(swabme, sb->s_imap_blocks);
116
83
    zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
117
83
    firstz  = minix_swab16(swabme, sb->s_firstdatazone);
118
83
    zone_size = sb->s_log_zone_size;
119
83
    block_size = minix_swab16(swabme, sb->s_blocksize);
120
121
83
    break;
122
1.49k
  }
123
103
  default:
124
103
    return 1;
125
1.68k
  }
126
127
  /* sanity checks to be sure that the FS is really minix.
128
   * see disk-utils/fsck.minix.c read_superblock
129
   */
130
397
  if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX)
131
198
    return 1;
132
199
  if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
133
93
    return 1;
134
106
  if (firstz > (off_t) zones)
135
7
    return 1;
136
99
  if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
137
51
    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
48
  ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
144
48
  if (!ext)
145
0
    return errno ? -errno : 1;
146
147
48
  if (memcmp(ext, "\123\357", 2) == 0)
148
12
    return 1;
149
150
36
  blkid_probe_sprintf_version(pr, "%d", version);
151
36
  blkid_probe_set_fsblocksize(pr, block_size);
152
36
  blkid_probe_set_block_size(pr, block_size);
153
36
  blkid_probe_set_fsendianness(pr, !swabme ?
154
24
      BLKID_ENDIANNESS_NATIVE : BLKID_ENDIANNESS_OTHER);
155
36
  return 0;
156
48
}
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