int vfat_check(blkdev_t *dev)
{
    int rc;
    boolean rw = true;

#if VFAT_DEBUG
    LOG_VOL("vfat_check(%d:%d):", dev->major, dev->minor);
#endif

    if (access(FSCK_MSDOS_PATH, X_OK)) {
        LOGE("vfat_check(%d:%d): %s not found (skipping checks)",
             dev->major, dev->minor, FSCK_MSDOS_PATH);
        return 0;
    }

    int pass = 1;
    do {
        char *args[5];
        args[0] = FSCK_MSDOS_PATH;
        args[1] = "-p";
        args[2] = "-f";
        args[3] = blkdev_get_devpath(dev);
        args[4] = NULL;
        rc = logwrap(4, args, 1);
        free(args[3]);

        if (rc == 0) {
            LOG_VOL("Filesystem check completed OK");
            return 0;
        } else if (rc == 2) {
            LOG_VOL("Filesystem check failed (not a FAT filesystem)");
            return -ENODATA;
        } else if (rc == 4) {
            if (pass++ <= 3) {
                LOG_VOL("Filesystem modified - rechecking (pass %d)",
                        pass);
                continue;
            } else {
                LOG_VOL("Failing check after too many rechecks");
                return -EIO;
            }
        } else if (rc == -11) {
            LOG_VOL("Filesystem check crashed");
            return -EIO;
        } else {
            LOG_VOL("Filesystem check failed (unknown exit code %d)", rc);
            return -EIO;
        }
    } while (0);
    return 0;
}
/*
 * Called when a volume is sucessfully unmounted for UMS enable
 */
static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg)
{
    int rc;
    char *devdir_path;

#if DEBUG_VOLMGR
    LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point);
#endif
    devdir_path = blkdev_get_devpath(v->dev->disk);

    if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) {
        free(devdir_path);
        LOGE("Error enabling ums (%d)", rc);
        return;
    }
    free(devdir_path);
    volume_setstate(v, volstate_ums);
    pthread_mutex_unlock(&v->lock);
}
Exemplo n.º 3
0
/*
 * Called when a volume is sucessfully unmounted for UMS enable
 */
static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg)
{
    int rc;
    char *devdir_path;

#if DEBUG_VOLMGR
    LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point);
#endif
    devdir_path = blkdev_get_devpath(v->dev->disk);

#ifdef ADD_ISO
    LOG_VOL("call ums_enable:ums_path=%s\n", v->ums_path);
    if ((rc = ums_enable(devdir_path, v->ums_path, true)) < 0) {
#else
    if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) {
#endif
        free(devdir_path);
        LOGE("Error enabling ums (%d)", rc);
        return;
    }
    free(devdir_path);
    volume_setstate(v, volstate_ums);
    pthread_mutex_unlock(&v->lock);
}

static int volmgr_readconfig(char *cfg_path)
{
    cnode *root = config_node("", "");
    cnode *node;

    config_load_file(root, cfg_path);
    node = root->first_child;

    while (node) {
        if (!strncmp(node->name, "volume_", 7))
            volmgr_config_volume(node);
        else
            LOGE("Skipping unknown configuration node '%s'", node->name);
        node = node->next;
    }
    return 0;
}
int vfat_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode)
{
    int flags, rc;
    char *devpath;

    devpath = blkdev_get_devpath(dev);

#if VFAT_DEBUG
    LOG_VOL("vfat_mount(%d:%d, %s, %d):", dev->major, dev->minor, vol->mount_point, safe_mode);
#endif

    flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;

    if (vol->state == volstate_mounted) {
        LOG_VOL("Remounting %d:%d on %s, safe mode %d", dev->major,
                dev->minor, vol->mount_point, safe_mode);
        flags |= MS_REMOUNT;
    }

    /*
     * Note: This is a temporary hack. If the sampling profiler is enabled,
     * we make the SD card world-writable so any process can write snapshots.
     *
     * TODO: Remove this code once we have a drop box in system_server.
     */
    char value[PROPERTY_VALUE_MAX];
    property_get("persist.sampling_profiler", value, "");
    if (value[0] == '1') {
        LOGW("The SD card is world-writable because the"
            " 'persist.sampling_profiler' system property is set to '1'.");
        rc = mount(devpath, vol->mount_point, "vfat", flags,
                "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed");
    } else {
        /*
         * The mount masks restrict access so that:
         * 1. The 'system' user cannot access the SD card at all -
         *    (protects system_server from grabbing file references)
         * 2. Group users can RWX
         * 3. Others can only RX
         */
        rc = mount(devpath, vol->mount_point, "vfat", flags,
                "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed");
    }

    if (rc && errno == EROFS) {
        LOGE("vfat_mount(%d:%d, %s): Read only filesystem - retrying mount RO",
             dev->major, dev->minor, vol->mount_point);
        flags |= MS_RDONLY;
        rc = mount(devpath, vol->mount_point, "vfat", flags,
                   "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed");
    }

    if (rc == 0) {
        char *lost_path;
        asprintf(&lost_path, "%s/LOST.DIR", vol->mount_point);
        if (access(lost_path, F_OK)) {
            /*
             * Create a LOST.DIR in the root so we have somewhere to put
             * lost cluster chains (fsck_msdos doesn't currently do this)
             */
            if (mkdir(lost_path, 0755)) {
                LOGE("Unable to create LOST.DIR (%s)", strerror(errno));
            }
        }
        free(lost_path);
    }

#if VFAT_DEBUG
    LOG_VOL("vfat_mount(%s, %d:%d): mount rc = %d", dev->major,k dev->minor,
            vol->mount_point, rc);
#endif
    free (devpath);
    return rc;
}
int blkdev_refresh(blkdev_t *blk)
{
    int fd = 0;
    char *devpath = NULL;
    unsigned char *block = NULL;
    int i, rc;

    if (!(block = malloc(512)))
        goto out;

    /*
     * Get the device size
     */
    devpath = blkdev_get_devpath(blk);

    if ((fd = open(devpath, O_RDONLY)) < 0) {
        LOGE("Unable to open device '%s' (%s)", devpath, strerror(errno));
        return -errno;
    }

    if (ioctl(fd, BLKGETSIZE, &blk->nr_sec)) {
        LOGE("Unable to get device size (%m)");
        return -errno;
    }
    close(fd);
    free(devpath);

    /*
     * Open the disk partition table
     */
    devpath = blkdev_get_devpath(blk->disk);
    if ((fd = open(devpath, O_RDONLY)) < 0) {
        LOGE("Unable to open device '%s' (%s)", devpath,
             strerror(errno));
        free(devpath);
        return -errno;
    }

    free(devpath);

    if ((rc = read(fd, block, 512)) != 512) {
        LOGE("Unable to read device partition table (%d, %s)",
             rc, strerror(errno));
        goto out;
    }

    /*
     * If we're a disk, then process the partition table. Otherwise we're
     * a partition so get the partition type
     */

    if (blk->type == blkdev_disk) {
        blk->nr_parts = 0;

        if ((block[0x1fe] != 0x55) || (block[0x1ff] != 0xAA)) {
            LOGI("Disk %d:%d does not contain a partition table",
                 blk->major, blk->minor);
            goto out;
        }

        for (i = 0; i < 4; i++) {
            struct dos_partition part;

            dos_partition_dec(block + DOSPARTOFF + i * sizeof(struct dos_partition), &part);
            if (part.dp_flag != 0 && part.dp_flag != 0x80) {
                struct fat_boot_sector *fb = (struct fat_boot_sector *) &block[0];
             
                if (!i && fb->reserved && fb->fats && fat_valid_media(fb->media)) {
                    LOGI("Detected FAT filesystem in partition table");
                    break;
                } else {
                    LOGI("Partition table looks corrupt");
                    break;
                }
            }
            if (part.dp_size != 0 && part.dp_typ != 0)
                blk->nr_parts++;
        }
    } else if (blk->type == blkdev_partition) {
        struct dos_partition part;
        int part_no = blk->minor -1;

        if (part_no < 4) {
            dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
            blk->part_type = part.dp_typ;
        } else {
            LOGW("Skipping partition %d", part_no);
        }
    }

 out:

    if (block)
        free(block);

    char tmp[255];
    char tmp2[32];
    sprintf(tmp, "%s (blkdev %d:%d), %u secs (%u MB)",
                 (blk->type == blkdev_disk ? "Disk" : "Partition"),
                 blk->major, blk->minor,
                 blk->nr_sec,
                 (uint32_t) (((uint64_t) blk->nr_sec * 512) / 1024) / 1024);

    if (blk->type == blkdev_disk) 
        sprintf(tmp2, " %d partitions", blk->nr_parts);
    else
        sprintf(tmp2, " type 0x%x", blk->part_type);

    strcat(tmp, tmp2);
    LOGI(tmp);

    close(fd);

    return 0;
}