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); }
/* * 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; }