Coverage Report

Created: 2026-03-03 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/superblocks/swap.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 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
#include <stdio.h>
12
#include <stdlib.h>
13
#include <unistd.h>
14
#include <string.h>
15
#include <errno.h>
16
#include <ctype.h>
17
#include <stdint.h>
18
19
#include "superblocks.h"
20
21
/* linux-2.6/include/linux/swap.h */
22
struct swap_header_v1_2 {
23
     /* char    bootbits[1024]; */ /* Space for disklabel etc. */
24
  uint32_t  version;
25
  uint32_t  lastpage;
26
  uint32_t  nr_badpages;
27
  unsigned char uuid[16];
28
  unsigned char volume[16];
29
  uint32_t  padding[117];
30
  uint32_t  badpages[1];
31
} __attribute__((packed));
32
33
#define PAGESIZE_MIN  0xff6 /* 4086 (arm, i386, ...) */
34
#define PAGESIZE_MAX  0xfff6  /* 65526 (ia64) */
35
36
861
#define TOI_MAGIC_STRING  "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
37
539
#define TOI_MAGIC_STRLEN  (sizeof(TOI_MAGIC_STRING) - 1)
38
39
static void swap_set_info_swap1(blkid_probe pr,
40
    const struct blkid_idmag *mag,
41
    const struct swap_header_v1_2 *hdr)
42
14
{
43
14
  enum blkid_endianness endianness = le32_to_cpu(hdr->version) == 1 ?
44
10
    BLKID_ENDIANNESS_LITTLE : BLKID_ENDIANNESS_BIG;
45
14
  blkid_probe_set_fsendianness(pr, endianness);
46
47
14
  uint32_t pagesize = mag->sboff + mag->len;
48
14
  blkid_probe_set_fsblocksize(pr, pagesize);
49
50
  /* note that "lastpage" in swap header means number of pages used by
51
   * swap, see mkswap */
52
14
  uint32_t lastpage = endianness == BLKID_ENDIANNESS_LITTLE ?
53
10
    le32_to_cpu(hdr->lastpage) : be32_to_cpu(hdr->lastpage);
54
14
  blkid_probe_set_fssize(pr, (uint64_t) pagesize * lastpage);
55
14
  blkid_probe_set_fslastblock(pr, lastpage + 1);
56
14
}
57
58
static int swap_set_info(blkid_probe pr, const struct blkid_idmag *mag,
59
    const char *version)
60
416
{
61
416
  struct swap_header_v1_2 *hdr;
62
63
  /* Swap header always located at offset of 1024 bytes */
64
416
  hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
65
416
        sizeof(struct swap_header_v1_2));
66
416
  if (!hdr)
67
0
    return errno ? -errno : 1;
68
69
  /* SWAPSPACE2 - check for wrong version or zeroed pagecount */
70
416
  if (strcmp(version, "1") == 0) {
71
203
    if (hdr->version != 1 && swab32(hdr->version) != 1) {
72
182
      DBG(LOWPROBE, ul_debug("incorrect swap version"));
73
182
      return 1;
74
182
    }
75
21
    if (hdr->lastpage == 0) {
76
7
      DBG(LOWPROBE, ul_debug("not set last swap page"));
77
7
      return 1;
78
7
    }
79
14
    swap_set_info_swap1(pr, mag, hdr);
80
14
  }
81
82
  /* arbitrary sanity check.. is there any garbage down there? */
83
227
  if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
84
62
    if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
85
34
        sizeof(hdr->volume)) < 0)
86
0
      return 1;
87
62
    if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
88
0
      return 1;
89
62
  }
90
91
227
  blkid_probe_set_version(pr, version);
92
227
  return 0;
93
227
}
94
95
static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
96
217
{
97
217
  const unsigned char *buf;
98
99
217
  if (!mag)
100
0
    return 1;
101
102
  /* TuxOnIce keeps valid swap header at the end of the 1st page */
103
217
  buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
104
217
  if (!buf)
105
0
    return errno ? -errno : 1;
106
107
217
  if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
108
3
    return 1;  /* Ignore swap signature, it's TuxOnIce */
109
110
214
  if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
111
    /* swap v0 doesn't support LABEL or UUID */
112
11
    blkid_probe_set_version(pr, "0");
113
11
    return 0;
114
115
11
  }
116
117
203
  if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
118
203
    return swap_set_info(pr, mag, "1");
119
120
0
  return 1;
121
203
}
122
123
static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
124
213
{
125
213
  if (!mag)
126
0
    return 1;
127
213
  if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
128
23
    return swap_set_info(pr, mag, "s1suspend");
129
190
  if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
130
45
    return swap_set_info(pr, mag, "s2suspend");
131
145
  if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
132
40
    return swap_set_info(pr, mag, "ulsuspend");
133
105
  if (!memcmp(mag->magic, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN))
134
28
    return swap_set_info(pr, mag, "tuxonice");
135
77
  if (!memcmp(mag->magic, "LINHIB0001", mag->len))
136
77
    return swap_set_info(pr, mag, "linhib0001");
137
138
0
  return 1; /* no signature detected */
139
77
}
140
141
const struct blkid_idinfo swap_idinfo =
142
{
143
  .name   = "swap",
144
  .usage    = BLKID_USAGE_OTHER,
145
  .probefunc  = probe_swap,
146
  .minsz    = 10 * 4096,  /* 10 pages */
147
  .magics   =
148
  {
149
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0xff6 },
150
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0xff6 },
151
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x1ff6 },
152
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x1ff6 },
153
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x3ff6 },
154
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x3ff6 },
155
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x7ff6 },
156
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x7ff6 },
157
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0xfff6 },
158
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0xfff6 },
159
    { NULL }
160
  }
161
};
162
163
164
const struct blkid_idinfo swsuspend_idinfo =
165
{
166
  .name   = "swsuspend",
167
  .usage    = BLKID_USAGE_OTHER,
168
  .probefunc  = probe_swsuspend,
169
  .minsz    = 10 * 4096,  /* 10 pages */
170
  .magics   =
171
  {
172
    { .magic = TOI_MAGIC_STRING, .len = TOI_MAGIC_STRLEN },
173
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0xff6 },
174
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0xff6 },
175
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0xff6 },
176
    { .magic = "LINHIB0001", .len = 10, .sboff = 0xff6 },
177
178
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x1ff6 },
179
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x1ff6 },
180
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x1ff6 },
181
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x1ff6 },
182
183
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x3ff6 },
184
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x3ff6 },
185
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x3ff6 },
186
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x3ff6 },
187
188
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x7ff6 },
189
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x7ff6 },
190
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x7ff6 },
191
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x7ff6 },
192
193
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0xfff6 },
194
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0xfff6 },
195
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0xfff6 },
196
    { .magic = "LINHIB0001", .len = 10, .sboff = 0xfff6 },
197
    { NULL }
198
  }
199
};