int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) { int fd; const char *args[11]; int rc; int status; if (wipe) { Fat::wipe(fsPath, numSectors); } args[0] = MKDOSFS_PATH; args[1] = "-F"; args[2] = "32"; args[3] = "-O"; args[4] = "android"; args[5] = "-c"; args[6] = "64"; args[7] = "-A"; if (numSectors) { char tmp[32]; snprintf(tmp, sizeof(tmp), "%u", numSectors); const char *size = tmp; args[8] = "-s"; args[9] = size; args[10] = fsPath; rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); } else { args[8] = fsPath; rc = android_fork_execvp(9, (char **)args, &status, false, true); } if (rc != 0) { SLOGE("Filesystem format failed due to logwrap error"); errno = EIO; return -1; } if (!WIFEXITED(status)) { SLOGE("Filesystem format did not exit properly"); errno = EIO; return -1; } status = WEXITSTATUS(status); if (status == 0) { SLOGI("Filesystem formatted OK"); return 0; } else { SLOGE("Format failed (unknown exit code %d)", status); errno = EIO; return -1; } return 0; }
int Exfat::format(const char *fsPath) { int fd; const char *args[3]; int rc = -1; int status; if (access(EXFAT_MKFS, X_OK)) { SLOGE("Unable to format, mkexfatfs not found."); return -1; } args[0] = EXFAT_MKFS; args[1] = fsPath; args[2] = NULL; rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); if (rc == 0) { SLOGI("Filesystem (exFAT) formatted OK"); return 0; } else { SLOGE("Format (exFAT) failed (unknown exit code %d)", rc); errno = EIO; return -1; } return 0; }
bool handle_command_flash_boot_partition(Socket *client, const char *file, const char *devname) { const char *mountpoint = "/data/misc/fastbootd/mnt"; send_reply(client, "INFO", "format boot partition ..."); { const char *argv[] = { "/system/bin/newfs_msdos", "-F", "32", "-L", "boot", "-b", "512", "-A", devname, }; int status; android_fork_execvp(sizeof(argv) / sizeof(argv[0]), (char **)argv, &status, true, true); } send_reply(client, "INFO", "mount boot partition ..."); { int rc = mount(devname, mountpoint, "vfat", MS_NODEV | MS_NOSUID | MS_DIRSYNC, "utf8,uid=0,gid=0,shortname=mixed"); if (rc != 0) { send_reply(client, "FAIL", "failed to mount boot partition"); return false; } } send_reply(client, "INFO", "extract files to boot partition ..."); { const char *argv[] = { "/system/bin/tar", "-C", mountpoint, "-xvf", file, }; int status; android_fork_execvp(sizeof(argv) / sizeof(argv[0]), (char **)argv, &status, true, true); } send_reply(client, "INFO", "umount boot partition ..."); umount(mountpoint); sync(); return send_reply(client, "OKAY", ""); }
int BandwidthController::runIptablesCmd(const char *cmd, IptJumpOp jumpHandling, IptIpVer iptVer, IptFailureLog failureHandling) { char buffer[MAX_CMD_LEN]; const char *argv[MAX_CMD_ARGS]; int argc = 0; char *next = buffer; char *tmp; int res; int status = 0; std::string fullCmd = cmd; switch (jumpHandling) { case IptJumpReject: /* * Must be carefull what one rejects with, as uper layer protocols will just * keep on hammering the device until the number of retries are done. * For port-unreachable (default), TCP should consider as an abort (RFC1122). */ fullCmd += " --jump REJECT"; break; case IptJumpReturn: fullCmd += " --jump RETURN"; break; case IptJumpNoAdd: break; } fullCmd.insert(0, " -w "); fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH); if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) { ALOGE("iptables command too long"); return -1; } argc = 0; while ((tmp = strsep(&next, " "))) { argv[argc++] = tmp; if (argc >= MAX_CMD_ARGS) { ALOGE("iptables argument overflow"); return -1; } } argv[argc] = NULL; res = android_fork_execvp(argc, (char **)argv, &status, false, failureHandling == IptFailShow); res = res || !WIFEXITED(status) || WEXITSTATUS(status); if (res && failureHandling == IptFailShow) { ALOGE("runIptablesCmd(): res=%d status=%d failed %s", res, status, fullCmd.c_str()); } return res; }
int Exfat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask) { int rc = -1; char mountData[255]; const char *args[6]; int status; if (access(EXFAT_MOUNT, X_OK)) { SLOGE("Unable to mount, exFAT FUSE helper not found!"); return rc; } sprintf(mountData, "noatime,nodev,nosuid,dirsync,uid=%d,gid=%d,fmask=%o,dmask=%o,%s,%s", ownerUid, ownerGid, permMask, permMask, (executable ? "exec" : "noexec"), (ro ? "ro" : "rw")); args[0] = EXFAT_MOUNT; args[1] = "-o"; args[2] = mountData; args[3] = fsPath; args[4] = mountPoint; args[5] = NULL; SLOGW("Executing exFAT mount (%s) -> (%s)", fsPath, mountPoint); rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); if (rc && errno == EROFS) { SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); strcat(mountData, ",ro"); rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); } return rc; }
void start_modem(){ int fd; const char *args[3]; int rc; int status; SLOGD("Just use muxreport to start modem\n"); args[0] = "/system/bin/muxreport"; args[1] = "4"; rc = android_fork_execvp(2, (char **)args, &status, false, true); if (rc != 0) { SLOGE("start md1 failed due to logwrap error"); } args[1] = "8"; rc = android_fork_execvp(2, (char **)args, &status, false, true); if (rc != 0) { SLOGE("start md2 failed due to logwrap error"); } }
static int execIptablesCommand(int argc, const char *argv[], bool silent) { int res; int status; res = android_fork_execvp(argc, (char **)argv, &status, false, !silent); if (res || !WIFEXITED(status) || WEXITSTATUS(status)) { if (!silent) { logExecError(argv, res, status); } if (res) return res; if (!WIFEXITED(status)) return ECHILD; } return WEXITSTATUS(status); }
int Exfat::check(const char *fsPath) { int rc = -1; int status; if (access(EXFAT_FSCK, X_OK)) { SLOGW("Skipping fs checks, exfatfsck not found.\n"); return 0; } do { const char *args[3]; args[0] = EXFAT_FSCK; args[1] = fsPath; args[2] = NULL; rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); switch(rc) { case 0: SLOGI("exFAT filesystem check completed OK.\n"); return 0; case 1: SLOGI("exFAT filesystem check completed, errors corrected OK.\n"); return 0; case 2: SLOGE("exFAT filesystem check completed, errors corrected, need reboot.\n"); return 0; case 4: SLOGE("exFAT filesystem errors left uncorrected.\n"); return 0; case 8: SLOGE("exfatfsck operational error.\n"); errno = EIO; return -1; default: SLOGE("exFAT filesystem check failed (unknown exit code %d).\n", rc); errno = EIO; return -1; } } while (0); return 0; }
int NatController::runCmd(int argc, const char **argv) { int res; res = android_fork_execvp(argc, (char **)argv, NULL, false, false); #if !LOG_NDEBUG std::string full_cmd = argv[0]; argc--; argv++; /* * HACK: Sometimes runCmd() is called with a ridcously large value (32) * and it works because the argv[] contains a NULL after the last * true argv. So here we use the NULL argv[] to terminate when the argc * is horribly wrong, and argc for the normal cases. */ for (; argc && argv[0]; argc--, argv++) { full_cmd += " "; full_cmd += argv[0]; } ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res); #endif return res; }
int Fat::check(const char *fsPath) { bool rw = true; if (access(FSCK_MSDOS_PATH, X_OK)) { SLOGW("Skipping fs checks\n"); return 0; } int pass = 1; int rc = 0; do { const char *args[4]; int status; args[0] = FSCK_MSDOS_PATH; args[1] = "-p"; args[2] = "-f"; args[3] = fsPath; rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); if (rc != 0) { SLOGE("Filesystem check failed due to logwrap error"); errno = EIO; return -1; } if (!WIFEXITED(status)) { SLOGE("Filesystem check did not exit properly"); errno = EIO; return -1; } status = WEXITSTATUS(status); switch(status) { case 0: SLOGI("Filesystem check completed OK"); return 0; case 2: SLOGE("Filesystem check failed (not a FAT filesystem)"); errno = ENODATA; return -1; case 4: if (pass++ <= 3) { SLOGW("Filesystem modified - rechecking (pass %d)", pass); continue; } SLOGE("Failing check after too many rechecks"); errno = EIO; return -1; default: SLOGE("Filesystem check failed (unknown exit code %d)", status); errno = EIO; return -1; } } while (0); return 0; }
int SecondaryTableController::runCmd(int argc, const char **argv) { int ret = 0; ret = android_fork_execvp(argc, (char **)argv, NULL, false, false); return ret; }
int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe, bool forceFat32) { int fd; const char *args[11]; int rc; int status; int curArg = 0; #ifndef MTK_FORMAT_NOT_PARAM unsigned int bps; unsigned int bsize; #endif if (wipe) { Fat::wipe(fsPath, numSectors); } if (forceFat32){ SLOGI("%s: force to fat32! \n", __FUNCTION__); } args[curArg++] = MKDOSFS_PATH; if (forceFat32){ args[curArg++] = "-F"; args[curArg++] = "32"; } else { #ifndef MTK_FORMAT_NOT_PARAM args[curArg++] = "-F"; if (-1 == (fd = open(fsPath, O_RDONLY, 0644)) ) { SLOGE("failed to open %s\n", fsPath); errno = EIO; return -1; } if (ioctl(fd, BLKSSZGET, &bps)) { bps = 0; SLOGE("failed to get %s bytes/sector\n", fsPath); } if (ioctl(fd, BLKGETSIZE, &bsize)) { bsize = 0; SLOGE("failed to get %s device size\n", fsPath); } close(fd); SLOGD("total cluster is %llu", ( (unsigned long long)bsize * 512) / (bps * 8)); if (!numSectors && bps && bsize) { if ( (((unsigned long long)bsize * 512) / (bps * 8)) > 65536 ) args[curArg++] = "32"; else args[curArg++] = "16"; } else { args[curArg++] = "32"; } #endif } args[curArg++] = "-O"; args[curArg++] = "android"; #ifndef MTK_FORMAT_NOT_PARAM args[curArg++] = "-c"; args[curArg++] = "64"; args[curArg++] = "-A"; #endif if (numSectors) { char tmp[32]; snprintf(tmp, sizeof(tmp), "%u", numSectors); const char *size = tmp; args[curArg++] = "-s"; args[curArg++] = size; args[curArg++] = fsPath; } else { args[curArg++] = fsPath; } SLOGD("Arg num=%d", curArg); for(int i = 0; i<curArg; i++) { SLOGD("%s", args[i]); } rc = android_fork_execvp(curArg, (char **)args, &status, false, true); if (rc != 0) { SLOGE("Filesystem format failed due to logwrap error"); errno = EIO; return -1; } if (!WIFEXITED(status)) { SLOGE("Filesystem format did not exit properly"); errno = EIO; return -1; } status = WEXITSTATUS(status); if (status == 0) { sync(); SLOGI("Filesystem formatted OK"); return 0; } else { SLOGE("Format failed (unknown exit code %d)", status); errno = EIO; return -1; } return 0; }
int Fat::check(const char *fsPath) { bool rw = true; if (access(FSCK_MSDOS_PATH, X_OK)) { SLOGW("Skipping fs checks\n"); return 0; } #ifdef FSCK_MSDOS_MTK SLOGI("-- MTK_FSCK_MSDOS_MTK enabled--"); int fsck_enhanced = 0 ; // 0 : original ver(fsck_msdos), 1 : enhanced ver(fsck_msdos_mtk) if (access(FSCK_MSDOS_MTK_PATH, X_OK)) { SLOGW("Because %s does not exist, we just use fsck_msdos (original ver.)", FSCK_MSDOS_MTK_PATH) ; fsck_enhanced = 0 ; } else { SLOGI("vold:fat:check fs = %s\n", fsPath) ; int fd = open(fsPath, O_RDONLY); if(fd < 0) { SLOGW("Because cannot read dev, we just use fsck_msdos (original ver.)") ; fsck_enhanced = 0 ; } else { struct bootblock boot ; if(readboot(fd, &boot) == 0) { if(boot.ClustMask == 0xfff) { SLOGW("Because fsck_msdos_mtk only supports FAT32, but this is FAT12!") ; SLOGW("We still use fsck_msdos for FAT12!") ; fsck_enhanced = 0 ; } else if(boot.ClustMask == 0xffff) { SLOGW("Because fsck_msdos_mtk only supports FAT32, but this is FAT16!") ; SLOGW("We still use fsck_msdos for FAT16!") ; fsck_enhanced = 0 ; } else { SLOGW("We always use fsck_msdos_mtk for FAT32 now!") ; fsck_enhanced = 1 ; } /*if(boot.NumClusters * 16 > 8*1024*1024) { SLOGI("It may need %d bytes ! It is too much ! Try enhanced fsck -- fsck_msdos_mtk !", boot.NumClusters * 16) ; fsck_enhanced = 1 ; } else SLOGW("Use fsck_msdos (original ver.)") ; */ } close(fd) ; } } #endif int pass = 1; int rc = 0; do { const char *args[4]; int status; #ifdef FSCK_MSDOS_MTK if(fsck_enhanced) args[0] = FSCK_MSDOS_MTK_PATH; else #endif args[0] = FSCK_MSDOS_PATH; args[1] = "-p"; args[2] = "-f"; args[3] = fsPath; rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); if (rc != 0) { SLOGE("Filesystem check failed due to logwrap error"); errno = EIO; return -1; } if (!WIFEXITED(status)) { SLOGE("Filesystem check did not exit properly"); errno = EIO; return -1; } status = WEXITSTATUS(status); switch(status) { case 0: SLOGI("Filesystem check completed OK"); return 0; case 2: SLOGE("Filesystem check failed (not a FAT filesystem)"); errno = ENODATA; return -1; case 4: if (pass++ <= 3) { SLOGW("Filesystem modified - rechecking (pass %d)", pass); continue; } SLOGE("Failing check after too many rechecks"); errno = EIO; return -1; case 16: SLOGE("Filesystem check failed (not support file system, %d)", status); errno = ENODATA; return -1; default: SLOGE("Filesystem check failed (unknown exit code %d)", status); errno = EIO; return -1; } } while (1); return 0; }
bool handle_command(Socket *client, std::string cmd, std::vector<std::string> args) { const char *trampfile = "/data/misc/fastbootd/mid.bin"; if (cmd == "getvar") { if (args[0] == "max-download-size") { return send_reply(client, "OKAY", "%d", kMaxDownloadSize); } else if (args[0] == "partition-type") { for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[1] == part_info[i].name) { return send_reply(client, "OKAY", part_info[i].type); } } } else if (args[0] == "product") { char property[PROPERTY_VALUE_MAX]; property_get("ro.product.board", property, ""); return send_reply(client, "OKAY", property); } else if (args[0] == "serialno") { char property[PROPERTY_VALUE_MAX]; property_get("ro.serialno", property, ""); return send_reply(client, "OKAY", property); } else if (args[0] == "version-bootloader") { return send_reply(client, "OKAY", "0.1"); } return send_reply(client, "OKAY", ""); } else if (cmd == "download") { uint32_t size = strtol(args[0].c_str(), 0, 16); send_reply(client, "DATA", "%08x", size); int fd = open(trampfile, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { send_reply(client, "FAIL", "fail to create trampoline file to store data!"); return false; } while (size > 0) { char buffer[4096]; ssize_t read = client->Receive(buffer, 8, 0); if (read != 8) { send_reply(client, "FAIL", "fail to receive data!"); close(fd); return false; } size_t length = ExtractMessageLength(buffer); do { read = client->Receive(buffer, std::min(length, sizeof(buffer)), 0); if (read < 0) { close(fd); return false; } write(fd, buffer, read); length -= read; size -= read; } while (length > 0); } close(fd); return send_reply(client, "OKAY", ""); } else if (cmd == "flash") { std::unique_ptr<char, int (*)(const char *)> tmpfile((char *)trampfile, unlink); int fd = open(tmpfile.get(), O_RDONLY); if (fd < 0) { send_reply(client, "FAIL", "please run download command first!"); return false; } const char *devname = NULL; const char *partname = NULL; for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[0] == part_info[i].name) { devname = part_info[i].device; partname = part_info[i].name; break; } } if (devname == NULL) { close(fd); send_reply(client, "FAIL", "partition: %s does not exist!", args[0].c_str()); return false; } if (!strcmp("boot", partname)) { close(fd); return handle_command_flash_boot_partition(client, tmpfile.get(), devname); } int fddev = open(devname, O_WRONLY | O_CREAT, 0600); if (fddev < 0) { close(fd); send_reply(client, "FAIL", "failed to open partition: %s", args[0].c_str()); return false; } struct sparse_file *s = sparse_file_import(fd, true, false); if (!s) { close(fd); close(fddev); send_reply(client, "FAIL", "failed to read sparse file!"); return false; } sparse_file_write(s, fddev, false, false, false); sparse_file_destroy(s); close(fd); close(fddev); sync(); return send_reply(client, "OKAY", ""); } else if (cmd == "erase") { const char *devname = NULL; for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[0] == part_info[i].name) { devname = part_info[i].device; break; } } if (devname == NULL) { send_reply(client, "FAIL", "partition: %s does not exist!", args[0].c_str()); return false; } uint64_t devsize = 0; int fd = open(devname, O_RDONLY); ioctl(fd, BLKGETSIZE64, &devsize); const uint64_t blksize = 64 * 1024; const uint64_t numblk = (devsize + blksize - 1) / blksize; const uint64_t updsize = (numblk / 10) * blksize; for (uint64_t offset = 0; offset < devsize; offset += updsize) { uint64_t realsize = std::min(updsize, devsize - offset); const char *argv[] = { "/system/bin/dd", "if=/dev/zero", android::base::StringPrintf("of=%s", devname).c_str(), android::base::StringPrintf("seek=%lld", offset).c_str(), android::base::StringPrintf("bs=%lld", realsize).c_str(), "count=1", }; int status; android_fork_execvp(sizeof(argv) / sizeof(argv[0]), (char **)argv, &status, true, true); send_reply(client, "INFO", android::base::StringPrintf("erase %s: %3lld/100", devname, (offset + realsize) * 100 / devsize).c_str()); } return send_reply(client, "OKAY", ""); } else if (cmd == "continue") { android::base::WriteStringToFile("5", "/sys/module/bcm2709/parameters/reboot_part"); android_reboot(ANDROID_RB_RESTART, 0, NULL); // while (true) { pause(); } return send_reply(client, "OKAY", ""); } else if (cmd == "reboot" || cmd == "reboot-bootloader") { android::base::WriteStringToFile("0", "/sys/module/bcm2709/parameters/reboot_part"); android_reboot(ANDROID_RB_RESTART, 0, NULL); // while (true) { pause(); } return send_reply(client, "OKAY", ""); } return send_reply(client, "FAIL", "unknown command: %s", cmd.c_str()); }