2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2005-2008 Zmanda Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #define selfp (self->_priv)
22 #include "taper-port-source.h"
24 /* here are local prototypes */
25 static void taper_port_source_class_init (TaperPortSourceClass * c);
26 static ssize_t taper_port_source_read (TaperSource * pself, void * buf,
28 static void taper_port_source_init (TaperPortSource * self);
29 static gboolean taper_port_source_is_partial(TaperSource * self);
30 static int taper_port_source_predict_parts(TaperSource * pself);
31 static dumpfile_t * taper_port_source_get_first_header(TaperSource * pself);
34 /* pointer to the class of our parent */
35 static TaperSourceClass *parent_class = NULL;
38 taper_port_source_get_type (void)
40 static GType type = 0;
42 if G_UNLIKELY(type == 0) {
43 static const GTypeInfo info = {
44 sizeof (TaperPortSourceClass),
46 (GBaseFinalizeFunc) NULL,
47 (GClassInitFunc) taper_port_source_class_init,
48 (GClassFinalizeFunc) NULL,
49 NULL /* class_data */,
50 sizeof (TaperPortSource),
52 (GInstanceInitFunc) taper_port_source_init,
56 type = g_type_register_static (TAPER_SOURCE_TYPE, "TaperPortSource",
57 &info, (GTypeFlags)0);
63 static void taper_port_source_finalize(GObject * obj_self) {
64 TaperPortSource *self = TAPER_PORT_SOURCE(obj_self);
65 if (self->socket_fd >= 0) {
66 aclose(self->socket_fd);
69 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
72 static void taper_port_source_class_init (TaperPortSourceClass * c) {
73 TaperSourceClass *taper_source_class = (TaperSourceClass *)c;
74 GObjectClass *g_object_class = (GObjectClass*)c;
76 parent_class = g_type_class_ref (TAPER_SOURCE_TYPE);
78 taper_source_class->read = taper_port_source_read;
79 taper_source_class->is_partial = taper_port_source_is_partial;
80 taper_source_class->get_first_header = taper_port_source_get_first_header;
81 taper_source_class->predict_parts = taper_port_source_predict_parts;
83 g_object_class->finalize = taper_port_source_finalize;
86 /* Check if the header has been read; if not, read and parse it. */
87 static void check_first_header(TaperPortSource * self) {
88 TaperSource * pself = (TaperSource*)self;
89 char buf[DISK_BLOCK_BYTES];
93 if (G_LIKELY(pself->first_header != NULL)) {
97 result = full_read(self->socket_fd, buf, DISK_BLOCK_BYTES);
98 if (result != DISK_BLOCK_BYTES) {
101 rval = malloc(sizeof(dumpfile_t));
102 parse_file_header(buf, rval, DISK_BLOCK_BYTES);
103 pself->first_header = rval;
106 static int taper_port_source_predict_parts(TaperSource * pself) {
107 TaperPortSource * self = TAPER_PORT_SOURCE(pself);
108 g_return_val_if_fail(self != NULL, -1);
113 static dumpfile_t * taper_port_source_get_first_header(TaperSource * pself) {
114 TaperPortSource * self = TAPER_PORT_SOURCE(pself);
115 g_return_val_if_fail(self != NULL, NULL);
117 check_first_header(self);
119 if (parent_class->get_first_header) {
120 return (parent_class->get_first_header)(pself);
126 static void taper_port_source_init (TaperPortSource * self) {
127 /* Subclasses may do as they please, but if we are the final word,
128 then there will be no rewinding. */
129 if (G_TYPE_FROM_INSTANCE(self) == TAPER_TYPE_PORT_SOURCE) {
130 TAPER_SOURCE(self)->max_part_size = 0;
132 self->socket_fd = -1;
135 static ssize_t taper_port_source_read (TaperSource * pself, void * buf,
137 TaperPortSource * self = (TaperPortSource*)pself;
139 g_return_val_if_fail (self != NULL, -1);
140 g_return_val_if_fail (TAPER_IS_PORT_SOURCE (pself), -1);
141 g_return_val_if_fail (buf != NULL, -1);
142 g_return_val_if_fail (count > 0, -1);
144 check_first_header(self);
147 read_result = read(self->socket_fd, buf, count);
148 if (read_result > 0) {
150 } else if (read_result == 0) {
151 pself->end_of_data = TRUE;
152 aclose(self->socket_fd);
159 || errno == EWOULDBLOCK
173 g_assert_not_reached();
177 taper_port_source_is_partial(TaperSource * pself) {
178 struct cmdargs *cmdargs;
180 TaperPortSource * self = (TaperPortSource*)pself;
182 g_return_val_if_fail(self->socket_fd < 0, FALSE);
184 /* Query DRIVER about partial dump. */
185 putresult(DUMPER_STATUS, "%s\n", pself->driver_handle);
187 if (cmdargs->cmd == FAILED) {
189 } else if (cmdargs->cmd == DONE) {
192 error("Driver gave invalid response "
193 "to query DUMPER-STATUS.\n");
194 g_assert_not_reached();
197 free_cmdargs(cmdargs);