Coverage Report

Created: 2025-10-10 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/superblocks/ufs.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3
 *
4
 * Inspired by libvolume_id by
5
 *     Kay Sievers <kay.sievers@vrfy.org>
6
 *
7
 * This file may be redistributed under the terms of the
8
 * GNU Lesser General Public License.
9
 */
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
#include <stddef.h>
19
20
#include "superblocks.h"
21
22
struct ufs_super_block {
23
  uint32_t  fs_link;
24
  uint32_t  fs_rlink;
25
  uint32_t  fs_sblkno;
26
  uint32_t  fs_cblkno;
27
  uint32_t  fs_iblkno;
28
  uint32_t  fs_dblkno;
29
  uint32_t  fs_cgoffset;
30
  uint32_t  fs_cgmask;
31
  uint32_t  fs_time;
32
  uint32_t  fs_size;
33
  uint32_t  fs_dsize;
34
  uint32_t  fs_ncg;
35
  uint32_t  fs_bsize;
36
  uint32_t  fs_fsize;
37
  uint32_t  fs_frag;
38
  uint32_t  fs_minfree;
39
  uint32_t  fs_rotdelay;
40
  uint32_t  fs_rps;
41
  uint32_t  fs_bmask;
42
  uint32_t  fs_fmask;
43
  uint32_t  fs_bshift;
44
  uint32_t  fs_fshift;
45
  uint32_t  fs_maxcontig;
46
  uint32_t  fs_maxbpg;
47
  uint32_t  fs_fragshift;
48
  uint32_t  fs_fsbtodb;
49
  uint32_t  fs_sbsize;
50
  uint32_t  fs_csmask;
51
  uint32_t  fs_csshift;
52
  uint32_t  fs_nindir;
53
  uint32_t  fs_inopb;
54
  uint32_t  fs_nspf;
55
  uint32_t  fs_optim;
56
  uint32_t  fs_npsect_state;
57
  uint32_t  fs_interleave;
58
  uint32_t  fs_trackskew;
59
  uint32_t  fs_id[2];
60
  uint32_t  fs_csaddr;
61
  uint32_t  fs_cssize;
62
  uint32_t  fs_cgsize;
63
  uint32_t  fs_ntrak;
64
  uint32_t  fs_nsect;
65
  uint32_t  fs_spc;
66
  uint32_t  fs_ncyl;
67
  uint32_t  fs_cpg;
68
  uint32_t  fs_ipg;
69
  uint32_t  fs_fpg;
70
  struct ufs_csum {
71
    uint32_t  cs_ndir;
72
    uint32_t  cs_nbfree;
73
    uint32_t  cs_nifree;
74
    uint32_t  cs_nffree;
75
  } fs_cstotal;
76
  int8_t    fs_fmod;
77
  int8_t    fs_clean;
78
  int8_t    fs_ronly;
79
  int8_t    fs_flags;
80
  union {
81
    struct {
82
      int8_t  fs_fsmnt[512];
83
      uint32_t  fs_cgrotor;
84
      uint32_t  fs_csp[31];
85
      uint32_t  fs_maxcluster;
86
      uint32_t  fs_cpc;
87
      uint16_t  fs_opostbl[16][8];
88
    } fs_u1;
89
    struct {
90
      int8_t    fs_fsmnt[468];
91
      uint8_t   fs_volname[32];
92
      uint64_t  fs_swuid;
93
      int32_t   fs_pad;
94
      uint32_t  fs_cgrotor;
95
      uint32_t  fs_ocsp[28];
96
      uint32_t  fs_contigdirs;
97
      uint32_t  fs_csp;
98
      uint32_t  fs_maxcluster;
99
      uint32_t  fs_active;
100
      int32_t   fs_old_cpc;
101
      int32_t   fs_maxbsize;
102
      int64_t   fs_sparecon64[17];
103
      int64_t   fs_sblockloc;
104
      struct ufs2_csum_total {
105
        uint64_t  cs_ndir;
106
        uint64_t  cs_nbfree;
107
        uint64_t  cs_nifree;
108
        uint64_t  cs_nffree;
109
        uint64_t  cs_numclusters;
110
        uint64_t  cs_spare[3];
111
      } fs_cstotal;
112
      struct ufs_timeval {
113
        int32_t   tv_sec;
114
        int32_t   tv_usec;
115
      } fs_time;
116
      int64_t   fs_size;
117
      int64_t   fs_dsize;
118
      uint64_t  fs_csaddr;
119
      int64_t   fs_pendingblocks;
120
      int32_t   fs_pendinginodes;
121
    } __attribute__((packed)) fs_u2;
122
  }  fs_u11;
123
  union {
124
    struct {
125
      int32_t   fs_sparecon[53];
126
      int32_t   fs_reclaim;
127
      int32_t   fs_sparecon2[1];
128
      int32_t   fs_state;
129
      uint32_t  fs_qbmask[2];
130
      uint32_t  fs_qfmask[2];
131
    } fs_sun;
132
    struct {
133
      int32_t   fs_sparecon[53];
134
      int32_t   fs_reclaim;
135
      int32_t   fs_sparecon2[1];
136
      uint32_t  fs_npsect;
137
      uint32_t  fs_qbmask[2];
138
      uint32_t  fs_qfmask[2];
139
    } fs_sunx86;
140
    struct {
141
      int32_t   fs_sparecon[50];
142
      int32_t   fs_contigsumsize;
143
      int32_t   fs_maxsymlinklen;
144
      int32_t   fs_inodefmt;
145
      uint32_t  fs_maxfilesize[2];
146
      uint32_t  fs_qbmask[2];
147
      uint32_t  fs_qfmask[2];
148
      int32_t   fs_state;
149
    } fs_44;
150
  } fs_u2;
151
  int32_t   fs_postblformat;
152
  int32_t   fs_nrpos;
153
  int32_t   fs_postbloff;
154
  int32_t   fs_rotbloff;
155
  uint32_t  fs_magic;
156
  uint8_t   fs_space[1];
157
} __attribute__((packed));
158
159
2.99k
#define UFS_MAGIC     0x00011954
160
3.06k
#define UFS2_MAGIC      0x19540119
161
2.99k
#define UFS_MAGIC_FEA     0x00195612
162
2.99k
#define UFS_MAGIC_LFN     0x00095014
163
2.99k
#define UFS_MAGIC_SEC     0x00612195
164
2.99k
#define UFS_MAGIC_4GB     0x05231994
165
166
static int probe_ufs(blkid_probe pr,
167
    const struct blkid_idmag *mag __attribute__((__unused__)))
168
2.99k
{
169
2.99k
  int offsets[] = { 0, 8, 64, 256 };
170
2.99k
  uint32_t mags[] = {
171
2.99k
    UFS2_MAGIC, UFS_MAGIC, UFS_MAGIC_FEA, UFS_MAGIC_LFN,
172
2.99k
    UFS_MAGIC_SEC, UFS_MAGIC_4GB
173
2.99k
  };
174
2.99k
  size_t i;
175
2.99k
  uint32_t magic;
176
2.99k
  struct ufs_super_block *ufs;
177
2.99k
  int is_be;
178
179
6.49k
  for (i = 0; i < ARRAY_SIZE(offsets); i++) {
180
6.26k
    uint32_t magLE, magBE;
181
6.26k
    size_t y;
182
183
6.26k
    ufs = (struct ufs_super_block *)
184
6.26k
        blkid_probe_get_buffer(pr,
185
6.26k
          offsets[i] * 1024,
186
6.26k
          sizeof(struct ufs_super_block));
187
6.26k
    if (!ufs)
188
2.69k
      return errno ? -errno : 1;
189
190
3.56k
    magBE = be32_to_cpu(ufs->fs_magic);
191
3.56k
    magLE = le32_to_cpu(ufs->fs_magic);
192
193
24.7k
    for (y = 0; y < ARRAY_SIZE(mags); y++) {
194
21.2k
      if (magLE == mags[y] || magBE == mags[y]) {
195
70
        magic = mags[y];
196
70
        is_be = (magBE == mags[y]);
197
70
        goto found;
198
70
      }
199
21.2k
    }
200
3.56k
  }
201
202
233
  return 1;
203
204
70
found:
205
70
  if (magic == UFS2_MAGIC) {
206
22
    blkid_probe_set_version(pr, "2");
207
22
    blkid_probe_set_label(pr, ufs->fs_u11.fs_u2.fs_volname,
208
22
        sizeof(ufs->fs_u11.fs_u2.fs_volname));
209
22
  } else
210
48
    blkid_probe_set_version(pr, "1");
211
70
  if (ufs->fs_id[0] || ufs->fs_id[1])
212
60
  {
213
60
    if (is_be)
214
30
      blkid_probe_sprintf_uuid(pr,
215
30
           (unsigned char *) &ufs->fs_id,
216
30
             sizeof(ufs->fs_id),
217
30
             "%08x%08x",
218
30
             be32_to_cpu(ufs->fs_id[0]),
219
30
             be32_to_cpu(ufs->fs_id[1]));
220
30
    else
221
30
      blkid_probe_sprintf_uuid(pr,
222
30
           (unsigned char *) &ufs->fs_id,
223
30
             sizeof(ufs->fs_id),
224
30
             "%08x%08x",
225
30
             le32_to_cpu(ufs->fs_id[0]),
226
30
             le32_to_cpu(ufs->fs_id[1]));
227
60
  }
228
229
70
  if (blkid_probe_set_magic(pr,
230
70
      (offsets[i] * 1024) +
231
70
        offsetof(struct ufs_super_block, fs_magic),
232
70
      sizeof(ufs->fs_magic),
233
70
      (unsigned char *) &ufs->fs_magic))
234
0
    return 1;
235
236
70
  uint32_t bsize = 0;
237
70
  if (!is_be)
238
40
    bsize = le32_to_cpu(ufs->fs_fsize);
239
30
  else
240
30
    bsize = be32_to_cpu(ufs->fs_fsize);
241
242
70
  blkid_probe_set_fsblocksize(pr, bsize);
243
70
  blkid_probe_set_block_size(pr, bsize);
244
70
  blkid_probe_set_fsendianness(pr, is_be ?
245
40
      BLKID_ENDIANNESS_BIG : BLKID_ENDIANNESS_LITTLE);
246
247
70
  return 0;
248
70
}
249
250
/*
251
 * According to libvolume_id the UFS superblock could be on four positions.
252
 * The original libblkid has checked one position (.kboff=8) only.
253
 *
254
 * We know four UFS magic strings and UFS could be both little-endian and
255
 * big-endian. ... so we have:
256
 *
257
 *  4 position * 4 string * 2 version = 32 magic strings
258
 *
259
 * It seems simpler to check for these string in probing function that hardcode
260
 * all in the .magic array.
261
 */
262
const struct blkid_idinfo ufs_idinfo =
263
{
264
  .name   = "ufs",
265
  .usage    = BLKID_USAGE_FILESYSTEM,
266
  .probefunc  = probe_ufs,
267
  .magics   = BLKID_NONE_MAGIC
268
};
269