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 }