summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Golle <daniel@makrotopia.org>2016-07-24 15:16:16 +0200
committerDaniel Golle <daniel@makrotopia.org>2016-07-24 17:25:22 +0200
commit415bb93aac1b3b658d6957e7114ed3835ae3724d (patch)
tree58c63651cabd536e49b1a4a2347f3eb61a2bb75c
parente7e1a1b0ab05454ed63e09ccf29d24ed187d7220 (diff)
downloadfstools-415bb93aac1b3b658d6957e7114ed3835ae3724d.tar.gz
block: get mountpoints from /proc/self/mountinfo
Instead of using two different implementations reading /proc/mounts and /proc/self/mountinfo, gather all information on mountpoints from /proc/self/mountinfo. While at it, tokenize mountinfo inline instead of using strtok_r because it's hard to tell whether strtok_r allocated new memory or merely returns a pointer to the (last) token. This might later on be relevant once we want to free that memory... Tokenizing mountinfo using strchr inline works without allocating any new memory by scanning and re-writing the string returned by gets(). As a result, the returned string needs to be duplicated to be safe for use even after the fclose(). Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-rw-r--r--block.c100
1 files changed, 67 insertions, 33 deletions
diff --git a/block.c b/block.c
index e674521..3326458 100644
--- a/block.c
+++ b/block.c
@@ -587,52 +587,83 @@ static struct blkid_struct_probe* find_block_info(char *uuid, char *label, char
static char* find_mount_point(char *block)
{
- FILE *fp = fopen("/proc/mounts", "r");
- static char line[256], *saveptr;
+ FILE *fp = fopen("/proc/self/mountinfo", "r");
+ static char line[256];
int len = strlen(block);
- char *point = NULL;
+ char *point = NULL, *pos, *tmp, *cpoint, *devname;
struct stat s;
+ unsigned int minor, major;
- if(!fp)
+ if (!fp)
+ return NULL;
+
+ if (stat(block, &s))
return NULL;
while (fgets(line, sizeof(line), fp)) {
- if (!strncmp(line, block, len)) {
- char *p = &line[len + 1];
- char *t = strstr(p, " ");
+ pos = strchr(line, ' ');
+ if (!pos)
+ continue;
- if (!t) {
- fclose(fp);
- return NULL;
- }
- *t = '\0';
- point = p;
- break;
- }
- }
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
- fclose(fp);
+ tmp = ++pos;
+ pos = strchr(pos, ':');
+ if (!pos)
+ continue;
- if (point)
- return point;
+ *pos = '\0';
+ major = atoi(tmp);
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
- if (stat(block, &s))
- return NULL;
+ *pos = '\0';
+ minor = atoi(tmp);
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+ tmp = ++pos;
- if (!S_ISBLK(s.st_mode))
- return NULL;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+ *pos = '\0';
+ cpoint = tmp;
- fp = fopen("/proc/self/mountinfo", "r");
- if(!fp)
- return NULL;
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
- while (fgets(line, sizeof(line), fp)) {
- strtok_r(line, " \t", &saveptr);
- strtok_r(NULL, " \t", &saveptr);
- if (atoi(strtok_r(NULL, ":", &saveptr)) == major(s.st_rdev) &&
- atoi(strtok_r(NULL, " \t", &saveptr)) == minor(s.st_rdev)) {
- strtok_r(NULL, " \t", &saveptr);
- point = strtok_r(NULL, " \t", &saveptr);
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ devname = tmp;
+ if (!strncmp(block, devname, len)) {
+ point = strdup(cpoint);
+ break;
+ }
+
+ if (!S_ISBLK(s.st_mode))
+ continue;
+
+ if (major == major(s.st_rdev) &&
+ minor == minor(s.st_rdev)) {
+ point = strdup(cpoint);
break;
}
}
@@ -750,6 +781,7 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug)
mp = find_mount_point(pr->dev);
if (mp) {
ULOG_ERR("%s is already mounted on %s\n", pr->dev, mp);
+ free(mp);
return -1;
}
@@ -832,6 +864,7 @@ static int umount_device(struct blkid_struct_probe *pr)
ULOG_INFO("unmounted %s (%s)\n",
pr->dev, mp);
+ free(mp);
return err;
}
@@ -857,6 +890,7 @@ static int main_hotplug(int argc, char **argv)
ULOG_ERR("umount of %s failed (%d) - %s\n",
mount_point, err, strerror(err));
+ free(mount_point);
return 0;
} else if (strcmp(action, "add")) {
ULOG_ERR("Unkown action %s\n", action);