1/*
2 * CDDL HEADER START
3 *
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.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Copyright (c) 2012 by Delphix. All rights reserved.
29 */
30
31#include "../file_common.h"
32#include <sys/types.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <string.h>
36#include <linux/falloc.h>
37
38/*
39 * Create a file with assigned size and then free the specified
40 * section of the file
41 */
42
43static void usage(char *progname);
44
45static void
46usage(char *progname)
47{
48	(void) fprintf(stderr,
49	    "usage: %s [-l filesize] [-s start-offset]"
50	    "[-n section-len] filename\n", progname);
51	exit(1);
52}
53
54int
55main(int argc, char *argv[])
56{
57	char *filename = NULL;
58	char *buf = NULL;
59	size_t filesize = 0;
60	off_t start_off = 0;
61	off_t off_len = 0;
62	int  fd, ch;
63	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
64
65	while ((ch = getopt(argc, argv, "l:s:n:")) != EOF) {
66		switch (ch) {
67		case 'l':
68			filesize = atoll(optarg);
69			break;
70		case 's':
71			start_off = atoll(optarg);
72			break;
73		case 'n':
74			off_len = atoll(optarg);
75			break;
76		default:
77			usage(argv[0]);
78			break;
79		}
80	}
81
82	if (optind == argc - 1)
83		filename = argv[optind];
84	else
85		usage(argv[0]);
86
87	if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) {
88		perror("open");
89		return (1);
90	}
91
92	buf = (char *)calloc(1, filesize);
93	if (buf == NULL) {
94		perror("write");
95		close(fd);
96		return (1);
97	}
98	memset(buf, 'c', filesize);
99
100	if (write(fd, buf, filesize) < filesize) {
101		free(buf);
102		perror("write");
103		close(fd);
104		return (1);
105	}
106
107	free(buf);
108
109#if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)
110	if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
111	    start_off, off_len) < 0) {
112		perror("fallocate");
113		close(fd);
114		return (1);
115	}
116#else /* !(defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)) */
117	{
118		perror("FALLOC_FL_PUNCH_HOLE unsupported");
119		close(fd);
120		return (1);
121	}
122#endif /* defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) */
123	close(fd);
124	return (0);
125}
126