smart_device * smart_interface::get_smart_device(const char * name, const char * type) { clear_err(); // Call platform specific autodetection if no device type specified smart_device * dev; if (!type || !*type) { dev = autodetect_smart_device(name); if (!dev && !get_errno()) set_err(EINVAL, "Unable to detect device type"); return dev; } // First check for platform specific device types dev = get_custom_smart_device(name, type); if (dev || get_errno()) return dev; if (!strcmp(type, "ata")) dev = get_ata_device(name, type); else if (!strcmp(type, "scsi")) dev = get_scsi_device(name, type); else if ( ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3]))) || (!strncmp(type, "usb", 3)))) { // Split "sat...+base..." -> ("sat...", "base...") unsigned satlen = strcspn(type, "+"); std::string sattype(type, satlen); const char * basetype = (type[satlen] ? type+satlen+1 : ""); // Recurse to allocate base device, default is standard SCSI if (!*basetype) basetype = "scsi"; smart_device_auto_ptr basedev( get_smart_device(name, basetype) ); if (!basedev) { set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg()); return 0; } // Result must be SCSI if (!basedev->is_scsi()) { set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype); return 0; } // Attach SAT tunnel ata_device * satdev = get_sat_device(sattype.c_str(), basedev->to_scsi()); if (!satdev) return 0; basedev.release(); return satdev; } else { set_err(EINVAL, "Unknown device type '%s'", type); return 0; } if (!dev && !get_errno()) set_err(EINVAL, "Not a device of type '%s'", type); return dev; }
int add_entry_label(struct data_entry *entry, int label) { int *atable = NULL; clear_err(); /* adding an empty label does nothing */ if (label == LABEL_EMPTY) return 0; /* add first label to entry */ if (entry->num_labs == 0) { entry->num_labs = 1; entry->lab.label = label; return 0; } /* if there is already one label, we need to allocate a table for the labels */ if (entry->num_labs == 1) { atable = malloc(sizeof(int) * ATABLE_INCREMENT); if (atable == NULL) return ERR_NOMEM; /* move old entry to table and add the new label */ entry->num_labs++; atable[0] = entry->lab.label; atable[1] = label; entry->lab.label_array = atable; return 0; } atable = entry->lab.label_array; /* enlarge label array if needed */ if ((entry->num_labs % ATABLE_INCREMENT) == 0) { /* need more space */ atable = realloc(atable, sizeof(int) * (entry->num_labs + ATABLE_INCREMENT)); if (atable == NULL) return ERR_NOMEM; entry->lab.label_array = atable; } atable[entry->num_labs++] = label; return 0; }
struct hitlist *new_hitlist(void) { struct hitlist *hl; clear_err(); hl = malloc(sizeof(struct hitlist)); if (hl == NULL) { ERROR(ERR_NOMEM); return NULL; } hl->head = hl->tail = NULL; hl->entries = 0; return hl; }
/** * \brief Calls the qualified compressor (inflate) * * \param[in] cdata pointer to compressed data * \param[in] cdata_size length of compressed data in bytes * \param[in,out] rdata pointer to memory for decompressed data * \param[out] rdata_size available space ar \p rdata in bytes * \param[in] rdata_element_size size of one element in decompressed vector * \returns true on success */ bool unpack( void* cdata, size_t cdata_size, void* rdata, size_t rdata_size, size_t rdata_element_size ) { bool status = false; assert( rdata && rdata_size > 0 ); free_result(); clear_data(); clear_err(); /// acquire compressed data m_cdata = cdata; m_cdata_size = cdata_size; m_rdata = rdata; m_rdata_size = rdata_size; m_rdata_element_size = rdata_element_size; /// dispatch switch( m_eCompressorType ) { case CT_BLOSC: status = bloscDecompress(); break; case CT_QLIN16: status = linlogQuantizerDecompress( /* bDoLog*/ false ); break; case CT_QLOG16: status = linlogQuantizerDecompress( /* bDoLog*/ true ); break; default: break; } /// deplay result (uncompressed/raw data) m_result_is_const = true; m_result = m_rdata; m_result_size = m_rdata_size; return status; }
/** * \brief Calls the qualified compressor (deflate) which always allocates sufficient memory (m_cdata) * * \param[in] rdata pointer to raw data (byte stream) * \param[in] rdata_size length of raw data in bytes * \param[in] rdata_element_size size of one element in bytes * \param[in] isDoubleClass true, if elements represent double types * \returns true on success */ bool pack( void* rdata, size_t rdata_size, size_t rdata_element_size, bool isDoubleClass ) { bool status = false; free_result(); clear_data(); clear_err(); // acquire raw data m_rdata = rdata; m_rdata_size = rdata_size; m_rdata_element_size = rdata_element_size; m_rdata_is_double_type = isDoubleClass; // dispatch switch( m_eCompressorType ) { case CT_BLOSC: status = bloscCompress(); break; case CT_QLIN16: status = linlogQuantizerCompress( /* bDoLog*/ false ); break; case CT_QLOG16: status = linlogQuantizerCompress( /* bDoLog*/ true ); break; default: break; } /// deploy result (compressed data) m_result_is_const = false; m_result = m_cdata; m_result_size = m_cdata_size; return status; }
int copy_entry_labels(struct data_entry *dest, struct data_entry *source) { int blocks, size, *atable; clear_err(); clear_entry_labels(dest); /* remove old labels first */ if (source->num_labs <= 1) dest->lab.label = source->lab.label; else { blocks = (source->num_labs + ATABLE_INCREMENT - 1) / ATABLE_INCREMENT; size = sizeof(int) * blocks * ATABLE_INCREMENT; atable = malloc(size); if (atable == NULL) return ERR_NOMEM; memcpy(atable, source->lab.label_array, size); dest->lab.label_array = atable; } dest->num_labs = source->num_labs; return 0; }
bool ata_device_with_command_set::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) { if (!ata_cmd_is_ok(in, true)) // data_out_support return false; smart_command_set command = (smart_command_set)-1; int select = 0; char * data = (char *)in.buffer; char buffer[512]; switch (in.in_regs.command) { case ATA_IDENTIFY_DEVICE: command = IDENTIFY; break; case ATA_IDENTIFY_PACKET_DEVICE: command = PIDENTIFY; break; case ATA_CHECK_POWER_MODE: command = CHECK_POWER_MODE; data = buffer; data[0] = 0; break; case ATA_SMART_CMD: switch (in.in_regs.features) { case ATA_SMART_ENABLE: command = ENABLE; break; case ATA_SMART_READ_VALUES: command = READ_VALUES; break; case ATA_SMART_READ_THRESHOLDS: command = READ_THRESHOLDS; break; case ATA_SMART_READ_LOG_SECTOR: command = READ_LOG; select = in.in_regs.lba_low; break; case ATA_SMART_WRITE_LOG_SECTOR: command = WRITE_LOG; select = in.in_regs.lba_low; break; case ATA_SMART_DISABLE: command = DISABLE; break; case ATA_SMART_STATUS: command = (in.out_needed.lba_high ? STATUS_CHECK : STATUS); break; case ATA_SMART_AUTO_OFFLINE: command = AUTO_OFFLINE; select = in.in_regs.sector_count; break; case ATA_SMART_AUTOSAVE: command = AUTOSAVE; select = in.in_regs.sector_count; break; case ATA_SMART_IMMEDIATE_OFFLINE: command = IMMEDIATE_OFFLINE; select = in.in_regs.lba_low; break; default: return set_err(ENOSYS, "Unknown SMART command"); } break; default: return set_err(ENOSYS, "Non-SMART commands not implemented"); } clear_err(); errno = 0; int rc = ata_command_interface(command, select, data); if (rc < 0) { if (!get_errno()) set_err(errno); return false; } switch (command) { case CHECK_POWER_MODE: out.out_regs.sector_count = data[0]; break; case STATUS_CHECK: switch (rc) { case 0: // Good SMART status out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f; break; case 1: // Bad SMART status out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4; break; } break; default: break; } return true; }