chiark / gitweb /
volume_id: split raid and filesystem detection
[elogind.git] / extras / volume_id / libvolume_id / volume_id.c
1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      This program is free software; you can redistribute it and/or modify it
7  *      under the terms of the GNU General Public License as published by the
8  *      Free Software Foundation version 2 of the License.
9  */
10
11 #ifndef _GNU_SOURCE
12 #define _GNU_SOURCE 1
13 #endif
14
15 #ifdef HAVE_CONFIG_H
16 #  include <config.h>
17 #endif
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <sys/stat.h>
28
29 #include "volume_id.h"
30 #include "logging.h"
31 #include "util.h"
32
33
34 int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size)
35 {
36         if (id == NULL)
37                 return -EINVAL;
38
39         /* probe for raid first, cause fs probes may be successful on raid members */
40         if (size) {
41                 if (volume_id_probe_linux_raid(id, off, size) == 0)
42                         goto exit;
43
44                 if (volume_id_probe_intel_software_raid(id, off, size) == 0)
45                         goto exit;
46
47                 if (volume_id_probe_lsi_mega_raid(id, off, size) == 0)
48                         goto exit;
49
50                 if (volume_id_probe_via_raid(id, off, size) == 0)
51                         goto exit;
52
53                 if (volume_id_probe_silicon_medley_raid(id, off, size) == 0)
54                         goto exit;
55
56                 if (volume_id_probe_nvidia_raid(id, off, size) == 0)
57                         goto exit;
58
59                 if (volume_id_probe_promise_fasttrack_raid(id, off, size) == 0)
60                         goto exit;
61
62                 if (volume_id_probe_highpoint_45x_raid(id, off, size) == 0)
63                         goto exit;
64         }
65
66         if (volume_id_probe_lvm1(id, off) == 0)
67                 goto exit;
68
69         if (volume_id_probe_lvm2(id, off) == 0)
70                 goto exit;
71
72         if (volume_id_probe_highpoint_37x_raid(id, off) == 0)
73                 goto exit;
74
75 exit:
76         /* If recognized, we free the allocated buffers */
77         volume_id_free_buffer(id);
78         return 0;
79 }
80
81 int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size)
82 {
83         if (id == NULL)
84                 return -EINVAL;
85
86         if (volume_id_probe_luks(id, off) == 0)
87                 goto exit;
88
89         /* signature in the first block, only small buffer needed */
90         if (volume_id_probe_vfat(id, off) == 0)
91                 goto exit;
92
93         if (volume_id_probe_xfs(id, off) == 0)
94                 goto exit;
95
96         /* fill buffer with maximum */
97         volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);
98
99         if (volume_id_probe_linux_swap(id, off) == 0)
100                 goto exit;
101
102         if (volume_id_probe_ext(id, off) == 0)
103                 goto exit;
104
105         if (volume_id_probe_reiserfs(id, off) == 0)
106                 goto exit;
107
108         if (volume_id_probe_jfs(id, off) == 0)
109                 goto exit;
110
111         if (volume_id_probe_udf(id, off) == 0)
112                 goto exit;
113
114         if (volume_id_probe_iso9660(id, off) == 0)
115                 goto exit;
116
117         if (volume_id_probe_hfs_hfsplus(id, off) == 0)
118                 goto exit;
119
120         if (volume_id_probe_ufs(id, off) == 0)
121                 goto exit;
122
123         if (volume_id_probe_ntfs(id, off)  == 0)
124                 goto exit;
125
126         if (volume_id_probe_cramfs(id, off) == 0)
127                 goto exit;
128
129         if (volume_id_probe_romfs(id, off) == 0)
130                 goto exit;
131
132         if (volume_id_probe_hpfs(id, off) == 0)
133                 goto exit;
134
135         if (volume_id_probe_sysv(id, off) == 0)
136                 goto exit;
137
138         if (volume_id_probe_minix(id, off) == 0)
139                 goto exit;
140
141         if (volume_id_probe_ocfs1(id, off) == 0)
142                 goto exit;
143
144         if (volume_id_probe_ocfs2(id, off) == 0)
145                 goto exit;
146
147         if (volume_id_probe_vxfs(id, off) == 0)
148                 goto exit;
149
150         return -1;
151
152 exit:
153         /* If recognized, we free the allocated buffers */
154         volume_id_free_buffer(id);
155         return 0;
156 }
157
158 int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
159 {
160         if (id == NULL)
161                 return -EINVAL;
162
163         if (volume_id_probe_raid(id, off, size) == 0)
164                 return 0;
165
166         if (volume_id_probe_filesystem(id, off, size) == 0)
167                 return 0;
168
169         return -1;
170 }
171
172 /* open volume by already open file descriptor */
173 struct volume_id *volume_id_open_fd(int fd)
174 {
175         struct volume_id *id;
176
177         id = malloc(sizeof(struct volume_id));
178         if (id == NULL)
179                 return NULL;
180         memset(id, 0x00, sizeof(struct volume_id));
181
182         id->fd = fd;
183
184         return id;
185 }
186
187 /* open volume by device node */
188 struct volume_id *volume_id_open_node(const char *path)
189 {
190         struct volume_id *id;
191         int fd;
192
193         fd = open(path, O_RDONLY);
194         if (fd < 0) {
195                 dbg("unable to open '%s'", path);
196                 return NULL;
197         }
198
199         id = volume_id_open_fd(fd);
200         if (id == NULL)
201                 return NULL;
202
203         /* close fd on device close */
204         id->fd_close = 1;
205
206         return id;
207 }
208
209 void volume_id_close(struct volume_id *id)
210 {
211         if (id == NULL)
212                 return;
213
214         if (id->fd_close != 0)
215                 close(id->fd);
216
217         volume_id_free_buffer(id);
218
219         if (id->partitions != NULL)
220                 free(id->partitions);
221
222         free(id);
223 }