慕田峪7331174
这extend_file_and_insert()或多或少是完成工作的功能。#include #include enum { BUFFERSIZE = 64 * 1024 };#define MIN(x, y) (((x) < (y)) ? (x) : (y))/*off_t is signedssize_t is signedsize_t is unsignedoff_t for lseek() offset and returnsize_t for read()/write() lengthssize_t for read()/write() returnoff_t for st_size*/static int extend_file_and_insert(int fd, off_t offset, char const *insert, size_t inslen){ char buffer[BUFFERSIZE]; struct stat sb; int rc = -1; if (fstat(fd, &sb) == 0) { if (sb.st_size > offset) { /* Move data after offset up by inslen bytes */ size_t bytes_to_move = sb.st_size - offset; off_t read_end_offset = sb.st_size; while (bytes_to_move != 0) { ssize_t bytes_this_time = MIN(BUFFERSIZE, bytes_to_move); ssize_t rd_off = read_end_offset - bytes_this_time; ssize_t wr_off = rd_off + inslen; lseek(fd, rd_off, SEEK_SET); if (read(fd, buffer, bytes_this_time) != bytes_this_time) return -1; lseek(fd, wr_off, SEEK_SET); if (write(fd, buffer, bytes_this_time) != bytes_this_time) return -1; bytes_to_move -= bytes_this_time; read_end_offset -= bytes_this_time; /* Added 2013-07-19 */ } } lseek(fd, offset, SEEK_SET); write(fd, insert, inslen); rc = 0; } return rc;}(请注意,在2013年7月19日增加了另一行;它是一个错误,仅在缓冲区大小小于要复制到文件上的数据量时才显示。感谢malat指出了该错误。现在对代码进行测试BUFFERSIZE = 4)这是一些小型测试代码:#include #include static const char base_data[] = "12345";typedef struct Data{ off_t posn; const char *data;} Data;static const Data insert[] ={ { 2, "456" }, { 4, "XxxxxxX" }, { 12, "ZzzzzzzzzzzzzzzzzzzzzzzzX" }, { 22, "YyyyyyyyyyyyyyyY" },}; enum { NUM_INSERT = sizeof(insert) / sizeof(insert[0]) };int main(void){ int fd = open("test.dat", O_RDWR | O_TRUNC | O_CREAT, 0644); if (fd > 0) { ssize_t base_len = sizeof(base_data) - 1; if (write(fd, base_data, base_len) == base_len) { for (int i = 0; i < NUM_INSERT; i++) { off_t length = strlen(insert[i].data); if (extend_file_and_insert(fd, insert[i].posn, insert[i].data, length) != 0) break; lseek(fd, 0, SEEK_SET); char buffer[BUFFERSIZE]; ssize_t nbytes; while ((nbytes = read(fd, buffer, sizeof(buffer))) > 0) write(1, buffer, nbytes); write(1, "\n", 1); } } close(fd); } return(0);}它产生输出:124563451245XxxxxxX63451245XxxxxxX6ZzzzzzzzzzzzzzzzzzzzzzzzZ3451245XxxxxxX6ZzzzzzzzzzYyyyyyyyyyyyyyyYzzzzzzzzzzzzzzZ345应该在一些更大的文件上进行测试(比BUFFERSIZE大一些,但是使用比64 KiB小得多的BUFFERSIZE进行测试是明智的;我使用32字节,这似乎还可以)。我只是关注结果,但是这些模式旨在让您容易看出它们是正确的。该代码不检查任何lseek()调用。这是一个较小的风险。这extend_file_and_insert()