int do_wait(int nargs, char **args) { if (nargs == 2) { return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT); } else if (nargs == 3) { return wait_for_file(args[1], atoi(args[2])); } else return -1; }
static int mount_and_run(struct fstab *fstab) { struct fstab_part *datap = fstab_find_first_by_path(fstab, "/data"); if(!datap) { ERROR("Failed to find /data partition in fstab\n"); return -1; } if(access(datap->device, R_OK) < 0) { INFO("Waiting for %s\n", datap->device); if(wait_for_file(datap->device, 5) < 0) { ERROR("Waiting too long for dev %s\n", datap->device); return -1; } } mkdir(REALDATA, 0755); if(try_mount_all_entries(fstab, datap) < 0) { #ifndef MR_ENCRYPTION ERROR("Failed to mount /data with all possible filesystems!\n"); return -1; #else INFO("Failed to mount /data, trying encryption...\n"); switch(encryption_before_mount(fstab)) { case ENC_RES_ERR: ERROR("/data decryption failed!\n"); return -1; case ENC_RES_BOOT_INTERNAL: return 0; default: case ENC_RES_OK: { if(try_mount_all_entries(fstab, datap) < 0) { ERROR("Failed to mount decrypted /data with all possible filesystems!\n"); return -1; } break; } } #endif } if(find_multirom() == -1) { ERROR("Could not find multirom folder!\n"); return -1; } adb_init(path_multirom); run_multirom(); adb_quit(); return 0; }
int do_wait(int nargs, char **args) { if (nargs == 2) { return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT); } return -1; }
/* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password */ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, char *tmp_mount_point) { int i = 0; int ret = -1; char *m; if (!fstab) { return ret; } for (i = 0; i < fstab->num_entries; i++) { if (!fs_match(fstab->recs[i].mount_point, n_name)) { continue; } /* We found our match */ /* If this is a raw partition, report an error */ if (!strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { ERROR("Cannot mount filesystem of type %s on %s\n", fstab->recs[i].fs_type, n_blk_device); goto out; } /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(n_blk_device, WAIT_TIMEOUT); } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point); } /* Now mount it where requested */ if (tmp_mount_point) { m = tmp_mount_point; } else { m = fstab->recs[i].mount_point; } if (mount(n_blk_device, m, fstab->recs[i].fs_type, fstab->recs[i].flags, fstab->recs[i].fs_options)) { ERROR("Cannot mount filesystem on %s at %s\n", n_blk_device, m); goto out; } else { ret = 0; goto out; } } /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); out: return ret; }
int fs_mgr_mount_all(char *fstab_file) { int i = 0; int encrypted = 0; int ret = -1; int mret; struct fstab_rec *fstab = 0; if (!(fstab = read_fstab(fstab_file))) { return ret; } for (i = 0; fstab[i].blk_dev; i++) { if (fstab[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); } if (fstab[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); } mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type, fstab[i].flags, fstab[i].fs_options); if (!mret) { /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encrypted and deal with it */ if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ if (mount("tmpfs", fstab[i].mnt_point, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", fstab[i].mnt_point); goto out; } encrypted = 1; } else { ERROR("Cannot mount filesystem on %s at %s\n", fstab[i].blk_dev, fstab[i].mnt_point); goto out; } } if (encrypted) { ret = 1; } else { ret = 0; } out: free_fstab(fstab); return ret; }
static int wait_for_coldboot_done_action(int nargs, char **args) { int ret; INFO("wait for %s\n", coldboot_done); ret = wait_for_file(coldboot_done, COMMAND_RETRY_TIMEOUT); if (ret) ERROR("Timed out waiting for %s\n", coldboot_done); return ret; }
/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password */ int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point) { int i = 0; int ret = -1; struct fstab_rec *fstab = 0; char *m; if (!(fstab = read_fstab(fstab_file))) { return ret; } for (i = 0; fstab[i].blk_dev; i++) { if (!fs_match(fstab[i].mnt_point, n_name)) { continue; } /* We found our match */ /* First check the filesystem if requested */ if (fstab[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); } if (fstab[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); } /* Now mount it where requested */ if (tmp_mnt_point) { m = tmp_mnt_point; } else { m = fstab[i].mnt_point; } if (mount(n_blk_dev, m, fstab[i].type, fstab[i].flags, fstab[i].fs_options)) { ERROR("Cannot mount filesystem on %s at %s\n", n_blk_dev, m); goto out; } else { ret = 0; goto out; } } /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point); out: free_fstab(fstab); return ret; }
static int wait_for_coldboot_done_action(const std::vector<std::string>& args) { Timer t; NOTICE("Waiting for %s...\n", COLDBOOT_DONE); // Any longer than 1s is an unreasonable length of time to delay booting. // If you're hitting this timeout, check that you didn't make your // sepolicy regular expressions too expensive (http://b/19899875). if (wait_for_file(COLDBOOT_DONE, 1)) { ERROR("Timed out waiting for %s\n", COLDBOOT_DONE); } NOTICE("Waiting for %s took %.2fs.\n", COLDBOOT_DONE, t.duration()); return 0; }
static int run_core(void) { int res = -1; struct fstab *fstab = NULL; if(wait_for_file("/dev/graphics/fb0", 5) < 0) { ERROR("Waiting too long for fb0"); goto exit; } #ifdef MR_POPULATE_BY_NAME_PATH Populate_ByName_using_emmc(); #endif fstab = fstab_auto_load(); if(!fstab) goto exit; #if 0 fstab_dump(fstab); //debug #endif // mount and run multirom from sdcard res = mount_and_run(fstab); if(res < 0 && mrom_is_second_boot()) { ERROR("This is second boot and we couldn't mount /data, reboot!\n"); sync(); //android_reboot(ANDROID_RB_RESTART, 0, 0); android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); // favour reboot to recovery, to avoid possible bootlooping while(1) sleep(1); } if(access(KEEP_REALDATA, F_OK) < 0) { umount(REALDATA); rmdir(REALDATA); encryption_destroy(); } encryption_cleanup(); exit: if(fstab) fstab_destroy(fstab); return res; }
static int ubi_dev_read_int(int dev, const char *file, int def) { int fd, val = def; char path[128], buf[64]; sprintf(path, UBI_SYS_PATH "/ubi%d/%s", dev, file); wait_for_file(path, 5); fd = open(path, O_RDONLY); if (fd == -1) { return val; } if (read(fd, buf, 64) > 0) { val = atoi(buf); } close(fd); return val; }
/* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one * in turn, and stop on 1st success, or no more match. */ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, char *tmp_mount_point) { int i = 0; int ret = FS_MGR_DOMNT_FAILED; int mount_errors = 0; int first_mount_errno = 0; char *m; if (!fstab) { return ret; } for (i = 0; i < fstab->num_entries; i++) { if (!fs_match(fstab->recs[i].mount_point, n_name)) { continue; } /* We found our match */ /* If this swap or a raw partition, report an error */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { ERROR("Cannot mount filesystem of type %s on %s\n", fstab->recs[i].fs_type, n_blk_device); goto out; } /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(n_blk_device, WAIT_TIMEOUT); } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } /* Now mount it where requested */ if (tmp_mount_point) { m = tmp_mount_point; } else { m = fstab->recs[i].mount_point; } if (__mount(n_blk_device, m, &fstab->recs[i], FS_MGR_MNTALL_DEV_NOT_ENCRYPTED)) { if (!first_mount_errno) first_mount_errno = errno; mount_errors++; continue; } else { ret = 0; goto out; } } if (mount_errors) { ERROR("Cannot mount filesystem on %s at %s. error: %s\n", n_blk_device, m, strerror(first_mount_errno)); if (first_mount_errno == EBUSY) { ret = FS_MGR_DOMNT_BUSY; } else { ret = FS_MGR_DOMNT_FAILED; } } else { /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); } out: return ret; }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } ERROR("[xiaolei] : blk device name %s\n", fstab->recs[i].blk_device); #ifdef MTK_UBIFS_SUPPORT if (!strcmp(fstab->recs[i].fs_type, "ubifs")) { char tmp[80]; int n = ubi_attach_mtd(fstab->recs[i].blk_device + 5); if (n < 0) { return -1; } n = sprintf(tmp, "/dev/ubi%d_0", n); free(fstab->recs[i].blk_device); fstab->recs[i].blk_device = malloc(n+1); sprintf(fstab->recs[i].blk_device, "%s", tmp); ERROR("debug : ubifs blk_device %s", fstab->recs[i].blk_device); } #endif if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx, encryptable); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ if ((fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)) { if (umount(fstab->recs[attempted_idx].mount_point) == 0) { if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; } else { ERROR("Only one encryptable/encrypted partition supported\n"); encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } } else { INFO("Could not umount %s - allow continue unencrypted\n", fstab->recs[attempted_idx].mount_point); continue; } } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if(partition_wiped(fstab->recs[attempted_idx].blk_device)) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }
static int ubi_attach_mtd(const char *name) { int ret; int mtd_num, ubi_num, vid_off; int ubi_ctrl, ubi_dev; int vols, avail_lebs, leb_size; char path[128]; struct ubi_attach_req attach_req; struct ubi_mkvol_req mkvol_req; mtd_num = mtd_name_to_number(name); if (mtd_num == -1) { return -1; } for (ubi_num = 0; ubi_num < 4; ubi_num++) { sprintf(path, "/sys/class/ubi/ubi%d/mtd_num", ubi_num); ubi_dev = open(path, O_RDONLY); if (ubi_dev != -1) { ret = read(ubi_dev, path, sizeof(path)); close(ubi_dev); if (ret > 0 && mtd_num == atoi(path)) return ubi_num; } } ubi_ctrl = open(UBI_CTRL_DEV, O_RDONLY); if (ubi_ctrl == -1) { return -1; } memset(&attach_req, 0, sizeof(struct ubi_attach_req)); attach_req.ubi_num = UBI_DEV_NUM_AUTO; attach_req.mtd_num = mtd_num; attach_req.vid_hdr_offset = UBI_VID_OFFSET_AUTO; ret = ioctl(ubi_ctrl, UBI_IOCATT, &attach_req); if (ret == -1) { close(ubi_ctrl); return -1; } ubi_num = attach_req.ubi_num; vid_off = attach_req.vid_hdr_offset; vols = ubi_dev_read_int(ubi_num, "volumes_count", -1); if (vols == 0) { sprintf(path, "/dev/ubi%d", ubi_num); ret = wait_for_file(path, 50); ubi_dev = open(path, O_RDONLY); if (ubi_dev == -1) { close(ubi_ctrl); return ubi_num; } avail_lebs = ubi_dev_read_int(ubi_num, "avail_eraseblocks", 0); leb_size = ubi_dev_read_int(ubi_num, "eraseblock_size", 0); memset(&mkvol_req, 0, sizeof(struct ubi_mkvol_req)); mkvol_req.vol_id = UBI_VOL_NUM_AUTO; mkvol_req.alignment = 1; mkvol_req.bytes = (long long)avail_lebs * leb_size; mkvol_req.vol_type = UBI_DYNAMIC_VOLUME; ret = snprintf(mkvol_req.name, UBI_MAX_VOLUME_NAME + 1, "%s", name); mkvol_req.name_len = ret; ioctl(ubi_dev, UBI_IOCMKVOL, &mkvol_req); close(ubi_dev); } close(ubi_ctrl); return ubi_num; }
int main(int argc, char *argv[]) { int i, res; static char *const cmd[] = { "/init", NULL }; struct fstab *fstab = NULL; for(i = 1; i < argc; ++i) { if(strcmp(argv[i], "-v") == 0) { printf("%d\n", VERSION_TRAMPOLINE); fflush(stdout); return 0; } } umask(000); // Init only the little we need, leave the rest for real init mkdir("/dev", 0755); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); klog_init(); ERROR("Running trampoline v%d\n", VERSION_TRAMPOLINE); if(is_charger_mode()) { ERROR("Charger mode detected, skipping multirom\n"); goto run_main_init; } #if MR_DEVICE_HOOKS >= 3 tramp_hook_before_device_init(); #endif ERROR("Initializing devices..."); devices_init(); ERROR("Done initializing"); if(wait_for_file("/dev/graphics/fb0", 5) < 0) { ERROR("Waiting too long for fb0"); goto exit; } fstab = fstab_auto_load(); if(!fstab) goto exit; #if 0 fstab_dump(fstab); //debug #endif // mount and run multirom from sdcard mount_and_run(fstab); exit: if(fstab) fstab_destroy(fstab); // close and destroy everything devices_close(); run_main_init: if(access(KEEP_REALDATA, F_OK) < 0) { umount(REALDATA); umount("/dev/pts"); umount("/dev"); rmdir("/dev/pts"); rmdir("/dev/socket"); rmdir("/dev"); rmdir(REALDATA); } umount("/proc"); umount("/sys"); rmdir("/proc"); rmdir("/sys"); ERROR("Running main_init\n"); fixup_symlinks(); chmod("/main_init", EXEC_MASK); rename("/main_init", "/init"); res = execve(cmd[0], cmd, NULL); ERROR("execve returned %d %d %s\n", res, errno, strerror(errno)); return 0; }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } /* Translate LABEL= file system labels into block devices */ if (!strcmp(fstab->recs[i].fs_type, "ext2") || !strcmp(fstab->recs[i].fs_type, "ext3") || !strcmp(fstab->recs[i].fs_type, "ext4")) { int tret = translate_ext_labels(&fstab->recs[i]); if (tret < 0) { ERROR("Could not translate label to block device\n"); continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { // Log and continue ERROR("Only one encryptable/encrypted partition supported\n"); } encryptable = status; } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if(partition_wiped(fstab->recs[attempted_idx].blk_device)) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }
int main(int argc, char **argv) { struct fstab *fstab; int ret=0, syspart, i, status; char filenamePatched[PATH_MAX], filenameSystem[PATH_MAX]; // check arguments if(argc!=2) { ERROR("Invalid Arguments"); return -EINVAL; } // get syspart from cmdline syspart = getDualbootSyspart(); if(syspart<0) { ERROR("Cannot read system number"); return -EINVAL; } // patch fstab sprintf(filenamePatched, "%s.patched", argv[1]); sprintf(filenameSystem, "%s.system", argv[1]); patch_fstab(argv[1], filenamePatched, filenameSystem, syspart); // mount system fstab = fs_mgr_read_fstab(filenameSystem); ret = fs_mgr_mount_all(fstab); fs_mgr_free_fstab(fstab); if (ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); } // mount data fstab = fs_mgr_read_fstab(argv[1]); for (i = 0; i < fstab->num_entries; ++i) { struct fstab_rec* v = &fstab->recs[i]; if(strcmp(PARTITION_USERDATA, v->blk_device)) continue; if (v->fs_mgr_flags & MF_WAIT) { wait_for_file(v->blk_device, WAIT_TIMEOUT); } if (v->fs_mgr_flags & MF_CHECK) { check_fs(v->blk_device, v->fs_type, v->mount_point); } if(mountScriptExists()) { char *e2fsck_argv[] = { "/system/bin/mount_ext4.sh", v->blk_device, v->mount_point }; ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, &status, true, LOG_KLOG, true, NULL); } else { ret = mount(v->blk_device, v->mount_point, v->fs_type, v->flags, v->fs_options); } } fs_mgr_free_fstab(fstab); if (ret == -1) { ERROR("error mounting userdata\n"); } return ret; }
/* mount <type> <device> <path> <flags ...> <options> */ int do_mount(int nargs, char **args) { char tmp[64]; char *source, *target, *system; char *options = NULL; unsigned flags = 0; int n, i; int wait = 0; for (n = 4; n < nargs; n++) { for (i = 0; mount_flags[i].name; i++) { if (!strcmp(args[n], mount_flags[i].name)) { flags |= mount_flags[i].flag; break; } } if (!mount_flags[i].name) { if (!strcmp(args[n], "wait")) wait = 1; /* if our last argument isn't a flag, wolf it up as an option string */ else if (n + 1 == nargs) options = args[n]; } } system = args[1]; source = args[2]; target = args[3]; if (!strncmp(source, "mtd@", 4)) { n = mtd_name_to_number(source + 4); if (n < 0) { return -1; } sprintf(tmp, "/dev/block/mtdblock%d", n); if (wait) wait_for_file(tmp, COMMAND_RETRY_TIMEOUT); if (mount(tmp, target, system, flags, options) < 0) { return -1; } goto exit_success; } else if (!strncmp(source, "loop@", 5)) { int mode, loop, fd; struct loop_info info; mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; fd = open(source + 5, mode); if (fd < 0) { return -1; } for (n = 0; ; n++) { sprintf(tmp, "/dev/block/loop%d", n); loop = open(tmp, mode); if (loop < 0) { return -1; } /* if it is a blank loop device */ if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { /* if it becomes our loop device */ if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { close(fd); if (mount(tmp, target, system, flags, options) < 0) { ioctl(loop, LOOP_CLR_FD, 0); close(loop); return -1; } close(loop); goto exit_success; } } close(loop); } close(fd); ERROR("out of loopback devices"); return -1; } else { if (wait) wait_for_file(source, COMMAND_RETRY_TIMEOUT); if (mount(source, target, system, flags, options) < 0) { /* If this fails, it may be an encrypted filesystem * or it could just be wiped. If wiped, that will be * handled later in the boot process. * We only support encrypting /data. Check * if we're trying to mount it, and if so, * assume it's encrypted, mount a tmpfs instead. * Then save the orig mount parms in properties * for vold to query when it mounts the real * encrypted /data. */ if (!strcmp(target, DATA_MNT_POINT) && !partition_wiped(source)) { const char *tmpfs_options; tmpfs_options = property_get("ro.crypto.tmpfs_options"); if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, tmpfs_options) < 0) { return -1; } /* Set the property that triggers the framework to do a minimal * startup and ask the user for a password */ property_set("ro.crypto.state", "encrypted"); property_set("vold.decrypt", "1"); } else { return -1; } } if (!strcmp(target, DATA_MNT_POINT)) { char fs_flags[32]; /* Save the original mount options */ property_set("ro.crypto.fs_type", system); property_set("ro.crypto.fs_real_blkdev", source); property_set("ro.crypto.fs_mnt_point", target); if (options) { property_set("ro.crypto.fs_options", options); } snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags); property_set("ro.crypto.fs_flags", fs_flags); } } exit_success: /* If not running encrypted, then set the property saying we are * unencrypted, and also trigger the action for a nonencrypted system. */ if (!strcmp(target, DATA_MNT_POINT)) { const char *prop; prop = property_get("ro.crypto.state"); if (! prop) { prop = "notset"; } if (strcmp(prop, "encrypted")) { property_set("ro.crypto.state", "unencrypted"); action_for_each_trigger("nonencrypted", action_add_queue_tail); } } return 0; }
/* mount <type> <device> <path> <flags ...> <options> */ int do_mount(int nargs, char **args) { char tmp[64]; char *source, *target, *type; char *options = NULL; unsigned flags = 0; int n, i; int wait = 0; //add for power loss test struct stat stbuf; for (n = 4; n < nargs; n++) { for (i = 0; mount_flags[i].name; i++) { if (!strcmp(args[n], mount_flags[i].name)) { flags |= mount_flags[i].flag; break; } } if (!mount_flags[i].name) { if (!strcmp(args[n], "wait")) wait = 1; /* if our last argument isn't a flag, wolf it up as an option string */ else if (n + 1 == nargs) options = args[n]; } } type = args[1]; source = args[2]; target = args[3]; if (!strncmp(source, "mtd@", 4)) { n = mtd_name_to_number(source + 4); if (n < 0) { return -1; } sprintf(tmp, "/dev/block/mtdblock%d", n); if (wait) wait_for_file(tmp, COMMAND_RETRY_TIMEOUT); if (mount(tmp, target, type, flags, options) < 0) { return -1; } goto exit_success; } else if (!strncmp(source, "loop@", 5)) { int mode, loop, fd; struct loop_info info; mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; fd = open(source + 5, mode); if (fd < 0) { return -1; } for (n = 0; ; n++) { sprintf(tmp, "/dev/block/loop%d", n); loop = open(tmp, mode); if (loop < 0) { return -1; } /* if it is a blank loop device */ if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { /* if it becomes our loop device */ if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { close(fd); if (mount(tmp, target, type, flags, options) < 0) { ioctl(loop, LOOP_CLR_FD, 0); close(loop); return -1; } close(loop); goto exit_success; } } close(loop); } close(fd); ERROR("out of loopback devices"); return -1; } else { #ifdef MTK_EMMC_SUPPORT struct phone_encrypt_state ps; if (!strcmp(target, DATA_MNT_POINT)) { if (misc_get_phone_encrypt_state(&ps) < 0) { printf("Failed to get encrypted status in MISC\n"); } else { printf("Success: get encrypted status: 0x%x in MISC\n", ps.state); } } #endif if (wait) wait_for_file(source, COMMAND_RETRY_TIMEOUT); if (mount(source, target, type, flags, options) < 0) { /* If this fails, it may be an encrypted filesystem * or it could just be wiped. If wiped, that will be * handled later in the boot process. * We only support encrypting /data. Check * if we're trying to mount it, and if so, * assume it's encrypted, mount a tmpfs instead. * Then save the orig mount parms in properties * for vold to query when it mounts the real * encrypted /data. */ if (!strcmp(target, DATA_MNT_POINT)) { int fd; if ((fd = open(source, O_RDONLY)) < 0) { printf("Mount /data fail because source(%s) doesn't exist.", source); return -1; } } if (!strcmp(target, DATA_MNT_POINT) && !partition_wiped(source)) { const char *tmpfs_options; tmpfs_options = property_get("ro.crypto.tmpfs_options"); if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, tmpfs_options) < 0) { return -1; } /* Set the property that triggers the framework to do a minimal * startup and ask the user for a password */ property_set("ro.crypto.state", "encrypted"); property_set("vold.decrypt", "1"); } else { return -1; } } #ifdef MTK_EMMC_SUPPORT else { if (!strcmp(target, DATA_MNT_POINT)) { if (ps.state == PHONE_ENCRYPTED) { ps.state = PHONE_UNCRYPTED; if (misc_set_phone_encrypt_state(&ps) < 0) { printf("Failed to set encrypted status to 0x%x in MISC\n", ps.state); } else { printf("Success: Set encrypted status to 0x%x in MISC\n", ps.state); } } } } #endif if (!strcmp(target, DATA_MNT_POINT)) { char fs_flags[32]; /* Save the original mount options */ property_set("ro.crypto.fs_type", type); property_set("ro.crypto.fs_real_blkdev", source); property_set("ro.crypto.fs_mnt_point", target); if (options) { property_set("ro.crypto.fs_options", options); } snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags); property_set("ro.crypto.fs_flags", fs_flags); } if (!strncmp(type, "ext4", 4)){ if (!strncmp(target, "/data", 5)){ printf("delete lost-found in data dir\n"); system("/system/bin/rm -r /data/lost+found/*"); if (stat("/data/data", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/data file\n"); system("/system/bin/rm -r /data/data"); } if (stat("/data/system", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/system file\n"); system("/system/bin/rm -r /data/system"); } if (stat("/data/misc", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/misc file\n"); system("/system/bin/rm -r /data/misc"); } if (stat("/data/local", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/local file\n"); system("/system/bin/rm -r /data/local"); } if (stat("/data/app-private", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/app-private file\n"); system("/system/bin/rm -r /data/app-private"); } if (stat("/data/dalvik-cache", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/dalvik-cache file\n"); system("/system/bin/rm -r /data/dalvik-cache"); } if (stat("/data/property", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/property file\n"); system("/system/bin/rm -r /data/property"); } if (stat("/data/mvg_root", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/mvg_root file\n"); system("/system/bin/rm -r /data/mvg_root"); } if (stat("/data/anr", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/anr file\n"); system("/system/bin/rm -r /data/anr"); } if (stat("/data/app", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/app file\n"); system("/system/bin/rm -r /data/app"); } if (stat("/data/nvram", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/nvram file\n"); system("/system/bin/rm -r /data/nvram"); } if (stat("/data/secure", &stbuf) < 0){ printf("stat syscall fail\n"); } if (S_ISREG(stbuf.st_mode)){ printf("delete /data/secure file\n"); system("/system/bin/rm -r /data/secure"); } } if (!strncmp(target, "/cache", 6)){ printf("delete lost-found in cache dir\n"); system("/system/bin/rm -r /cache/lost+found/*"); } } } exit_success: /* If not running encrypted, then set the property saying we are * unencrypted, and also trigger the action for a nonencrypted system. */ if (!strcmp(target, DATA_MNT_POINT)) { const char *prop; prop = property_get("ro.crypto.state"); if (! prop) { prop = "notset"; } if (strcmp(prop, "encrypted")) { property_set("ro.crypto.state", "unencrypted"); action_for_each_trigger("nonencrypted", action_add_queue_tail); } } return 0; }
int ensure_path_mounted(const char* path) { Volume* v = volume_for_path(path); if (v == NULL) { LOGE("unknown volume for path [%s]\n", path); return -1; } if (strcmp(v->fs_type, "ramdisk") == 0) { // the ramdisk is always mounted. return 0; } int result; result = scan_mounted_volumes(); if (result < 0) { LOGE("failed to scan mounted volumes\n"); return -1; } const MountedVolume* mv = find_mounted_volume_by_mount_point(v->mount_point); if (mv) { #if defined(CACHE_MERGE_SUPPORT) if (strncmp(path, "/cache", 6) == 0) { if (symlink(DATA_CACHE_ROOT, "/cache")) { if (errno != EEXIST) { LOGE("create symlink from %s to %s failed(%s)\n", DATA_CACHE_ROOT, "/cache", strerror(errno)); return -1; } } } #endif // volume is already mounted return 0; } mkdir(v->mount_point, 0755); // in case it doesn't already exist #if defined (UBIFS_SUPPORT) if (strcmp(v->fs_type, "ubifs") == 0) { printf("Trying to mount %s \n", v->mount_point); //Attatch UBI device & Make UBI volum int n = -1; n = ubi_attach_mtd_user(v->mount_point); if ((n != -1) && (n < 4)) { printf("Try to attatch %s \n", v->blk_device); printf("/dev/ubi%d_0 is attached \n", n); } else { LOGE("failed to attach %s\n", v->blk_device); } //Mount UBI volume const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME; char tmp[64]; sprintf(tmp, "/dev/ubi%d_0", n); wait_for_file(tmp, 5); result = mount(tmp, v->mount_point, v->fs_type, flags, ""); if (result < 0) { ubi_detach_dev(n); return -1; } else if (result == 0) { goto mount_done; //Volume successfully mounted } } #endif if (strcmp(v->fs_type, "yaffs2") == 0) { // mount an MTD partition as a YAFFS2 filesystem. mtd_scan_partitions(); const MtdPartition* partition; partition = mtd_find_partition_by_name(v->blk_device); if (partition == NULL) { LOGE("failed to find \"%s\" partition to mount at \"%s\"\n", v->blk_device, v->mount_point); return -1; } return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0); } else if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "squashfs") == 0 || strcmp(v->fs_type, "vfat") == 0) { mt_ensure_dev_ready(v->mount_point); result = mount(v->blk_device, v->mount_point, v->fs_type, v->flags, v->fs_options); if (result == 0) { goto mount_done; } else { result = mt_ensure_path_mounted(v); if (result == 0) goto mount_done; } LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno)); return -1; } LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, v->mount_point); return -1; mount_done: #if defined(CACHE_MERGE_SUPPORT) if (strcmp(v->mount_point, "/data") == 0) { if (mkdir(DATA_CACHE_ROOT, 0770)) { if (errno != EEXIST) { LOGE("mkdir %s error: %s\n", DATA_CACHE_ROOT, strerror(errno)); return -1; } else if (need_clear_cache) { LOGI("cache exists, clear it...\n"); if (remove_dir(DATA_CACHE_ROOT)) { LOGE("remove_dir %s error: %s\n", DATA_CACHE_ROOT, strerror(errno)); return -1; } if (mkdir(DATA_CACHE_ROOT, 0770) != 0) { LOGE("mkdir %s error: %s\n", DATA_CACHE_ROOT, strerror(errno)); return -1; } } } if (symlink(DATA_CACHE_ROOT, "/cache")) { if (errno != EEXIST) { LOGE("create symlink from %s to %s failed(%s)\n", DATA_CACHE_ROOT, "/cache", strerror(errno)); return -1; } } need_clear_cache = 0; } #endif return 0; }
int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encrypted = 0; int ret = -1; int mret; if (!fstab) { return ret; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point); } mret = mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, fstab->recs[i].fs_type, fstab->recs[i].flags, fstab->recs[i].fs_options); if (!mret) { /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encrypted and deal with it */ if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab->recs[i].blk_device)) { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", fstab->recs[i].mount_point); goto out; } encrypted = 1; } else { ERROR("Cannot mount filesystem on %s at %s\n", fstab->recs[i].blk_device, fstab->recs[i].mount_point); goto out; } } if (encrypted) { ret = 1; } else { ret = 0; } out: return ret; }
/* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one * in turn, and stop on 1st success, or no more match. */ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, char *tmp_mount_point) { int i = 0; int ret = FS_MGR_DOMNT_FAILED; int mount_errors = 0; int first_mount_errno = 0; char *m; if (!fstab) { return ret; } for (i = 0; i < fstab->num_entries; i++) { if (!fs_match(fstab->recs[i].mount_point, n_name)) { continue; } /* We found our match */ /* If this swap or a raw partition, report an error */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { ERROR("Cannot mount filesystem of type %s on %s\n", fstab->recs[i].fs_type, n_blk_device); goto out; } /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(n_blk_device, WAIT_TIMEOUT); } int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type, &fstab->recs[i]); if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) { check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point); } if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) { do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } /* Now mount it where requested */ if (tmp_mount_point) { m = tmp_mount_point; } else { m = fstab->recs[i].mount_point; } if (__mount(n_blk_device, m, &fstab->recs[i])) { if (!first_mount_errno) first_mount_errno = errno; mount_errors++; continue; } else { ret = 0; goto out; } } if (mount_errors) { ERROR("Cannot mount filesystem on %s at %s. error: %s\n", n_blk_device, m, strerror(first_mount_errno)); if (first_mount_errno == EBUSY) { ret = FS_MGR_DOMNT_BUSY; } else { ret = FS_MGR_DOMNT_FAILED; } } else { /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); } out: return ret; }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold or not for the mount mode*/ if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) || ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) || ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } /* Skip mounting the root partition, as it will already have been mounted */ if (!strcmp(fstab->recs[i].mount_point, "/")) { if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) { fs_mgr_set_blk_ro(fstab->recs[i].blk_device); } continue; } /* Translate LABEL= file system labels into block devices */ if (!strcmp(fstab->recs[i].fs_type, "ext2") || !strcmp(fstab->recs[i].fs_type, "ext3") || !strcmp(fstab->recs[i].fs_type, "ext4")) { int tret = translate_ext_labels(&fstab->recs[i]); if (tret < 0) { ERROR("Could not translate label to block device\n"); continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; int top_idx = i; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { int status = handle_encryptable(&fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { // Log and continue ERROR("Only one encryptable/encrypted partition supported\n"); } encryptable = status; } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, handle the encryptable/formattable case */ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); bool crypt_footer = false; if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { /* top_idx and attempted_idx point at the same partition, but sometimes * at two different lines in the fstab. Use the top one for formatting * as that is the preferred one. */ ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, fstab->recs[top_idx].fs_type); if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY); if (fd >= 0) { INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); wipe_block_device(fd, get_file_size(fd)); close(fd); } else { ERROR("%s(): %s wouldn't open (%s)\n", __func__, fstab->recs[top_idx].key_loc, strerror(errno)); } } else if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && !strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { crypt_footer = true; } if (fs_mgr_do_format(&fstab->recs[top_idx], crypt_footer) == 0) { /* Let's replay the mount actions. */ i = top_idx - 1; continue; } else { ERROR("%s(): Format failed. Suggest recovery...\n", __func__); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } } if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if (wiped) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) { ERROR("Ignoring failure to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; } continue; } } if (error_count) { return -1; } else { return encryptable; } }
/* This must be called after mount_all, because the mkswap command needs to be * available. */ int fs_mgr_swapon_all(struct fstab *fstab) { int i = 0; int flags = 0; int err = 0; int ret = 0; int status; char *mkswap_argv[2] = { MKSWAP_BIN, NULL }; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Skip non-swap entries */ if (strcmp(fstab->recs[i].fs_type, "swap")) { continue; } if (fstab->recs[i].zram_size > 0) { /* A zram_size was specified, so we need to configure the * device. There is no point in having multiple zram devices * on a system (all the memory comes from the same pool) so * we can assume the device number is 0. */ FILE *zram_fp; zram_fp = fopen(ZRAM_CONF_DEV, "r+"); if (zram_fp == NULL) { ERROR("Unable to open zram conf device %s\n", ZRAM_CONF_DEV); ret = -1; continue; } fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); fclose(zram_fp); } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } /* Initialize the swap area */ mkswap_argv[1] = fstab->recs[i].blk_device; err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, &status, true, LOG_KLOG, false, NULL); if (err) { ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); ret = -1; continue; } /* If -1, then no priority was specified in fstab, so don't set * SWAP_FLAG_PREFER or encode the priority */ if (fstab->recs[i].swap_prio >= 0) { flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK; flags |= SWAP_FLAG_PREFER; } else { flags = 0; } err = swapon(fstab->recs[i].blk_device, flags); if (err) { ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); ret = -1; } } return ret; }
int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) { int status = 0; try { ACE_DEBUG((LM_INFO,"(%P|%t) %T subscriber main\n")); ::DDS::DomainParticipantFactory_var dpf = TheParticipantFactoryWithArgs(argc, argv); // TheServiceParticipant->liveliness_factor(100); // let the Service_Participant (in above line) strip out -DCPSxxx parameters // and then get application specific parameters. parse_args(argc, argv); if (!topics) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) Must run with one or more of the following: -s1 -s2 -s3 -s4 -s5 -p6 -p7\n"))); return 1; } ::T1::Foo1TypeSupport_var fts1; ::T4::Foo4TypeSupport_var fts4; if (topics & (TOPIC_T1 | TOPIC_T3 | TOPIC_T4| TOPIC_T5)) { fts1 = new ::T1::Foo1TypeSupportImpl; } if (topics & TOPIC_T2) { fts4 = new ::T4::Foo4TypeSupportImpl; } ::DDS::DomainParticipant_var dp = dpf->create_participant(MY_DOMAIN, PARTICIPANT_QOS_DEFAULT, ::DDS::DomainParticipantListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(dp)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) create_participant failed.\n"))); return 1; } if (topics & (TOPIC_T1 | TOPIC_T3 | TOPIC_T4 | TOPIC_T5)) { if (::DDS::RETCODE_OK != fts1->register_type(dp, MY_TYPE1)) { ACE_ERROR((LM_ERROR, ACE_TEXT("Failed to register the Foo1TypeSupport."))); return 1; } } if (topics & TOPIC_T2) { if (::DDS::RETCODE_OK != fts4->register_type(dp, MY_TYPE4)) { ACE_ERROR((LM_ERROR, ACE_TEXT("Failed to register the Foo4TypeSupport."))); return 1; } } ::DDS::Topic_var topic1; ::DDS::Topic_var topic2; ::DDS::Topic_var topic3; ::DDS::Topic_var topic4; ::DDS::Topic_var topic5; ::DDS::Topic_var topic6; ::DDS::Topic_var topic7; if (topics & TOPIC_T1) { topic1 = dp->create_topic(MY_TOPIC1, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic1)) { return 1; } } if (topics & TOPIC_T2) { topic2 = dp->create_topic(MY_TOPIC2, MY_TYPE4, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic2)) { return 1; } } if (topics & TOPIC_T3) { topic3 = dp->create_topic(MY_TOPIC3, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic3)) { return 1; } } if (topics & TOPIC_T4) { topic4 = dp->create_topic(MY_TOPIC4, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic4)) { return 1; } } if (topics & TOPIC_T5) { topic5 = dp->create_topic(MY_TOPIC5, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic5)) { return 1; } } if (publish_topics & TOPIC_T6) { topic6 = dp->create_topic(MY_TOPIC6, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic6)) { return 1; } } if (publish_topics & TOPIC_T7) { topic7 = dp->create_topic(MY_TOPIC7, MY_TYPE1, TOPIC_QOS_DEFAULT, ::DDS::TopicListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(topic7)) { return 1; } } //////////////////////////////////////////////////////////////////////////// // Create the publisher and datawriter //////////////////////////////////////////////////////////////////////////// ::DDS::Publisher_var pub = dp->create_publisher(PUBLISHER_QOS_DEFAULT, ::DDS::PublisherListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(pub)) { ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) create_publisher failed.\n")), 1); } ::DDS::DataWriterQos dw_qos; pub->get_default_datawriter_qos(dw_qos); dw_qos.resource_limits.max_samples_per_instance = max_samples_per_instance; dw_qos.liveliness.lease_duration.sec = LEASE_DURATION_SEC; dw_qos.liveliness.lease_duration.nanosec = 0; int num_writers(0); ::DDS::DataWriter_var dw1; ::DDS::DataWriter_var dw2; if (publish_topics & TOPIC_T6) { dw1 = pub->create_datawriter(topic6, dw_qos, ::DDS::DataWriterListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(dw1)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) create_datawriter failed.\n"))); return 1; } ++num_writers; } if (publish_topics & TOPIC_T7) { dw2 = pub->create_datawriter(topic7, dw_qos, ::DDS::DataWriterListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(dw2)) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) create_datawriter failed.\n"))); return 1; } ++num_writers; } Writer** writers = new Writer*[num_writers]; int idx(0); if (publish_topics & TOPIC_T6) { writers[idx++] = new Writer(dw1, 1, num_ops_per_thread); } if (publish_topics & TOPIC_T7) { writers[idx++] = new Writer(dw2, 1, num_ops_per_thread); } for (int i = 0; i < num_writers; ++i) { writers[i]->start(); } //////////////////////////////////////////////////////////////////////////// // Create the subscriber //////////////////////////////////////////////////////////////////////////// ::DDS::Subscriber_var sub = dp->create_subscriber(SUBSCRIBER_QOS_DEFAULT, ::DDS::SubscriberListener::_nil(), ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); if (CORBA::is_nil(sub)) { ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) create_subscriber failed.\n")), 1); } // Create the Datareaders ::DDS::DataReaderQos dr_qos; sub->get_default_datareader_qos(dr_qos); dr_qos.resource_limits.max_samples_per_instance = max_samples_per_instance; dr_qos.liveliness.lease_duration.sec = LEASE_DURATION_SEC; dr_qos.liveliness.lease_duration.nanosec = 0; dr_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; ::DDS::DataReader_var dr1; ::DDS::DataReader_var dr2_1; ::DDS::DataReader_var dr2_2; ::DDS::DataReader_var dr2_3; ::DDS::DataReader_var dr3; ::DDS::DataReader_var dr4; ::DDS::DataReader_var dr5; ::DDS::DataReaderListener_var drl1 = new DataReaderListenerImpl1(num_ops_per_thread); ::DDS::DataReaderListener_var drl2_1 = new DataReaderListenerImpl4(num_ops_per_thread); ::DDS::DataReaderListener_var drl2_2 = new DataReaderListenerImpl4(num_ops_per_thread); ::DDS::DataReaderListener_var drl2_3 = new DataReaderListenerImpl4(num_ops_per_thread); ::DDS::DataReaderListener_var drl3 = new DataReaderListenerImpl1(num_ops_per_thread); ::DDS::DataReaderListener_var drl4 = new DataReaderListenerImpl1(num_ops_per_thread); ::DDS::DataReaderListener_var drl5 = new DataReaderListenerImpl1(num_ops_per_thread); if (topics & TOPIC_T1) { dr1 = sub->create_datareader(topic1, dr_qos, drl1, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); } if (topics & TOPIC_T2) { dr2_1 = sub->create_datareader(topic2, dr_qos, drl2_1, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); dr2_2 = sub->create_datareader(topic2, dr_qos, drl2_2, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); dr2_3 = sub->create_datareader(topic2, dr_qos, drl2_3, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); } if (topics & TOPIC_T3) { dr3 = sub->create_datareader(topic3, dr_qos, drl3, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); } if (topics & TOPIC_T4) { dr4 = sub->create_datareader(topic4, dr_qos, drl4, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); } if (topics & TOPIC_T5) { dr5 = sub->create_datareader(topic5, dr_qos, drl5, ::OpenDDS::DCPS::DEFAULT_STATUS_MASK); } if (topics & TOPIC_T1) { const DataReaderListenerImpl* const drl_servant = dynamic_cast<const DataReaderListenerImpl*>(drl1.in()); if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC1))) status = 1; } if (topics & TOPIC_T2) { const DataReaderListenerImpl* const drl2_1srv = dynamic_cast<const DataReaderListenerImpl*>(drl2_1.in()); if (!check_listener(drl2_1srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2))) status = 1; const DataReaderListenerImpl* const drl2_2srv = dynamic_cast<const DataReaderListenerImpl*>(drl2_2.in()); if (!check_listener(drl2_2srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2))) status = 1; const DataReaderListenerImpl* const drl2_3srv = dynamic_cast<const DataReaderListenerImpl*>(drl2_3.in()); if (!check_listener(drl2_3srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2))) status = 1; } if (topics & TOPIC_T3) { const DataReaderListenerImpl* const drl_servant = dynamic_cast<const DataReaderListenerImpl*>(drl3.in()); if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC3))) status = 1; } if (topics & TOPIC_T4) { const DataReaderListenerImpl* const drl_servant = dynamic_cast<const DataReaderListenerImpl*>(drl4.in()); if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC4))) status = 1; } if (topics & TOPIC_T5) { const DataReaderListenerImpl* const drl_servant = dynamic_cast<const DataReaderListenerImpl*>(drl5.in()); if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC5))) status = 1; } if (topics & TOPIC_T1) { wait_for_file(ACE_TEXT(MY_TOPIC1), pub_finished_filename); } if (topics & TOPIC_T2) { wait_for_file(ACE_TEXT(MY_TOPIC2), pub_finished_filename); } if (topics & TOPIC_T3) { wait_for_file(ACE_TEXT(MY_TOPIC3), pub_finished_filename); } if (topics & TOPIC_T4) { wait_for_file(ACE_TEXT(MY_TOPIC4), pub_finished_filename); } if (topics & TOPIC_T5) { wait_for_file(ACE_TEXT(MY_TOPIC5), pub_finished_filename); } if (publish_topics) { bool writers_finished = false; while (!writers_finished && num_writers) { writers_finished = true; for (int m = 0; m < num_writers; m++) { writers_finished = writers_finished && writers[m]->is_finished(); } if (!writers_finished) ACE_OS::sleep(small_time); } } if (publish_topics & TOPIC_T6) { ACE_TString t6_filename = ACE_TEXT(MY_TOPIC6) + pub_finished_filename; FILE* writers_completed = ACE_OS::fopen(t6_filename.c_str(), ACE_TEXT("w")); if (writers_completed == 0) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Unable to create publisher ") ACE_TEXT("completed file\n"))); status = 1; } else { ACE_OS::fclose(writers_completed); } } if (publish_topics & TOPIC_T7) { ACE_TString t7_filename = ACE_TEXT(MY_TOPIC7) + pub_finished_filename; FILE* writers_completed = ACE_OS::fopen(t7_filename.c_str(), ACE_TEXT("w")); if (writers_completed == 0) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: Unable to create publisher ") ACE_TEXT("completed file\n"))); status = 1; } else { ACE_OS::fclose(writers_completed); } } ACE_DEBUG((LM_DEBUG, "(%P|%t) delete contained entities on pub\n")); pub->delete_contained_entities(); for (int n = 0; n < num_writers; ++n) { delete writers[n]; } delete [] writers; dp->delete_contained_entities(); dpf->delete_participant(dp); TheServiceParticipant->shutdown(); } catch (const TestException&) { ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) TestException caught in main.cpp.\n"))); return 1; } catch (const CORBA::Exception& ex) { ex._tao_print_exception ("Exception caught in main.cpp:"); return 1; } return status; }
/* returns size of the file in bytes if OK, otherwise a negative error */ static long long get_cached_file (const char * user_id, const char * url, const char * file_id, const char * instance_id, const char * file_name, char * file_path, sem * s, int convert_to_disk, long long limit_mb) { char tmp_digest_path [BUFSIZE]; char cached_dir [BUFSIZE]; char cached_path [BUFSIZE]; char staging_path [BUFSIZE]; char digest_path [BUFSIZE]; snprintf (file_path, BUFSIZE, "%s/%s/%s/%s", sc_instance_path, user_id, instance_id, file_name); snprintf (tmp_digest_path, BUFSIZE, "%s-digest", file_path); snprintf (cached_dir, BUFSIZE, "%s/%s/cache/%s", sc_instance_path, EUCALYPTUS_ADMIN, file_id); /* cache is in admin's directory */ snprintf (cached_path, BUFSIZE, "%s/%s", cached_dir, file_name); snprintf (staging_path, BUFSIZE, "%s-staging", cached_path); snprintf (digest_path, BUFSIZE, "%s-digest", cached_path); retry: /* under a lock, figure out the state of the file */ sem_p (sc_sem); /***** acquire lock *****/ ensure_subdirectory_exists (file_path); /* creates missing directories */ struct stat mystat; int cached_exists = ! stat (cached_path, &mystat); int staging_exists = ! stat (staging_path, &mystat); int e = ERROR; int action; enum { ABORT, VERIFY, WAIT, STAGE }; if ( staging_exists ) { action = WAIT; } else { if ( cached_exists ) { action = VERIFY; } else { action = STAGE; } } /* we return the sum of these */ long long file_size_b = 0; long long digest_size_b = 0; /* while still under lock, decide whether to cache */ int should_cache = 0; if (action==STAGE) { e = walrus_object_by_url (url, tmp_digest_path, 0); /* get the digest to see how big the file is */ if (e==OK && stat (tmp_digest_path, &mystat)) { digest_size_b = (long long)mystat.st_size; } if (e==OK) { /* pull the size out of the digest */ char * xml_file = file2str (tmp_digest_path); if (xml_file) { file_size_b = str2longlong (xml_file, "<size>", "</size>"); free (xml_file); } if (file_size_b > 0) { long long full_size_b = file_size_b+digest_size_b; if (convert_to_disk) { full_size_b += swap_size_mb*MEGABYTE + MEGABYTE; /* TODO: take into account extra padding required for disks (over partitions) */ } if ( full_size_b/MEGABYTE + 1 > limit_mb ) { logprintfl (EUCAFATAL, "error: insufficient disk capacity remaining (%lldMB) in VM Type of instance %s for component %s\n", limit_mb, instance_id, file_name); action = ABORT; } else if ( ok_to_cache (cached_path, full_size_b) ) { /* will invalidate the cache, if needed */ ensure_path_exists (cached_dir); /* creates missing directories */ should_cache = 1; if ( touch (staging_path) ) { /* indicate that we'll be caching it */ logprintfl (EUCAERROR, "error: failed to create staging file %s\n", staging_path); action = ABORT; } } } else { logprintfl (EUCAERROR, "error: failed to obtain file size from digest %s\n", url); action = ABORT; } } else { logprintfl (EUCAERROR, "error: failed to obtain digest from %s\n", url); action = ABORT; } } sem_v (sc_sem); /***** release lock *****/ switch (action) { case STAGE: logprintfl (EUCAINFO, "downloding image into %s...\n", file_path); e = walrus_image_by_manifest_url (url, file_path, 1); /* for KVM, convert partition into disk */ if (e==OK && convert_to_disk) { sem_p (s); /* for the cached disk swap==0 and ephemeral==0 as we'll append them below */ if ((e=vrun("%s %s %d %d", disk_convert_command_path, file_path, 0, 0))!=0) { logprintfl (EUCAERROR, "error: partition-to-disk image conversion command failed\n"); } sem_v (s); /* recalculate file size now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } /* cache the partition or disk, if possible */ if ( e==OK && should_cache ) { if ( (e=vrun ("cp -a %s %s", file_path, cached_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s into cache at %s\n", file_path, cached_path); } if ( e==OK && (e=vrun ("cp -a %s %s", tmp_digest_path, digest_path)) != 0) { logprintfl (EUCAERROR, "failed to copy digest file %s into cache at %s\n", tmp_digest_path, digest_path); } } sem_p (sc_sem); if (should_cache) { unlink (staging_path); } if ( e ) { logprintfl (EUCAERROR, "error: failed to download file from Walrus into %s\n", file_path); unlink (file_path); unlink (tmp_digest_path); if (should_cache) { unlink (cached_path); unlink (digest_path); if ( rmdir(cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } } } sem_v (sc_sem); break; case WAIT: logprintfl (EUCAINFO, "waiting for disapperance of %s...\n", staging_path); /* wait for staging_path to disappear, which means both either the * download succeeded or it failed */ if ( (e=wait_for_file (NULL, staging_path, 180, "cached image")) ) return 0L; /* yes, it is OK to fall through */ case VERIFY: logprintfl (EUCAINFO, "verifying cached file in %s...\n", cached_path); sem_p (sc_sem); /***** acquire lock *****/ e = ERROR; if ( stat (cached_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", cached_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", cached_path); } else if ((e=walrus_verify_digest (url, digest_path))<0) { /* negative status => digest changed */ unlink (cached_path); unlink (staging_path); /* TODO: needed? */ unlink (digest_path); if ( rmdir (cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } else { logprintfl (EUCAINFO, "due to failure, removed cache directory %s\n", cached_dir); } } else { file_size_b = mystat.st_size; /* touch the digest so cache can use mtime for invalidation */ if ( touch (digest_path) ) { logprintfl (EUCAERROR, "error: failed to touch digest file %s\n", digest_path); } else if ( stat (digest_path, &mystat) ) { logprintfl (EUCAERROR, "error: digest file %s not found\n", digest_path); } else { digest_size_b = (long long)mystat.st_size; } } sem_v (sc_sem); /***** release lock *****/ if (e<0) { /* digest changed */ if (action==VERIFY) { /* i.e. we did not download/waited for this file */ /* try downloading anew */ goto retry; } else { logprintfl (EUCAERROR, "error: digest mismatch, giving up\n"); return 0L; } } else if (e>0) { /* problem with file or digest */ return 0L; } else { /* all good - copy it, finally */ ensure_subdirectory_exists (file_path); /* creates missing directories */ if ( (e=vrun ("cp -a %s %s", cached_path, file_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s from cache at %s\n", file_path, cached_path); return 0L; } } break; case ABORT: logprintfl (EUCAERROR, "get_cached_file() failed (errno=%d)\n", e); e = ERROR; } if (e==OK && file_size_b > 0 && convert_to_disk ) { // if all went well above long long ephemeral_mb = limit_mb - swap_size_mb - (file_size_b+digest_size_b)/MEGABYTE; if ( swap_size_mb>0L || ephemeral_mb>0L ) { sem_p (s); if ((e=vrun("%s %s %lld %lld", disk_convert_command_path, file_path, swap_size_mb, ephemeral_mb))!=0) { logprintfl (EUCAERROR, "error: failed to add swap or ephemeral to the disk image\n"); } sem_v (s); /* recalculate file size (again!) now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } } if (e==OK && action!=ABORT) return file_size_b + digest_size_b; return 0L; }
static void mount_and_run(struct fstab *fstab) { struct fstab_part *p = fstab_find_by_path(fstab, "/data"); if(!p) { ERROR("Failed to find /data partition in fstab\n"); return; } if(wait_for_file(p->device, 5) < 0) { ERROR("Waiting too long for dev %s", p->device); return; } // Remove nosuid flag, because secondary ROMs have // su binaries on /data p->mountflags &= ~(MS_NOSUID); mkdir(REALDATA, 0755); if (mount(p->device, REALDATA, p->type, p->mountflags, p->options) < 0) { ERROR("Failed to mount /realdata, err %d, trying all filesystems\n", errno); const char *fs_types[] = { "ext4", "f2fs", "ext3", "ext2" }; const char *fs_opts [] = { "barrier=1,data=ordered,nomblk_io_submit,noauto_da_alloc,errors=panic", // ext4 "inline_xattr,flush_merge,errors=recover", // f2fs "", // ext3 "" // ext2 }; int mounted = 0; size_t i; for(i = 0; i < ARRAY_SIZE(fs_types); ++i) { ERROR("Trying to mount %s with fs %s\n", p->device, fs_types[i]); if(mount(p->device, REALDATA, fs_types[i], p->mountflags, fs_opts[i]) >= 0) { ERROR("/realdata successfuly mounted with fs %s\n", fs_types[i]); mounted = 1; break; } } if(!mounted) { ERROR("Failed to mount /realdata with all possible filesystems!"); return; } } if(find_multirom() == -1) { ERROR("Could not find multirom folder!"); return; } adb_init(path_multirom); run_multirom(); adb_quit(); }
/* mount <type> <device> <path> <flags ...> <options> */ int do_mount(int nargs, char **args) { char tmp[64]; char *source, *target, *system; char *options = NULL; unsigned flags = 0; int n, i; int wait = 0; for (n = 4; n < nargs; n++) { for (i = 0; mount_flags[i].name; i++) { if (!strcmp(args[n], mount_flags[i].name)) { flags |= mount_flags[i].flag; break; } } if (!mount_flags[i].name) { if (!strcmp(args[n], "wait")) wait = 1; /* if our last argument isn't a flag, wolf it up as an option string */ else if (n + 1 == nargs) options = args[n]; } } system = args[1]; source = args[2]; target = args[3]; if (!strncmp(source, "mtd@", 4)) { n = mtd_name_to_number(source + 4); if (n < 0) { return -1; } sprintf(tmp, "/dev/block/mtdblock%d", n); if (wait) wait_for_file(tmp, COMMAND_RETRY_TIMEOUT); if (mount(tmp, target, system, flags, options) < 0) { return -1; } goto exit_success; } else if (!strncmp(source, "loop@", 5)) { int mode, loop, fd; struct loop_info info; mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; fd = open(source + 5, mode); if (fd < 0) { return -1; } for (n = 0; ; n++) { sprintf(tmp, "/dev/block/loop%d", n); loop = open(tmp, mode); if (loop < 0) { return -1; } /* if it is a blank loop device */ if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { /* if it becomes our loop device */ if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { close(fd); if (mount(tmp, target, system, flags, options) < 0) { ioctl(loop, LOOP_CLR_FD, 0); close(loop); return -1; } close(loop); goto exit_success; } } close(loop); } close(fd); ERROR("out of loopback devices"); return -1; } else { if (wait) wait_for_file(source, COMMAND_RETRY_TIMEOUT); if (mount(source, target, system, flags, options) < 0) { return -1; } } exit_success: return 0; }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; int top_idx = i; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT) || (device_is_force_encrypted() && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) { if (umount(fstab->recs[attempted_idx].mount_point) == 0) { if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; } else { ERROR("Only one encryptable/encrypted partition supported\n"); encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } } else { INFO("Could not umount %s - allow continue unencrypted\n", fstab->recs[attempted_idx].mount_point); continue; } } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, handle the encryptable/formattable case */ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { /* top_idx and attempted_idx point at the same partition, but sometimes * at two different lines in the fstab. Use the top one for formatting * as that is the preferred one. */ ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, fstab->recs[top_idx].fs_type); if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644); if (fd >= 0) { INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); wipe_block_device(fd, get_file_size(fd)); close(fd); } else { ERROR("%s(): %s wouldn't open (%s)\n", __func__, fstab->recs[top_idx].key_loc, strerror(errno)); } } if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) { /* Let's replay the mount actions. */ i = top_idx - 1; continue; } } if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if (wiped) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }
int main(int argc, const char * argv[]) { // insert code here... //std::cout << "Hello, World!\n"; Palette c64palette(c64_colors, num_64_colors); Ditherer* ditherer = Ditherer::createC64Ditherer(); const char* dirname = argv[1]; const char* outdirname = argv[2]; const char* out64fname = argv[3]; int index = 0; char thisfname[256]; char nextfname[256]; char outfname[256]; unsigned char* c64frame = NULL; FILE* fp = fopen(out64fname, "wb"); NetPort port(192,168,1,25,99998,99999); Tools::Timer frameTimer; frameTimer.start(); for (index = 1; index < 9999; index++) { // check if file can be opened sprintf(thisfname, "%s/%04d.ppm", dirname, index); sprintf(nextfname, "%s/%04d.ppm", dirname, index+1); wait_for_file(nextfname); printf("%s\n", thisfname); // open image Image inputImage(thisfname); int imWidth = inputImage.getWidth(); int imHeight = inputImage.getHeight(); Image halfImage(inputImage, imWidth/2, imHeight); Image* dithered = ditherer->createDitheredImageFromImageWithPalette(halfImage, c64palette); C64Image* c64im = (C64Image*)dithered; /* // test - output to new ppm sprintf(outfname, "%s/%04d.ppm", outdirname, index); Image fullImage(*dithered, imWidth, imHeight); fullImage.writePPM(outfname); */ int c64FrameSize = c64im->getC64FrameSize(); if (!c64frame) { c64frame = (unsigned char*)malloc(sizeof(unsigned char) * c64FrameSize); } float time = (float)index / 8.0; c64im->getC64Frame(c64frame, time); fwrite(c64frame, 1, c64FrameSize, fp); float thisTime = frameTimer.getTime(); printf("pts %f, time %f\n", time, thisTime); while (thisTime < time) { float diff = time - thisTime; float usec = diff * 1000000.0; usleep(usec); thisTime = frameTimer.getTime(); } // send bytes to port port.send(&c64frame[4], 9216); delete dithered; } fclose(fp); return 0; }
int main(int argc, char *argv[]) { int i, res; static char *const cmd[] = { "/init", NULL }; struct fstab *fstab = NULL; char *inject_path = NULL; char *mrom_dir = NULL; int force_inject = 0; for(i = 1; i < argc; ++i) { if(strcmp(argv[i], "-v") == 0) { printf("%d\n", VERSION_TRAMPOLINE); fflush(stdout); return 0; } else if(strstartswith(argv[i], "--inject=")) inject_path = argv[i] + strlen("--inject="); else if(strstartswith(argv[i], "--mrom_dir=")) mrom_dir = argv[i] + strlen("--mrom_dir="); else if(strcmp(argv[i], "-f") == 0) force_inject = 1; } if(inject_path) { if(!mrom_dir) { printf("--mrom_dir=[path to multirom's data dir] needs to be specified!\n"); fflush(stdout); return 1; } mrom_set_dir(mrom_dir); mrom_set_log_tag("trampoline_inject"); return inject_bootimg(inject_path, force_inject); } umask(000); // Init only the little we need, leave the rest for real init mkdir("/dev", 0755); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); mount("pstore", "/sys/fs/pstore", "pstore", 0, NULL); #if MR_USE_DEBUGFS_MOUNT // Mount the debugfs kernel sysfs mkdir("/sys/kernel/debug", 0755); mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL); #endif klog_init(); // output all messages to dmesg, // but it is possible to filter out INFO messages klog_set_level(6); mrom_set_log_tag("trampoline"); INFO("Running trampoline v%d\n", VERSION_TRAMPOLINE); if(is_charger_mode()) { INFO("Charger mode detected, skipping multirom\n"); goto run_main_init; } #if MR_DEVICE_HOOKS >= 3 tramp_hook_before_device_init(); #endif INFO("Initializing devices...\n"); devices_init(); INFO("Done initializing\n"); if(wait_for_file("/dev/graphics/fb0", 5) < 0) { ERROR("Waiting too long for fb0"); goto exit; } #ifdef MR_POPULATE_BY_NAME_PATH //nkk71 M7 hack Populate_ByName_using_emmc(); #endif fstab = fstab_auto_load(); if(!fstab) goto exit; #if 0 fstab_dump(fstab); //debug #endif // mount and run multirom from sdcard if(mount_and_run(fstab) < 0 && mrom_is_second_boot()) { ERROR("This is second boot and we couldn't mount /data, reboot!\n"); sync(); android_reboot(ANDROID_RB_RESTART, 0, 0); while(1) sleep(1); } exit: if(fstab) fstab_destroy(fstab); // close and destroy everything devices_close(); run_main_init: umount("/dev/pts"); rmdir("/dev/pts"); rmdir("/dev/socket"); if(access(KEEP_REALDATA, F_OK) < 0) { umount(REALDATA); umount("/dev"); rmdir(REALDATA); encryption_destroy(); } encryption_cleanup(); #if MR_USE_DEBUGFS_MOUNT umount("/sys/kernel/debug"); #endif umount("/proc"); umount("/sys/fs/pstore"); umount("/sys"); INFO("Running main_init\n"); fixup_symlinks(); chmod("/main_init", EXEC_MASK); rename("/main_init", "/init"); res = execve(cmd[0], cmd, NULL); ERROR("execve returned %d %d %s\n", res, errno, strerror(errno)); return 0; }