void Volume::protectFromAutorunStupidity() { char filename[255]; snprintf(filename, sizeof(filename), "%s/autorun.inf", SEC_STGDIR); if (!access(filename, F_OK)) { SLOGW("Volume contains an autorun.inf! - removing"); /* * Ensure the filename is all lower-case so * the process killer can find the inode. * Probably being paranoid here but meh. */ rename(filename, filename); Process::killProcessesWithOpenFiles(filename, 2); if (unlink(filename)) { SLOGE("Failed to remove %s (%s)", filename, strerror(errno)); } } }
void NetlinkHandler::onEvent(NetlinkEvent *evt) { VolumeManager *vm = VolumeManager::Instance(); const char *subsys = evt->getSubsystem(); if (!subsys) { SLOGW("No subsystem found in netlink event"); return; } if (!strcmp(subsys, "block")) { vm->handleBlockEvent(evt); } #if defined(BOARD_USES_HDMI) || defined(S5P_BOARD_USES_HDMI) else if ((!strcmp(subsys, "misc")) || (!strcmp(subsys, "video4linux"))) { vm->handleMiscEvent(evt); } #endif }
int Ext::check(const char *fsPath) { bool rw = true; if (access(FSCK_EXT_PATH, X_OK)) { SLOGW("Skipping fs checks\n"); return 0; } int pass = 1; int rc = 0; do { const char *args[5]; args[0] = FSCK_EXT_PATH; args[1] = "-p"; args[2] = "-f"; args[3] = fsPath; args[4] = NULL; rc = logwrap(4, args, 1); switch(rc) { case 0: case 1: SLOGI("Filesystem check completed OK"); return 0; case 2: SLOGE("Filesystem check completed, system should be rebooted"); errno = ENODATA; return -1; case 4: SLOGE("Filesystem errors left uncorrected"); errno = EIO; return -1; default: SLOGE("Filesystem check failed (exit code %d)", rc); errno = EIO; return -1; } } while (0); return 0; }
void NetlinkHandler::onEvent(NetlinkEvent *evt) { VolumeManager *vm = VolumeManager::Instance(); const char *subsys = evt->getSubsystem(); if (!subsys) { SLOGW("No subsystem found in netlink event"); return; } if (!strcmp(subsys, "block")) { vm->handleBlockEvent(evt); } else if (!strcmp(subsys, "switch")) { vm->handleSwitchEvent(evt); } else if (!strcmp(subsys, "usb_composite")) { vm->handleUsbCompositeEvent(evt); } else if (!strcmp(subsys, "battery")) { } else if (!strcmp(subsys, "power_supply")) { } }
int Volume::formatVol() { if (getState() == Volume::State_NoMedia) { errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX errno = EBUSY; return -1; } // Just format one partition but not the whole disk if (devicePath[0] == 0) { dev_t diskNode = getDiskDevice(); dev_t partNode = MKDEV(MAJOR(diskNode), 1); // XXX: Hmmm sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(diskNode), MINOR(diskNode)); } if (mDebug) { SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); } setState(Volume::State_Formatting); if (Fat::format(devicePath, 0)) { SLOGE("Failed to format (%s)", strerror(errno)); goto err; } setState(Volume::State_Idle); return 0; err: return -1; }
// hunt down and kill processes that have files open on the given mount point void Process::killProcessesWithOpenFiles(const char *path, int action) { DIR* dir; struct dirent* de; if (!(dir = opendir("/proc"))) { SLOGE("opendir failed (%s)", strerror(errno)); return; } while ((de = readdir(dir))) { int killed = 0; int pid = getPid(de->d_name); char name[PATH_MAX]; if (pid == -1) continue; getProcessName(pid, name, sizeof(name)); char openfile[PATH_MAX]; if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) { SLOGE("Process %s (%d) has open file %s", name, pid, openfile); } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) { SLOGE("Process %s (%d) has open filemap for %s", name, pid, openfile); } else if (checkSymLink(pid, path, "cwd")) { SLOGE("Process %s (%d) has cwd within %s", name, pid, path); } else if (checkSymLink(pid, path, "root")) { SLOGE("Process %s (%d) has chroot within %s", name, pid, path); } else if (checkSymLink(pid, path, "exe")) { SLOGE("Process %s (%d) has executable path within %s", name, pid, path); } else { continue; } if (action == 1) { SLOGW("Sending SIGHUP to process %d", pid); kill(pid, SIGTERM); } else if (action == 2) { SLOGE("Sending SIGKILL to process %d", pid); kill(pid, SIGKILL); } } closedir(dir); }
void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { mDiskMajor = atoi(evt->findParam("MAJOR")); mDiskMinor = atoi(evt->findParam("MINOR")); if(first_udisk_major==-1&&first_udisk_minor==-1){ SLOGD("first udisk add\n"); first_udisk_major = mDiskMajor; first_udisk_minor = mDiskMinor; }else{ SLOGD("not first udisk add\n"); return ; } const char *tmp = evt->findParam("NPARTS"); if (tmp) { mDiskNumParts = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'NPARTS'"); mDiskNumParts = 1; } int partmask = 0; int i; for (i = 1; i <= mDiskNumParts; i++) { partmask |= (1 << i); } mPendingPartMap = partmask; if (mDiskNumParts == 0) { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - No partitions - good to go son!"); #endif setState(Volume::State_Idle); } else { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - waiting for %d partitions (mask 0x%x)", mDiskNumParts, mPendingPartMap); #endif setState(Volume::State_Pending); } }
void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { mDiskMajor = atoi(evt->findParam("MAJOR")); mDiskMinor = atoi(evt->findParam("MINOR")); const char *tmp = evt->findParam("NPARTS"); if (tmp) { mDiskNumParts = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'NPARTS'"); mDiskNumParts = 1; } char msg[255]; /* int partmask = 0; int i; for (i = 1; i <= mDiskNumParts; i++) { partmask |= (1 << i); } */ mPendingPartNum = mDiskNumParts; for (int i = 0; i < MAX_PARTITIONS; i++) mPartMinors[i] = -1; if (mDiskNumParts == 0) { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - No partitions - good to go son!"); #endif setState(Volume::State_Idle); } else { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - waiting for %d partitions (pending partitions: %d)", mDiskNumParts, mPendingPartNum); #endif setState(Volume::State_Pending); } if(mVm->getIpoState() == VolumeManager::State_Ipo_Start) { snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)", getLabel(), getMountpoint(), mDiskMajor, mDiskMinor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted, msg, false); } }
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); if (tmp) { part_num = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'PARTN'"); part_num = 1; } if (part_num > mDiskNumParts) { mDiskNumParts = part_num; } if (major != mDiskMajor) { SLOGE("Partition '%s' has a different major than its disk!", devpath); return; } #ifdef PARTITION_DEBUG SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor); #endif mPartMinors[part_num -1] = minor; mPendingPartMap &= ~(1 << part_num); if (!mPendingPartMap) { #ifdef PARTITION_DEBUG SLOGD("Dv:partAdd: Got all partitions - ready to rock!"); #endif if (getState() != Volume::State_Formatting) { setState(Volume::State_Idle); } } else { #ifdef PARTITION_DEBUG SLOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap); #endif } }
void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { mDiskMajor = atoi(evt->findParam("MAJOR")); mDiskMinor = atoi(evt->findParam("MINOR")); const char *tmp = evt->findParam("NPARTS"); if (tmp) { mDiskNumParts = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'NPARTS'"); mDiskNumParts = 1; } if (strcmp(devpath, "/devices/virtual/block/stheno") == 0) mDiskNumParts = 0; char msg[255]; int partmask = 0; int i; for (i = 1; i <= mDiskNumParts; i++) { partmask |= (1 << i); } mPendingPartMap = partmask; if (mDiskNumParts == 0) { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - No partitions - good to go son!"); #endif setState(Volume::State_Idle); } else { #ifdef PARTITION_DEBUG SLOGD("Dv::diskIns - waiting for %d partitions (mask 0x%x)", mDiskNumParts, mPendingPartMap); #endif setState(Volume::State_Pending); } snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)", getLabel(), getMountpoint(), mDiskMajor, mDiskMinor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted, msg, false); }
int Exfat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool ISVfat) { int rc; unsigned long flags; char mountData[255]; bool isexecutable = executable; /* * Note: This is a temporary hack. If the sampling profiler is enabled, * we make the SD card world-writable so any process can write snapshots. * * TODO: Remove this code once we have a drop box in system_server. */ char value[PROPERTY_VALUE_MAX]; property_get("ro.vold.permissivefs", value, ""); if (value[0] == '1') { SLOGW("The SD card is world-writable because the" " 'persist.sampling_profiler' system property is set to '1'."); permMask = 0; isexecutable = true; } flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; flags |= (isexecutable ? 0 : MS_NOEXEC); flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid, ownerGid, permMask, permMask); if(ISVfat == true) { rc = mount(fsPath, mountPoint, "vfat", flags, mountData); } else { rc = mount(fsPath, mountPoint, "texfat", flags, mountData); } if (rc !=0 && ISVfat == false) { rc = mount(fsPath, mountPoint, "exfat", flags, mountData); } return rc; }
int main(void) { /* Library initialization. Must be called only once. */ SLOG_Init(SLOG_STDERR, "example02-log.txt"); /* Setting log levels: all messages to console and all to the file. * Default settings are: all messages to file and >= INFO to console. */ SLOG_SetLevel(SLOG_DEBUG, SLOG_DEBUG); SLOGD(TAG, "debug message"); SLOGI(TAG, "info"); SLOGW(TAG, "warning"); SLOGE(TAG, "error"); SLOGI(TAG, "formatted message (%d, %s)", 123, "bar"); /* Library deinitialization. */ SLOG_Deinit(); return 0; }
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 Volume::setState(int state) { char msg[255]; int oldState = mState; if (oldState == state) { SLOGW("Duplicate state (%d)\n", state); return; } mState = state; SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel, oldState, stateToStr(oldState), mState, stateToStr(mState)); snprintf(msg, sizeof(msg), "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(), getMountpoint(), oldState, stateToStr(oldState), mState, stateToStr(mState)); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange, msg, false); }
void DirectVolume::udiskSetState(int state,int index,char * mountpoint) { char msg[255]; int mState = 0; int oldState = mState; if(state == State_Idle){ oldState = State_Unmounting; } if(state == State_Unmounting){ oldState = State_Mounted; } if(state == State_NoMedia){ oldState = State_Idle; } if (oldState == state) { SLOGW("Duplicate state (%d)\n", state); return; } if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) { mRetryMount = false; } mState = state; SLOGD("Volume Udisk%d path %s state changing %d (%s) -> %d (%s)", index,mountpoint, oldState, stateToStr(oldState), mState, stateToStr(mState)); snprintf(msg, sizeof(msg), "Volume Udisk%d %s state changed from %d (%s) to %d (%s)", index, mountpoint, oldState, stateToStr(oldState), mState, stateToStr(mState)); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange, msg, false); }
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { const char *devpath = evt->findParam("DEVPATH"); /* Lookup a volume to handle this device */ VolumeCollection::iterator it; bool hit = false; for (it = mVolumes->begin(); it != mVolumes->end(); ++it) { if (!(*it)->handleBlockEvent(evt)) { #ifdef NETLINK_DEBUG SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel()); #endif hit = true; break; } } if (!hit) { #ifdef NETLINK_DEBUG SLOGW("No volumes handled block event for '%s'", devpath); #endif } }
int usbset(int index,int cmd) { bool rw = true; if (access(USBPOWER_PATH, X_OK)) { SLOGW("No USBPOWER_PATH file\n"); return -1; } int rc = 0; do { const char *args[4]; args[0] = USBPOWER_PATH; args[1] = usb_index_str[index]; args[2] = usb_state_str[cmd]; args[3] = NULL; rc = logwrap(3, args, 1); } while (0); return rc; }
void PhoneMachine::Request(const sp<IPhoneClient>& client, int token, int message, int ivalue, const String16& svalue) { SLOGV("Client request: token=%d message=%d ivalue=%d\n", token, message, ivalue); RILRequest *request = new RILRequest(client, token, message); switch(message) { case RIL_REQUEST_GET_SIM_STATUS: break; case RIL_REQUEST_GET_CURRENT_CALLS: break; case RIL_REQUEST_DIAL: request->writeString(svalue); request->writeInt(0); // CLIR: Use subscription default value request->writeInt(0); // UUS information is absent request->writeInt(0); // UUS information is absent break; case RIL_REQUEST_HANGUP: request->writeInt(1); request->writeInt(ivalue); // This is really the GSM index break; case RIL_REQUEST_SIGNAL_STRENGTH: break; #if defined(SHORT_PLATFORM_VERSION) && (SHORT_PLATFORM_VERSION == 23) #else case RIL_REQUEST_VOICE_REGISTRATION_STATE: break; #endif case RIL_REQUEST_OPERATOR: break; case RIL_REQUEST_ANSWER: break; case RIL_REQUEST_UDUB: break; case RIL_REQUEST_SET_MUTE: request->writeInt(1); request->writeInt(ivalue ? 1 : 0); break; case RIL_REQUEST_GET_MUTE: break; default: SLOGW("Unrecognized request %d\n", message); // ### TODO: Put in an error code here and send the message back break; } sendToRILD(request); }
static int initCtx(uid_t uid, int pid, struct ctx *ctx) { int ret; char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; convertUidPidToPath(path, sizeof(path), uid, pid); strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); int fd = open(path, O_RDONLY); if (fd < 0) { ret = -errno; SLOGW("failed to open %s: %s", path, strerror(errno)); return ret; } ctx->fd = fd; ctx->buf_ptr = ctx->buf; ctx->buf_len = 0; ctx->initialized = true; SLOGV("Initialized context for %s", path); return 0; }
int VolumeManager::unmountVolume(const char *label, bool force, bool revert) { Volume *v = lookupVolume(label); if (!v) { errno = ENOENT; return -1; } if (v->getState() == Volume::State_NoMedia) { errno = ENODEV; return -1; } if (v->getState() != Volume::State_Mounted) { SLOGW("Attempt to unmount volume which isn't mounted (%d)\n", v->getState()); errno = EBUSY; return UNMOUNT_NOT_MOUNTED_ERR; } cleanupAsec(v, force); return v->unmountVol(force, revert); }
int VolumeManager::renameAsec(const char *id1, const char *id2) { char asecFilename1[255]; char *asecFilename2; char mountPoint[255]; const char *dir; if (!isLegalAsecId(id1)) { SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1); errno = EINVAL; return -1; } if (!isLegalAsecId(id2)) { SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2); errno = EINVAL; return -1; } if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) { SLOGE("Couldn't find ASEC %s", id1); return -1; } asprintf(&asecFilename2, "%s/%s.asec", dir, id2); int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1); if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { SLOGE("Rename failed: couldn't construct mountpoint"); goto out_err; } if (isMountpointMounted(mountPoint)) { SLOGW("Rename attempt when src mounted"); errno = EBUSY; goto out_err; } written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2); if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { SLOGE("Rename failed: couldn't construct mountpoint2"); goto out_err; } if (isMountpointMounted(mountPoint)) { SLOGW("Rename attempt when dst mounted"); errno = EBUSY; goto out_err; } if (!access(asecFilename2, F_OK)) { SLOGE("Rename attempt when dst exists"); errno = EADDRINUSE; goto out_err; } if (rename(asecFilename1, asecFilename2)) { SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno)); goto out_err; } free(asecFilename2); return 0; out_err: free(asecFilename2); return -1; }
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 Fat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) { int rc; unsigned long flags; char mountData[255]; flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; flags |= (executable ? 0 : MS_NOEXEC); flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); /* * Note: This is a temporary hack. If the sampling profiler is enabled, * we make the SD card world-writable so any process can write snapshots. * * TODO: Remove this code once we have a drop box in system_server. */ char value[PROPERTY_VALUE_MAX]; property_get("persist.sampling_profiler", value, ""); if (value[0] == '1') { SLOGW("The SD card is world-writable because the" " 'persist.sampling_profiler' system property is set to '1'."); permMask = 0; } sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", ownerUid, ownerGid, permMask, permMask); rc = mount(fsPath, mountPoint, "vfat", flags, mountData); if (rc && errno == EROFS) { SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); flags |= MS_RDONLY; rc = mount(fsPath, mountPoint, "vfat", flags, mountData); } if (rc == 0 && createLost) { char *lost_path; asprintf(&lost_path, "%s/LOST.DIR", mountPoint); if (access(lost_path, F_OK)) { /* * Create a LOST.DIR in the root so we have somewhere to put * lost cluster chains (fsck_msdos doesn't currently do this) */ if (mkdir(lost_path, 0755)) { SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); } } free(lost_path); } return rc; }
int Volume::mountVol() { dev_t deviceNodes[4]; int n, i, rc = 0; char errmsg[255]; const char* externalStorage = getenv("EXTERNAL_STORAGE"); bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage); char decrypt_state[PROPERTY_VALUE_MAX]; char crypto_state[PROPERTY_VALUE_MAX]; char encrypt_progress[PROPERTY_VALUE_MAX]; int flags; property_get("vold.decrypt", decrypt_state, ""); property_get("vold.encrypt_progress", encrypt_progress, ""); /* Don't try to mount the volumes if we have not yet entered the disk password * or are in the process of encrypting. */ if ((getState() == Volume::State_NoMedia) || ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) { snprintf(errmsg, sizeof(errmsg), "Volume %s %s mount failed - no media", getLabel(), getMountpoint()); mVm->getBroadcaster()->sendBroadcast( ResponseCode::VolumeMountFailedNoMedia, errmsg, false); errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; if (getState() == Volume::State_Pending) { mRetryMount = true; } return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX return 0; } n = getDeviceNodes((dev_t *) &deviceNodes, 4); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } /* If we're running encrypted, and the volume is marked as encryptable and nonremovable, * and vold is asking to mount the primaryStorage device, then we need to decrypt * that partition, and update the volume object to point to it's new decrypted * block device */ property_get("ro.crypto.state", crypto_state, ""); flags = getFlags(); if (primaryStorage && ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) && !strcmp(crypto_state, "encrypted") && !isDecrypted()) { char new_sys_path[MAXPATHLEN]; char nodepath[256]; int new_major, new_minor; if (n != 1) { /* We only expect one device node returned when mounting encryptable volumes */ SLOGE("Too many device nodes returned when mounting %d\n", getMountpoint()); return -1; } if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), new_sys_path, sizeof(new_sys_path), &new_major, &new_minor)) { SLOGE("Cannot setup encryption mapping for %d\n", getMountpoint()); return -1; } /* We now have the new sysfs path for the decrypted block device, and the * majore and minor numbers for it. So, create the device, update the * path to the new sysfs path, and continue. */ snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", new_major, new_minor); if (createDeviceNode(nodepath, new_major, new_minor)) { SLOGE("Error making device node '%s' (%s)", nodepath, strerror(errno)); } // Todo: Either create sys filename from nodepath, or pass in bogus path so // vold ignores state changes on this internal device. updateDeviceInfo(nodepath, new_major, new_minor); /* Get the device nodes again, because they just changed */ n = getDeviceNodes((dev_t *) &deviceNodes, 4); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } } for (i = 0; i < n; i++) { char devicePath[255]; sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]), MINOR(deviceNodes[i])); SLOGI("%s being considered for volume %s\n", devicePath, getLabel()); errno = 0; setState(Volume::State_Checking); if (Fat::check(devicePath)) { if (errno == ENODATA) { SLOGW("%s does not contain a FAT filesystem\n", devicePath); continue; } errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); return -1; } /* * Mount the device on our internal staging mountpoint so we can * muck with it before exposing it to non priviledged users. */ errno = 0; int gid; if (primaryStorage) { // Special case the primary SD card. // For this we grant write access to the SDCARD_RW group. gid = AID_SDCARD_RW; } else { // For secondary external storage we keep things locked up. gid = AID_MEDIA_RW; } if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false, AID_SYSTEM, gid, 0702, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); protectFromAutorunStupidity(); // only create android_secure on primary storage if (primaryStorage && createBindMounts()) { SLOGE("Failed to create bindmounts (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } /* * Now that the bindmount trickery is done, atomically move the * whole subtree to expose it to non priviledged users. */ if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) { SLOGE("Failed to move mount (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } setState(Volume::State_Mounted); mCurrentlyMountedKdev = deviceNodes[i]; return 0; } SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); setState(Volume::State_Idle); return -1; }
int Volume::formatVol() { if (getState() == Volume::State_NoMedia) { errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX errno = EBUSY; return -1; } bool formatEntireDevice = (mPartIdx == -1); char devicePath[255]; dev_t diskNode = getDiskDevice(); dev_t partNode = MKDEV(MAJOR(diskNode), (formatEntireDevice ? 1 : mPartIdx)); setState(Volume::State_Formatting); int ret = -1; // Only initialize the MBR if we are formatting the entire device if (formatEntireDevice) { sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(diskNode), MINOR(diskNode)); if (initializeMbr(devicePath)) { SLOGE("Failed to initialize MBR (%s)", strerror(errno)); goto err; } } sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(partNode), MINOR(partNode)); #ifdef VOLD_EMMC_SHARES_DEV_MAJOR // If emmc and sdcard share dev major number, vold may pick // incorrectly based on partition nodes alone, formatting // the wrong device. Use device nodes instead. dev_t deviceNodes; getDeviceNodes((dev_t *) &deviceNodes, 1); sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes), MINOR(deviceNodes)); #endif if (mDebug) { SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); } if (Fat::format(devicePath, 0)) { SLOGE("Failed to format (%s)", strerror(errno)); goto err; } ret = 0; err: setState(Volume::State_Idle); return ret; }
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[5]; #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; args[4] = NULL; rc = logwrap(4, args, 1); switch(rc) { 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)", rc); errno = EIO; return -1; } } while (1); return 0; }
int Volume::mountVol() { dev_t deviceNodes[4]; int n, i, rc = 0; char errmsg[255]; if (getState() == Volume::State_NoMedia) { snprintf(errmsg, sizeof(errmsg), "Volume %s %s mount failed - no media", getLabel(), getMountpoint()); mVm->getBroadcaster()->sendBroadcast( ResponseCode::VolumeMountFailedNoMedia, errmsg, false); errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX return 0; } n = getDeviceNodes((dev_t *) &deviceNodes, 4); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } for (i = 0; i < n; i++) { char devicePath[255]; sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]), MINOR(deviceNodes[i])); SLOGI("%s being considered for volume %s\n", devicePath, getLabel()); errno = 0; setState(Volume::State_Checking); if (Fat::check(devicePath)) { if (errno == ENODATA) { SLOGW("%s does not contain a FAT filesystem\n", devicePath); continue; } errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); return -1; } /* * Mount the device on our internal staging mountpoint so we can * muck with it before exposing it to non priviledged users. */ errno = 0; if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false, 1000, 1015, 0702, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); protectFromAutorunStupidity(); if (createBindMounts()) { SLOGE("Failed to create bindmounts (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } /* * Now that the bindmount trickery is done, atomically move the * whole subtree to expose it to non priviledged users. */ if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) { SLOGE("Failed to move mount (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } setState(Volume::State_Mounted); mCurrentlyMountedKdev = deviceNodes[i]; return 0; } SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); setState(Volume::State_Idle); return -1; }
int Fat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool createLost, bool discard) { #else //MTK_EMMC_DISCARD int Fat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) { #endif //MTK_EMMC_DISCARD int rc; unsigned long flags; char mountData[255]; flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; flags |= (executable ? 0 : MS_NOEXEC); flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); /* * Note: This is a temporary hack. If the sampling profiler is enabled, * we make the SD card world-writable so any process can write snapshots. * * TODO: Remove this code once we have a drop box in system_server. */ char value[PROPERTY_VALUE_MAX]; property_get("persist.sampling_profiler", value, ""); if (value[0] == '1') { SLOGW("The SD card is world-writable because the" " 'persist.sampling_profiler' system property is set to '1'."); permMask = 0; } #ifndef VENDOR_EDIT //[email protected], 2012/01/31, Modify for for CTS that other users are not permmited to write SD card /* #ifdef MTK_EMMC_DISCARD sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed%s", ownerUid, ownerGid, permMask, permMask, (discard? ",discard": "") ); #else //MTK_EMMC_DISCARD sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", ownerUid, ownerGid, permMask, permMask); #endif //MTK_EMMC_DISCARD */ #else /* VENDOR_EDIT */ sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", ownerUid, ownerGid, 0002, 0002); SLOGW("vold:: mount %s to %s,ro =%d,remount =%d",fsPath,mountPoint,ro,remount); #endif /* VENDOR_EDIT */ rc = mount(fsPath, mountPoint, "vfat", flags, mountData); if (rc && errno == EROFS) { SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); flags |= MS_RDONLY; rc = mount(fsPath, mountPoint, "vfat", flags, mountData); } if (rc == 0 && createLost) { char *lost_path; asprintf(&lost_path, "%s/LOST.DIR", mountPoint); if (access(lost_path, F_OK)) { /* * Create a LOST.DIR in the root so we have somewhere to put * lost cluster chains (fsck_msdos doesn't currently do this) */ if (mkdir(lost_path, 0755)) { SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); } } free(lost_path); } return rc; }
int VolumeManager::unmountLoopImage(const char *id, const char *idHash, const char *fileName, const char *mountPoint, bool force) { if (!isMountpointMounted(mountPoint)) { SLOGE("Unmount request for %s when not mounted", id); errno = ENOENT; return -1; } int i, rc; for (i = 1; i <= UNMOUNT_RETRIES; i++) { rc = umount(mountPoint); if (!rc) { break; } if (rc && (errno == EINVAL || errno == ENOENT)) { SLOGI("Container %s unmounted OK", id); rc = 0; break; } SLOGW("%s unmount attempt %d failed (%s)", id, i, strerror(errno)); int action = 0; // default is to just complain if (force) { if (i > (UNMOUNT_RETRIES - 2)) action = 2; // SIGKILL else if (i > (UNMOUNT_RETRIES - 3)) action = 1; // SIGHUP } Process::killProcessesWithOpenFiles(mountPoint, action); usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); } if (rc) { errno = EBUSY; SLOGE("Failed to unmount container %s (%s)", id, strerror(errno)); return -1; } int retries = 10; while(retries--) { if (!rmdir(mountPoint)) { break; } SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno)); usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); } if (!retries) { SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno)); } if (Devmapper::destroy(idHash) && errno != ENXIO) { SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno)); } char loopDevice[255]; if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { Loop::destroyByDevice(loopDevice); } else { SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno)); } AsecIdCollection::iterator it; for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) { ContainerData* cd = *it; if (!strcmp(cd->id, id)) { free(*it); mActiveContainers->erase(it); break; } } if (it == mActiveContainers->end()) { SLOGW("mActiveContainers is inconsistent!"); } return 0; }
void PhoneMachine::receiveSolicited(const Parcel& data) { int serial = data.readInt32(); int result = data.readInt32(); RILRequest *request = getPending(serial); if (!request) { SLOGW("receiveSolicited: not requested serial=%d result=%d\n", serial, result); return; } SLOGV("<<< Solicited message=%s [%d] serial=%d result=%d\n", rilMessageStr(request->message()), request->message(), serial, result); int token = request->token(); int message = request->message(); int ivalue = 0; Parcel extra; switch (message) { case RIL_REQUEST_GET_SIM_STATUS: ivalue = data.readInt32(); // Store the card state break; case RIL_REQUEST_GET_CURRENT_CALLS: { // We retrieve audio information for the client. // We also update the AudioFlinger audio state appropriately based // on the current call state ivalue = data.readInt32(); // How many calls there are audio_mode_t audio_mode = AUDIO_MODE_NORMAL; for (int i = 0 ; i < ivalue ; i++) { RILCall call(data); CallState call_state(call.state, call.index, call.number, call.numberPresentation, call.name, call.namePresentation); call_state.writeToParcel(&extra); if (call.state == RIL_CALL_INCOMING) audio_mode = AUDIO_MODE_RINGTONE; else if (call.state == RIL_CALL_ACTIVE || call.state == RIL_CALL_DIALING || call.state == RIL_CALL_ALERTING) audio_mode = AUDIO_MODE_IN_CALL; } SLOGV(" %d calls, audio_mode=%d\n", ivalue, audio_mode); updateAudioMode(audio_mode); break; } case RIL_REQUEST_DIAL: case RIL_REQUEST_HANGUP: case RIL_REQUEST_ANSWER: case RIL_REQUEST_UDUB: case RIL_REQUEST_SET_MUTE: break; case RIL_REQUEST_GET_MUTE: ivalue = data.readInt32(); break; case RIL_REQUEST_SIGNAL_STRENGTH: // In actuality, we should probably read all 12 signal strengths ivalue = data.readInt32(); break; #if defined(SHORT_PLATFORM_VERSION) && (SHORT_PLATFORM_VERSION == 23) #else case RIL_REQUEST_VOICE_REGISTRATION_STATE: ivalue = data.readInt32(); // Starts with the number of strings for (int i = 0 ; i < ivalue ; i++) extra.writeString16(data.readString16()); break; #endif case RIL_REQUEST_OPERATOR: { ivalue = data.readInt32(); assert(ivalue == 3); extra.writeString16(data.readString16()); extra.writeString16(data.readString16()); extra.writeString16(data.readString16()); break; } case RIL_REQUEST_RADIO_POWER: SLOGV(" RIL Radio Power\n"); // No response.... break; default: SLOGV("Unhandled RIL request %d\n", message); break; } if (request->client() != NULL) { SLOGV(" Passing solicited message to client token=%d message=%d result=%d ivalue=%d...\n", token, message, result, ivalue); request->client()->Response( token, message, result, ivalue, extra ); } delete request; }