Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_append.c
48674 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
23
/*
24
* Copyright (c) 2022 by Triad National Security, LLC
25
*/
26
27
#include "file_common.h"
28
#include <unistd.h>
29
#include <sys/sysmacros.h>
30
31
static char *filename = NULL;
32
static int expected_offset = -1;
33
static int blocksize = 131072; /* 128KiB */
34
static int numblocks = 8;
35
static const char *execname = "file_append";
36
static int use_odirect = 0;
37
38
static void
39
usage(void)
40
{
41
(void) fprintf(stderr,
42
"usage %s -f filename -e expected_offset [-b blocksize] \n"
43
" [-n numblocks] [-d use_odirect] [-h help]\n"
44
"\n"
45
"Opens a file using O_APPEND and writes numblocks blocksize\n"
46
"blocks to filename.\n"
47
"Checks if expected_offst == lseek(fd, 0, SEEK_CUR)).\n"
48
"\n"
49
" filename: File to open with O_APPEND and write to.\n"
50
" expected_offset: Expected file offset after writing\n"
51
" blocksize numblocks to filename\n"
52
" blocksize: Size of each block to writei (must be at\n"
53
" least >= 512). If using use_odirect (-d)\n"
54
" must be a mutltiple of _SC_PAGE_SIZE\n"
55
" numblocks: Total number of blocksized blocks to\n"
56
" write.\n"
57
" use_odirect: Open file using O_DIRECT.\n"
58
" help: Print usage information and exit.\n"
59
"\n"
60
" Required parameters:\n"
61
" filename\n"
62
" expected_offset\n"
63
"\n"
64
" Default values:\n"
65
" blocksize -> 131072 (128 KiB)\n"
66
" numblocks -> 8\n"
67
" use_odirect -> False\n",
68
execname);
69
(void) exit(1);
70
}
71
72
static void
73
parse_options(int argc, char *argv[])
74
{
75
int c;
76
int errflag = 0;
77
extern char *optarg;
78
extern int optind, optopt;
79
80
while ((c = getopt(argc, argv, "b:de:f:hn:")) != -1) {
81
switch (c) {
82
case 'b':
83
blocksize = atoi(optarg);
84
break;
85
case 'd':
86
use_odirect = 1;
87
break;
88
case 'e':
89
expected_offset = atoi(optarg);
90
break;
91
case 'f':
92
filename = optarg;
93
break;
94
case 'h':
95
(void) usage();
96
break;
97
case 'n':
98
numblocks = atoi(optarg);
99
break;
100
case ':':
101
(void) fprintf(stderr,
102
"Option -%c requires an operand\n",
103
optopt);
104
errflag++;
105
break;
106
case '?':
107
default:
108
(void) fprintf(stderr,
109
"Unrecognized option: -%c\n", optopt);
110
errflag++;
111
break;
112
}
113
}
114
115
if (errflag)
116
(void) usage();
117
118
if (use_odirect && ((blocksize % sysconf(_SC_PAGE_SIZE)) != 0)) {
119
(void) fprintf(stderr,
120
"blocksize parameter invalid when using O_DIRECT.\n");
121
(void) usage();
122
}
123
124
if (blocksize < 512 || expected_offset < 0 || filename == NULL ||
125
numblocks <= 0) {
126
(void) fprintf(stderr,
127
"Required parameters(s) missing or invalid value for "
128
"parameter.\n");
129
(void) usage();
130
}
131
}
132
133
int
134
main(int argc, char *argv[])
135
{
136
int err;
137
const char *datapattern = "0xf00ba3";
138
int fd = -1;
139
int fd_flags = O_WRONLY | O_CREAT | O_APPEND;
140
int buf_offset = 0;
141
char *buf;
142
143
parse_options(argc, argv);
144
145
if (use_odirect)
146
fd_flags |= O_DIRECT;
147
148
fd = open(filename, fd_flags, 0666);
149
if (fd == -1) {
150
(void) fprintf(stderr, "%s: %s: ", execname, filename);
151
perror("open");
152
(void) exit(2);
153
}
154
155
err = posix_memalign((void **)&buf, sysconf(_SC_PAGE_SIZE),
156
blocksize);
157
158
if (err != 0) {
159
(void) fprintf(stderr,
160
"%s: %s\n", execname, strerror(err));
161
(void) exit(2);
162
}
163
164
/* Putting known data pattern in buffer */
165
int left = blocksize;
166
while (left) {
167
size_t amt = MIN(strlen(datapattern), left);
168
memcpy(&buf[buf_offset], datapattern, amt);
169
buf_offset += amt;
170
left -= amt;
171
}
172
173
for (int i = 0; i < numblocks; i++) {
174
int wrote = write(fd, buf, blocksize);
175
176
if (wrote != blocksize) {
177
if (wrote < 0) {
178
perror("write");
179
} else {
180
(void) fprintf(stderr,
181
"%s: unexpected short write, wrote %d "
182
"byte, expected %d\n", execname, wrote,
183
blocksize);
184
}
185
(void) exit(2);
186
}
187
}
188
189
/* Getting current file offset */
190
off_t off = lseek(fd, 0, SEEK_CUR);
191
192
if (off == -1) {
193
perror("output seek");
194
(void) exit(2);
195
} else if (off != expected_offset) {
196
(void) fprintf(stderr,
197
"%s: expected offset %d but current offset in %s is set "
198
"to %ld\n", execname, expected_offset, filename,
199
(long int)off);
200
(void) exit(2);
201
}
202
203
(void) close(fd);
204
free(buf);
205
206
return (0);
207
}
208
209