void write_buffer_queue_init( write_buffer_queue_t* queue, request_context_t* request_context, write_callback_t write_callback, void* write_context, bool_t reuse_buffers) { queue->request_context = request_context; queue->write_callback = write_callback; queue->write_context = write_context; queue->reuse_buffers = reuse_buffers; initialize_list_head(&queue->buffers); queue->cur_write_buffer = NULL; queue->cur_offset = 0; }
int main(int argc, char **argv) { buffer_t* new_buffer; FILE *source; long buffer_start_offset; long cur_line_count; long initial_offset; long bytes_to_read; long offset; long requested_line_count = DEFAULT_N_LINES; int inotify_fd = -1; // parse the command line parse_options(argc, argv, &requested_line_count); requested_line_count++; if (optind + 1 != argc) { usage(EXIT_FAILURE); } // open the file source = fopen(argv[optind], "rb"); if (source == NULL) { printf("fopen %s failed %d\n", argv[optind], errno); goto error; } if (forever) { // set an inotify watch inotify_fd = inotify_init(); if (inotify_fd == -1) { printf("inotify_init failed %d", errno); goto error; } if (inotify_add_watch(inotify_fd, argv[optind], IN_MODIFY) == -1) { printf("inotify_add_watch failed %d", errno); goto error; } } // seek to the end if (fseek(source, 0, SEEK_END) == -1) { printf("fseek failed (1) %d\n", errno); goto error; } initial_offset = ftell(source); if (initial_offset == -1) { printf("ftell failed %d\n", errno); goto error; } offset = initial_offset; initialize_list_head(&buffer_queue); for (;;) { if (offset > CHUNK_SIZE_READ) { bytes_to_read = CHUNK_SIZE_READ; } else { bytes_to_read = offset; } offset -= bytes_to_read; if (offset + MEMORY_LIMIT < initial_offset) { printf("memory limit exceeded\n"); goto error; } // allocate a buffer new_buffer = (buffer_t*)malloc(sizeof(buffer_t)); if (new_buffer == NULL) { printf("malloc failed (1)\n"); goto error; } new_buffer->data = malloc(bytes_to_read); if (new_buffer->data == NULL) { printf("malloc failed (2)\n"); goto error; } insert_head_list(&buffer_queue, &new_buffer->node); new_buffer->offset = offset; new_buffer->size = bytes_to_read; // read from the file if (fseek(source, offset, SEEK_SET) == -1) { printf("fseek failed (2) %d\n", errno); goto error; } if (fread(new_buffer->data, 1, bytes_to_read, source) != bytes_to_read) { printf("fread failed %d\n", errno); goto error; } cur_line_count = get_line_count(new_buffer, &buffer_start_offset); if (cur_line_count >= requested_line_count) { // read enough data, seek to the initial offset and print the result if (fseek(source, initial_offset, SEEK_SET) == -1) { printf("fseek failed (3) %d\n", errno); goto error; } return print_lines(source, inotify_fd, new_buffer, buffer_start_offset, cur_line_count - requested_line_count + 1); } if (offset > 0) { continue; } if (cur_line_count <= 0) { goto error; } // reached the beginning of the file, seek to the initial offset and print the result if (fseek(source, initial_offset, SEEK_SET) == -1) { printf("fseek failed (4) %d\n", errno); goto error; } return print_lines(source, inotify_fd, new_buffer, buffer_start_offset, 0); } return 0; error: // not bothering to clean up anything since the process quits return 1; }