+static void
+tape_device_base_init (TapeDeviceClass * c)
+{
+ DeviceClass *device_class = (DeviceClass *)c;
+
+ device_class_register_property(device_class, PROPERTY_BROKEN_GMT_ONLINE,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_FSF,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_FSF_AFTER_FILEMARK,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_BSF,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_FSR,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_BSR,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_EOM,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_BSF_AFTER_EOM,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_NONBLOCKING_OPEN,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_feature_property_fn);
+
+ device_class_register_property(device_class, PROPERTY_FINAL_FILEMARKS,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_final_filemarks_fn);
+
+ /* We don't (yet?) support reading the device's compression state, so not
+ * gettable. */
+ device_class_register_property(device_class, PROPERTY_COMPRESSION,
+ PROPERTY_ACCESS_SET_MASK,
+ NULL,
+ tape_device_set_compression_fn);
+
+ device_class_register_property(device_class, PROPERTY_READ_BUFFER_SIZE,
+ PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
+ device_simple_property_get_fn,
+ tape_device_set_read_buffer_size_fn);
+}
+
+static gboolean
+tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
+ GValue *val, PropertySurety surety, PropertySource source)
+{
+ TapeDevice *self = TAPE_DEVICE(p_self);
+ GValue old_val;
+ gboolean old_bool, new_bool;
+ PropertySurety old_surety;
+ PropertySource old_source;
+
+ new_bool = g_value_get_boolean(val);
+
+ /* get the old source and surety and see if we're willing to make this change */
+ bzero(&old_val, sizeof(old_val));
+ if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
+ old_bool = g_value_get_boolean(&old_val);
+
+ if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
+ if (new_bool != old_bool) {
+ device_set_error(p_self, vstrallocf(_(
+ "Value for property '%s' was autodetected and cannot be changed"),
+ base->name),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return FALSE;
+ } else {
+ /* pretend we set it, but don't change surety/source */
+ return TRUE;
+ }
+ }
+ }
+
+ /* (note: PROPERTY_* are not constants, so we can't use switch) */
+ if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
+ self->broken_gmt_online = new_bool;
+ else if (base->ID == PROPERTY_FSF)
+ self->fsf = new_bool;
+ else if (base->ID == PROPERTY_FSF_AFTER_FILEMARK)
+ self->fsf_after_filemark = new_bool;
+ else if (base->ID == PROPERTY_BSF)
+ self->bsf = new_bool;
+ else if (base->ID == PROPERTY_FSR)
+ self->fsr = new_bool;
+ else if (base->ID == PROPERTY_BSR)
+ self->bsr = new_bool;
+ else if (base->ID == PROPERTY_EOM)
+ self->eom = new_bool;
+ else if (base->ID == PROPERTY_BSF_AFTER_EOM)
+ self->bsf_after_eom = new_bool;
+ else if (base->ID == PROPERTY_NONBLOCKING_OPEN)
+ self->nonblocking_open = new_bool;
+ else
+ return FALSE; /* shouldn't happen */
+
+ return device_simple_property_set_fn(p_self, base, val, surety, source);
+}
+
+static gboolean
+tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
+ GValue *val, PropertySurety surety, PropertySource source)
+{
+ TapeDevice *self = TAPE_DEVICE(p_self);
+ GValue old_val;
+ gboolean old_int, new_int;
+ PropertySurety old_surety;
+ PropertySource old_source;
+
+ new_int = g_value_get_uint(val);
+
+ /* get the old source and surety and see if we're willing to make this change */
+ bzero(&old_val, sizeof(old_val));
+ if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
+ old_int = g_value_get_uint(&old_val);
+
+ if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
+ if (new_int != old_int) {
+ device_set_error(p_self, vstrallocf(_(
+ "Value for property '%s' was autodetected and cannot be changed"),
+ base->name),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return FALSE;
+ } else {
+ /* pretend we set it, but don't change surety/source */
+ return TRUE;
+ }
+ }
+ }
+
+ self->final_filemarks = new_int;
+
+ return device_simple_property_set_fn(p_self, base, val, surety, source);
+}
+
+static gboolean
+tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
+ GValue *val, PropertySurety surety, PropertySource source)
+{
+ TapeDevice *self = TAPE_DEVICE(p_self);
+ gboolean request = g_value_get_boolean(val);
+
+ /* We allow this property to be set at any time. This is mostly
+ * because setting compression is a hit-and-miss proposition
+ * at any time; some drives accept the mode setting but don't
+ * actually support compression, while others do support
+ * compression but do it via density settings or some other
+ * way. Set this property whenever you want, but all we'll do
+ * is report whether or not the ioctl succeeded. */
+ if (tape_setcompression(self->fd, request)) {
+ /* looks good .. let's start the device over, though */
+ device_clear_volume_details(p_self);
+ } else {
+ return FALSE;
+ }
+
+ return device_simple_property_set_fn(p_self, base, val, surety, source);
+}
+
+static gboolean
+tape_device_set_read_buffer_size_fn(Device *p_self, DevicePropertyBase *base,
+ GValue *val, PropertySurety surety, PropertySource source)
+{
+ TapeDevice *self = TAPE_DEVICE(p_self);
+ guint buffer_size = g_value_get_uint(val);
+
+ if (buffer_size != 0 &&
+ ((gsize)buffer_size < p_self->block_size ||
+ (gsize)buffer_size > p_self->max_block_size))
+ return FALSE;
+
+ self->private->read_buffer_size = buffer_size;
+
+ return device_simple_property_set_fn(p_self, base, val, surety, source);
+}
+