Coverage Report

Created: 2024-05-21 06:33

/src/util-linux/libblkid/src/superblocks/exfs.c
Line
Count
Source (jump to first uncovered line)
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
 * Copyright (C) 2013 Eric Sandeen <sandeen@redhat.com>
8
 * Copyright (C) 2017 Hewlett Packard Enterprise Development LP
9
 *
10
 * This file may be redistributed under the terms of the
11
 * GNU Lesser General Public License.
12
 */
13
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <unistd.h>
17
#include <string.h>
18
#include <errno.h>
19
#include <ctype.h>
20
#include <stdint.h>
21
22
#include "superblocks.h"
23
24
struct exfs_super_block {
25
  uint32_t  sb_magicnum;  /* magic number == EXFS_SB_MAGIC */
26
  uint32_t  sb_blocksize; /* logical block size, bytes */
27
  uint64_t  sb_dblocks; /* number of data blocks */
28
  uint64_t  sb_rblocks; /* number of realtime blocks */
29
  uint64_t  sb_rextents;  /* number of realtime extents */
30
  unsigned char sb_uuid[16];  /* file system unique id */
31
  uint64_t  sb_logstart;  /* starting block of log if internal */
32
  uint64_t  sb_rootino; /* root inode number */
33
  uint64_t  sb_rbmino;  /* bitmap inode for realtime extents */
34
  uint64_t  sb_rsumino; /* summary inode for rt bitmap */
35
  uint32_t  sb_rextsize;  /* realtime extent size, blocks */
36
  uint32_t  sb_agblocks;  /* size of an allocation group */
37
  uint32_t  sb_agcount; /* number of allocation groups */
38
  uint32_t  sb_rbmblocks; /* number of rt bitmap blocks */
39
  uint32_t  sb_logblocks; /* number of log blocks */
40
41
  uint16_t  sb_versionnum;  /* header version == EXFS_SB_VERSION */
42
  uint16_t  sb_sectsize;  /* volume sector size, bytes */
43
  uint16_t  sb_inodesize; /* inode size, bytes */
44
  uint16_t  sb_inopblock; /* inodes per block */
45
  char    sb_fname[12]; /* file system name */
46
  uint8_t   sb_blocklog;  /* log2 of sb_blocksize */
47
  uint8_t   sb_sectlog; /* log2 of sb_sectsize */
48
  uint8_t   sb_inodelog;  /* log2 of sb_inodesize */
49
  uint8_t   sb_inopblog;  /* log2 of sb_inopblock */
50
  uint8_t   sb_agblklog;  /* log2 of sb_agblocks (rounded up) */
51
  uint8_t   sb_rextslog;  /* log2 of sb_rextents */
52
  uint8_t   sb_inprogress;  /* mkfs is in progress, don't mount */
53
  uint8_t   sb_imax_pct;  /* max % of fs for inode space */
54
          /* statistics */
55
  uint64_t  sb_icount;  /* allocated inodes */
56
  uint64_t  sb_ifree; /* free inodes */
57
  uint64_t  sb_fdblocks;  /* free data blocks */
58
  uint64_t  sb_frextents; /* free realtime extents */
59
60
  /* this is not all... but enough for libblkid */
61
62
} __attribute__((packed));
63
64
1.32k
#define EXFS_MIN_BLOCKSIZE_LOG  9  /* i.e. 512 bytes */
65
1.31k
#define EXFS_MAX_BLOCKSIZE_LOG  16  /* i.e. 65536 bytes */
66
947
#define EXFS_MIN_BLOCKSIZE  (1 << EXFS_MIN_BLOCKSIZE_LOG)
67
944
#define EXFS_MAX_BLOCKSIZE  (1 << EXFS_MAX_BLOCKSIZE_LOG)
68
1.55k
#define EXFS_MIN_SECTORSIZE_LOG 9  /* i.e. 512 bytes */
69
1.50k
#define EXFS_MAX_SECTORSIZE_LOG 15  /* i.e. 32768 bytes */
70
1.07k
#define EXFS_MIN_SECTORSIZE (1 << EXFS_MIN_SECTORSIZE_LOG)
71
1.05k
#define EXFS_MAX_SECTORSIZE (1 << EXFS_MAX_SECTORSIZE_LOG)
72
73
1.18k
#define EXFS_DINODE_MIN_LOG 8
74
1.17k
#define EXFS_DINODE_MAX_LOG 11
75
877
#define EXFS_DINODE_MIN_SIZE  (1 << EXFS_DINODE_MIN_LOG)
76
872
#define EXFS_DINODE_MAX_SIZE  (1 << EXFS_DINODE_MAX_LOG)
77
78
284
#define EXFS_MAX_RTEXTSIZE  (1024 * 1024 * 1024)  /* 1GB */
79
#define EXFS_DFL_RTEXTSIZE  (64 * 1024)   /* 64kB */
80
277
#define EXFS_MIN_RTEXTSIZE  (4 * 1024)    /* 4kB */
81
82
137
#define EXFS_MIN_AG_BLOCKS  64
83
804
#define EXFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks)
84
137
#define EXFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) *  \
85
137
       (s)->sb_agblocks + EXFS_MIN_AG_BLOCKS)
86
87
88
static void sb_from_disk(const struct exfs_super_block *from,
89
       struct exfs_super_block *to)
90
542
{
91
92
542
  to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
93
542
  to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
94
542
  to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
95
542
  to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
96
542
  to->sb_rextents = be64_to_cpu(from->sb_rextents);
97
542
  to->sb_logstart = be64_to_cpu(from->sb_logstart);
98
542
  to->sb_rootino = be64_to_cpu(from->sb_rootino);
99
542
  to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
100
542
  to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
101
542
  to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
102
542
  to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
103
542
  to->sb_agcount = be32_to_cpu(from->sb_agcount);
104
542
  to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
105
542
  to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
106
542
  to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
107
542
  to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
108
542
  to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
109
542
  to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
110
542
  to->sb_blocklog = from->sb_blocklog;
111
542
  to->sb_sectlog = from->sb_sectlog;
112
542
  to->sb_inodelog = from->sb_inodelog;
113
542
  to->sb_inopblog = from->sb_inopblog;
114
542
  to->sb_agblklog = from->sb_agblklog;
115
542
  to->sb_rextslog = from->sb_rextslog;
116
542
  to->sb_inprogress = from->sb_inprogress;
117
542
  to->sb_imax_pct = from->sb_imax_pct;
118
542
  to->sb_icount = be64_to_cpu(from->sb_icount);
119
542
  to->sb_ifree = be64_to_cpu(from->sb_ifree);
120
542
  to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
121
542
  to->sb_frextents = be64_to_cpu(from->sb_frextents);
122
542
}
123
124
static int exfs_verify_sb(const struct exfs_super_block *ondisk)
125
542
{
126
542
  struct exfs_super_block sb, *sbp = &sb;
127
128
  /* beXX_to_cpu(), but don't convert UUID and fsname! */
129
542
  sb_from_disk(ondisk, sbp);
130
131
  /* sanity checks, we don't want to rely on magic string only */
132
542
  if (sbp->sb_agcount <= 0          ||
133
542
      sbp->sb_sectsize < EXFS_MIN_SECTORSIZE      ||
134
542
      sbp->sb_sectsize > EXFS_MAX_SECTORSIZE      ||
135
542
      sbp->sb_sectlog < EXFS_MIN_SECTORSIZE_LOG      ||
136
542
      sbp->sb_sectlog > EXFS_MAX_SECTORSIZE_LOG      ||
137
542
      sbp->sb_sectsize != (1 << sbp->sb_sectlog)      ||
138
542
      sbp->sb_blocksize < EXFS_MIN_BLOCKSIZE      ||
139
542
      sbp->sb_blocksize > EXFS_MAX_BLOCKSIZE      ||
140
542
      sbp->sb_blocklog < EXFS_MIN_BLOCKSIZE_LOG      ||
141
542
      sbp->sb_blocklog > EXFS_MAX_BLOCKSIZE_LOG      ||
142
542
      sbp->sb_blocksize != (1ULL << sbp->sb_blocklog)    ||
143
542
      sbp->sb_inodesize < EXFS_DINODE_MIN_SIZE      ||
144
542
      sbp->sb_inodesize > EXFS_DINODE_MAX_SIZE      ||
145
542
      sbp->sb_inodelog < EXFS_DINODE_MIN_LOG      ||
146
542
      sbp->sb_inodelog > EXFS_DINODE_MAX_LOG      ||
147
542
      sbp->sb_inodesize != (1 << sbp->sb_inodelog)    ||
148
542
      (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)  ||
149
542
      (sbp->sb_rextsize * sbp->sb_blocksize > EXFS_MAX_RTEXTSIZE)  ||
150
542
      (sbp->sb_rextsize * sbp->sb_blocksize < EXFS_MIN_RTEXTSIZE)  ||
151
542
      (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)  ||
152
542
      sbp->sb_dblocks == 0          ||
153
542
      sbp->sb_dblocks > EXFS_MAX_DBLOCKS(sbp)     ||
154
542
      sbp->sb_dblocks < EXFS_MIN_DBLOCKS(sbp))
155
538
    return 0;
156
4
  return 1;
157
542
}
158
159
static int probe_exfs(blkid_probe pr, const struct blkid_idmag *mag)
160
542
{
161
542
  const struct exfs_super_block *xs;
162
163
542
  xs = blkid_probe_get_sb(pr, mag, struct exfs_super_block);
164
542
  if (!xs)
165
0
    return errno ? -errno : 1;
166
167
542
  if (!exfs_verify_sb(xs))
168
538
    return 1;
169
170
4
  if (*xs->sb_fname != '\0')
171
3
    blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
172
3
        sizeof(xs->sb_fname));
173
174
4
  blkid_probe_set_uuid(pr, xs->sb_uuid);
175
176
4
  blkid_probe_set_fsblocksize(pr, be32_to_cpu(xs->sb_blocksize));
177
4
  blkid_probe_set_block_size(pr, be32_to_cpu(xs->sb_blocksize));
178
179
4
  return 0;
180
542
}
181
182
const struct blkid_idinfo exfs_idinfo =
183
{
184
  .name   = "exfs",
185
  .usage    = BLKID_USAGE_FILESYSTEM,
186
  .probefunc  = probe_exfs,
187
  .magics   =
188
  {
189
    { .magic = "EXFS", .len = 4 },
190
    { NULL }
191
  }
192
};