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; }
static int large_writev(void) { struct string str; ne_socket *sock; ssize_t n; struct ne_iovec vec[4]; str.data = ne_malloc(LARGE_SIZE); str.len = LARGE_SIZE; for (n = 0; n < LARGE_SIZE; n++) str.data[n] = 41 + n % 130; for (n = 0; n < 4; n++) { vec[n].base = str.data + n * LARGE_SIZE / 4; vec[n].len = LARGE_SIZE / 4; } CALL(begin(&sock, serve_expect, &str)); CALL(full_writev(sock, vec, 4)); ne_free(str.data); return finish(sock, 1); }