extern "C" { #include #define BSTREAM_USE_MALLOC #include #include int bstream_write_blob(backup_stream *s, bstream_blob buf); int bstream_read_blob(backup_stream *s, bstream_blob buf); int bstream_end_chunk(backup_stream *s); } typedef bstream_byte byte; typedef bstream_blob blob; class Stream: public st_backup_stream { public: Stream(const char *path); int open_wr(size_t block_size =0); int open_rd(); int close(); private: const char *m_path; int m_fd; static int write(void*, blob*, blob); static int read(void*, blob*, blob); static int forward(void*, unsigned long*); }; #define CHUNK_SIZE 128 #define BLOCK_SIZE 10 int main() { byte buf[CHUNK_SIZE]; blob data; Stream str("bug45093.bst"); memset(buf,0x5C, CHUNK_SIZE); buf[0]= 0xC5; if (str.open_wr(BLOCK_SIZE)) { perror("Can not open stream for writing!"); exit(2); }; data.begin= buf; data.end= buf + CHUNK_SIZE; bstream_write_blob(&str, data); bstream_end_chunk(&str); data.begin= buf; bstream_write_blob(&str, data); str.close(); if (str.open_rd()) { perror("Can not open stream for reading!"); exit(2); }; data.begin= buf; data.end= buf + CHUNK_SIZE/4 + 1; bstream_read_blob(&str, data); bstream_next_chunk(&str); data.begin= buf; bstream_read_blob(&str, data); if (buf[0] != 0xC5 || buf[1] != 0x5C) { printf("Wrong data! (0x%02X,0x%02X)\n", buf[0],buf[1]); exit(1); } else { printf("Test OK\n"); exit(0); } } /*==================================================================== * * Implementation of Stream class * *====================================================================*/ Stream::Stream(const char *path): m_path(path) { memset(&stream, 0, sizeof(stream)); } int Stream::open_wr(size_t block_size) { // open file for writing m_fd= open(m_path, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); if (m_fd < 0) return BSTREAM_ERROR; stream.write= write; stream.forward= forward; return bstream_open_wr(this, block_size, 0); } int Stream::open_rd() { // open file for reading m_fd= open(m_path, O_RDONLY); if (m_fd < 0) return BSTREAM_ERROR; stream.read= read; stream.forward= forward; return bstream_open_rd(this, 0); } int Stream::close() { (void)bstream_close(this); // close the stream if (m_fd >= 0) ::close(m_fd); return BSTREAM_OK; } int Stream::write(void *stream, blob *buf, blob) { int fd; int res; DBUG_ASSERT(stream); DBUG_ASSERT(buf); Stream *s= (Stream*)stream; fd= s->m_fd; DBUG_ASSERT(fd >= 0); if (!buf->begin || buf->begin == buf->end) return BSTREAM_OK; DBUG_ASSERT(buf->end); size_t howmuch = buf->end - buf->begin; while (howmuch) { ssize_t written= ::write(fd, buf->begin, howmuch); if (written <= 0) return BSTREAM_ERROR; buf->begin += written; howmuch -= written; } return BSTREAM_OK; } int Stream::read(void *stream, blob *buf, blob) { int fd; size_t howmuch; DBUG_ASSERT(stream); DBUG_ASSERT(buf); Stream *s= (Stream*)stream; fd= s->m_fd; DBUG_ASSERT(fd >= 0); if (!buf->begin || buf->begin == buf->end) return BSTREAM_OK; DBUG_ASSERT(buf->end); howmuch= buf->end - buf->begin; while (howmuch) { ssize_t bytes_read= ::read(fd, buf->begin, howmuch); if (bytes_read == 0) return BSTREAM_EOS; if (bytes_read < 0) return BSTREAM_ERROR; buf->begin += bytes_read; howmuch -= bytes_read; } return BSTREAM_OK; } int Stream::forward(void *stream, unsigned long int *offset) { int fd; size_t howmuch; DBUG_ASSERT(stream); DBUG_ASSERT(offset); Stream *s= (Stream*)stream; fd= s->m_fd; DBUG_ASSERT(fd >= 0); if (*offset == 0) return BSTREAM_OK; howmuch= *offset; lseek(fd, howmuch, SEEK_CUR); *offset= 0; return BSTREAM_OK; } /*==================================================================== * * Trivial implementatios of stream library callback functions * *====================================================================*/ int bcat_reset(struct st_bstream_image_header *catalogue) { return BSTREAM_OK; } int bcat_close(struct st_bstream_image_header *catalogue) { return BSTREAM_OK; } int bcat_add_item(struct st_bstream_image_header *catalogue, struct st_bstream_item_info *item) { return BSTREAM_OK; } void* bcat_iterator_get(struct st_bstream_image_header *catalogue, unsigned int type) { return NULL; } struct st_bstream_item_info* bcat_iterator_next(struct st_bstream_image_header *catalogue, void *iter) { return NULL; } void bcat_iterator_free(struct st_bstream_image_header *catalogue, void *iter) {} void* bcat_db_iterator_get(struct st_bstream_image_header *catalogue, struct st_bstream_db_info *db) { return NULL; } /** Return next item from database items iterator */ struct st_bstream_dbitem_info* bcat_db_iterator_next(struct st_bstream_image_header *catalogue, struct st_bstream_db_info *db, void *iter) { return NULL; } /** Free database items iterator resources */ void bcat_db_iterator_free(struct st_bstream_image_header *catalogue, struct st_bstream_db_info *db, void *iter) {} int bcat_get_item_create_query(struct st_bstream_image_header *catalogue, struct st_bstream_item_info *item, bstream_blob *stmt) { return BSTREAM_OK; } int bcat_get_item_create_data(struct st_bstream_image_header *catalogue, struct st_bstream_item_info *item, bstream_blob *data) { return BSTREAM_OK; } int bcat_create_item(struct st_bstream_image_header *catalogue, struct st_bstream_item_info *item, bstream_blob create_stmt, bstream_blob other_meta_data) { return BSTREAM_OK; }