|
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 |
}
|