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