static svn_error_t * read_handler_apr(void *baton, char *buffer, apr_size_t *len) { struct baton_apr *btn = baton; svn_error_t *err; svn_boolean_t eof; if (*len == 1) { err = svn_io_file_getc(buffer, btn->file, btn->pool); if (err) { *len = 0; if (APR_STATUS_IS_EOF(err->apr_err)) { svn_error_clear(err); err = SVN_NO_ERROR; } } } else err = svn_io_file_read_full2(btn->file, buffer, *len, len, &eof, btn->pool); return svn_error_trace(err); }
/* There are enough quirks in the deprecated svn_hash_read that we should just preserve its implementation. */ svn_error_t * svn_hash_read(apr_hash_t *hash, apr_file_t *srcfile, apr_pool_t *pool) { svn_error_t *err; char buf[SVN_KEYLINE_MAXLEN]; apr_size_t num_read; char c; int first_time = 1; while (1) { /* Read a key length line. Might be END, though. */ apr_size_t len = sizeof(buf); err = svn_io_read_length_line(srcfile, buf, &len, pool); if (err && APR_STATUS_IS_EOF(err->apr_err) && first_time) { /* We got an EOF on our very first attempt to read, which means it's a zero-byte file. No problem, just go home. */ svn_error_clear(err); return SVN_NO_ERROR; } else if (err) /* Any other circumstance is a genuine error. */ return err; first_time = 0; if (((len == 3) && (buf[0] == 'E') && (buf[1] == 'N') && (buf[2] == 'D')) || ((len == 9) && (buf[0] == 'P') && (buf[1] == 'R') /* We formerly used just "END" to */ && (buf[2] == 'O') /* end a property hash, but later */ && (buf[3] == 'P') /* we added "PROPS-END", so that */ && (buf[4] == 'S') /* the fs dump format would be */ && (buf[5] == '-') /* more human-readable. That's */ && (buf[6] == 'E') /* why we accept either way here. */ && (buf[7] == 'N') && (buf[8] == 'D'))) { /* We've reached the end of the dumped hash table, so leave. */ return SVN_NO_ERROR; } else if ((buf[0] == 'K') && (buf[1] == ' ')) { size_t keylen; int parsed_len; void *keybuf; /* Get the length of the key */ SVN_ERR(svn_cstring_atoi(&parsed_len, buf + 2)); keylen = parsed_len; /* Now read that much into a buffer, + 1 byte for null terminator */ keybuf = apr_palloc(pool, keylen + 1); SVN_ERR(svn_io_file_read_full2(srcfile, keybuf, keylen, &num_read, NULL, pool)); ((char *) keybuf)[keylen] = '\0'; /* Suck up extra newline after key data */ SVN_ERR(svn_io_file_getc(&c, srcfile, pool)); if (c != '\n') return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL); /* Read a val length line */ len = sizeof(buf); SVN_ERR(svn_io_read_length_line(srcfile, buf, &len, pool)); if ((buf[0] == 'V') && (buf[1] == ' ')) { svn_string_t *value = apr_palloc(pool, sizeof(*value)); apr_size_t vallen; void *valbuf; /* Get the length of the value */ SVN_ERR(svn_cstring_atoi(&parsed_len, buf + 2)); vallen = parsed_len; /* Again, 1 extra byte for the null termination. */ valbuf = apr_palloc(pool, vallen + 1); SVN_ERR(svn_io_file_read_full2(srcfile, valbuf, vallen, &num_read, NULL, pool)); ((char *) valbuf)[vallen] = '\0'; /* Suck up extra newline after val data */ SVN_ERR(svn_io_file_getc(&c, srcfile, pool)); if (c != '\n') return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL); value->data = valbuf; value->len = vallen; /* The Grand Moment: add a new hash entry! */ apr_hash_set(hash, keybuf, keylen, value); } else { return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL); } } else { return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL); } } /* while (1) */ }