Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_append.c
48674 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (c) 2022 by Triad National Security, LLC24*/2526#include "file_common.h"27#include <unistd.h>28#include <sys/sysmacros.h>2930static char *filename = NULL;31static int expected_offset = -1;32static int blocksize = 131072; /* 128KiB */33static int numblocks = 8;34static const char *execname = "file_append";35static int use_odirect = 0;3637static void38usage(void)39{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",67execname);68(void) exit(1);69}7071static void72parse_options(int argc, char *argv[])73{74int c;75int errflag = 0;76extern char *optarg;77extern int optind, optopt;7879while ((c = getopt(argc, argv, "b:de:f:hn:")) != -1) {80switch (c) {81case 'b':82blocksize = atoi(optarg);83break;84case 'd':85use_odirect = 1;86break;87case 'e':88expected_offset = atoi(optarg);89break;90case 'f':91filename = optarg;92break;93case 'h':94(void) usage();95break;96case 'n':97numblocks = atoi(optarg);98break;99case ':':100(void) fprintf(stderr,101"Option -%c requires an operand\n",102optopt);103errflag++;104break;105case '?':106default:107(void) fprintf(stderr,108"Unrecognized option: -%c\n", optopt);109errflag++;110break;111}112}113114if (errflag)115(void) usage();116117if (use_odirect && ((blocksize % sysconf(_SC_PAGE_SIZE)) != 0)) {118(void) fprintf(stderr,119"blocksize parameter invalid when using O_DIRECT.\n");120(void) usage();121}122123if (blocksize < 512 || expected_offset < 0 || filename == NULL ||124numblocks <= 0) {125(void) fprintf(stderr,126"Required parameters(s) missing or invalid value for "127"parameter.\n");128(void) usage();129}130}131132int133main(int argc, char *argv[])134{135int err;136const char *datapattern = "0xf00ba3";137int fd = -1;138int fd_flags = O_WRONLY | O_CREAT | O_APPEND;139int buf_offset = 0;140char *buf;141142parse_options(argc, argv);143144if (use_odirect)145fd_flags |= O_DIRECT;146147fd = open(filename, fd_flags, 0666);148if (fd == -1) {149(void) fprintf(stderr, "%s: %s: ", execname, filename);150perror("open");151(void) exit(2);152}153154err = posix_memalign((void **)&buf, sysconf(_SC_PAGE_SIZE),155blocksize);156157if (err != 0) {158(void) fprintf(stderr,159"%s: %s\n", execname, strerror(err));160(void) exit(2);161}162163/* Putting known data pattern in buffer */164int left = blocksize;165while (left) {166size_t amt = MIN(strlen(datapattern), left);167memcpy(&buf[buf_offset], datapattern, amt);168buf_offset += amt;169left -= amt;170}171172for (int i = 0; i < numblocks; i++) {173int wrote = write(fd, buf, blocksize);174175if (wrote != blocksize) {176if (wrote < 0) {177perror("write");178} else {179(void) fprintf(stderr,180"%s: unexpected short write, wrote %d "181"byte, expected %d\n", execname, wrote,182blocksize);183}184(void) exit(2);185}186}187188/* Getting current file offset */189off_t off = lseek(fd, 0, SEEK_CUR);190191if (off == -1) {192perror("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);200}201202(void) close(fd);203free(buf);204205return (0);206}207208209