int dc_fill_disk_info(dev_hook *hook) { PARTITION_INFORMATION pti; PARTITION_INFORMATION_EX ptix; DISK_GEOMETRY_EX dgx; DISK_GEOMETRY dg; u64 d_size; if (hook->pnp_state != Started) { return ST_RW_ERR; } if (hook->flags & F_CDROM) { if (io_hook_ioctl(hook, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg)) != ST_OK) { return ST_RW_ERR; } if (io_hook_ioctl(hook, IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX, NULL, 0, &dgx, sizeof(dgx)) == ST_OK) { d_size = dgx.DiskSize.QuadPart; } else { d_size = d64(dg.Cylinders.QuadPart) * d64(dg.TracksPerCylinder) * d64(dg.SectorsPerTrack) * d64(dg.BytesPerSector); } } else { if (io_hook_ioctl(hook, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg)) != ST_OK) { return ST_RW_ERR; } if (io_hook_ioctl(hook, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &ptix, sizeof(ptix)) != ST_OK) { if (io_hook_ioctl(hook, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &pti, sizeof(pti)) != ST_OK) { return ST_RW_ERR; } d_size = pti.PartitionLength.QuadPart; } else { d_size = ptix.PartitionLength.QuadPart; } } if ( (hook->flags & F_REMOVABLE) && (dc_verify_device(hook) == ST_NO_MEDIA) ) { return ST_NO_MEDIA; } hook->dsk_size = d_size; hook->bps = dg.BytesPerSector; hook->chg_last_v = hook->chg_count; hook->max_chunk = dc_get_device_mtl(hook); hook->head_len = max(sizeof(dc_header), hook->bps); if ( (hook->flags & (F_REMOVABLE | F_CDROM)) == 0 ) { if (dc_is_this_ssd(hook) != 0) hook->flags |= F_SSD; } return ST_OK; }
static NTSTATUS dc_trim_irp(dev_hook *hook, PIRP irp) { PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp); PDEVICE_MANAGE_DATA_SET_ATTRIBUTES p_set = irp->AssociatedIrp.SystemBuffer; u32 length = irp_sp->Parameters.DeviceIoControl.InputBufferLength; u64 offset, rnglen; PDEVICE_DATA_SET_RANGE range; PDEVICE_MANAGE_DATA_SET_ATTRIBUTES n_set; u64 off1, off2; u64 len1, len2; u32 i; if ( (length < sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES)) || (p_set->Action != DeviceDsmAction_Trim) || (length < d64(p_set->DataSetRangesOffset) + d64(p_set->DataSetRangesLength)) ) { return dc_forward_irp(hook, irp); } if (dc_conf_flags & CONF_DISABLE_TRIM) { return dc_release_irp(hook, irp, STATUS_SUCCESS); } if ( (n_set = mm_pool_alloc(TRIM_BUFF_MAX(p_set))) == NULL ) { return dc_release_irp(hook, irp, STATUS_INSUFFICIENT_RESOURCES); } n_set->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES); n_set->Action = DeviceDsmAction_Trim; n_set->Flags = 0; n_set->ParameterBlockOffset = 0; n_set->ParameterBlockLength = 0; n_set->DataSetRangesOffset = _align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(DEVICE_DATA_SET_RANGE)); n_set->DataSetRangesLength = 0; if (p_set->Flags & DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE) { if (hook->flags & F_NO_REDIRECT) { TRIM_ADD_RANGE(n_set, hook->head_len, hook->dsk_size - hook->head_len); } else { TRIM_ADD_RANGE(n_set, hook->head_len, LEN_BEFORE_STORAGE(hook)); TRIM_ADD_RANGE(n_set, OFF_END_OF_STORAGE(hook), LEN_AFTER_STORAGE(hook)); } } else { for (i = 0, range = addof(p_set, p_set->DataSetRangesOffset); i < p_set->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE); i++, range++) { if ( (offset = range->StartingOffset) + (rnglen = range->LengthInBytes) > hook->use_size ) { continue; } if (hook->flags & F_NO_REDIRECT) { TRIM_ADD_RANGE(n_set, offset + hook->head_len, min(rnglen, hook->use_size - offset)); continue; } len1 = intersect(&off1, offset, rnglen, hook->head_len, LEN_BEFORE_STORAGE(hook)); len2 = intersect(&off2, offset, rnglen, OFF_END_OF_STORAGE(hook), LEN_AFTER_STORAGE(hook)); TRIM_ADD_RANGE(n_set, off1, len1); TRIM_ADD_RANGE(n_set, off2, len2); } } if (n_set->DataSetRangesLength != 0) { io_hook_ioctl(hook, IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES, n_set, TRIM_BUFF_LENGTH(n_set), NULL, 0); } mm_pool_free(n_set); return dc_release_irp(hook, irp, STATUS_SUCCESS); }
//! //! Update the value part. //! void StringPair::setV(double v) { D64 d64(v); v_ = d64.toString(); }
//! //! Return the value part. //! double StringPair::vAsD64() const { D64 d64(v_); return d64; }
int main(int argc, char **argv) { int restart = 0; const char *fn = NULL; struct stat st; int fd; char *buf = NULL; uint64_t nblocks = 0, nbytes = 0; const char *hlp; dump_stump_t stump = NULL, tstump = NULL; double t0, t1; int c; (void)ts(); /* Arguments */ hlp = strrchr(argv[0], '/'); if (hlp == NULL) av0 = argv[0]; else av0 = hlp + 1; opterr = 0; while ((c = getopt(argc, argv, "+rS:")) > 0) { switch (c) { case 'r': restart = 1; break; case 'S': tstump = dump_stump_parse(optarg); if (tstump == NULL) { dprintf(2, "%s: Invalid stump spec in option '%c'. Must be <offset>:<string>\n", av0, optopt); dprintf(2, "Usage: %s [ -r ] <destination device or file>\n", av0); fsync(2); exit(1); } tstump->next = stump; stump = tstump; tstump = NULL; break; default: dprintf(2, "%s: Invalid option '%c'.\n", av0, optopt); dprintf(2, "Usage: %s [ -r ] <destination device or file>\n", av0); fsync(2); exit(1); } } argc -= optind; argv += optind; if (argc == 1) { fn = argv[0]; } else { dprintf(2, "Usage: %s [ -r ] <destination device or file>\n", av0); fsync(2); exit(1); } if (lstat(fn, &st) != 0) { dprintf(2, "Can't stat destination \"%s\"\n", fn); fsync(2); exit(1); } /* Output type check */ if (S_ISREG(st.st_mode)) { dprintf(1, "Destination is a regular file.\n"); fsync(1); } else if (S_ISCHR(st.st_mode)) { dprintf(1, "Destination is a character device.\n"); fsync(1); } else if (S_ISBLK(st.st_mode)) { dprintf(1, "Destination is a block device.\n"); fsync(1); } else { dprintf(2, "Destination \"%s\" is not regular file or device node\n", fn); fsync(2); exit(1); } /* Buffer */ if (! (buf = malloc(FBUF_LEN))) { dprintf(2, "Out of memory\n"); fsync(2); exit(1); } /* Read and check magic */ if (r(0, buf, 8) != 8) { dprintf(2, "Read error (magic)\n"); fsync(2); exit(1); } if (d64(buf) != DUMP_FILE_MAGIC) { dprintf(2, "Bad magic\n"); fsync(2); exit(1); } /* Open output */ fd = open(fn, O_WRONLY | /*O_SYNC |*/ O_NOFOLLOW, 0); if (fd < 0) { dprintf(2, "Destination \"%s\" open for writing failed\n", fn); fsync(2); exit(1); } /* Main loop */ while (1) { uint64_t off, len; if (r(0, buf, 16) != 16) { dprintf(2, "Read error (header)\n"); fsync(2); exit(1); } off = d64(buf); len = d64(buf + 8); if ((off == 0) && (len == 0)) { dprintf(1, "End of input reached.\n"); fsync(1); break; } nblocks++; dprintf(1, "block=%lu, offset=%lu, length=%lu\n", (unsigned long)nblocks, (unsigned long)off, (unsigned long)len); fsync(1); if (off != (off_t)off) { dprintf(2, "Bad offset\n"); fsync(2); exit(1); } if (lseek(fd, (off_t)off, SEEK_SET) != (off_t)off) { dprintf(2, "Can't seek output\n"); fsync(2); exit(1); } t0 = ts(); while (len > 0) { size_t cl = (len <= FBUF_LEN) ? len : FBUF_LEN; if (r(0, buf, cl) != cl) { dprintf(2, "Read error (content)\n"); fsync(2); exit(1); } if (w(fd, buf, cl) != cl) { dprintf(2, "Write error\n"); fsync(2); exit(1); } write(1, ".", 1); fsync(1); len -= cl; nbytes += cl; } t1 = ts(); dprintf(1, "\nblock=%lu ok in %.6fs\n", nblocks, t1 - t0); fsync(1); } /* Write stumps. */ if (stump != NULL) { for (tstump = stump; tstump != NULL; tstump = tstump->next) { t0 = ts(); if (lseek(fd, (off_t)tstump->o, SEEK_SET) != (off_t)tstump->o) { dprintf(2, "Can't seek output\n"); fsync(2); exit(1); } if (w(fd, tstump->s, tstump->l) != tstump->l) { dprintf(2, "Write error\n"); fsync(2); exit(1); } t1 = ts(); dprintf(1, "stump ok in %.6fs\n", t1 - t0); fsync(1); } if (stump != NULL) { dprintf(1, "End of stumps reached.\n"); fsync(1); } } /* Sync output */ if (fsync(fd) != 0) { dprintf(2, "Destination sync failed\n"); fsync(2); exit(1); } /* Close output */ if (close(fd) != 0) { dprintf(2, "Closing destination \"%s\" failed\n", fn); fsync(2); exit(1); } /* Final report */ dprintf(1, "Written %lu blocks, %lu bytes total.\n", (unsigned long)nblocks, (unsigned long)nbytes); fsync(1); /* Cleanup */ free(buf); buf = NULL; while (stump != NULL) { tstump = stump; stump = tstump->next; free(tstump->s); free(tstump); } /* Immediate reboot */ if (restart) { dprintf(1, "Attempting to reboot\n"); fsync(1); sleep(1); REBOOT_NOW(); sleep(1); dprintf(2, "Reboot failed errno=%d (%s)\n", errno, strerror(errno)); fsync(2); exit(1); } exit(0); }