Coverage Report

Created: 2026-03-18 07:08

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