/* * Read the entire contents of a file into a buffer. This is a slight * optimization over buffer_read_all because it can stat the file descriptor * first and size the buffer appropriately. buffer_read_all will still handle * the case where the file size changes while it's being read. Returns true * on success, false on failure (in which case errno will be set). */ bool buffer_read_file(struct buffer *buffer, int fd) { struct stat st; size_t used = buffer->used + buffer->left; if (fstat(fd, &st) < 0) return false; buffer_resize(buffer, st.st_size + used); return buffer_read_all(buffer, fd); }
static int buffer_move_and_read_all (rtsp_client_t *client) { if (buffer_len(client) == RECV_BUFF_DEFAULT_LEN) { dTRACE("buffer is full when read, len=%d\n", RECV_BUFF_DEFAULT_LEN); return RECV_BUFF_DEFAULT_LEN; } buffer_move_head(client); buffer_read_all(client); return buffer_len(client); }
int rtsp_recv_response (rtsp_client_t *client, rtsp_resp_t *response) { const char *line; const char *p; rtsp_resp_t *decode; int done; int len; decode = response; if (buffer_move_and_read_all(client) == 0) { dTRACE("#######string buffer is null and no data recv\n"); return -1; } do { line = get_next_line(client); if (line == 0) { dTRACE("couldn't get response first line\n"); return -1; } } while (*line == '\0'); if (strncasecmp(line, "RTSP/1.0", strlen("RTSP/1.0")) != 0) { char str[20]; p = line; while ( *p != ' ') { p++; } memcpy(str, line, p - line); str[p-line] = '\0'; decode->caption = rtsp_strdup(str); } else { p = line + strlen("RTSP/1.0"); SKIP_SPACE(p); memcpy(decode->retcode, p, 3); decode->retcode[3] = '\0'; p += 3; SKIP_SPACE(p); decode->retresp = rtsp_strdup((char*)p); decode->caption = rtsp_strdup("RTSP/1.0"); } done = 0; do { line = get_next_line(client); if (line == 0) { dTRACE("couldn't get line from response content\n"); return -1; } if (*line != '\0') { rtsp_decode_header(line, response, client); } else { dTRACE("done ======= 1\n"); done = 1; } } while (done == 0); if (decode->content_length != 0) { decode->body = (char*)malloc(decode->content_length + 1); decode->body[decode->content_length] = '\0'; len = buffer_len(client); dTRACE("response body length=%d, current buffer size=%d, offset=%d\n", decode->content_length, len, client->m_offset_on); if (len < decode->content_length) { memcpy(decode->body, client->m_recv_buffer + client->m_offset_on, len); while (len < decode->content_length) { int left; int ret; client->m_offset_on = 0; client->m_buffer_len = 0; ret = buffer_read_all(client); if (ret <= 0) { dTRACE("recv fail at get rtsp body\n"); return -1; } left = decode->content_length - len; if (left < client->m_buffer_len) { memcpy(decode->body + len, client->m_recv_buffer, left); len += left; client->m_offset_on = left; } else { memcpy(decode->body + len, client->m_recv_buffer, client->m_buffer_len); len += client->m_buffer_len; client->m_offset_on = client->m_buffer_len; } } } else { memcpy(decode->body, client->m_recv_buffer + client->m_offset_on, decode->content_length); client->m_offset_on += decode->content_length; } } if (decode->body != 0) { dTRACE("%s", decode->body); } dTRACE("complete recv response, buffer state: offset=%d len=%d\n", client->m_offset_on, buffer_len(client)); return 0; }
int main(void) { struct buffer one = { 0, 0, 0, NULL }; struct buffer two = { 0, 0, 0, NULL }; struct buffer *three; int fd; char *data; ssize_t count; size_t offset; plan(89); /* buffer_set, buffer_append, buffer_swap */ buffer_set(&one, test_string1, sizeof(test_string1)); is_int(1024, one.size, "minimum size is 1024"); is_int(0, one.used, "used starts at 0"); is_int(sizeof(test_string1), one.left, "left is correct"); is_string(test_string1, one.data, "data is corect"); buffer_append(&one, test_string2, sizeof(test_string2)); is_int(1024, one.size, "appended data doesn't change size"); is_int(0, one.used, "or used"); is_int(sizeof(test_string3), one.left, "but left is the right size"); ok(memcmp(one.data, test_string3, sizeof(test_string3)) == 0, "and the resulting data is correct"); one.left -= sizeof(test_string1); one.used += sizeof(test_string1); buffer_append(&one, test_string1, sizeof(test_string1)); is_int(1024, one.size, "size still isn't larger after adding data"); is_int(sizeof(test_string1), one.used, "and used is preserved on append"); is_int(sizeof(test_string3), one.left, "and left is updated properly"); ok(memcmp(one.data + one.used, test_string2, sizeof(test_string2)) == 0, "and the middle data is unchanged"); ok(memcmp(one.data + one.used + sizeof(test_string2), test_string1, sizeof(test_string1)) == 0, "and the final data is correct"); buffer_set(&one, test_string1, sizeof(test_string1)); buffer_set(&two, test_string2, sizeof(test_string2)); buffer_swap(&one, &two); is_int(1024, one.size, "swap #1 size is correct"); is_int(0, one.used, "swap #1 used is correct"); is_int(sizeof(test_string2), one.left, "swap #1 left is correct"); is_string(test_string2, one.data, "swap #1 data is correct"); is_int(1024, two.size, "swap #2 size is correct"); is_int(0, two.used, "swap #2 used is correct"); is_int(sizeof(test_string1), two.left, "swap #2 left is correct"); is_string(test_string1, two.data, "swap #2 data is correct"); free(one.data); free(two.data); one.data = NULL; two.data = NULL; one.size = 0; two.size = 0; /* buffer_resize */ three = buffer_new(); ok(three != NULL, "buffer_new works"); if (three == NULL) bail("buffer_new returned NULL"); is_int(0, three->size, "initial size is 0"); buffer_set(three, test_string1, sizeof(test_string1)); is_int(1024, three->size, "size becomes 1024 when adding data"); buffer_resize(three, 512); is_int(1024, three->size, "resizing to something smaller doesn't change"); buffer_resize(three, 1025); is_int(2048, three->size, "resizing to something larger goes to 2048"); buffer_free(three); /* buffer_read, buffer_find_string, buffer_compact */ fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd < 0) sysbail("cannot create buffer-test"); data = bmalloc(2048); memset(data, 'a', 1023); data[1023] = '\r'; data[1024] = '\n'; memset(data + 1025, 'b', 1023); if (xwrite(fd, data, 2048) < 2048) sysbail("cannot write to buffer-test"); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) sysbail("cannot rewind buffer-test"); three = buffer_new(); ok(three != NULL, "buffer_new works"); if (three == NULL) bail("buffer_new returned NULL"); is_int(0, three->size, "and initial size is 0"); buffer_resize(three, 1024); is_int(1024, three->size, "resize to 1024 works"); count = buffer_read(three, fd); is_int(1024, count, "reading into a buffer of size 1024 reads 1024"); offset = 0; ok(!buffer_find_string(three, "\r\n", 0, &offset), "buffer_find_string with truncated string fails"); is_int(0, offset, "and offset is unchanged"); ok(memcmp(three->data, data, three->size) == 0, "buffer data is correct"); buffer_resize(three, 2048); is_int(2048, three->size, "resizing the buffer to 2048 works"); count = buffer_read(three, fd); is_int(1024, count, "and now we can read the rest of the data"); ok(memcmp(three->data, data, 2048) == 0, "and it's all there"); ok(!buffer_find_string(three, "\r\n", 1024, &offset), "buffer_find_string with a string starting before offset fails"); is_int(0, offset, "and offset is unchanged"); ok(buffer_find_string(three, "\r\n", 0, &offset), "finding the string on the whole buffer works"); is_int(1023, offset, "and returns the correct location"); three->used += 400; three->left -= 400; buffer_compact(three); is_int(2048, three->size, "compacting buffer doesn't change the size"); is_int(0, three->used, "but used is now zero"); is_int(1648, three->left, "and left is decreased appropriately"); ok(memcmp(three->data, data + 400, 1648) == 0, "and the data is correct"); count = buffer_read(three, fd); is_int(0, count, "reading at EOF returns 0"); close(fd); unlink("buffer-test"); free(data); buffer_free(three); /* buffer_sprintf and buffer_append_sprintf */ three = buffer_new(); buffer_append_sprintf(three, "testing %d testing", 6); is_int(0, three->used, "buffer_append_sprintf doesn't change used"); is_int(17, three->left, "but sets left correctly"); buffer_append(three, "", 1); is_int(18, three->left, "appending a nul works"); is_string("testing 6 testing", three->data, "and the data is correct"); three->left--; three->used += 5; three->left -= 5; buffer_append_sprintf(three, " %d", 7); is_int(14, three->left, "appending a digit works"); buffer_append(three, "", 1); is_string("testing 6 testing 7", three->data, "and the data is correct"); buffer_sprintf(three, "%d testing", 8); is_int(9, three->left, "replacing the buffer works"); is_string("8 testing", three->data, "and the results are correct"); data = bmalloc(1050); memset(data, 'a', 1049); data[1049] = '\0'; is_int(1024, three->size, "size before large sprintf is 1024"); buffer_sprintf(three, "%s", data); is_int(2048, three->size, "size after large sprintf is 2048"); is_int(1049, three->left, "and left is correct"); buffer_append(three, "", 1); is_string(data, three->data, "and data is correct"); free(data); buffer_free(three); /* buffer_read_all */ fd = open("buffer-test", O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd < 0) sysbail("cannot create buffer-test"); data = bmalloc(2049); memset(data, 'a', 2049); if (xwrite(fd, data, 2049) < 2049) sysbail("cannot write to buffer-test"); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) sysbail("cannot rewind buffer-test"); three = buffer_new(); ok(buffer_read_all(three, fd), "buffer_read_all succeeds"); is_int(0, three->used, "and unused is zero"); is_int(2049, three->left, "and left is correct"); is_int(4096, three->size, "and size is correct"); ok(memcmp(data, three->data, 2049) == 0, "and data is correct"); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) sysbail("cannot rewind buffer-test"); ok(buffer_read_all(three, fd), "reading again succeeds"); is_int(0, three->used, "and used is correct"); is_int(4098, three->left, "and left is now larger"); is_int(8192, three->size, "and size doubled"); ok(memcmp(data, three->data + 2049, 2049) == 0, "and data is correct"); /* buffer_read_file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1) sysbail("cannot rewind buffer-test"); buffer_free(three); three = buffer_new(); ok(buffer_read_file(three, fd), "buffer_read_file succeeds"); is_int(0, three->used, "and leaves unused at 0"); is_int(2049, three->left, "and left is correct"); is_int(3072, three->size, "and size is a multiple of 1024"); ok(memcmp(data, three->data, 2049) == 0, "and the data is correct"); /* buffer_read_all and buffer_read_file errors */ close(fd); ok(!buffer_read_all(three, fd), "buffer_read_all on closed fd fails"); is_int(3072, three->size, "and size is unchanged"); ok(!buffer_read_file(three, fd), "buffer_read_file on closed fd fails"); is_int(3072, three->size, "and size is unchanged"); is_int(2049, three->left, "and left is unchanged"); unlink("buffer-test"); free(data); buffer_free(three); /* buffer_vsprintf and buffer_append_vsprintf */ three = buffer_new(); test_append_vsprintf(three, "testing %d testing", 6); is_int(0, three->used, "buffer_append_vsprintf leaves used as 0"); is_int(17, three->left, "and left is correct"); buffer_append(three, "", 1); is_int(18, three->left, "and left is correct after appending a nul"); is_string("testing 6 testing", three->data, "and data is correct"); three->left--; three->used += 5; three->left -= 5; test_append_vsprintf(three, " %d", 7); is_int(14, three->left, "and appending results in the correct left"); buffer_append(three, "", 1); is_string("testing 6 testing 7", three->data, "and the right data"); test_vsprintf(three, "%d testing", 8); is_int(9, three->left, "replacing the buffer results in the correct size"); is_string("8 testing", three->data, "and the correct data"); data = bmalloc(1050); memset(data, 'a', 1049); data[1049] = '\0'; is_int(1024, three->size, "size is 1024 before large vsprintf"); test_vsprintf(three, "%s", data); is_int(2048, three->size, "and 2048 afterwards"); is_int(1049, three->left, "and left is correct"); buffer_append(three, "", 1); is_string(data, three->data, "and data is correct"); free(data); buffer_free(three); /* Test buffer_free with NULL and ensure it doesn't explode. */ buffer_free(NULL); return 0; }
void decode(const char* old_file, const char* diff_file, const char* target_file) { char *old_file_data; int old_file_size = mapfile(old_file, 0, (void*) &old_file_data); if (old_file_size < 0) exit(EXIT_FAILURE); struct delta_stream* stream = malloc(sizeof(struct delta_stream)); stream->fd = open(diff_file, O_RDONLY); lseek(stream->fd, 7, SEEK_CUR); //Skip MMDELTA int new_file_size; char *new_file_data; read(stream->fd, &new_file_size, sizeof(int)); if (mapfile(target_file, new_file_size, (void*) &new_file_data) < 0) exit(EXIT_FAILURE); lzma_stream_decoder(&stream->lzma, UINT64_MAX, LZMA_TELL_NO_CHECK); char* buffer; u_int32_t buffer_length = 0, buffer_offset, written = 0; u_int32_t last_length = 0; while (buffer_read_all(stream)) { for (int i=0;i<buffer_operations(stream).length;i++) { u_int32_t length; u_int8_t index; switch (buffer_operations(stream).data[i]) { case 'A': case 'C': if (buffer_length > 0) { memcpy(new_file_data + written, buffer + buffer_offset, buffer_length); written += buffer_length; buffer_length = 0; } } switch (buffer_operations(stream).data[i]) { case 'A': buffer_read(&buffer_lengths(stream), length); memcpy(new_file_data + written, buffer_data(stream).data + buffer_data(stream).offset, length); buffer_data(stream).offset += length; written += length; break; case 'C': buffer_read(&buffer_lengths(stream), buffer_length); buffer_read(&buffer_addresses(stream), buffer_offset); if (buffer_offset >= old_file_size / BLOCKSIZE) { buffer_offset -= old_file_size / BLOCKSIZE; buffer = new_file_data; } else buffer = old_file_data; buffer_offset *= BLOCKSIZE; last_length = 0; break; case 'E': buffer_read(&buffer_diff_index(stream), index); length = index+1; int position = buffer_read_uleb128(&buffer_offsets(stream)) - last_length; memcpy(new_file_data + written, buffer + buffer_offset, position); buffer_length -= position; buffer_offset += position; written += position; struct mismatch_diff *diff = mismatch_add_dec(buffer + buffer_offset, buffer_data(stream).data + buffer_data(stream).offset, length, written); buffer_data(stream).offset += length; memcpy(new_file_data + written, diff->new_data, length); buffer_length -= length; buffer_offset += length; written += length; last_length = length; break; case 'F': buffer_read(&buffer_diff_index(stream), index); length = (index & 0x3) + 1; index >>= 2; position = buffer_read_uleb128(&buffer_offsets(stream)) - last_length; memcpy(new_file_data + written, buffer + buffer_offset, position); written += position; buffer_length -= position; buffer_offset += position; if (index > 0) { diffs[length-1][index-1].last_usage = written; char mismatch_buffer[MAX_MISMATCHES]; for (int i=0;i<length;i++) { mismatch_buffer[i] = patch(buffer[buffer_offset+i], diffs[length-1][index-1].diff_data[i]); } memcpy(new_file_data + written, mismatch_buffer, length); } else { struct mismatch_diff* diff = mismatch_find_data(buffer + buffer_offset, length); if (diff == NULL) { printf("Mismatch diff can't be found\n"); exit(EXIT_FAILURE); } diff->last_usage = written; memcpy(new_file_data + written, diff->new_data, length); } buffer_length -= length; buffer_offset += length; last_length = length; written += length; break; default: fprintf(stderr, "Unsupported action '%c'\n", buffer_operations(stream).data[i]); exit(EXIT_FAILURE); } } } if (buffer_length > 0) { memcpy(new_file_data + written, buffer + buffer_offset, buffer_length); } }