am bacdfc0e: Merge "Fix compiling warnings"

* commit 'bacdfc0ed9a0882ee3e9ee889a8fd4cabb9a71f3':
  Fix compiling warnings
diff --git a/Android.mk b/Android.mk
index b7a4905..d13fa8b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,7 +8,6 @@
 	NetlinkHandler.cpp \
 	Volume.cpp \
 	DirectVolume.cpp \
-	logwrapper.c \
 	Process.cpp \
 	Ext4.cpp \
 	Fat.cpp \
@@ -28,6 +27,7 @@
 	libcutils \
 	libdiskconfig \
 	libhardware_legacy \
+	liblogwrap \
 	libcrypto
 
 include $(CLEAR_VARS)
diff --git a/Ext4.cpp b/Ext4.cpp
index 613d623..b82b4c5 100644
--- a/Ext4.cpp
+++ b/Ext4.cpp
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/wait.h>
 
 #include <linux/kdev_t.h>
 
@@ -37,13 +38,13 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include <logwrap/logwrap.h>
+
 #include "Ext4.h"
+#include "VoldUtil.h"
 
 #define MKEXT4FS_PATH "/system/bin/make_ext4fs";
 
-extern "C" int logwrap(int argc, const char **argv, int background);
-
-
 int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
         bool executable) {
     int rc;
@@ -68,22 +69,36 @@
 
 int Ext4::format(const char *fsPath, const char *mountpoint) {
     int fd;
-    const char *args[6];
+    const char *args[5];
     int rc;
+    int status;
 
     args[0] = MKEXT4FS_PATH;
     args[1] = "-J";
     args[2] = "-a";
     args[3] = mountpoint;
     args[4] = fsPath;
-    args[5] = NULL;
-    rc = logwrap(5, args, 1);
+    rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false,
+            true);
+    if (rc != 0) {
+        SLOGE("Filesystem (ext4) format failed due to logwrap error");
+        errno = EIO;
+        return -1;
+    }
 
-    if (rc == 0) {
+    if (!WIFEXITED(status)) {
+        SLOGE("Filesystem (ext4) format did not exit properly");
+        errno = EIO;
+        return -1;
+    }
+
+    status = WEXITSTATUS(status);
+
+    if (status == 0) {
         SLOGI("Filesystem (ext4) formatted OK");
         return 0;
     } else {
-        SLOGE("Format (ext4) failed (unknown exit code %d)", rc);
+        SLOGE("Format (ext4) failed (unknown exit code %d)", status);
         errno = EIO;
         return -1;
     }
diff --git a/Fat.cpp b/Fat.cpp
index a7fcc28..807f440 100644
--- a/Fat.cpp
+++ b/Fat.cpp
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/wait.h>
 
 #include <linux/kdev_t.h>
 
@@ -37,11 +38,13 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include <logwrap/logwrap.h>
+
 #include "Fat.h"
+#include "VoldUtil.h"
 
 static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos";
 static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos";
-extern "C" int logwrap(int argc, const char **argv, int background);
 extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *);
 
 int Fat::check(const char *fsPath) {
@@ -54,16 +57,30 @@
     int pass = 1;
     int rc = 0;
     do {
-        const char *args[5];
+        const char *args[4];
+        int status;
         args[0] = FSCK_MSDOS_PATH;
         args[1] = "-p";
         args[2] = "-f";
         args[3] = fsPath;
-        args[4] = NULL;
 
-        rc = logwrap(4, args, 1);
+        rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status,
+                false, true);
+        if (rc != 0) {
+            SLOGE("Filesystem check failed due to logwrap error");
+            errno = EIO;
+            return -1;
+        }
 
-        switch(rc) {
+        if (!WIFEXITED(status)) {
+            SLOGE("Filesystem check did not exit properly");
+            errno = EIO;
+            return -1;
+        }
+
+        status = WEXITSTATUS(status);
+
+        switch(status) {
         case 0:
             SLOGI("Filesystem check completed OK");
             return 0;
@@ -84,7 +101,7 @@
             return -1;
 
         default:
-            SLOGE("Filesystem check failed (unknown exit code %d)", rc);
+            SLOGE("Filesystem check failed (unknown exit code %d)", status);
             errno = EIO;
             return -1;
         }
@@ -152,8 +169,9 @@
 
 int Fat::format(const char *fsPath, unsigned int numSectors) {
     int fd;
-    const char *args[11];
+    const char *args[10];
     int rc;
+    int status;
 
     args[0] = MKDOSFS_PATH;
     args[1] = "-F";
@@ -170,19 +188,33 @@
         args[7] = "-s";
         args[8] = size;
         args[9] = fsPath;
-        args[10] = NULL;
-        rc = logwrap(11, args, 1);
+        rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status,
+                false, true);
     } else {
         args[7] = fsPath;
-        args[8] = NULL;
-        rc = logwrap(9, args, 1);
+        rc = android_fork_execvp(8, (char **)args, &status, false,
+                true);
     }
 
-    if (rc == 0) {
+    if (rc != 0) {
+        SLOGE("Filesystem format failed due to logwrap error");
+        errno = EIO;
+        return -1;
+    }
+
+    if (!WIFEXITED(status)) {
+        SLOGE("Filesystem format did not exit properly");
+        errno = EIO;
+        return -1;
+    }
+
+    status = WEXITSTATUS(status);
+
+    if (status == 0) {
         SLOGI("Filesystem formatted OK");
         return 0;
     } else {
-        SLOGE("Format failed (unknown exit code %d)", rc);
+        SLOGE("Format failed (unknown exit code %d)", status);
         errno = EIO;
         return -1;
     }
diff --git a/VoldUtil.h b/VoldUtil.h
new file mode 100644
index 0000000..30a3add
--- /dev/null
+++ b/VoldUtil.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _VOLDUTIL_H
+#define _VOLDUTIL_H
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+#endif
diff --git a/cryptfs.c b/cryptfs.c
index bcacc39..d926334 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -67,8 +67,8 @@
 static char *saved_data_blkdev;
 static char *saved_mount_point;
 static int  master_key_saved = 0;
-#define FSTAB_PREFIX "/fstab."
-static char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+
+extern struct fstab *fstab;
 
 static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags)
 {
@@ -126,19 +126,6 @@
   return nr_sec;
 }
 
-/* Get and cache the name of the fstab file so we don't
- * keep talking over the socket to the property service.
- */
-static char *get_fstab_filename(void)
-{
-    if (fstab_filename[0] == 0) {
-        strcpy(fstab_filename, FSTAB_PREFIX);
-        property_get("ro.hardware", fstab_filename + sizeof(FSTAB_PREFIX) - 1, "");
-    }
-
-    return fstab_filename;
-}
-
 /* key or salt can be NULL, in which case just skip writing that value.  Useful to
  * update the failed mount count but not change the key.
  */
@@ -153,7 +140,7 @@
   char key_loc[PROPERTY_VALUE_MAX];
   struct stat statbuf;
 
-  fs_mgr_get_crypt_info(get_fstab_filename(), key_loc, 0, sizeof(key_loc));
+  fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
 
   if (!strcmp(key_loc, KEY_IN_FOOTER)) {
     fname = real_blk_name;
@@ -252,7 +239,7 @@
   char *fname;
   struct stat statbuf;
 
-  fs_mgr_get_crypt_info(get_fstab_filename(), key_loc, 0, sizeof(key_loc));
+  fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
 
   if (!strcmp(key_loc, KEY_IN_FOOTER)) {
     fname = real_blk_name;
@@ -377,6 +364,86 @@
 
 }
 
+static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key,
+                                     char *real_blk_name, const char *name, int fd,
+                                     char *extra_params)
+{
+  char buffer[DM_CRYPT_BUF_SIZE];
+  struct dm_ioctl *io;
+  struct dm_target_spec *tgt;
+  char *crypt_params;
+  char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */
+  int i;
+
+  io = (struct dm_ioctl *) buffer;
+
+  /* Load the mapping table for this device */
+  tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
+
+  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+  io->target_count = 1;
+  tgt->status = 0;
+  tgt->sector_start = 0;
+  tgt->length = crypt_ftr->fs_size;
+  strcpy(tgt->target_type, "crypt");
+
+  crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
+  convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
+  sprintf(crypt_params, "%s %s 0 %s 0 %s", crypt_ftr->crypto_type_name,
+          master_key_ascii, real_blk_name, extra_params);
+  crypt_params += strlen(crypt_params) + 1;
+  crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
+  tgt->next = crypt_params - buffer;
+
+  for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
+    if (! ioctl(fd, DM_TABLE_LOAD, io)) {
+      break;
+    }
+    usleep(500000);
+  }
+
+  if (i == TABLE_LOAD_RETRIES) {
+    /* We failed to load the table, return an error */
+    return -1;
+  } else {
+    return i + 1;
+  }
+}
+
+
+static int get_dm_crypt_version(int fd, const char *name,  int *version)
+{
+    char buffer[DM_CRYPT_BUF_SIZE];
+    struct dm_ioctl *io;
+    struct dm_target_versions *v;
+    int i;
+
+    io = (struct dm_ioctl *) buffer;
+
+    ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+
+    if (ioctl(fd, DM_LIST_VERSIONS, io)) {
+        return -1;
+    }
+
+    /* Iterate over the returned versions, looking for name of "crypt".
+     * When found, get and return the version.
+     */
+    v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
+    while (v->next) {
+        if (! strcmp(v->name, "crypt")) {
+            /* We found the crypt driver, return the version, and get out */
+            version[0] = v->version[0];
+            version[1] = v->version[1];
+            version[2] = v->version[2];
+            return 0;
+        }
+        v = (struct dm_target_versions *)(((char *)v) + v->next);
+    }
+
+    return -1;
+}
+
 static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key,
                                     char *real_blk_name, char *crypto_blk_name, const char *name)
 {
@@ -389,6 +456,9 @@
   int fd;
   int i;
   int retval = -1;
+  int version[3];
+  char *extra_params;
+  int load_count;
 
   if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) {
     SLOGE("Cannot open device-mapper\n");
@@ -412,40 +482,27 @@
   minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
   snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
 
-  /* Load the mapping table for this device */
-  tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
-
-  ioctl_init(io, 4096, name, 0);
-  io->target_count = 1;
-  tgt->status = 0;
-  tgt->sector_start = 0;
-  tgt->length = crypt_ftr->fs_size;
-  strcpy(tgt->target_type, "crypt");
-
-  crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
-  convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
-  sprintf(crypt_params, "%s %s 0 %s 0", crypt_ftr->crypto_type_name,
-          master_key_ascii, real_blk_name);
-  crypt_params += strlen(crypt_params) + 1;
-  crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
-  tgt->next = crypt_params - buffer;
-
-  for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
-    if (! ioctl(fd, DM_TABLE_LOAD, io)) {
-      break;
-    }
-    usleep(500000);
+  extra_params = "";
+  if (! get_dm_crypt_version(fd, name, version)) {
+      /* Support for allow_discards was added in version 1.11.0 */
+      if ((version[0] >= 2) ||
+          ((version[0] == 1) && (version[1] >= 11))) {
+          extra_params = "1 allow_discards";
+          SLOGI("Enabling support for allow_discards in dmcrypt.\n");
+      }
   }
 
-  if (i == TABLE_LOAD_RETRIES) {
+  load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name,
+                                         fd, extra_params);
+  if (load_count < 0) {
       SLOGE("Cannot load dm-crypt mapping table.\n");
       goto errout;
-  } else if (i) {
-      SLOGI("Took %d tries to load dmcrypt table.\n", i + 1);
+  } else if (load_count > 1) {
+      SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
   }
 
   /* Resume this device to activate it */
-  ioctl_init(io, 4096, name, 0);
+  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
 
   if (ioctl(fd, DM_DEV_SUSPEND, io)) {
     SLOGE("Cannot resume the dm-crypt device\n");
@@ -707,7 +764,7 @@
 
     if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) {
         /* If that succeeded, then mount the decrypted filesystem */
-        fs_mgr_do_mount(get_fstab_filename(), DATA_MNT_POINT, crypto_blkdev, 0);
+        fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0);
 
         property_set("vold.decrypt", "trigger_load_persist_props");
         /* Create necessary paths on /data */
@@ -745,10 +802,10 @@
     return 1;
   }
 
-  fs_mgr_get_crypt_info(get_fstab_filename(), 0, real_blkdev, sizeof(real_blkdev));
+  fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
   if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) {
-    fs_mgr_get_crypt_info(get_fstab_filename(), key_loc, 0, sizeof(key_loc));
+    fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
 
     /*
      * Only report this error if key_loc is a file and it exists.
@@ -795,7 +852,7 @@
     return -1;
   }
 
-  fs_mgr_get_crypt_info(get_fstab_filename(), 0, real_blkdev, sizeof(real_blkdev));
+  fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
   if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) {
     SLOGE("Error getting crypt footer and key\n");
@@ -824,7 +881,7 @@
    */
   sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point);
   mkdir(tmp_mount_point, 0755);
-  if (fs_mgr_do_mount(get_fstab_filename(), DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
+  if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
     SLOGE("Error temp mounting decrypted block device\n");
     delete_crypto_blk_dev(label);
     crypt_ftr.failed_decrypt_count++;
@@ -955,7 +1012,7 @@
         return -1;
     }
 
-    fs_mgr_get_crypt_info(get_fstab_filename(), 0, real_blkdev, sizeof(real_blkdev));
+    fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
     if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) {
         SLOGE("Error getting crypt footer and key\n");
@@ -1157,7 +1214,7 @@
         goto error_unencrypted;
     }
 
-    fs_mgr_get_crypt_info(get_fstab_filename(), key_loc, 0, sizeof(key_loc));
+    fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
 
     if (!strcmp(howarg, "wipe")) {
       how = CRYPTO_ENABLE_WIPE;
@@ -1168,7 +1225,7 @@
       goto error_unencrypted;
     }
 
-    fs_mgr_get_crypt_info(get_fstab_filename(), 0, real_blkdev, sizeof(real_blkdev));
+    fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
     /* Get the size of the real block device */
     fd = open(real_blkdev, O_RDONLY);
@@ -1461,7 +1518,7 @@
         return -1;
     }
 
-    fs_mgr_get_crypt_info(get_fstab_filename(), 0, real_blkdev, sizeof(real_blkdev));
+    fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
     if (strlen(real_blkdev) == 0) {
         SLOGE("Can't find real blkdev");
         return -1;
diff --git a/logwrapper.c b/logwrapper.c
deleted file mode 100644
index 34a1e5a..0000000
--- a/logwrapper.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "private/android_filesystem_config.h"
-#include "cutils/log.h"
-#include "cutils/sched_policy.h"
-
-int parent(const char *tag, int parent_read) {
-    int status;
-    char buffer[4096];
-
-    int a = 0;  // start index of unprocessed data
-    int b = 0;  // end index of unprocessed data
-    int sz;
-    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
-
-        sz += b;
-        // Log one line at a time
-        for (b = 0; b < sz; b++) {
-            if (buffer[b] == '\r') {
-                buffer[b] = '\0';
-            } else if (buffer[b] == '\n') {
-                buffer[b] = '\0';
-
-                ALOG(LOG_INFO, tag, "%s", &buffer[a]);
-                a = b + 1;
-            }
-        }
-
-        if (a == 0 && b == sizeof(buffer) - 1) {
-            // buffer is full, flush
-            buffer[b] = '\0';
-            ALOG(LOG_INFO, tag, "%s", &buffer[a]);
-            b = 0;
-        } else if (a != b) {
-            // Keep left-overs
-            b -= a;
-            memmove(buffer, &buffer[a], b);
-            a = 0;
-        } else {
-            a = 0;
-            b = 0;
-        }
-
-    }
-    // Flush remaining data
-    if (a != b) {
-        buffer[b] = '\0';
-        ALOG(LOG_INFO, tag, "%s", &buffer[a]);
-    }
-    status = 0xAAAA;
-    if (wait(&status) != -1) {  // Wait for child
-        if (WIFEXITED(status)) {
-            if (WEXITSTATUS(status) != 0) {
-                ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
-                        WEXITSTATUS(status));
-            }
-            return WEXITSTATUS(status);
-        } else if (WIFSIGNALED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
-                    WTERMSIG(status));
-        else if (WIFSTOPPED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
-                    WSTOPSIG(status));
-    } else
-        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
-                strerror(errno), errno);
-    return -EAGAIN;
-}
-
-void child(int argc, const char**argv) {
-    // create null terminated argv_child array
-    char* argv_child[argc + 1];
-    memcpy(argv_child, argv, argc * sizeof(char *));
-    argv_child[argc] = NULL;
-
-    // XXX: PROTECT FROM VIKING KILLER
-    if (execv(argv_child[0], argv_child)) {
-        ALOG(LOG_ERROR, "logwrapper",
-            "executing %s failed: %s", argv_child[0], strerror(errno));
-        exit(-1);
-    }
-}
-
-int logwrap(int argc, const char* argv[], int background)
-{
-    pid_t pid;
-
-    int parent_ptty;
-    int child_ptty;
-    char *child_devname = NULL;
-
-    /* Use ptty instead of socketpair so that STDOUT is not buffered */
-    parent_ptty = open("/dev/ptmx", O_RDWR);
-    if (parent_ptty < 0) {
-        ALOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
-        return -errno;
-    }
-
-    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
-            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
-        close(parent_ptty);
-        ALOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
-        return -1;
-    }
-
-    pid = fork();
-    if (pid < 0) {
-        close(parent_ptty);
-        ALOG(LOG_ERROR, "logwrapper", "Failed to fork");
-        return -errno;
-    } else if (pid == 0) {
-        /*
-         * Child
-         */
-        child_ptty = open(child_devname, O_RDWR);
-        if (child_ptty < 0) {
-            close(parent_ptty);
-            ALOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
-            return -errno;
-        }
-
-        // redirect stdout and stderr
-        close(parent_ptty);
-        dup2(child_ptty, 1);
-        dup2(child_ptty, 2);
-        close(child_ptty);
-
-        if (background) {
-            int err = set_sched_policy(getpid(), SP_BACKGROUND);
-            if (err < 0) {
-                ALOG(LOG_WARN, "logwrapper",
-                    "Unable to background process (%s)", strerror(-err));
-            }
-        }
-
-        child(argc, argv);
-    } else {
-        /*
-         * Parent
-         */
-        int rc = parent(argv[0], parent_ptty);
-        close(parent_ptty);
-        return rc;
-    }
-
-    return 0;
-}
diff --git a/main.cpp b/main.cpp
index 5924fe4..9c75980 100644
--- a/main.cpp
+++ b/main.cpp
@@ -23,10 +23,12 @@
 
 #include <fcntl.h>
 #include <dirent.h>
+#include <fs_mgr.h>
 
 #define LOG_TAG "Vold"
 
 #include "cutils/log.h"
+#include "cutils/properties.h"
 
 #include "VolumeManager.h"
 #include "CommandListener.h"
@@ -37,6 +39,9 @@
 static int process_config(VolumeManager *vm);
 static void coldboot(const char *path);
 
+#define FSTAB_PREFIX "/fstab."
+struct fstab *fstab;
+
 int main() {
 
     VolumeManager *vm;
@@ -142,111 +147,54 @@
     }
 }
 
-static int parse_mount_flags(char *mount_flags)
+static int process_config(VolumeManager *vm)
 {
-    char *save_ptr;
-    int flags = 0;
+    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+    char propbuf[PROPERTY_VALUE_MAX];
+    int i;
+    int ret = -1;
+    int flags;
 
-    if (strcasestr(mount_flags, "encryptable")) {
-        flags |= VOL_ENCRYPTABLE;
-    }
+    property_get("ro.hardware", propbuf, "");
+    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
 
-    if (strcasestr(mount_flags, "nonremovable")) {
-        flags |= VOL_NONREMOVABLE;
-    }
-
-    return flags;
-}
-
-static int process_config(VolumeManager *vm) {
-    FILE *fp;
-    int n = 0;
-    char line[255];
-
-    if (!(fp = fopen("/etc/vold.fstab", "r"))) {
+    fstab = fs_mgr_read_fstab(fstab_filename);
+    if (!fstab) {
+        SLOGE("failed to open %s\n", fstab_filename);
         return -1;
     }
 
-    while(fgets(line, sizeof(line), fp)) {
-        const char *delim = " \t";
-        char *save_ptr;
-        char *type, *label, *mount_point, *mount_flags, *sysfs_path;
-        int flags;
-
-        n++;
-        line[strlen(line)-1] = '\0';
-
-        if (line[0] == '#' || line[0] == '\0')
-            continue;
-
-        if (!(type = strtok_r(line, delim, &save_ptr))) {
-            SLOGE("Error parsing type");
-            goto out_syntax;
-        }
-        if (!(label = strtok_r(NULL, delim, &save_ptr))) {
-            SLOGE("Error parsing label");
-            goto out_syntax;
-        }
-        if (!(mount_point = strtok_r(NULL, delim, &save_ptr))) {
-            SLOGE("Error parsing mount point");
-            goto out_syntax;
-        }
-
-        if (!strcmp(type, "dev_mount")) {
+    /* Loop through entries looking for ones that vold manages */
+    for (i = 0; i < fstab->num_entries; i++) {
+        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
             DirectVolume *dv = NULL;
-            char *part;
+            flags = 0;
 
-            if (!(part = strtok_r(NULL, delim, &save_ptr))) {
-                SLOGE("Error parsing partition");
-                goto out_syntax;
-            }
-            if (strcmp(part, "auto") && atoi(part) == 0) {
-                SLOGE("Partition must either be 'auto' or 1 based index instead of '%s'", part);
-                goto out_syntax;
+            dv = new DirectVolume(vm, fstab->recs[i].label,
+                                  fstab->recs[i].mount_point,
+                                  fstab->recs[i].partnum);
+
+            if (dv->addPath(fstab->recs[i].blk_device)) {
+                SLOGE("Failed to add devpath %s to volume %s",
+                      fstab->recs[i].blk_device, fstab->recs[i].label);
+                goto out_fail;
             }
 
-            if (!strcmp(part, "auto")) {
-                dv = new DirectVolume(vm, label, mount_point, -1);
-            } else {
-                dv = new DirectVolume(vm, label, mount_point, atoi(part));
+            /* Set any flags that might be set for this volume */
+            if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
+                flags |= VOL_NONREMOVABLE;
             }
-
-            while ((sysfs_path = strtok_r(NULL, delim, &save_ptr))) {
-                if (*sysfs_path != '/') {
-                    /* If the first character is not a '/', it must be flags */
-                    break;
-                }
-                if (dv->addPath(sysfs_path)) {
-                    SLOGE("Failed to add devpath %s to volume %s", sysfs_path,
-                         label);
-                    goto out_fail;
-                }
+            if (fs_mgr_is_encryptable(&fstab->recs[i])) {
+                flags |= VOL_ENCRYPTABLE;
             }
-
-            /* If sysfs_path is non-null at this point, then it contains
-             * the optional flags for this volume
-             */
-            if (sysfs_path)
-                flags = parse_mount_flags(sysfs_path);
-            else
-                flags = 0;
             dv->setFlags(flags);
 
             vm->addVolume(dv);
-        } else if (!strcmp(type, "map_mount")) {
-        } else {
-            SLOGE("Unknown type '%s'", type);
-            goto out_syntax;
         }
     }
 
-    fclose(fp);
-    return 0;
+    ret = 0;
 
-out_syntax:
-    SLOGE("Syntax error on config line %d", n);
-    errno = -EINVAL;
 out_fail:
-    fclose(fp);
-    return -1;   
+    return ret;
 }