Пример #1
0
static gboolean
flush_buffer(
	amar_t *archive,
	GError **error)
{
    if (archive->buf_len) {
	if (full_write(archive->fd, archive->buf, archive->buf_len) != archive->buf_len) {
	    g_set_error(error, amar_error_quark(), errno,
			"Error writing to amanda archive: %s", strerror(errno));
	    return FALSE;
	}
	archive->buf_len = 0;
    }

    return TRUE;
}
Пример #2
0
static gboolean
write_record(
	amar_t *archive,
	amar_file_t *file,
	guint16  attrid,
	gboolean eoa,
	gpointer data,
	gsize data_size,
	GError **error)
{
    /* the buffer always has room for a new record header */
    MKRECORD(archive->buf + archive->buf_len, file->filenum, attrid, data_size, eoa);
    archive->buf_len += RECORD_SIZE;

    /* is it worth copying this record into the buffer? */
    if (archive->buf_len + RECORD_SIZE + data_size < WRITE_BUFFER_SIZE - RECORD_SIZE) {
	/* yes, it is */
	if (data_size)
	    memcpy(archive->buf + archive->buf_len, data, data_size);
	archive->buf_len += data_size;
    } else {
	/* no, it's not */
	struct iovec iov[2];

	/* flush the buffer and write the new data, all in one syscall */
	iov[0].iov_base = archive->buf;
	iov[0].iov_len = archive->buf_len;
	iov[1].iov_base = data;
	iov[1].iov_len = data_size;
	if (full_writev(archive->fd, iov, 2) < 0) {
	    g_set_error(error, amar_error_quark(), errno,
			"Error writing to amanda archive: %s", strerror(errno));
	    return FALSE;
	}
	archive->buf_len = 0;
    }

    archive->position += data_size + RECORD_SIZE;
    file->size += data_size + RECORD_SIZE;
    return TRUE;
}
Пример #3
0
amar_file_t *
amar_new_file(
    amar_t *archive,
    char *filename_buf,
    gsize filename_len,
    off_t *header_offset,
    GError **error)
{
    amar_file_t *file = NULL;

    g_assert(archive->mode == O_WRONLY);
    g_assert(filename_buf != NULL);

    /* set filename_len if it wasn't specified */
    if (!filename_len)
	filename_len = strlen(filename_buf);
    g_assert(filename_len != 0);

    if (filename_len > MAX_RECORD_DATA_SIZE) {
	g_set_error(error, amar_error_quark(), ENOSPC,
		    "filename is too long for an amanda archive");
	return NULL;
    }

    /* pick a new, unused filenum */

    if (g_hash_table_size(archive->files) == 65535) {
	g_set_error(error, amar_error_quark(), ENOSPC,
		    "No more file numbers available");
	return NULL;
    }

    do {
	gint filenum;

	archive->maxfilenum++;

	/* MAGIC_FILENUM can't be used because it matches the header record text */
	if (archive->maxfilenum == MAGIC_FILENUM) {
	    continue;
	}

	/* see if this fileid is already in use */
	filenum = archive->maxfilenum;
	if (g_hash_table_lookup(archive->files, &filenum))
	    continue;

    } while (0);

    file = g_new0(amar_file_t, 1);
    if (!file) {
	g_set_error(error, amar_error_quark(), ENOSPC,
		    "No more memory");
	return NULL;
    }
    file->archive = archive;
    file->filenum = archive->maxfilenum;
    file->attributes = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free);
    g_hash_table_insert(archive->files, &file->filenum, file);

    /* record the current position and write a header there, if desired */
    if (header_offset) {
	*header_offset = archive->position;
	if (!write_header(archive, error))
	    goto error_exit;
    }

    /* add a filename record */
    if (!write_record(archive, file->filenum, AMAR_ATTR_FILENAME,
		      1, filename_buf, filename_len, error))
	goto error_exit;

    return file;

error_exit:
    if (file) {
	g_hash_table_remove(archive->files, &file->filenum);
	g_hash_table_destroy(file->attributes);
	g_free(file);
    }
    return NULL;
}