1/*
2 * Copyright 2008-2009, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <errno.h>
8#include <fcntl.h>
9#include <getopt.h>
10#include <stdlib.h>
11#include <stdint.h>
12#include <stdio.h>
13#include <string.h>
14#include <unistd.h>
15
16#include <OS.h>
17
18
19extern const char* __progname;
20const char* kProgramName = __progname;
21
22const int32_t kDefaultFiles = -1;
23const off_t kDefaultFileSize = 4096;
24
25
26static void
27usage(int status)
28{
29	printf("usage: %s [--files <num-of-files>] [--size <file-size>]\n",
30		kProgramName);
31	printf("options:\n");
32	printf("  -f  --files  Number of files to be created. Defaults to as "
33		"many as fit.\n");
34	printf("  -s  --size   Size of each file. Defaults to %lldKB.\n",
35		kDefaultFileSize / 1024);
36
37	exit(status);
38}
39
40
41static bool
42create_file(int32_t i, const char* suffix, const char* buffer, size_t size)
43{
44	char name[64];
45	snprintf(name, sizeof(name), "fragments/%06d%s", i, suffix);
46
47	int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
48	if (fd < 0) {
49		fprintf(stderr, "%s: Could not create file %d: %s\n", kProgramName,
50			i, strerror(errno));
51		return false;
52	}
53
54	if (write(fd, buffer, size) < (ssize_t)size) {
55		fprintf(stderr, "%s: Could not write file %d: %s\n", kProgramName,
56			i, strerror(errno));
57		return false;
58	}
59
60	close(fd);
61	return true;
62}
63
64
65int
66main(int argc, char** argv)
67{
68	int32_t numFiles = kDefaultFiles;
69	off_t fileSize = kDefaultFileSize;
70
71	int optionIndex = 0;
72	int opt;
73	static struct option longOptions[] = {
74		{"help", no_argument, 0, 'h'},
75		{"size", required_argument, 0, 's'},
76		{"files", required_argument, 0, 'f'},
77		{0, 0, 0, 0}
78	};
79
80	do {
81		opt = getopt_long(argc, argv, "hs:f:", longOptions, &optionIndex);
82		switch (opt) {
83			case -1:
84				// end of arguments, do nothing
85				break;
86
87			case 'f':
88				numFiles = strtoul(optarg, NULL, 0);
89				break;
90
91			case 's':
92				fileSize = strtoul(optarg, NULL, 0);
93				break;
94
95			case 'h':
96			default:
97				usage(0);
98				break;
99		}
100	} while (opt != -1);
101
102	// fill buffer
103
104	char* buffer = (char*)malloc(fileSize);
105	if (buffer == NULL) {
106		fprintf(stderr, "%s: not enough memory.\n", kProgramName);
107		exit(1);
108	}
109
110	for (uint32_t i = 0; i < fileSize; i++) {
111		buffer[i] = (char)(i & 0xff);
112	}
113
114	// create files
115
116	if (numFiles > 0)
117		printf("Creating %d files...\n", numFiles);
118	else
119		printf("Creating as many files as fit...\n");
120
121	mkdir("fragments", 0777);
122
123	int32_t filesCreated = 0;
124	bigtime_t lastTime = 0;
125
126	for (int32_t i = 0; i < numFiles || numFiles < 0; i++) {
127		if (!create_file(i, "", buffer, fileSize)
128			|| !create_file(i, ".remove", buffer, fileSize))
129			break;
130
131		filesCreated++;
132
133		if (lastTime + 250000LL < system_time()) {
134			printf("%10d\33[1A\n", filesCreated);
135			lastTime = system_time();
136		}
137	}
138
139	free(buffer);
140
141	// delete fragmentation files
142
143	printf("Deleting %d temporary files...\n", filesCreated);
144
145	for (int32_t i = 0; i < filesCreated; i++) {
146		char name[64];
147		snprintf(name, sizeof(name), "fragments/%06d.remove", i);
148
149		if (remove(name) != 0) {
150			fprintf(stderr, "%s: Could not remove file %d: %s\n",
151				kProgramName, i, strerror(errno));
152		}
153
154		if (lastTime + 250000LL < system_time()) {
155			printf("%10d\33[1A\n", i);
156			lastTime = system_time();
157		}
158	}
159
160	printf("          \33[1A\n");
161		// delete progress count
162
163	return 0;
164}
165