summaryrefslogtreecommitdiffhomepage
path: root/util-linux/volume_id/volume_id.c
blob: c3f07a741a21c70faa67193b684bf79a521156b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*
 * volume_id - reads filesystem label and uuid
 *
 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 of the License, or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public
 *	License along with this library; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

//kbuild:lib-$(CONFIG_VOLUMEID) += volume_id.o util.o

#include "volume_id_internal.h"


/* Some detection routines do not set label or uuid anyway,
 * so they are disabled. */

/* Looks for partitions, we don't use it: */
#define ENABLE_FEATURE_VOLUMEID_MAC           0
/* #define ENABLE_FEATURE_VOLUMEID_MSDOS      0 - NB: this one
 * was not properly added to probe table anyway - ??! */

/* None of RAIDs have label or uuid, except LinuxRAID: */
#define ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID 0
#define ENABLE_FEATURE_VOLUMEID_ISWRAID       0
#define ENABLE_FEATURE_VOLUMEID_LSIRAID       0
#define ENABLE_FEATURE_VOLUMEID_LVM           0
#define ENABLE_FEATURE_VOLUMEID_NVIDIARAID    0
#define ENABLE_FEATURE_VOLUMEID_PROMISERAID   0
#define ENABLE_FEATURE_VOLUMEID_SILICONRAID   0
#define ENABLE_FEATURE_VOLUMEID_VIARAID       0

/* These filesystems also have no label or uuid: */
#define ENABLE_FEATURE_VOLUMEID_HPFS          0
#define ENABLE_FEATURE_VOLUMEID_UFS           0


typedef int FAST_FUNC (*raid_probe_fptr)(struct volume_id *id, /*uint64_t off,*/ uint64_t size);
typedef int FAST_FUNC (*probe_fptr)(struct volume_id *id /*, uint64_t off*/);

static const raid_probe_fptr raid1[] = {
#if ENABLE_FEATURE_VOLUMEID_LINUXRAID
	volume_id_probe_linux_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_ISWRAID
	volume_id_probe_intel_software_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_LSIRAID
	volume_id_probe_lsi_mega_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_VIARAID
	volume_id_probe_via_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_SILICONRAID
	volume_id_probe_silicon_medley_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_NVIDIARAID
	volume_id_probe_nvidia_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_PROMISERAID
	volume_id_probe_promise_fasttrack_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
	volume_id_probe_highpoint_45x_raid,
#endif
};

static const probe_fptr raid2[] = {
#if ENABLE_FEATURE_VOLUMEID_LVM
	volume_id_probe_lvm1,
	volume_id_probe_lvm2,
#endif
#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
	volume_id_probe_highpoint_37x_raid,
#endif
#if ENABLE_FEATURE_VOLUMEID_LUKS
	volume_id_probe_luks,
#endif
};

/* signature in the first block, only small buffer needed */
static const probe_fptr fs1[] = {
#if ENABLE_FEATURE_VOLUMEID_FAT
	volume_id_probe_vfat,
#endif
#if ENABLE_FEATURE_VOLUMEID_EXFAT
	volume_id_probe_exfat,
#endif
#if ENABLE_FEATURE_VOLUMEID_LFS
	volume_id_probe_lfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_MAC
	volume_id_probe_mac_partition_map,
#endif
#if ENABLE_FEATURE_VOLUMEID_SQUASHFS
	volume_id_probe_squashfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_XFS
	volume_id_probe_xfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_BCACHE
	volume_id_probe_bcache,
#endif
};

/* fill buffer with maximum */
static const probe_fptr fs2[] = {
#if ENABLE_FEATURE_VOLUMEID_LINUXSWAP
	volume_id_probe_linux_swap,
#endif
#if ENABLE_FEATURE_VOLUMEID_EXT
	volume_id_probe_ext,
#endif
#if ENABLE_FEATURE_VOLUMEID_BTRFS
	volume_id_probe_btrfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_REISERFS
	volume_id_probe_reiserfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_JFS
	volume_id_probe_jfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_UDF
	volume_id_probe_udf,
#endif
#if ENABLE_FEATURE_VOLUMEID_ISO9660
	volume_id_probe_iso9660,
#endif
#if ENABLE_FEATURE_VOLUMEID_HFS
	volume_id_probe_hfs_hfsplus,
#endif
#if ENABLE_FEATURE_VOLUMEID_UFS
	volume_id_probe_ufs,
#endif
#if ENABLE_FEATURE_VOLUMEID_F2FS
	volume_id_probe_f2fs,
#endif
#if ENABLE_FEATURE_VOLUMEID_NILFS
	volume_id_probe_nilfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_NTFS
	volume_id_probe_ntfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_CRAMFS
	volume_id_probe_cramfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_ROMFS
	volume_id_probe_romfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_HPFS
	volume_id_probe_hpfs,
#endif
#if ENABLE_FEATURE_VOLUMEID_SYSV
	volume_id_probe_sysv,
#endif
#if ENABLE_FEATURE_VOLUMEID_MINIX
	volume_id_probe_minix,
#endif
#if ENABLE_FEATURE_VOLUMEID_OCFS2
	volume_id_probe_ocfs2,
#endif
#if ENABLE_FEATURE_VOLUMEID_UBIFS
	volume_id_probe_ubifs,
#endif
};

int FAST_FUNC volume_id_probe_all(struct volume_id *id, /*uint64_t off,*/ uint64_t size)
{
	unsigned i;

	/* probe for raid first, cause fs probes may be successful on raid members */
	if (size) {
		for (i = 0; i < ARRAY_SIZE(raid1); i++) {
			if (raid1[i](id, /*off,*/ size) == 0)
				goto ret;
			if (id->error)
				goto ret;
		}
	}

	for (i = 0; i < ARRAY_SIZE(raid2); i++) {
		if (raid2[i](id /*,off*/) == 0)
			goto ret;
		if (id->error)
			goto ret;
	}

	/* signature in the first block, only small buffer needed */
	for (i = 0; i < ARRAY_SIZE(fs1); i++) {
		if (fs1[i](id /*,off*/) == 0)
			goto ret;
		if (id->error)
			goto ret;
	}

	/* fill buffer with maximum */
	volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);

	for (i = 0; i < ARRAY_SIZE(fs2); i++) {
		if (fs2[i](id /*,off*/) == 0)
			goto ret;
		if (id->error)
			goto ret;
	}

 ret:
	volume_id_free_buffer(id);
	return (- id->error); /* 0 or -1 */
}

/* open volume by device node */
struct volume_id* FAST_FUNC volume_id_open_node(int fd)
{
	struct volume_id *id;

	id = xzalloc(sizeof(struct volume_id));
	id->fd = fd;
	///* close fd on device close */
	//id->fd_close = 1;
	return id;
}

#ifdef UNUSED
/* open volume by major/minor */
struct volume_id* FAST_FUNC volume_id_open_dev_t(dev_t devt)
{
	struct volume_id *id;
	char *tmp_node[VOLUME_ID_PATH_MAX];

	tmp_node = xasprintf("/dev/.volume_id-%u-%u-%u",
		(unsigned)getpid(), (unsigned)major(devt), (unsigned)minor(devt));

	/* create temporary node to open block device */
	unlink(tmp_node);
	if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
		bb_perror_msg_and_die("can't mknod(%s)", tmp_node);

	id = volume_id_open_node(tmp_node);
	unlink(tmp_node);
	free(tmp_node);
	return id;
}
#endif

void FAST_FUNC free_volume_id(struct volume_id *id)
{
	if (id == NULL)
		return;

	//if (id->fd_close != 0) - always true
		close(id->fd);
	volume_id_free_buffer(id);
#ifdef UNUSED_PARTITION_CODE
	free(id->partitions);
#endif
	free(id);
}