summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2011-04-05 19:42:00 +0100
committerRichard W.M. Jones <rjones@redhat.com>2011-04-05 20:01:15 +0100
commit9b945cfa781a0f25c3b81239e2fcddceeede6e44 (patch)
tree413a3cb9e59e21af3a3312ab2a9b68d2cbc83534
parentf3eea44f97340f747e46b0df6931a04b53abaf01 (diff)
downloadlibguestfs-9b945cfa781a0f25c3b81239e2fcddceeede6e44.tar.gz
libguestfs-9b945cfa781a0f25c3b81239e2fcddceeede6e44.tar.xz
libguestfs-9b945cfa781a0f25c3b81239e2fcddceeede6e44.zip
daemon: Reimplement 'mounts' and 'mountpoints' commands.
Reimplement these so they read /proc/mounts instead of trying to parse the output of the 'mount' external command. One consequence of this is that these commands now work again for ntfs-3g filesystems.
-rw-r--r--daemon/mount.c77
1 files changed, 29 insertions, 48 deletions
diff --git a/daemon/mount.c b/daemon/mount.c
index fd0f6b29..a379d39e 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -174,68 +174,49 @@ do_umount (const char *pathordevice)
return 0;
}
+/* Implement 'mounts' (mp==0) and 'mountpoints' (mp==1) calls. */
static char **
mounts_or_mountpoints (int mp)
{
- char *out, *err;
- int r;
+ FILE *fp;
+ struct mntent *m;
char **ret = NULL;
int size = 0, alloc = 0;
- char *p, *pend, *p2;
- int len;
- char matching[5 + sysroot_len];
size_t i;
+ int r;
- r = command (&out, &err, "mount", NULL);
- if (r == -1) {
- reply_with_error ("mount: %s", err);
- free (out);
- free (err);
- return NULL;
- }
-
- free (err);
-
- /* Lines have the format:
- * /dev/foo on /mountpoint type ...
+ /* NB: Eventually we should aim to parse /proc/self/mountinfo, but
+ * that requires custom parsing code.
*/
- snprintf (matching, 5 + sysroot_len, " on %s", sysroot);
-
- p = out;
- while (p) {
- pend = strchr (p, '\n');
- if (pend) {
- *pend = '\0';
- pend++;
- }
+ fp = setmntent ("/proc/mounts", "r");
+ if (fp == NULL) {
+ perror ("/proc/mounts");
+ exit (EXIT_FAILURE);
+ }
- p2 = strstr (p, matching);
- if (p2 != NULL) {
- *p2 = '\0';
- if (add_string (&ret, &size, &alloc, p) == -1) {
- free (out);
+ while ((m = getmntent (fp)) != NULL) {
+ /* Allow a mount directory like "/sysroot". */
+ if (sysroot_len > 0 && STREQ (m->mnt_dir, sysroot)) {
+ if (add_string (&ret, &size, &alloc, m->mnt_fsname) == -1) {
+ error:
+ endmntent (fp);
return NULL;
}
- if (mp) {
- p2 += 4 + sysroot_len; /* skip " on /sysroot" */
- len = strcspn (p2, " ");
-
- if (len == 0) /* .. just /sysroot, so we turn it into "/" */
- p2 = (char *) "/";
- else
- p2[len] = '\0';
-
- if (add_string (&ret, &size, &alloc, p2) == -1) {
- free (out);
- return NULL;
- }
- }
+ if (mp &&
+ add_string (&ret, &size, &alloc, "/") == -1)
+ goto error;
+ }
+ /* Or allow a mount directory like "/sysroot/...". */
+ if (STRPREFIX (m->mnt_dir, sysroot) && m->mnt_dir[sysroot_len] == '/') {
+ if (add_string (&ret, &size, &alloc, m->mnt_fsname) == -1)
+ goto error;
+ if (mp &&
+ add_string (&ret, &size, &alloc, &m->mnt_dir[sysroot_len]) == -1)
+ goto error;
}
-
- p = pend;
}
- free (out);
+ endmntent (fp);
if (add_string (&ret, &size, &alloc, NULL) == -1)
return NULL;