xref: /illumos-gate/usr/src/test/smbclient-tests/cmd/prot_mmap/prot_mmap.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2012 Jilin Xpd <jilinxpd@gmail.com>
14  * Copyright 2018 Nexenta Systems, Inc.
15  */
16 
17 /*
18  * use mmap to copy data from src file to des file,
19  * with given flags and modes.
20  * the src & des file should exist and have the same size.
21  */
22 
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 
33 void
34 usage(void)
35 {
36 	fprintf(stderr,
37 	    "usage: "
38 	    "prot_mmap -o <r|w> <r|w>"
39 	    " -m <r|w|s|p> <r|w|s|p>"
40 	    " -f <srcfile> <desfile>\n");
41 	exit(1);
42 }
43 
44 int
45 main(int argc, char **argv)
46 {
47 	struct stat sb;
48 	char *src_addr, *des_addr;
49 	char *src_file = NULL, *des_file = NULL;
50 	off_t offset;
51 	size_t filesize;
52 	size_t blksize;
53 	size_t numblks;
54 	size_t i, j;
55 	int src_fid, des_fid;
56 	int mret = 0;
57 	int flags0 = 0, mflags0 = 0, prot0 = 0; /* flags for src file */
58 	int flags1 = 0, mflags1 = 0, prot1 = 0; /* flags for des file */
59 
60 	/*
61 	 * parse arguments
62 	 * Not getopt because -o -m -f all have 2 optargs each.
63 	 */
64 	if (argc != 10) {
65 		usage();
66 	}
67 	for (i = 1; i < argc; ) {
68 		switch (argv[i][1]) {
69 			case 'o': /* options for open() */
70 				i++;
71 				for (j = 0; argv[i][j]; j++) {
72 					if (argv[i][j] == 'r')
73 						flags0 |= O_RDONLY;
74 					else if (argv[i][j] == 'w')
75 						flags0 |= O_WRONLY;
76 				}
77 				if ((flags0 & (O_RDONLY | O_WRONLY)) ==
78 				    (O_RDONLY | O_WRONLY))
79 					flags0 = O_RDWR;
80 				i++;
81 				for (j = 0; argv[i][j]; j++) {
82 					if (argv[i][j] == 'r')
83 						flags1 |= O_RDONLY;
84 					else if (argv[i][j] == 'w')
85 						flags1 |= O_WRONLY;
86 				}
87 				if ((flags1 & (O_RDONLY | O_WRONLY)) ==
88 				    (O_RDONLY | O_WRONLY))
89 					flags1 = O_RDWR;
90 				i++;
91 				break;
92 			case 'm': /* options for mmap() */
93 				i++;
94 				for (j = 0; argv[i][j]; j++) {
95 					if (argv[i][j] == 'r')
96 						prot0 |= PROT_READ;
97 					else if (argv[i][j] == 'w')
98 						prot0 |= PROT_WRITE;
99 					else if (argv[i][j] == 's')
100 						mflags0 |= MAP_SHARED;
101 					else if (argv[i][j] == 'p')
102 						mflags0 |= MAP_PRIVATE;
103 				}
104 				i++;
105 				for (j = 0; argv[i][j]; j++) {
106 					if (argv[i][j] == 'r')
107 						prot1 |= PROT_READ;
108 					else if (argv[i][j] == 'w')
109 						prot1 |= PROT_WRITE;
110 					else if (argv[i][j] == 's')
111 						mflags1 |= MAP_SHARED;
112 					else if (argv[i][j] == 'p')
113 						mflags1 |= MAP_PRIVATE;
114 				}
115 				i++;
116 				break;
117 			case 'f': /* src file and des file */
118 				i++;
119 				src_file = argv[i];
120 				i++;
121 				des_file = argv[i];
122 				i++;
123 		}
124 	}
125 
126 	/* source file */
127 	src_fid = open(src_file, flags0);
128 	if (src_fid == -1) {
129 		fprintf(stderr, "open %s error=%d\n", src_file, errno);
130 		return (1);
131 	}
132 	/* destination file */
133 	des_fid = open(des_file, flags1);
134 	if (des_fid == -1) {
135 		fprintf(stderr, "open %s error=%d\n", des_file, errno);
136 		mret = 1;
137 		goto exit3;
138 	}
139 
140 	/* get file size */
141 	if (fstat(src_fid, &sb) == -1) {
142 		fprintf(stderr, "fstat %s error=%d\n", src_file, errno);
143 		mret = 1;
144 		goto exit2;
145 	}
146 	filesize = sb.st_size;
147 	if (filesize < 4096) {
148 		fprintf(stderr, "file too small\n");
149 		mret = 1;
150 		goto exit2;
151 	}
152 
153 	if (fstat(des_fid, &sb) == -1) {
154 		fprintf(stderr, "fstat %s error=%d\n", des_file, errno);
155 		mret = 1;
156 		goto exit2;
157 	}
158 	if (filesize != sb.st_size) {
159 		fprintf(stderr, "file sizes differ\n");
160 		mret = 1;
161 		goto exit2;
162 	}
163 
164 	/* copy data */
165 	blksize = 64 * 1024 * 1024;
166 	numblks = (filesize + blksize - 1) / blksize;
167 	for (i = 0; i < numblks && mret == 0; i++) {
168 
169 		offset = (i % numblks) * blksize;
170 		if (offset + blksize > filesize)
171 			blksize = filesize - offset;
172 
173 		/* map file */
174 		src_addr = mmap(NULL, blksize, prot0, mflags0, src_fid, offset);
175 		if (src_addr == MAP_FAILED) {
176 			fprintf(stderr, "mmap %s error=%d\n", src_file, errno);
177 			mret = 1;
178 			break;
179 		}
180 		des_addr = mmap(NULL, blksize, prot1, mflags1, des_fid, offset);
181 		if (des_addr == MAP_FAILED) {
182 			fprintf(stderr, "mmap %s error=%d\n", des_file, errno);
183 			mret = 1;
184 			goto exit1;
185 		}
186 
187 		/* cp data from src addr to des addr */
188 		memcpy(des_addr, src_addr, blksize);
189 		/* sync mapped pages to file */
190 		if (msync(des_addr, blksize, MS_SYNC) == -1) {
191 			fprintf(stderr, "msync %s error=%d\n", des_file, errno);
192 			mret = 1;
193 		}
194 
195 		/* unmap file */
196 		if (munmap(des_addr, blksize) == -1) {
197 			fprintf(stderr, "munmap %s error=%d\n",
198 			    des_file, errno);
199 			mret = 1;
200 		}
201 exit1:
202 		if (munmap(src_addr, blksize) == -1) {
203 			fprintf(stderr, "munmap %s error=%d\n",
204 			    src_file, errno);
205 			mret = 1;
206 		}
207 	}
208 
209 	/* close file */
210 exit2:
211 	close(des_fid);
212 exit3:
213 	close(src_fid);
214 
215 	return (mret);
216 }
217