add missing includes
[project/fstools.git] / libfstools / find.c
1 /*
2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14 #include <errno.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/sysmacros.h>
19
20 #include "libfstools.h"
21
22 int
23 find_overlay_mount(char *overlay)
24 {
25 FILE *fp = fopen("/proc/mounts", "r");
26 static char line[256];
27 int ret = -1;
28
29 if(!fp)
30 return ret;
31
32 while (ret && fgets(line, sizeof(line), fp))
33 if (!strncmp(line, overlay, strlen(overlay)))
34 ret = 0;
35
36 fclose(fp);
37
38 return ret;
39 }
40
41 /*
42 * Find path of a device mounted to the given point.
43 */
44 char*
45 find_mount(char *mp)
46 {
47 FILE *fp = fopen("/proc/mounts", "r");
48 static char line[256];
49 char *point = NULL;
50
51 if(!fp)
52 return NULL;
53
54 while (fgets(line, sizeof(line), fp)) {
55 char *s, *t = strstr(line, " ");
56
57 if (!t) {
58 fclose(fp);
59 return NULL;
60 }
61 *t = '\0';
62 t++;
63 s = strstr(t, " ");
64 if (!s) {
65 fclose(fp);
66 return NULL;
67 }
68 *s = '\0';
69
70 if (!strcmp(t, mp)) {
71 fclose(fp);
72 return line;
73 }
74 }
75
76 fclose(fp);
77
78 return point;
79 }
80
81 /*
82 * Match filesystem type against a bunch of valid types
83 *
84 * jffs2reset may ask if the filesystem type is actually ready for use
85 * with overlayfs before wiping it...
86 */
87 static int fs_rootfs_only(char *fstype)
88 {
89 if (strncmp(fstype, "ext4", 4) &&
90 strncmp(fstype, "f2fs", 4) &&
91 strncmp(fstype, "jffs2", 5) &&
92 strncmp(fstype, "ubifs", 5)) {
93 ULOG_ERR("block is mounted with wrong fs\n");
94 return 1;
95 }
96 return 0;
97 }
98
99 /*
100 * Check if a given device is mounted and return its mountpoint
101 */
102 char*
103 find_mount_point(char *block, int root_only)
104 {
105 FILE *fp = fopen("/proc/self/mountinfo", "r");
106 static char line[256];
107 int len = strlen(block);
108 char *point = NULL, *pos, *tmp, *cpoint, *devname, *fstype;
109 struct stat s;
110 int rstat;
111 unsigned int minor, major;
112
113 if (!fp)
114 return NULL;
115
116 rstat = stat(block, &s);
117
118 while (fgets(line, sizeof(line), fp)) {
119 /* skip first two columns */
120 pos = strchr(line, ' ');
121 if (!pos)
122 continue;
123
124 pos = strchr(pos + 1, ' ');
125 if (!pos)
126 continue;
127
128 /* extract block device major:minor */
129 tmp = ++pos;
130 pos = strchr(pos, ':');
131 if (!pos)
132 continue;
133
134 *pos = '\0';
135 major = atoi(tmp);
136
137 tmp = ++pos;
138 pos = strchr(pos, ' ');
139 if (!pos)
140 continue;
141
142 *pos = '\0';
143 minor = atoi(tmp);
144
145 /* skip another column */
146 pos = strchr(pos + 1, ' ');
147 if (!pos)
148 continue;
149
150 /* get mountpoint */
151 tmp = ++pos;
152 pos = strchr(pos, ' ');
153 if (!pos)
154 continue;
155
156 *pos = '\0';
157 cpoint = tmp;
158
159 /* skip another two columns */
160 pos = strchr(pos + 1, ' ');
161 if (!pos)
162 continue;
163
164 pos = strchr(pos + 1, ' ');
165 if (!pos)
166 continue;
167
168 /* get fstype */
169 tmp = ++pos;
170 pos = strchr(pos, ' ');
171 if (!pos)
172 continue;
173
174 *pos = '\0';
175 fstype = tmp;
176
177 /* get device name */
178 tmp = ++pos;
179 pos = strchr(pos, ' ');
180 if (!pos)
181 continue;
182
183 *pos = '\0';
184 devname = tmp;
185
186 /* if device name matches */
187 if (!strncmp(block, devname, len)) {
188 if (root_only && fs_rootfs_only(fstype))
189 break;
190
191 /* found, return mountpoint */
192 point = strdup(cpoint);
193 break;
194 }
195
196 /* last chance: check if major:minor of block device match */
197 if (rstat)
198 continue;
199
200 if (!S_ISBLK(s.st_mode))
201 continue;
202
203 if (major == major(s.st_rdev) &&
204 minor == minor(s.st_rdev)) {
205 if (root_only && fs_rootfs_only(fstype))
206 break;
207
208 /* found, return mountpoint */
209 point = strdup(cpoint);
210 break;
211 }
212 }
213
214 fclose(fp);
215
216 return point;
217 }
218
219 int
220 find_filesystem(char *fs)
221 {
222 FILE *fp = fopen("/proc/filesystems", "r");
223 static char line[256];
224 int ret = -1;
225
226 if (!fp) {
227 ULOG_ERR("opening /proc/filesystems failed: %s\n", strerror(errno));
228 goto out;
229 }
230
231 while (ret && fgets(line, sizeof(line), fp))
232 if (strstr(line, fs))
233 ret = 0;
234
235 fclose(fp);
236
237 out:
238 return ret;
239 }