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