int main(int argc, char* argv[]) {
	char path[MAXPATHLEN];
	int new_maj, new_min;


	if(argc < 4) {
		printf("Usage: %s device mountPoint Password\n%s", argv[0],
		"\tdevice: path to the device to decrypt\n"
		"\tmountPoint: where to mount the decrypted filesystem\n"
		"\tPassword: The password used for decryption\n\n"
		"This program uses Android's vold code to decrypt an encrypted Android\n"
		"data volume. Based on code by the Android Open Source Project,\n"
		"Todd C. Miller, Colin Percival. Frontend by v1ne.\n");
		exit(1);
	}

	devname = argv[1];
	char *mountpoint = argv[2];
	char *pw = argv[3];

	struct stat devstat;
	if(stat(devname, &devstat)) {
		perror("Unable to stat, invalid path? Error:");
		exit(1);
	}

	if(cryptfs_setup_volume(dmvolname, devname,
		path, sizeof(path), &new_maj, &new_min)) {
		fprintf(stderr,	"Unable to decrypt %s\n", "TODO");
		release_dm_dev(dmvolname);
		exit(1);
	}

	if(test_mount_encrypted_fs(pw, mountpoint, dmvolname)) {
		printf("Mount failed, wrong password?\n");
		return 1;
	}

	printf("Successfully mounted volume %s at %s\n", dmvolname, mountpoint);
	printf("Use \"dmsetup remove %s\" to release the encrypted device\n", dmvolname);


	return 0;
}
Example #2
0
int Volume::mountVol() {
    dev_t deviceNodes[4];
    int n, i, rc = 0;
    char errmsg[255];
    const char* externalStorage = getenv("EXTERNAL_STORAGE");
    bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage);
    char decrypt_state[PROPERTY_VALUE_MAX];
    char crypto_state[PROPERTY_VALUE_MAX];
    char encrypt_progress[PROPERTY_VALUE_MAX];
    int flags;

    property_get("vold.decrypt", decrypt_state, "");
    property_get("vold.encrypt_progress", encrypt_progress, "");

    /* Don't try to mount the volumes if we have not yet entered the disk password
     * or are in the process of encrypting.
     */
    if ((getState() == Volume::State_NoMedia) ||
        ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) {
        snprintf(errmsg, sizeof(errmsg),
                 "Volume %s %s mount failed - no media",
                 getLabel(), getMountpoint());
        mVm->getBroadcaster()->sendBroadcast(
                                         ResponseCode::VolumeMountFailedNoMedia,
                                         errmsg, false);
        errno = ENODEV;
        return -1;
    } else if (getState() != Volume::State_Idle) {
        errno = EBUSY;
        if (getState() == Volume::State_Pending) {
            mRetryMount = true;
        }
        return -1;
    }

    if (isMountpointMounted(getMountpoint())) {
        SLOGW("Volume is idle but appears to be mounted - fixing");
        setState(Volume::State_Mounted);
        // mCurrentlyMountedKdev = XXX
        return 0;
    }

    n = getDeviceNodes((dev_t *) &deviceNodes, 4);
    if (!n) {
        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
        return -1;
    }

    /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
     * and vold is asking to mount the primaryStorage device, then we need to decrypt
     * that partition, and update the volume object to point to it's new decrypted
     * block device
     */
    property_get("ro.crypto.state", crypto_state, "");
    flags = getFlags();
    if (primaryStorage &&
        ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
        !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
       char new_sys_path[MAXPATHLEN];
       char nodepath[256];
       int new_major, new_minor;

       if (n != 1) {
           /* We only expect one device node returned when mounting encryptable volumes */
           SLOGE("Too many device nodes returned when mounting %d\n", getMountpoint());
           return -1;
       }

       if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
                                new_sys_path, sizeof(new_sys_path),
                                &new_major, &new_minor)) {
           SLOGE("Cannot setup encryption mapping for %d\n", getMountpoint());
           return -1;
       }
       /* We now have the new sysfs path for the decrypted block device, and the
        * majore and minor numbers for it.  So, create the device, update the
        * path to the new sysfs path, and continue.
        */
        snprintf(nodepath,
                 sizeof(nodepath), "/dev/block/vold/%d:%d",
                 new_major, new_minor);
        if (createDeviceNode(nodepath, new_major, new_minor)) {
            SLOGE("Error making device node '%s' (%s)", nodepath,
                                                       strerror(errno));
        }

        // Todo: Either create sys filename from nodepath, or pass in bogus path so
        //       vold ignores state changes on this internal device.
        updateDeviceInfo(nodepath, new_major, new_minor);

        /* Get the device nodes again, because they just changed */
        n = getDeviceNodes((dev_t *) &deviceNodes, 4);
        if (!n) {
            SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
            return -1;
        }
    }

    for (i = 0; i < n; i++) {
        char devicePath[255];

        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
                MINOR(deviceNodes[i]));

        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());

        errno = 0;
        setState(Volume::State_Checking);

        if (Fat::check(devicePath)) {
            if (errno == ENODATA) {
                SLOGW("%s does not contain a FAT filesystem\n", devicePath);
                continue;
            }
            errno = EIO;
            /* Badness - abort the mount */
            SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
            setState(Volume::State_Idle);
            return -1;
        }

        /*
         * Mount the device on our internal staging mountpoint so we can
         * muck with it before exposing it to non priviledged users.
         */
        errno = 0;
        int gid;

        if (primaryStorage) {
            // Special case the primary SD card.
            // For this we grant write access to the SDCARD_RW group.
            gid = AID_SDCARD_RW;
        } else {
            // For secondary external storage we keep things locked up.
            gid = AID_MEDIA_RW;
        }
        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
                AID_SYSTEM, gid, 0702, true)) {
            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
            continue;
        }

        SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());

        protectFromAutorunStupidity();

        // only create android_secure on primary storage
        if (primaryStorage && createBindMounts()) {
            SLOGE("Failed to create bindmounts (%s)", strerror(errno));
            umount("/mnt/secure/staging");
            setState(Volume::State_Idle);
            return -1;
        }

        /*
         * Now that the bindmount trickery is done, atomically move the
         * whole subtree to expose it to non priviledged users.
         */
        if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
            SLOGE("Failed to move mount (%s)", strerror(errno));
            umount("/mnt/secure/staging");
            setState(Volume::State_Idle);
            return -1;
        }
        setState(Volume::State_Mounted);
        mCurrentlyMountedKdev = deviceNodes[i];
        return 0;
    }

    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
    setState(Volume::State_Idle);

    return -1;
}
Example #3
0
int Volume::mountVol() {
    dev_t deviceNodes[MAX_SUP_PART];
    // dev_t deviceNodes[4];
    int n, i, curState, rc = 0;
    char errmsg[255];
    const char* externalStorage = getenv("EXTERNAL_STORAGE");
    bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage);
    char decrypt_state[PROPERTY_VALUE_MAX];
    char crypto_state[PROPERTY_VALUE_MAX];
    char encrypt_progress[PROPERTY_VALUE_MAX];
    int flags;

    property_get("vold.decrypt", decrypt_state, "");
    property_get("vold.encrypt_progress", encrypt_progress, "");

    /* Don't try to mount the volumes if we have not yet entered the disk password
     * or are in the process of encrypting.
     */
    if ((getState() == Volume::State_NoMedia) ||
        ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) {
        snprintf(errmsg, sizeof(errmsg),
                 "Volume %s %s mount failed - no media",
                 getLabel(), getMountpoint());
        mVm->getBroadcaster()->sendBroadcast(
                                         ResponseCode::VolumeMountFailedNoMedia,
                                         errmsg, false);
        errno = ENODEV;
        return -1;
    } else if (getState() != Volume::State_Idle) {
        errno = EBUSY;
        if (getState() == Volume::State_Pending) {
            mRetryMount = true;
        }
        return -1;
    }

    if (isMountpointMounted(getMountpoint())) {
        SLOGW("Volume is idle but appears to be mounted - fixing");
        setState(Volume::State_Mounted);
        // mCurrentlyMountedKdev = XXX
        return 0;
    }

    #ifdef MTK_SHARED_SDCARD
	  if (IsEmmcStorage()) {
		  setState(Volume::State_Mounted);
		  return 0;
	  }    
    #endif

    // n = getDeviceNodes((dev_t *) &deviceNodes, 4);
    n = getDeviceNodes((dev_t *) &deviceNodes, MAX_SUP_PART);
    if (!n) {
        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
        return -1;
    }
    SLOGD("Found %d device nodes", n);

#ifdef MTK_SD_REINIT_SUPPORT
    if (!IsEmmcStorage()) {
       SLOGD("Reinit SD card");
	   if (mVm->reinitExternalSD()){
		   SLOGD("Fail: reinitExternalSD()");
       }
    }
#endif
    /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
     * and vold is asking to mount the primaryStorage device, then we need to decrypt
     * that partition, and update the volume object to point to it's new decrypted
     * block device
     */
    property_get("ro.crypto.state", crypto_state, "");
    flags = getFlags();
    if (primaryStorage &&
        ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
        !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
       char new_sys_path[MAXPATHLEN];
       char nodepath[256];
       int new_major, new_minor;

       if (n != 1) {
           /* We only expect one device node returned when mounting encryptable volumes */
           SLOGE("Too many device nodes returned when mounting %d\n", getMountpoint());
           return -1;
       }

       if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
                                new_sys_path, sizeof(new_sys_path),
                                &new_major, &new_minor)) {
           SLOGE("Cannot setup encryption mapping for %d\n", getMountpoint());
           return -1;
       }
       /* We now have the new sysfs path for the decrypted block device, and the
        * majore and minor numbers for it.  So, create the device, update the
        * path to the new sysfs path, and continue.
        */
        snprintf(nodepath,
                 sizeof(nodepath), "/dev/block/vold/%d:%d",
                 new_major, new_minor);
        if (createDeviceNode(nodepath, new_major, new_minor)) {
            SLOGE("Error making device node '%s' (%s)", nodepath,
                                                       strerror(errno));
        }

        // Todo: Either create sys filename from nodepath, or pass in bogus path so
        //       vold ignores state changes on this internal device.
        updateDeviceInfo(nodepath, new_major, new_minor);

        /* Get the device nodes again, because they just changed */
        n = getDeviceNodes((dev_t *) &deviceNodes, MAX_SUP_PART);
        if (!n) {
            SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
            return -1;
        }
    }

    for (i = 0; i < n; i++) {
        char devicePath[255];

        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
                MINOR(deviceNodes[i]));

        if (deviceNodes[i] == (dev_t)(-1)) {
            SLOGE("Partition '%s' is invalid dev_t. Skip mounting!", devicePath);
            continue;
        }

        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());

        errno = 0;
        setState(Volume::State_Checking);

        /*
         * If FS check failed, we should move on to next partition
         * instead of returning an error
         */

__CHECK_FAT_AGAIN:
        if (Fat::check(devicePath)) {
#if 0
            if (errno == ENODATA) {
                SLOGW("%s does not contain a FAT filesystem\n", devicePath);
                continue;
            }
            errno = EIO;
            /* Badness - abort the mount */
            SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
            setState(Volume::State_Idle);
            return -1;
#else

#ifdef MTK_EMMC_SUPPORT
            if ( mVm->isFirstBoot() && IsEmmcStorage()) {
                SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath);
			    if (Fat::format(devicePath, 0)) {
				  SLOGE("Failed to format (%s)", strerror(errno));				  
			    }
                else {
                    SLOGI("Format successfully. (%s)\n", devicePath);
					property_set("persist.first_boot", "0");
                    goto __CHECK_FAT_AGAIN;
                }
            }
#endif

            SLOGW("%s failed FS checks, move on to next partition", devicePath);
            continue;
#endif                                        
        }

#ifdef MTK_EMMC_SUPPORT
        else {
             if ( mVm->isFirstBoot() && IsEmmcStorage()) {
                 property_set("persist.first_boot", "0");           
             }
        }  
#endif     


        /*
         * Mount the device on our internal staging mountpoint so we can
         * muck with it before exposing it to non priviledged users.
         */
        errno = 0;
        int gid;

        if (primaryStorage) {
            // Special case the primary SD card.
            // For this we grant write access to the SDCARD_RW group.
            gid = AID_SDCARD_RW;
        } else {
            // For secondary external storage we keep things locked up.
            /* Note: Change the google default setting from AID_MEDIA_RW to AID_SDCARD_RW. */
            gid = AID_SDCARD_RW;
        }
        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
                AID_SYSTEM, gid, 0702, true)) {
            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
            // kill the process anyway
            Process::killProcessesWithOpenFiles("/mnt/secure/staging", 2);
            continue;
        }

        SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());
        SLOGI("PrimaryStory = %d, externalStorage = %s", primaryStorage, externalStorage);

        protectFromAutorunStupidity();

        // only create android_secure on primary storage
        if (primaryStorage && createBindMounts()) {
            SLOGE("Failed to create bindmounts (%s)", strerror(errno));
            umount("/mnt/secure/staging");
            setState(Volume::State_Idle);
            return -1;
        }

        /*
         * Now that the bindmount trickery is done, atomically move the
         * whole subtree to expose it to non priviledged users.
         */
        if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
            SLOGE("Failed to move mount (%s)", strerror(errno));
            umount("/mnt/secure/staging");
            setState(Volume::State_Idle);
            return -1;
        }
        setState(Volume::State_Mounted);
        mCurrentlyMountedKdev = deviceNodes[i];
        return 0;
    }

    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
    spin_lock(&mStateLock);
    curState = getState();
    if ((curState != Volume::State_NoMedia) && 
	(curState != Volume::State_Mounted))
        setState(Volume::State_Idle);
        	
    if(curState == Volume::State_Mounted) {
	spin_unlock(&mStateLock);
        return 0;
    }
    spin_unlock(&mStateLock);
    return -1;
}
Example #4
0
int Volume::mountVol() {
    dev_t deviceNodes[DirectVolume::MAX_PARTITIONS];
    int n, i, rc = 0, curState;
    char errmsg[255];

    int flags = getFlags();
    
    /* we igore the setting of "VOL_PROVIDES_ASEC". if the storage is primary, then we will handle "Asec"  */
    //bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
    const char* externalStorage = getenv("EXTERNAL_STORAGE");
    bool providesAsec = externalStorage && !strcmp(getFuseMountpoint(), externalStorage);


    // TODO: handle "bind" style mounts, for emulated storage

    char decrypt_state[PROPERTY_VALUE_MAX];
    char crypto_state[PROPERTY_VALUE_MAX];
    char encrypt_progress[PROPERTY_VALUE_MAX];

    if (mPreState != Volume::State_Shared && mVm->isSomeVolumeShared()) {
        SLOGI("Some volume is State_Shared, force to share current volume, %s \n", getLabel());
        return mVm->shareVolume(getLabel(), "ums");
    }

    property_get("vold.decrypt", decrypt_state, "");
    property_get("vold.encrypt_progress", encrypt_progress, "");
#ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT
    char *otgNodePath = getOtgNodePath();
#endif

    /* Don't try to mount the volumes if we have not yet entered the disk password
     * or are in the process of encrypting.
     */
    if ((getState() == Volume::State_NoMedia) ||
        ((!strcmp(decrypt_state, "trigger_restart_min_framework") || encrypt_progress[0]) && providesAsec)) {
        snprintf(errmsg, sizeof(errmsg),
                 "Volume %s %s mount failed - no media",
                 getLabel(), getFuseMountpoint());
        mVm->getBroadcaster()->sendBroadcast(
                                         ResponseCode::VolumeMountFailedNoMedia,
                                         errmsg, false);
        errno = ENODEV;
        return -1;
    } else if (getState() != Volume::State_Idle) {
        errno = EBUSY;
        if (getState() == Volume::State_Pending) {
            mRetryMount = true;
        }
        return -1;
    }

    if (isMountpointMounted(getMountpoint())) {
        SLOGW("Volume is idle but appears to be mounted - fixing");
        setState(Volume::State_Mounted);
        // mCurrentlyMountedKdev = XXX
        return 0;
    }

#ifdef MTK_SHARED_SDCARD
    SLOGI("mountvol: IsEmmcStorage=%d", IsEmmcStorage());
    if (IsEmmcStorage()) {
         property_set("ctl.start", "sdcard");
         waitForServiceState("sdcard", "running");
         setState(Volume::State_Mounted);
         return 0;
    }     
#endif

    n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS);
    if (!n) {
        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
        return -1;
    }
    SLOGD("Found %d device nodes", n);

#ifndef MTK_EMULATOR_SUPPORT

    if (!IsEmmcStorage() && !strncmp(getLabel(), "sdcard", 6)) {
#ifdef MTK_FAT_ON_NAND
       if( -1 == mLoopDeviceIdx){
#endif
          SLOGD("Reinit SD card");
            if (mVm->reinitExternalSD()){
              SLOGE("Fail: reinitExternalSD()");
              /* Card inserted but fail to reinit, there is something wrong with this card */
              errno = EIO;
              return -1;
            }
#ifdef MTK_FAT_ON_NAND
          }
#endif
    }
    
#endif

    /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
     * and also marked as providing Asec storage, then we need to decrypt
     * that partition, and update the volume object to point to it's new decrypted
     * block device
     */
    property_get("ro.crypto.state", crypto_state, "");
    if (providesAsec &&
        ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
        !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
       char new_sys_path[MAXPATHLEN];
       char nodepath[256];
       int new_major, new_minor;

       if (n != 1) {
           /* We only expect one device node returned when mounting encryptable volumes */
           SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint());
           return -1;
       }

       if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
                                new_sys_path, sizeof(new_sys_path),
                                &new_major, &new_minor)) {
           SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint());
           return -1;
       }
#ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT
    if (0 == strcmp(getLabel(), "usbotg")) {
        if (createDeviceNode(otgNodePath, new_major, new_minor)) {
            SLOGE("usbotg: Volume mountVol Error making device node '%s' (%s)", otgNodePath,
                                                       strerror(errno));
        }
        updateDeviceInfo(otgNodePath, new_major, new_minor);
    } else
#endif
       /* We now have the new sysfs path for the decrypted block device, and the
        * majore and minor numbers for it.  So, create the device, update the
        * path to the new sysfs path, and continue.
        */
    {
        snprintf(nodepath,
                 sizeof(nodepath), "/dev/block/vold/%d:%d",
                 new_major, new_minor);
        if (createDeviceNode(nodepath, new_major, new_minor)) {
            SLOGE("Error making device node '%s' (%s)", nodepath,
                                                       strerror(errno));
        }

        // Todo: Either create sys filename from nodepath, or pass in bogus path so
        //       vold ignores state changes on this internal device.
        updateDeviceInfo(nodepath, new_major, new_minor);

        /* Get the device nodes again, because they just changed */
        n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS);
        if (!n) {
            SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
            return -1;
        }
    }
    }
#ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT
    if (0 == strcmp(getLabel(), "usbotg")) {
        setState(Volume::State_Checking);

        if (0 != mkdir(getMountpoint(), 0700)) {
            SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno));
        }
        else {
            SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint());
        }
        if (0 != chown(getMountpoint(), AID_MEDIA_RW, AID_MEDIA_RW)) {
            SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno));
        }
        else {
            SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint());
        }

        if (0 != mkdir(getFuseMountpoint(), 0755)) {
            SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getFuseMountpoint(), strerror(errno));
        }
        else {
            SLOGD("usbotg: Volume mountVol (%s) mkdir success", getFuseMountpoint());
        }

        
        int fd;
        int counter = 0;

        while(1) {            
            counter++;
            if( counter == 10)
            {
            	SLOGD("timeout open otgNodePath counter:%d\n",counter);
            	break;
            }
            
            if ((fd = open(otgNodePath, O_RDONLY)) < 0) {
                 SLOGE(" cannot open device '%s' (errno=%d) (%s)", otgNodePath, errno,strerror(errno));
                 usleep(30000);
            } else {
                 SLOGD(" can access %s successfully", otgNodePath);    
                 close(fd);
                 break;
            }
        }

        if (Fat::check(otgNodePath)) {
            SLOGE("usbotg:  %s fat check fail (%s)\n", otgNodePath, strerror(errno));
            char cmd[255] = {0};
            sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint());
            system(cmd);
            SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
            sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint());
            system(cmd);
            SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
            return -1;            
        }
        
        if (Fat::doMount(otgNodePath, getMountpoint(), false, false, false, 
            AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
            SLOGE("usbotg: Volume mountVol %s Otg failed to mount via VFAT (%s)\n", otgNodePath, strerror(errno));
            char cmd[255] = {0};
            sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint());
            system(cmd);
            SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
            sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint());
            system(cmd);
            SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
	    setState(Volume::State_Idle);
            return -1;
        }
    
        extractMetadata(otgNodePath);

        //fork sdcard process instead of witch service in init.rc

        struct sigaction act, oact;
        act.sa_handler = sigCld;
        act.sa_flags = 0;
        sigemptyset(&act.sa_mask);

        if (sigaction(SIGCHLD, &act, &oact) <0) {
            SLOGD("Error occured on signal");
            return -1;
        }   
        
        pid_t pid = fork();

        if (pid < 0) {
            SLOGD("Error occured on fork");
            return 0;
        } else if (pid == 0) {
            SLOGD("usbotg: Volume mountVol go execv,pid=%d", pid);
            const char* mountCmd = "/system/bin/sdcard";
            const char* mountpoint = getMountpoint();
            const char* fusemountpoint = getFuseMountpoint();
            const char* argv0[] = {
                        mountCmd,                
                        "-u",                
                        "1023",               
                        "-g",                             
                        "1023", 
                        "-w",
                        "1023",
                        "-d",
                        mountpoint,
                        fusemountpoint,
                        NULL 
                    };
            SLOGD("%s %s %s %s %s %s %s %s %s %s", argv0[0], argv0[1], argv0[2], argv0[3], argv0[4], argv0[5], argv0[6], argv0[7], argv0[8], argv0[9]);

            if (execv(mountCmd,(char* const*)argv0) < 0) {
                ALOGE("execv(%s) failed: %s\n", mountCmd, strerror(errno));
                SLOGD("usbotg: Volume mountVol mounted failed");
                char cmd[255] = {0};
                sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint());
                system(cmd);
                SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
                sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint());
                system(cmd);
                SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd);
                exit(127);
            }
            exit(127);
        } else{
            SLOGD("usbotg: Volume mountVol mounted succed,pid=%d",pid);
            setState(Volume::State_Mounted);
            mPid = pid;
            return 0;
        }
    }
#endif  

    for (i = 0; i < n; i++) {
        char devicePath[255];

        sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]),
                minor(deviceNodes[i]));

        if (deviceNodes[i] == (dev_t)(-1)) {
            SLOGE("Partition '%s' is invalid dev_t. Skip mounting!", devicePath);
            continue;
        }

        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());

        errno = 0;
        if ((getState() == Volume::State_NoMedia) ) {
            SLOGI("NoMedia! skip mounting the storage. Update errno to ENODEV");
            errno = ENODEV;
            return -1;
        } 
        setState(Volume::State_Checking);

        /*
         * If FS check failed, we should move on to next partition
         * instead of returning an error
         */

__CHECK_FAT_AGAIN:
        if (Fat::check(devicePath)) {
#if 0
            if (errno == ENODATA) {
                SLOGW("%s does not contain a FAT filesystem\n", devicePath);
                continue;
            }
            errno = EIO;
            /* Badness - abort the mount */
            SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
            setState(Volume::State_Idle);
            return -1;
#else

#ifdef MTK_EMMC_SUPPORT
            if ( mVm->isFirstBoot() && IsEmmcStorage()) {
                SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath);
                if (Fat::format(devicePath, 0, false)) {
                  SLOGE("Failed to format (%s)", strerror(errno));                
                }
                else {
                    SLOGI("Format successfully. (%s)\n", devicePath);
                    property_set("persist.vold.first_boot", "0");
                    goto __CHECK_FAT_AGAIN;
                }
            }
#endif
#ifdef MTK_FAT_ON_NAND
            char first_boot[PROPERTY_VALUE_MAX] ;
            property_get("persist.vold.fat_first_boot", first_boot, "1");
            
            if (!strcmp(first_boot, "1") && !strcmp(getLabel(), "sdcard0")) {
                SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath);
                if (Fat::format(devicePath, 0, false)) {
                  SLOGE("Failed to format %s(%d)", strerror(errno), errno);
                }
                else {
                    SLOGI("%s format successfully\n", devicePath);
                    property_set("persist.vold.fat_first_boot", "0");
                    goto __CHECK_FAT_AGAIN;
                }
            }
#endif
            SLOGW("%s failed FS checks, move on to next partition", devicePath);
            continue;
#endif                                        
        }

#ifdef MTK_EMMC_SUPPORT
        else {
             if ( mVm->isFirstBoot() && IsEmmcStorage()) {
                 property_set("persist.vold.first_boot", "0");           
             }
        }  
#endif     

        errno = 0;
        int gid;
#ifdef MTK_EMMC_DISCARD     
        if (Fat::doMount(devicePath, getMountpoint(), false, false, false,
                AID_MEDIA_RW, AID_MEDIA_RW, 0007, true, IsEmmcStorage())) {
            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
            continue;
        }
#else //MTK_EMMC_DISCARD   
        if (Fat::doMount(devicePath, getMountpoint(), false, false, false,
                AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
            continue;
        }
#endif //MTK_EMMC_DISCARD           

        SLOGI("providesAsec = %d", providesAsec);

        extractMetadata(devicePath);

#ifdef MTK_2SDCARD_SWAP
        char secImgDir[PATH_MAX];  
        sprintf(secImgDir, "%s/.android_secure", getMountpoint());
        SLOGI("Create %s in advance", secImgDir);
        /* Whether primary or secondary storage, create .android folder in advance to prevent from media out of space for Bindmounts fail 
           This case happens in SWAP feature.
        */
        if (access(secImgDir, R_OK | X_OK)) {
          if (errno == ENOENT) {
              if (mkdir(secImgDir, 0777)) {
                  SLOGE("Failed to create %s (%s)", secImgDir, strerror(errno));
              }
          } else {
              SLOGE("Failed to access %s (%s)", secImgDir, strerror(errno));
          }
        }
#endif

        if (providesAsec && mountAsecExternal() != 0) {
            SLOGE("Failed to mount secure area (%s)", strerror(errno));
            umount(getMountpoint());
            setState(Volume::State_Idle);
            return -1;
        }

        char service[64];
        char service_id[64];
        strcpy(service_id, getMountpoint()+strlen(Volume::MEDIA_DIR)+1);
        snprintf(service, 64, "fuse_%s", service_id);
        property_set("ctl.start", service);
        waitForServiceState(service, "running");

        int fd;
        if ((fd = open(devicePath, O_RDONLY)) < 0) {
           SLOGE("Cannot open device '%s' (errno=%d)", devicePath, errno);
        }
        else {
           setState(Volume::State_Mounted, Fat::isFat32(fd));
           close(fd);
        }
        mCurrentlyMountedKdev = deviceNodes[i];
        return 0;
    }

    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());

    curState = getState();
    if (curState == Volume::State_NoMedia) {
        SLOGI("Mount fail caused by NoMedia! Update errno to ENODEV");
        errno = ENODEV;
    } 

    if ((curState != Volume::State_NoMedia) && 
        (curState != Volume::State_Mounted)) {
         setState(Volume::State_Idle);
    }

    if(curState == Volume::State_Mounted) {
        return 0;
    }
    return -1;
}