⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rait-device.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 4 页
字号:
    GValue value;          /* IN/OUT */    gboolean label_changed; /* Did the device label change? OUT; _set only*/} PropertyOp;/* Creates a GPtrArray of PropertyOf for a get or set operation. */static GPtrArray * make_property_op_array(RaitDevice * self,                                          DevicePropertyId id,                                          GValue * value) {    guint i;    GPtrArray * ops;    ops = g_ptr_array_sized_new(self->private->children->len);    for (i = 0; i < self->private->children->len; i ++) {        PropertyOp * op;        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->id = id;        bzero(&(op->value), sizeof(op->value));        if (value != NULL) {            g_value_unset_copy(value, &(op->value));        }        g_ptr_array_add(ops, op);    }    return ops;}/* A GFunc. */static void property_get_do_op(gpointer data,                               gpointer user_data G_GNUC_UNUSED) {    PropertyOp * op = data;    bzero(&(op->value), sizeof(op->value));    op->base.result =        GINT_TO_POINTER(device_property_get(op->base.child, op->id,                                            &(op->value)));}/* Merge ConcurrencyParadigm results. */static gboolean property_get_concurrency(GPtrArray * ops, GValue * val) {    ConcurrencyParadigm result = CONCURRENCY_PARADIGM_RANDOM_ACCESS;    guint i = 0;        for (i = 0; i < ops->len; i ++) {        ConcurrencyParadigm cur;        PropertyOp * op = g_ptr_array_index(ops, i);        g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) ==                             CONCURRENCY_PARADIGM_TYPE, FALSE);        cur = g_value_get_enum(&(op->value));        if (result == CONCURRENCY_PARADIGM_EXCLUSIVE ||            cur == CONCURRENCY_PARADIGM_EXCLUSIVE) {            result = CONCURRENCY_PARADIGM_EXCLUSIVE;        } else if (result == CONCURRENCY_PARADIGM_SHARED_READ ||                   cur == CONCURRENCY_PARADIGM_SHARED_READ) {            result = CONCURRENCY_PARADIGM_SHARED_READ;        } else if (result == CONCURRENCY_PARADIGM_RANDOM_ACCESS &&                   cur == CONCURRENCY_PARADIGM_RANDOM_ACCESS) {            result = CONCURRENCY_PARADIGM_RANDOM_ACCESS;        } else {            g_return_val_if_fail(FALSE, FALSE);        }    }    g_value_unset_init(val, CONCURRENCY_PARADIGM_TYPE);    g_value_set_enum(val, result);    return TRUE;}/* Merge StreamingRequirement results. */static gboolean property_get_streaming(GPtrArray * ops, GValue * val) {    StreamingRequirement result = STREAMING_REQUIREMENT_NONE;    guint i = 0;        for (i = 0; i < ops->len; i ++) {        StreamingRequirement cur;        PropertyOp * op = g_ptr_array_index(ops, i);        g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) ==                             STREAMING_REQUIREMENT_TYPE, FALSE);        cur = g_value_get_enum(&(op->value));        if (result == STREAMING_REQUIREMENT_REQUIRED ||            cur == STREAMING_REQUIREMENT_REQUIRED) {            result = STREAMING_REQUIREMENT_REQUIRED;        } else if (result == STREAMING_REQUIREMENT_DESIRED ||                   cur == STREAMING_REQUIREMENT_DESIRED) {            result = STREAMING_REQUIREMENT_DESIRED;        } else if (result == STREAMING_REQUIREMENT_NONE &&                   cur == STREAMING_REQUIREMENT_NONE) {            result = STREAMING_REQUIREMENT_NONE;        } else {            g_return_val_if_fail(FALSE, FALSE);        }    }    g_value_unset_init(val, STREAMING_REQUIREMENT_TYPE);    g_value_set_enum(val, result);    return TRUE;}    /* Merge MediaAccessMode results. */static gboolean property_get_medium_type(GPtrArray * ops, GValue * val) {    MediaAccessMode result = 0;    guint i = 0;    for (i = 0; i < ops->len; i ++) {        MediaAccessMode cur;        PropertyOp * op = g_ptr_array_index(ops, i);        g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) ==                             MEDIA_ACCESS_MODE_TYPE, FALSE);        cur = g_value_get_enum(&(op->value));                if (i == 0) {            result = cur;        } else if ((result == MEDIA_ACCESS_MODE_READ_ONLY &&                    cur == MEDIA_ACCESS_MODE_WRITE_ONLY) ||                   (result == MEDIA_ACCESS_MODE_WRITE_ONLY &&                    cur == MEDIA_ACCESS_MODE_READ_ONLY)) {            /* Invalid combination; one device can only read, other               can only write. */            return FALSE;        } else if (result == MEDIA_ACCESS_MODE_READ_ONLY ||                   cur == MEDIA_ACCESS_MODE_READ_ONLY) {            result = MEDIA_ACCESS_MODE_READ_ONLY;        } else if (result == MEDIA_ACCESS_MODE_WRITE_ONLY ||                   cur == MEDIA_ACCESS_MODE_WRITE_ONLY) {            result = MEDIA_ACCESS_MODE_WRITE_ONLY;        } else if (result == MEDIA_ACCESS_MODE_WORM ||                   cur == MEDIA_ACCESS_MODE_WORM) {            result = MEDIA_ACCESS_MODE_WORM;        } else if (result == MEDIA_ACCESS_MODE_READ_WRITE &&                   cur == MEDIA_ACCESS_MODE_READ_WRITE) {            result = MEDIA_ACCESS_MODE_READ_WRITE;        } else {            g_return_val_if_fail(FALSE, FALSE);        }    }        g_value_unset_init(val, MEDIA_ACCESS_MODE_TYPE);    g_value_set_enum(val, result);    return TRUE;}    /* Merge QualifiedSize results. */static gboolean property_get_free_space(GPtrArray * ops, GValue * val) {    QualifiedSize result;    guint i = 0;    for (i = 0; i < ops->len; i ++) {        QualifiedSize cur;        PropertyOp * op = g_ptr_array_index(ops, i);        g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) ==                             QUALIFIED_SIZE_TYPE, FALSE);        cur = *(QualifiedSize*)(g_value_get_boxed(&(op->value)));        if (result.accuracy != cur.accuracy) {            result.accuracy = SIZE_ACCURACY_ESTIMATE;        }        if (result.accuracy == SIZE_ACCURACY_UNKNOWN &&            cur.accuracy != SIZE_ACCURACY_UNKNOWN) {            result.bytes = cur.bytes;        } else if (result.accuracy != SIZE_ACCURACY_UNKNOWN &&                   cur.accuracy == SIZE_ACCURACY_UNKNOWN) {            /* result.bytes unchanged. */        } else {            result.bytes = MIN(result.bytes, cur.bytes);        }    }    g_value_unset_init(val, QUALIFIED_SIZE_TYPE);    g_value_set_boxed(val, &result);    return TRUE;}    /* Merge boolean results by ANDing them together. */static gboolean property_get_boolean_and(GPtrArray * ops, GValue * val) {    gboolean result = FALSE;    guint i = 0;    for (i = 0; i < ops->len; i ++) {        gboolean cur;        PropertyOp * op = g_ptr_array_index(ops, i);        g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&(op->value)), FALSE);        cur = g_value_get_boolean(&(op->value));        result = result && cur;    }    g_value_unset_init(val, G_TYPE_BOOLEAN);    g_value_set_boolean(val, result);    return TRUE;}    static gboolean rait_device_property_get (Device * dself, DevicePropertyId id, GValue * val) {    GPtrArray * ops;    guint i;    gboolean success;    GValue result;    GValue * first_value;    RaitDevice * self = RAIT_DEVICE(dself);    g_return_val_if_fail(self != NULL, FALSE);    /* Some properties are handled completely differently. */    if (id == PROPERTY_BLOCK_SIZE) {        g_value_unset_init(val, G_TYPE_INT);        g_value_set_int(val, self->private->block_size);        return TRUE;    } else if (id == PROPERTY_MIN_BLOCK_SIZE ||        id == PROPERTY_MAX_BLOCK_SIZE) {        g_value_unset_init(val, G_TYPE_UINT);        g_value_set_uint(val, self->private->block_size);        return TRUE;    } else if (id == PROPERTY_CANONICAL_NAME) {        if (parent_class->property_get != NULL) {            return parent_class->property_get(dself, id, val);        } else {            return FALSE;        }    }    ops = make_property_op_array(self, id, NULL);        do_rait_child_ops(property_get_do_op, ops, NULL);    if (id == PROPERTY_CONCURRENCY) {        success = property_get_concurrency(ops, val);    } else if (id == PROPERTY_STREAMING) {         success = property_get_streaming(ops, val);    } else if (id == PROPERTY_APPENDABLE ||               id == PROPERTY_PARTIAL_DELETION) {        success = property_get_boolean_and(ops, val);    } else if (id == PROPERTY_MEDIUM_TYPE) {        success = property_get_medium_type(ops, val);    } else if (id == PROPERTY_FREE_SPACE) {        success = property_get_free_space(ops, val);    } else {        /* Generic handling; if all results are the same, we succeed           and return that result. If not, we fail. */        success = TRUE;                /* Set up comparison value. */        bzero(&result, sizeof(result));        first_value = &(((PropertyOp*)g_ptr_array_index(ops,0))->value);        if (G_IS_VALUE(first_value)) {            g_value_unset_copy(first_value, &result);        } else {            success = FALSE;        }                for (i = 0; i < ops->len; i ++) {            PropertyOp * op = g_ptr_array_index(ops, i);            if (!GPOINTER_TO_INT(op->base.result) ||                !G_IS_VALUE(first_value) ||                !g_value_compare(&result, &(op->value))) {                success = FALSE;            }            g_value_unset(&(op->value));        }        if (success) {            memcpy(val, &result, sizeof(result));        } else if (G_IS_VALUE(&result)) {            g_value_unset(&result);        }    }    g_ptr_array_free_full(ops);    return success;}/* A GFunc. */static void property_set_do_op(gpointer data,                               gpointer user_data G_GNUC_UNUSED) {    PropertyOp * op = data;    gboolean label_set = (op->base.child->volume_label != NULL);    op->base.result =        GINT_TO_POINTER(device_property_set(op->base.child, op->id,                                            &(op->value)));    op->label_changed = (label_set != (op->base.child->volume_label != NULL));}/* A BooleanExtractor */static gboolean extract_label_changed_property_op(gpointer data) {    PropertyOp * op = data;    return op->label_changed;}/* A GFunc. */static void clear_volume_details_do_op(gpointer data,                                       gpointer user_data G_GNUC_UNUSED) {    GenericOp * op = data;    device_clear_volume_details(op->child);}static gboolean rait_device_property_set (Device * d_self, DevicePropertyId id, GValue * val) {    RaitDevice * self;    GPtrArray * ops;    gboolean success;    gboolean label_changed;    self = RAIT_DEVICE(d_self);    g_return_val_if_fail(self != NULL, FALSE);    ops = make_property_op_array(self, id, val);        do_rait_child_ops(property_set_do_op, ops, NULL);    success = g_ptr_array_union_robust(self, ops, extract_boolean_generic_op);    label_changed =        g_ptr_array_union_robust(self, ops,                                 extract_label_changed_property_op);    g_ptr_array_free_full(ops);    if (label_changed) {        /* At least one device considered this property set a label-changing         * operation, so now we clear labels on all devices. */        ops = make_generic_boolean_op_array(self);        do_rait_child_ops(clear_volume_details_do_op, ops, NULL);        g_ptr_array_free_full(ops);    }    return success;}typedef struct {    GenericOp base;    guint filenum;} RecycleFileOp;/* A GFunc */static void recycle_file_do_op(gpointer data,                               gpointer user_data G_GNUC_UNUSED) {    RecycleFileOp * op = data;    op->base.result =        GINT_TO_POINTER(device_recycle_file(op->base.child, op->filenum));}static gboolean rait_device_recycle_file (Device * dself, guint filenum) {    GPtrArray * ops;    guint i;    gboolean success;    RaitDevice * self = RAIT_DEVICE(dself);    g_return_val_if_fail(self != NULL, FALSE);    ops = g_ptr_array_sized_new(self->private->children->len);    for (i = 0; i < self->private->children->len; i ++) {        RecycleFileOp * op;        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->filenum = filenum;        g_ptr_array_add(ops, op);    }        do_rait_child_ops(recycle_file_do_op, ops, NULL);    success = g_ptr_array_and(ops, extract_boolean_generic_op);    g_ptr_array_free_full(ops);    if (!success) {        return FALSE;    } else if (parent_class->recycle_file) {        return parent_class->recycle_file(dself, filenum);    } else {        return TRUE;    }}/* GFunc */static void finish_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) {    GenericOp * op = data;    op->result = GINT_TO_POINTER(device_finish(op->child));}static gboolean rait_device_finish (Device * self) {    GPtrArray * ops;    gboolean success;    ops = make_generic_boolean_op_array(RAIT_DEVICE(self));        do_rait_child_ops(finish_do_op, ops, NULL);    success = g_ptr_array_and(ops, extract_boolean_generic_op);    g_ptr_array_free_full(ops);    if (!success) {        return FALSE;    } else if (parent_class->finish) {        return parent_class->finish(self);    } else {        return TRUE;    }}Device *rait_device_factory (char * type, char * name) {    Device * rval;    g_assert(0 == strcmp(type, "rait"));    rval = DEVICE(g_object_new(TYPE_RAIT_DEVICE, NULL));    if (!device_open_device(rval, name)) {        g_object_unref(rval);        return NULL;    } else {        return rval;    }}Device * rait_device_new_from_devices(Device ** devices) {    RaitDevice * rval;    int i;    gboolean success = TRUE;    g_return_val_if_fail(devices != NULL && *devices != NULL, NULL);    rval = RAIT_DEVICE(g_object_new(TYPE_RAIT_DEVICE, NULL));    for (i = 0; devices[i] != NULL; i ++) {        g_assert(IS_DEVICE(devices[i]));        if (devices[i]->access_mode != ACCESS_NULL) {            success = FALSE;            break;        }        g_object_ref(devices[i]);        g_ptr_array_add(PRIVATE(rval)->children, devices[i]);    }    success = success && find_block_size(rval);    if (!success) {        g_ptr_array_free(PRIVATE(rval)->children, TRUE);        return NULL;    } else {        register_properties(rval);        return DEVICE(rval);    }}void rait_device_register (void) {    static const char * device_prefix_list[] = {"rait", NULL};    register_device(rait_device_factory, device_prefix_list);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -