static ssize_t ra_neon_body_provider(void *userdata, char *buffer, size_t buflen) { body_provider_baton_t *b = userdata; svn_ra_neon__request_t *req = b->req; apr_file_t *body_file = b->body_file; if (req->sess->callbacks && req->sess->callbacks->cancel_func) SVN_RA_NEON__REQ_ERR (req, (req->sess->callbacks->cancel_func)(req->sess->callback_baton)); if (req->err) return -1; svn_pool_clear(req->iterpool); if (buflen == 0) { /* This is the beginning of a new body pull. Rewind the file. */ apr_off_t offset = 0; SVN_RA_NEON__REQ_ERR (b->req, svn_io_file_seek(body_file, APR_SET, &offset, req->iterpool)); return (req->err ? -1 : 0); } else { apr_size_t nbytes = buflen; svn_error_t *err = svn_io_file_read(body_file, buffer, &nbytes, req->iterpool); if (err) { if (APR_STATUS_IS_EOF(err->apr_err)) { svn_error_clear(err); return 0; } SVN_RA_NEON__REQ_ERR(req, err); return -1; } else return nbytes; } }
/* Copy FILENAME from SRC_DIR to DST_DIR in byte increments of size CHUNKSIZE. The read/write buffer of size CHUNKSIZE will be allocated in POOL. If ALLOW_MISSING is set, we won't make a fuss if FILENAME isn't found in SRC_DIR; otherwise, we will. */ static svn_error_t * copy_db_file_safely(const char *src_dir, const char *dst_dir, const char *filename, u_int32_t chunksize, svn_boolean_t allow_missing, apr_pool_t *pool) { apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */ const char *file_src_path = svn_dirent_join(src_dir, filename, pool); const char *file_dst_path = svn_dirent_join(dst_dir, filename, pool); svn_error_t *err; char *buf; /* Open source file. If it's missing and that's allowed, there's nothing more to do here. */ err = svn_io_file_open(&s, file_src_path, (APR_READ | APR_LARGEFILE), APR_OS_DEFAULT, pool); if (err && APR_STATUS_IS_ENOENT(err->apr_err) && allow_missing) { svn_error_clear(err); return SVN_NO_ERROR; } SVN_ERR(err); /* Open destination file. */ SVN_ERR(svn_io_file_open(&d, file_dst_path, (APR_WRITE | APR_CREATE | APR_LARGEFILE), APR_OS_DEFAULT, pool)); /* Allocate our read/write buffer. */ buf = apr_palloc(pool, chunksize); /* Copy bytes till the cows come home. */ while (1) { apr_size_t bytes_this_time = chunksize; svn_error_t *read_err, *write_err; /* Read 'em. */ if ((read_err = svn_io_file_read(s, buf, &bytes_this_time, pool))) { if (APR_STATUS_IS_EOF(read_err->apr_err)) svn_error_clear(read_err); else { svn_error_clear(svn_io_file_close(s, pool)); svn_error_clear(svn_io_file_close(d, pool)); return read_err; } } /* Write 'em. */ if ((write_err = svn_io_file_write_full(d, buf, bytes_this_time, NULL, pool))) { svn_error_clear(svn_io_file_close(s, pool)); svn_error_clear(svn_io_file_close(d, pool)); return write_err; } /* read_err is either NULL, or a dangling pointer - but it is only a dangling pointer if it used to be an EOF error. */ if (read_err) { SVN_ERR(svn_io_file_close(s, pool)); SVN_ERR(svn_io_file_close(d, pool)); break; /* got EOF on read, all files closed, all done. */ } } return SVN_NO_ERROR; }
/* Return a memblock of content, if any is available. *mem will be NULL if no further content is available. The memblock should eventually be passed to return_buffer() (or stored into buf->out_for_reading which will grab that block at the next get_buffer() call). */ static svn_error_t * read_data(struct memblock_t **mem, svn_spillbuf_t *buf, apr_pool_t *scratch_pool) { svn_error_t *err; /* If we have some in-memory blocks, then return one. */ if (buf->head != NULL) { *mem = buf->head; if (buf->tail == *mem) buf->head = buf->tail = NULL; else buf->head = (*mem)->next; /* We're using less memory now. If we haven't hit the spill file, then we may be able to keep using memory. */ buf->memory_size -= (*mem)->size; return SVN_NO_ERROR; } /* No file? Done. */ if (buf->spill == NULL) { *mem = NULL; return SVN_NO_ERROR; } /* Assume that the caller has seeked the spill file to the correct pos. */ /* Get a buffer that we can read content into. */ *mem = get_buffer(buf); /* NOTE: mem's size/next are uninitialized. */ if ((apr_uint64_t)buf->spill_size < (apr_uint64_t)buf->blocksize) (*mem)->size = (apr_size_t)buf->spill_size; else (*mem)->size = buf->blocksize; /* The size of (*mem)->data */ (*mem)->next = NULL; /* Read some data from the spill file into the memblock. */ err = svn_io_file_read(buf->spill, (*mem)->data, &(*mem)->size, scratch_pool); if (err) { return_buffer(buf, *mem); return svn_error_trace(err); } /* Mark the data that we consumed from the spill file. */ buf->spill_start += (*mem)->size; /* Did we consume all the data from the spill file? */ if ((buf->spill_size -= (*mem)->size) == 0) { /* Close and reset our spill file information. */ SVN_ERR(svn_io_file_close(buf->spill, scratch_pool)); buf->spill = NULL; buf->spill_start = 0; } /* *mem has been initialized. Done. */ return SVN_NO_ERROR; }