1 /*
2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
4 */
5
6
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11
12 #include <algorithm>
13
14
15 void
test_for_content(int fd,off_t start,const char * contents,size_t length)16 test_for_content(int fd, off_t start, const char* contents, size_t length)
17 {
18 char buffer[4096];
19 while (length > 0) {
20 size_t toRead = std::min(length, sizeof(buffer));
21
22 if (pread(fd, buffer, toRead, start) != (ssize_t)toRead) {
23 perror("reading failed");
24 exit(1);
25 }
26
27 if (memcmp(contents, buffer, toRead)) {
28 fprintf(stderr, "Contents at %lld differ!\n", start);
29 exit(1);
30 }
31
32 contents += toRead;
33 start += toRead;
34 length -= toRead;
35 }
36 }
37
38
39 void
test_for_zero(int fd,off_t start,off_t end)40 test_for_zero(int fd, off_t start, off_t end)
41 {
42 while (start < end) {
43 char buffer[4096];
44 size_t length = std::min((size_t)(end - start), sizeof(buffer));
45
46 if (pread(fd, buffer, length, start) != (ssize_t)length) {
47 perror("reading failed");
48 exit(1);
49 }
50
51 for (size_t i = 0; i < length; i++) {
52 if (buffer[i] != 0) {
53 fprintf(stderr, "Buffer at %lld is not empty (%#x)!\n",
54 start + i, buffer[i]);
55 exit(1);
56 }
57 }
58
59 start += length;
60 }
61 }
62
63
64 int
main(int argc,char ** argv)65 main(int argc, char** argv)
66 {
67 const char* name = "/tmp/seek_and_write";
68 bool prefill = true;
69
70 for (int i = 1; i < argc; i++) {
71 if (argv[i][0] == '-') {
72 if (argv[i][1] == 'n')
73 prefill = false;
74 else {
75 fprintf(stderr, "Unknown option\n");
76 return 1;
77 }
78
79 continue;
80 }
81
82 name = argv[i];
83 }
84
85 int fd = open(name, O_RDWR | O_TRUNC | O_CREAT, 0644);
86 if (fd < 0) {
87 perror("failed to open file");
88 return 1;
89 }
90
91 char buffer[256];
92 for (size_t i = 0; i < 256; i++)
93 buffer[i] = i;
94
95 if (prefill) {
96 // Write test data to file to make sure it's not empty
97
98 for (size_t i = 0; i < 100; i++) {
99 if (write(fd, buffer, sizeof(buffer)) != (ssize_t)sizeof(buffer)) {
100 perror("writing failed");
101 return 1;
102 }
103 }
104 }
105
106 // Truncate it again in order to remove its contents
107
108 ftruncate(fd, 0);
109
110 // Seek past its end, and write something
111
112 pwrite(fd, "---", 3, 100 * 1024);
113 pwrite(fd, "+++", 3, 200 * 1024);
114
115 // Test contents
116
117 test_for_zero(fd, 0, 100 * 1024);
118 test_for_content(fd, 100 * 1024, "---", 3);
119 test_for_zero(fd, 100 * 1024 + 256, 200 * 1024);
120 test_for_content(fd, 200 * 1024, "+++", 3);
121
122 return 0;
123 }
124