Blame device-src/diskflat-device.c

Packit Service 392537
/*
Packit Service 392537
 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
Packit Service 392537
 * Copyright (c) 2009 University of Maryland at College Park
Packit Service 392537
 * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
Packit Service 392537
 * Copyright (c) 2013-2016 Carbonite, Inc.  All Rights Reserved.
Packit Service 392537
 * All Rights Reserved.
Packit Service 392537
 *
Packit Service 392537
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit Service 392537
 * documentation for any purpose is hereby granted without fee, provided that
Packit Service 392537
 * the above copyright notice appear in all copies and that both that
Packit Service 392537
 * copyright notice and this permission notice appear in supporting
Packit Service 392537
 * documentation, and that the name of U.M. not be used in advertising or
Packit Service 392537
 * publicity pertaining to distribution of the software without specific,
Packit Service 392537
 * written prior permission.  U.M. makes no representations about the
Packit Service 392537
 * suitability of this software for any purpose.  It is provided "as is"
Packit Service 392537
 * without express or implied warranty.
Packit Service 392537
 *
Packit Service 392537
 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
Packit Service 392537
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
Packit Service 392537
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit Service 392537
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
Packit Service 392537
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
Packit Service 392537
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit Service 392537
 *
Packit Service 392537
 * Author: Sam Couter <sam@couter.id.au>
Packit Service 392537
 */
Packit Service 392537
Packit Service 392537
#include "amanda.h"
Packit Service 392537
#include "vfs-device.h"
Packit Service 392537
Packit Service 392537
/*
Packit Service 392537
 * Type checking and casting macros
Packit Service 392537
 */
Packit Service 392537
#define TYPE_DISKFLAT_DEVICE	(diskflat_device_get_type())
Packit Service 392537
#define DISKFLAT_DEVICE(obj)	G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_DISKFLAT_DEVICE, DiskflatDevice)
Packit Service 392537
#define DISKFLAT_DEVICE_CONST(obj)	G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_DISKFLAT_DEVICE, DiskflatDevice const)
Packit Service 392537
#define DISKFLAT_DEVICE_CLASS(klass)	G_TYPE_CHECK_CLASS_CAST((klass), TYPE_DISKFLAT_DEVICE, DiskflatDeviceClass)
Packit Service 392537
#define IS_DISKFLAT_DEVICE(obj)	G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_DISKFLAT_DEVICE)
Packit Service 392537
#define DISKFLAT_DEVICE_GET_CLASS(obj)	G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_DISKFLAT_DEVICE, DiskflatDeviceClass)
Packit Service 392537
Packit Service 392537
/* Forward declaration */
Packit Service 392537
static GType diskflat_device_get_type(void);
Packit Service 392537
Packit Service 392537
/*
Packit Service 392537
 * Main object structure
Packit Service 392537
 */
Packit Service 392537
typedef struct _DiskflatDevice DiskflatDevice;
Packit Service 392537
struct _DiskflatDevice {
Packit Service 392537
    VfsDevice __parent__;
Packit Service 392537
Packit Service 392537
    char *filename;
Packit Service 392537
};
Packit Service 392537
Packit Service 392537
/*
Packit Service 392537
 * Class definition
Packit Service 392537
 */
Packit Service 392537
typedef struct _DiskflatDeviceClass DiskflatDeviceClass;
Packit Service 392537
struct _DiskflatDeviceClass {
Packit Service 392537
    VfsDeviceClass __parent__;
Packit Service 392537
};
Packit Service 392537
Packit Service 392537
Packit Service 392537
/* GObject housekeeping */
Packit Service 392537
void
Packit Service 392537
diskflat_device_register(void);
Packit Service 392537
Packit Service 392537
static Device*
Packit Service 392537
diskflat_device_factory(char *device_name, char *device_type, char *device_node);
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_class_init (DiskflatDeviceClass *c);
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_init (DiskflatDevice *self);
Packit Service 392537
Packit Service 392537
/* Methods */
Packit Service 392537
static void
Packit Service 392537
diskflat_device_open_device(Device *dself, char *device_name, char *device_type, char *device_node);
Packit Service 392537
Packit Service 392537
static dumpfile_t *
Packit Service 392537
diskflat_device_seek_file (Device * dself, guint requested_file);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_seek_block (Device * dself, guint64 block);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_erase (Device * dself);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_finish(Device *dself);
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_finalize(GObject *gself);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_start_file_open(Device *dself, dumpfile_t *ji);
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_update_volume_size(Device *dself);
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_release_file(Device *dself);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_clear_and_prepare_label(Device *dself, char *label, char *timestamp);
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_validate(Device *dself);
Packit Service 392537
Packit Service 392537
static GType
Packit Service 392537
diskflat_device_get_type (void)
Packit Service 392537
{
Packit Service 392537
    static GType type = 0;
Packit Service 392537
Packit Service 392537
    if (G_UNLIKELY(type == 0)) {
Packit Service 392537
        static const GTypeInfo info = {
Packit Service 392537
            sizeof (DiskflatDeviceClass),
Packit Service 392537
            (GBaseInitFunc) NULL,
Packit Service 392537
            (GBaseFinalizeFunc) NULL,
Packit Service 392537
            (GClassInitFunc) diskflat_device_class_init,
Packit Service 392537
            (GClassFinalizeFunc) NULL,
Packit Service 392537
            NULL /* class_data */,
Packit Service 392537
            sizeof (DiskflatDevice),
Packit Service 392537
            0 /* n_preallocs */,
Packit Service 392537
            (GInstanceInitFunc) diskflat_device_init,
Packit Service 392537
            NULL
Packit Service 392537
        };
Packit Service 392537
Packit Service 392537
        type = g_type_register_static (TYPE_VFS_DEVICE, "DiskflatDevice",
Packit Service 392537
                                       &info, (GTypeFlags)0);
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    return type;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
void
Packit Service 392537
diskflat_device_register(void)
Packit Service 392537
{
Packit Service 392537
    const char *device_prefix_list[] = { "diskflat", NULL };
Packit Service 392537
Packit Service 392537
    register_device(diskflat_device_factory, device_prefix_list);
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static Device *
Packit Service 392537
diskflat_device_factory(
Packit Service 392537
    char *device_name,
Packit Service 392537
    char *device_type,
Packit Service 392537
    char *device_node)
Packit Service 392537
{
Packit Service 392537
    Device *device;
Packit Service 392537
Packit Service 392537
    g_assert(g_str_has_prefix(device_type, "diskflat"));
Packit Service 392537
Packit Service 392537
    device = DEVICE(g_object_new(TYPE_DISKFLAT_DEVICE, NULL));
Packit Service 392537
    device_open_device(device, device_name, device_type, device_node);
Packit Service 392537
Packit Service 392537
    return device;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_class_init (
Packit Service 392537
    DiskflatDeviceClass *c)
Packit Service 392537
{
Packit Service 392537
    DeviceClass *device_class = DEVICE_CLASS(c);
Packit Service 392537
    GObjectClass *g_object_class = G_OBJECT_CLASS(c);
Packit Service 392537
Packit Service 392537
    device_class->open_device = diskflat_device_open_device;
Packit Service 392537
    device_class->seek_file = diskflat_device_seek_file;
Packit Service 392537
    device_class->seek_block = diskflat_device_seek_block;
Packit Service 392537
    device_class->erase = diskflat_device_erase;
Packit Service 392537
    device_class->finish = diskflat_device_finish;
Packit Service 392537
Packit Service 392537
    g_object_class->finalize = diskflat_device_finalize;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_init (
Packit Service 392537
    DiskflatDevice *self)
Packit Service 392537
{
Packit Service 392537
    Device *dself = DEVICE(self);
Packit Service 392537
    VfsDevice *vself = VFS_DEVICE(self);
Packit Service 392537
    GValue val;
Packit Service 392537
Packit Service 392537
    vself->device_start_file_open = &diskflat_device_start_file_open;
Packit Service 392537
    vself->update_volume_size = &diskflat_update_volume_size;
Packit Service 392537
    vself->release_file = &diskflat_release_file;
Packit Service 392537
    vself->clear_and_prepare_label = &diskflat_clear_and_prepare_label;
Packit Service 392537
    vself->validate = &diskflat_validate;
Packit Service 392537
Packit Service 392537
    bzero(&val, sizeof(val));
Packit Service 392537
Packit Service 392537
    g_value_init(&val, G_TYPE_BOOLEAN);
Packit Service 392537
    g_value_set_boolean(&val, FALSE);
Packit Service 392537
    device_set_simple_property(dself, PROPERTY_APPENDABLE,
Packit Service 392537
	&val, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
Packit Service 392537
    g_value_unset(&val;;
Packit Service 392537
Packit Service 392537
    g_value_init(&val, G_TYPE_BOOLEAN);
Packit Service 392537
    g_value_set_boolean(&val, FALSE);
Packit Service 392537
    device_set_simple_property(dself, PROPERTY_PARTIAL_DELETION,
Packit Service 392537
	&val, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
Packit Service 392537
    g_value_unset(&val;;
Packit Service 392537
Packit Service 392537
    g_value_init(&val, G_TYPE_BOOLEAN);
Packit Service 392537
    g_value_set_boolean(&val, TRUE);
Packit Service 392537
    device_set_simple_property(dself, PROPERTY_FULL_DELETION,
Packit Service 392537
	&val, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
Packit Service 392537
    g_value_unset(&val;;
Packit Service 392537
Packit Service 392537
    g_value_init(&val, G_TYPE_BOOLEAN);
Packit Service 392537
    g_value_set_boolean(&val, TRUE);
Packit Service 392537
    device_set_simple_property(dself, PROPERTY_LEOM,
Packit Service 392537
	&val, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
Packit Service 392537
    g_value_unset(&val;;
Packit Service 392537
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_open_device(
Packit Service 392537
    Device *dself,
Packit Service 392537
    char *device_name,
Packit Service 392537
    char *device_type,
Packit Service 392537
    char *device_node)
Packit Service 392537
{
Packit Service 392537
    DiskflatDevice *self = DISKFLAT_DEVICE(dself);
Packit Service 392537
    VfsDevice *vself = VFS_DEVICE(dself);
Packit Service 392537
    char *d;
Packit Service 392537
    DeviceClass *parent_class = DEVICE_CLASS(g_type_class_peek_parent(DISKFLAT_DEVICE_GET_CLASS(dself)));
Packit Service 392537
Packit Service 392537
    self->filename = g_strdup(device_node);
Packit Service 392537
    g_debug("device_node: %s", self->filename);
Packit Service 392537
Packit Service 392537
    parent_class->open_device(dself, device_name, device_type, device_node);
Packit Service 392537
Packit Service 392537
    /* retrieve the directory */
Packit Service 392537
    if ((d = rindex(vself->dir_name, '/')) != NULL) {
Packit Service 392537
	*d = '\0';
Packit Service 392537
	if ((d = rindex(vself->dir_name, '/')) != NULL) {
Packit Service 392537
	    *d = '\0';
Packit Service 392537
	}
Packit Service 392537
    }
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_start_file_open(
Packit Service 392537
    Device     *dself,
Packit Service 392537
    dumpfile_t *ji G_GNUC_UNUSED)
Packit Service 392537
{
Packit Service 392537
    if (dself->file >= 1) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Can't write more than one file to the diskflat device")),
Packit Service 392537
            DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    dself->file++;
Packit Service 392537
    return TRUE;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static dumpfile_t *
Packit Service 392537
diskflat_device_seek_file(
Packit Service 392537
    Device *dself,
Packit Service 392537
    guint requested_file)
Packit Service 392537
{
Packit Service 392537
    VfsDevice     *vself = VFS_DEVICE(dself);
Packit Service 392537
    DiskflatDevice *self  = DISKFLAT_DEVICE(dself);
Packit Service 392537
    dumpfile_t *rval;
Packit Service 392537
    char header_buffer[VFS_DEVICE_LABEL_SIZE];
Packit Service 392537
    int header_buffer_size = sizeof(header_buffer);
Packit Service 392537
    IoResult result;
Packit Service 392537
    off_t result_seek;
Packit Service 392537
Packit Service 392537
    if (device_in_error(dself)) return NULL;
Packit Service 392537
    if (requested_file > 1) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Can't seek to file number above 1")),
Packit Service 392537
            DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	return NULL;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    /* read_label before start */
Packit Service 392537
    if (requested_file == 0 && vself->open_file_fd == -1) {
Packit Service 392537
	vself->open_file_fd = robust_open(self->filename,
Packit Service 392537
                                          O_RDONLY, 0);
Packit Service 392537
	if (vself->open_file_fd < 0) {
Packit Service 392537
	    if (errno == ENOENT) {
Packit Service 392537
		device_set_error(dself,
Packit Service 392537
		    g_strdup_printf(_("Couldn't open file %s: %s (unlabeled)"), self->filename, strerror(errno)),
Packit Service 392537
			DEVICE_STATUS_VOLUME_UNLABELED);
Packit Service 392537
		rval = g_new(dumpfile_t, 1);
Packit Service 392537
		fh_init(rval);
Packit Service 392537
		return rval;
Packit Service 392537
	    } else {
Packit Service 392537
		device_set_error(dself,
Packit Service 392537
		    g_strdup_printf(_("Couldn't open file %s: %s"), self->filename, strerror(errno)),
Packit Service 392537
			DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
		return NULL;
Packit Service 392537
	    }
Packit Service 392537
	}
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    dself->is_eof = FALSE;
Packit Service 392537
    dself->block = 0;
Packit Service 392537
    g_mutex_lock(dself->device_mutex);
Packit Service 392537
    dself->in_file = FALSE;
Packit Service 392537
    dself->bytes_read = 0;
Packit Service 392537
    g_mutex_unlock(dself->device_mutex);
Packit Service 392537
Packit Service 392537
    result_seek = lseek(vself->open_file_fd, requested_file * DISK_BLOCK_BYTES,
Packit Service 392537
			SEEK_SET);
Packit Service 392537
    if (result_seek == -1) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Error seeking within file: %s"), strerror(errno)),
Packit Service 392537
            DEVICE_STATUS_DEVICE_ERROR);
Packit Service 392537
        return NULL;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    result = vfs_device_robust_read(vself, header_buffer,
Packit Service 392537
                                    &header_buffer_size);
Packit Service 392537
    if (result == RESULT_NO_DATA) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Problem reading Amanda header: empty file")),
Packit Service 392537
            DEVICE_STATUS_VOLUME_UNLABELED);
Packit Service 392537
        return NULL;
Packit Service 392537
    } else if (result != RESULT_SUCCESS) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Problem reading Amanda header: %s"), device_error(dself)),
Packit Service 392537
            DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
        return NULL;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    rval = g_new(dumpfile_t, 1);
Packit Service 392537
    parse_file_header(header_buffer, rval, header_buffer_size);
Packit Service 392537
    switch (rval->type) {
Packit Service 392537
	case F_DUMPFILE:
Packit Service 392537
	case F_CONT_DUMPFILE:
Packit Service 392537
	case F_SPLIT_DUMPFILE:
Packit Service 392537
	    break;
Packit Service 392537
Packit Service 392537
	case F_TAPESTART:
Packit Service 392537
	    /* file 0 should have a TAPESTART header; diskflat_device_read_label
Packit Service 392537
	        * uses this */
Packit Service 392537
	    if (requested_file == 0)
Packit Service 392537
		break;
Packit Service 392537
	    /* FALLTHROUGH */
Packit Service 392537
Packit Service 392537
	default:
Packit Service 392537
	    device_set_error(dself,
Packit Service 392537
		g_strdup(_("Invalid amanda header while reading file header")),
Packit Service 392537
		DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	    amfree(rval);
Packit Service 392537
	    return NULL;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    /* update our state */
Packit Service 392537
    if (requested_file == 0) {
Packit Service 392537
	dself->header_block_size = header_buffer_size;
Packit Service 392537
    } else {
Packit Service 392537
	g_mutex_lock(dself->device_mutex);
Packit Service 392537
	dself->in_file = TRUE;
Packit Service 392537
	g_mutex_unlock(dself->device_mutex);
Packit Service 392537
    }
Packit Service 392537
    dself->file = requested_file;
Packit Service 392537
Packit Service 392537
    return rval;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_seek_block(
Packit Service 392537
    Device *dself,
Packit Service 392537
    guint64 block)
Packit Service 392537
{
Packit Service 392537
    DiskflatDevice *self;
Packit Service 392537
    VfsDevice *vself;
Packit Service 392537
    off_t result;
Packit Service 392537
Packit Service 392537
    self = DISKFLAT_DEVICE(dself);
Packit Service 392537
    vself = VFS_DEVICE(dself);
Packit Service 392537
Packit Service 392537
    g_assert(vself->open_file_fd >= 0);
Packit Service 392537
    g_assert(sizeof(off_t) >= sizeof(guint64));
Packit Service 392537
    if (device_in_error(self)) return FALSE;
Packit Service 392537
Packit Service 392537
    /* Pretty simple. We figure out the blocksize and use that. */
Packit Service 392537
    result = lseek(vself->open_file_fd,
Packit Service 392537
                   (block) * dself->block_size + 2 * VFS_DEVICE_LABEL_SIZE,
Packit Service 392537
                   SEEK_SET);
Packit Service 392537
Packit Service 392537
    dself->block = block;
Packit Service 392537
Packit Service 392537
    if (result == (off_t)(-1)) {
Packit Service 392537
        device_set_error(dself,
Packit Service 392537
            g_strdup_printf(_("Error seeking within file: %s"), strerror(errno)),
Packit Service 392537
            DEVICE_STATUS_DEVICE_ERROR);
Packit Service 392537
        return FALSE;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    return TRUE;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_erase(
Packit Service 392537
    Device *dself)
Packit Service 392537
{
Packit Service 392537
    DiskflatDevice *self = DISKFLAT_DEVICE(dself);
Packit Service 392537
    VfsDevice *vself = VFS_DEVICE(dself);
Packit Service 392537
Packit Service 392537
    if (vself->open_file_fd >= 0) {
Packit Service 392537
	robust_close(vself->open_file_fd);
Packit Service 392537
	vself->open_file_fd = -1;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    if (unlink(self->filename) == -1 && errno != ENOENT)  {
Packit Service 392537
	device_set_error(dself,
Packit Service 392537
	    g_strdup_printf(_("Can't unlink file %s: %s"), self->filename, strerror(errno)),
Packit Service 392537
			    DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
    vself->release_file(dself);
Packit Service 392537
Packit Service 392537
    dumpfile_free(dself->volume_header);
Packit Service 392537
    dself->volume_header = NULL;
Packit Service 392537
    device_set_error(dself, g_strdup("Unlabeled volume"),
Packit Service 392537
                     DEVICE_STATUS_VOLUME_UNLABELED);
Packit Service 392537
Packit Service 392537
    return TRUE;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_device_finish(
Packit Service 392537
    Device *dself)
Packit Service 392537
{
Packit Service 392537
    VfsDevice *vself = VFS_DEVICE(dself);
Packit Service 392537
    gboolean result;
Packit Service 392537
    DeviceClass *parent_class = DEVICE_CLASS(g_type_class_peek_parent(DISKFLAT_DEVICE_GET_CLASS(dself)));
Packit Service 392537
Packit Service 392537
    g_debug("Finish DISKFLAT device");
Packit Service 392537
Packit Service 392537
    /* Save access mode before parent class messes with it */
Packit Service 392537
    if (vself->open_file_fd != -1) {
Packit Service 392537
	robust_close(vself->open_file_fd);
Packit Service 392537
	vself->open_file_fd = -1;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    result = parent_class->finish(dself);
Packit Service 392537
Packit Service 392537
    if (!result || device_in_error(dself)) {
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    return TRUE;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
diskflat_device_finalize(
Packit Service 392537
    GObject *gself)
Packit Service 392537
{
Packit Service 392537
    DiskflatDevice *self  = DISKFLAT_DEVICE(gself);
Packit Service 392537
Packit Service 392537
    GObjectClass *parent_class = G_OBJECT_CLASS(g_type_class_peek_parent(DISKFLAT_DEVICE_GET_CLASS(gself)));
Packit Service 392537
Packit Service 392537
    if (parent_class->finalize) {
Packit Service 392537
	parent_class->finalize(gself);
Packit Service 392537
    }
Packit Service 392537
    amfree(self->filename);
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static void 
Packit Service 392537
diskflat_release_file(
Packit Service 392537
    Device *dselfi G_GNUC_UNUSED)
Packit Service 392537
{
Packit Service 392537
    return;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
void
Packit Service 392537
diskflat_update_volume_size(
Packit Service 392537
    Device *dself)
Packit Service 392537
{
Packit Service 392537
    VfsDevice     *vself = VFS_DEVICE(dself);
Packit Service 392537
    DiskflatDevice *self  = DISKFLAT_DEVICE(dself);
Packit Service 392537
    struct stat stat_buf;
Packit Service 392537
Packit Service 392537
    /* stat the file */
Packit Service 392537
    if (stat(self->filename, &stat_buf) < 0) {
Packit Service 392537
	g_warning("Couldn't stat file %s: %s", self->filename, strerror(errno));
Packit Service 392537
	return;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    vself->volume_bytes += stat_buf.st_size;
Packit Service 392537
Packit Service 392537
    return;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_clear_and_prepare_label(
Packit Service 392537
    Device *dself,
Packit Service 392537
    char *label,
Packit Service 392537
    char *timestamp)
Packit Service 392537
{
Packit Service 392537
    dumpfile_t *label_header;
Packit Service 392537
    VfsDevice *vself = VFS_DEVICE(dself);
Packit Service 392537
    DiskflatDevice *self = DISKFLAT_DEVICE(dself);
Packit Service 392537
Packit Service 392537
    vself->open_file_fd = robust_open(self->filename,
Packit Service 392537
                                     O_CREAT | O_WRONLY,
Packit Service 392537
                                     VFS_DEVICE_CREAT_MODE);
Packit Service 392537
    if (vself->open_file_fd < 0) {
Packit Service 392537
	device_set_error(dself,
Packit Service 392537
	    g_strdup_printf(_("Can't open file %s: %s"), self->filename, strerror(errno)),
Packit Service 392537
	    DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
    label_header = make_tapestart_header(dself, label, timestamp);
Packit Service 392537
    if (!vfs_write_amanda_header(vself, label_header)) {
Packit Service 392537
	/* vfs_write_amanda_header sets error status if necessary */
Packit Service 392537
	dumpfile_free(label_header);
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
    dumpfile_free(dself->volume_header);
Packit Service 392537
    if (ftruncate(vself->open_file_fd, VFS_DEVICE_LABEL_SIZE) == -1) {
Packit Service 392537
	device_set_error(dself,
Packit Service 392537
	    g_strdup_printf("ftruncate of '%s' failed: %s", self->filename, strerror(errno)),
Packit Service 392537
	    DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
Packit Service 392537
	return FALSE;
Packit Service 392537
    }
Packit Service 392537
    dself->header_block_size = VFS_DEVICE_LABEL_SIZE;
Packit Service 392537
    dself->volume_header = label_header;
Packit Service 392537
    dself->file = 0;
Packit Service 392537
    vself->volume_bytes = VFS_DEVICE_LABEL_SIZE;
Packit Service 392537
    return TRUE;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static gboolean
Packit Service 392537
diskflat_validate(
Packit Service 392537
    Device *dself G_GNUC_UNUSED)
Packit Service 392537
{
Packit Service 392537
    return TRUE;
Packit Service 392537
}