int mmc_trim(int fd, off_t offset, off_t count) { uint64_t range[2] = {offset, offset + count}; if (ioctl(fd, BLKDISCARD, &range)) fwup_warnx("BLKDISCARD (TRIM command) failed on range %"PRIu64" to %"PRIu64" (ignoring)", range[0], range[1]); return 0; }
static dev_t root_disk_device() { // NOTE: We'd like to know the root device for the root directory, but stat // only returns the partition device for the root directory. Since it // is often the case of 16 minor devices to support each real device, // assume that if we mask the root directory's device off that we'll // get its parent. struct stat rootdev; if (stat("/", &rootdev) >= 0) { return (rootdev.st_dev & 0xfff0); } else { fwup_warnx("can't stat root directory"); return 0; } }
int mmc_eject(const char *mmc_device) { DADiskRef disk = mmc_device_to_diskref(mmc_device); int rc = -1; if (disk) { struct disk_op_context context; context.operation = "eject"; DADiskEject(disk, kDADiskEjectOptionDefault, disk_op_done_cb, &context); if (run_loop_for_time(10) < 0) fwup_warnx("unmount timed out"); if (context.succeeded) rc = 0; CFRelease(disk); } return rc; }
int mmc_umount_all(const char *mmc_device) { DADiskRef disk = mmc_device_to_diskref(mmc_device); int rc = -1; if (disk) { struct disk_op_context context; context.operation = "unmount"; DADiskUnmount(disk, kDADiskUnmountOptionWhole, disk_op_done_cb, &context); // Wait for a while since unmounting sometimes takes time. if (run_loop_for_time(10) < 0) fwup_warnx("unmount timed out"); if (context.succeeded) rc = 0; CFRelease(disk); } return rc; }
static void disk_op_done_cb(DADiskRef disk, DADissenterRef dissenter, void *c) { (void) disk; struct disk_op_context *context = (struct disk_op_context *) c; if (dissenter) { CFStringRef what = DADissenterGetStatusString(dissenter); fwup_warnx("%s failed: 0x%x (%d) %s)", context->operation, DADissenterGetStatus(dissenter), DADissenterGetStatus(dissenter), CFStringGetCStringPtr(what, kCFStringEncodingMacRoman)); context->succeeded = false; } else { context->succeeded = true; } CFRunLoopStop(CFRunLoopGetCurrent()); }
int mmc_umount_all(const char *mmc_device) { FILE *fp = fopen("/proc/mounts", "r"); if (!fp) fwup_err(EXIT_FAILURE, "/proc/mounts"); char *todo[64] = {0}; int todo_ix = 0; int ultimate_rc = 0; char line[FWUP_BLOCK_SIZE] = {0}; while (!feof(fp) && fgets(line, sizeof(line), fp)) { char devname[64]; char mountpoint[256]; if (sscanf(line, "%63s %255s", devname, mountpoint) != 2) continue; if (strstr(devname, mmc_device) == devname) { // mmc_device is a prefix of this device, i.e. mmc_device is /dev/sdc // and /dev/sdc1 is mounted. if (todo_ix == NUM_ELEMENTS(todo)) fwup_errx(EXIT_FAILURE, "Device mounted too many times"); // strings from /proc/mounts are escaped, so unescape them todo[todo_ix++] = unescape_string(mountpoint); } } fclose(fp); int mtab_exists = (access("/etc/mtab", F_OK) != -1); for (int i = 0; i < todo_ix; i++) { if (mtab_exists) { // If /etc/mtab, then call umount(8) so that // gets updated correctly. int rc = fork_exec("/bin/umount", todo[i]); if (rc != 0) { fwup_warnx("Error calling umount on '%s'", todo[i]); ultimate_rc = -1; } } else { // No /etc/mtab, so call the kernel directly. #if HAS_UMOUNT if (umount(todo[i]) < 0) { fwup_warnx("umount %s", todo[i]); ultimate_rc = -1; } #else // If no umount on this platform, warn, but don't // return failure. fwup_warnx("umount %s: not supported", todo[i]); #endif } } for (int i = 0; i < todo_ix; i++) free(todo[i]); return ultimate_rc; }