6dc571cf016caa5aaa53611fd17e29c00b824fff
[xfstests-dev.git] / dmapi / src / suite2 / src / mmap.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32 /*
33  *      This routine simulates
34  *      
35  *      cp      file1 file2
36  *
37  *
38  *      It is a demo program which does the copy by memory mapping each of the
39  *      files and then doing a byte at a time memory copy.
40  *
41  */
42 #include <stddef.h>
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include <sys/mman.h>
46 #include <sys/fcntl.h>
47 #include <sys/stat.h>
48 #include <strings.h>
49 #include <errno.h>
50
51
52 char * Progname;
53 off_t   len;                    /* length of file 1 */
54 off_t   offset = 0;
55 int     print_flags_set = 1;
56
57 typedef struct  fflag {
58         int     arg;            /* != 0 if ars specified */
59         int     value;          /* flags value */
60 } fflag_t;
61
62
63 typedef enum ftype {    /* flag bit types */
64         FL_MAP, FL_PROT, FL_OPEN, FL_MAX
65 } ftype_t;
66
67 typedef struct  mfile   {
68         fflag_t flags[FL_MAX];
69         char    *path;
70         int     fd;
71         struct  stat    st;
72         addr_t  p;
73 } mfile_t;
74
75
76 #define FLAG(symbol,type) { # symbol , symbol, type }
77 #define MAP_NONE        0
78
79 static  struct  {
80         char    *name;
81         int     value;
82         ftype_t type;
83 } Flags[] = {
84         FLAG(O_RDONLY, FL_OPEN),
85         FLAG(O_WRONLY, FL_OPEN),
86         FLAG(O_RDWR, FL_OPEN),
87         FLAG(O_NDELAY, FL_OPEN),
88         FLAG(O_NONBLOCK, FL_OPEN),
89         FLAG(O_APPEND, FL_OPEN),
90         FLAG(O_SYNC, FL_OPEN),
91         FLAG(O_TRUNC, FL_OPEN),
92         FLAG(O_CREAT, FL_OPEN),
93         FLAG(O_DIRECT, FL_OPEN),
94         FLAG(PROT_NONE, FL_PROT),
95         FLAG(PROT_READ, FL_PROT),
96         FLAG(PROT_WRITE, FL_PROT),
97         FLAG(PROT_EXEC, FL_PROT),
98         FLAG(PROT_EXECUTE, FL_PROT),
99         FLAG(MAP_SHARED, FL_MAP),
100         FLAG(MAP_PRIVATE, FL_MAP),
101         FLAG(MAP_FIXED, FL_MAP),
102         FLAG(MAP_RENAME, FL_MAP),
103         FLAG(MAP_AUTOGROW, FL_MAP),
104         FLAG(MAP_LOCAL, FL_MAP),
105         FLAG(MAP_AUTORESRV, FL_MAP),
106         FLAG(MAP_NONE, FL_MAP),
107 };
108
109 int     num_Flags = sizeof(Flags)/sizeof(Flags[0]);
110
111
112 mfile_t *ifile, *ofile;
113 mfile_t *hfile; /* Hack job */
114 static int      hack = 0;
115         
116 static  mfile_t *new_mfile(void);
117 static int mfile_opt(char * s, mfile_t * f);
118 static  void print_flags(char *s, mfile_t *f);
119 static void Usage(void);
120
121 main(int argc, char * argv[])
122 {
123         int     opt;
124
125         if ((Progname = strrchr(argv[0], '/')) == NULL)
126                 Progname = argv[0];
127         else
128                 Progname++;
129
130         ifile = new_mfile();
131         ofile = new_mfile();
132         hfile = new_mfile();
133         if (ifile == NULL || ofile == NULL || hfile == NULL) {
134                 fprintf(stderr,"%s: malloc failure.\n", Progname);
135                 exit (1);
136         }
137
138         /* Set default flags */
139         ifile->flags[FL_MAP].value = MAP_PRIVATE;
140         ifile->flags[FL_PROT].value = PROT_READ;
141         ifile->flags[FL_OPEN].value = O_RDONLY;
142         ofile->flags[FL_MAP].value = MAP_SHARED|MAP_AUTOGROW;
143         ofile->flags[FL_PROT].value = PROT_WRITE;
144         ofile->flags[FL_OPEN].value = O_RDWR|O_CREAT;
145
146         while ((opt = getopt(argc, argv, "i:o:h:d")) != EOF) {
147                 switch(opt) {
148                 case 'i':
149                         if (mfile_opt(optarg, ifile) != 0) {
150                                 fprintf(stderr, "%s: Invalid -i option %s\n",
151                                         Progname, optarg);
152                                 Usage();
153                         }
154                         break;
155
156                 case 'o':
157                         if (mfile_opt(optarg, ofile) != 0) {
158                                 fprintf(stderr, "%s: Invalid -o option %s\n",
159                                         Progname, optarg);
160                                 Usage();
161                         }
162                         break;
163
164                 case 'h':
165                         if (mfile_opt(optarg, hfile) != 0) {
166                                 fprintf(stderr, "%s: Invalid -h option %s\n",
167                                         Progname, optarg);
168                                 Usage();
169                         }
170                         hack = 1;
171                         break;
172
173                 case 'd':
174                         print_flags_set ^= 1;
175                         break;
176                 case '?':
177                         Usage();
178                 }
179         }
180
181         if (optind+1 > argc)
182                 Usage();
183
184         ifile->path = argv[optind++];
185         ofile->path = argv[optind++];
186
187         if (optind != argc)     /* Extra args on command line */
188                 Usage();
189
190         if (stat(ifile->path, &(ifile->st)) < 0) {
191                 fprintf(stderr,"%s: stat of %s failed.\n",
192                                                 Progname, ifile->path);
193                 perror(ifile->path);
194                 exit(2);
195         }
196
197         len = ifile->st.st_size;
198
199         ifile->fd = open(ifile->path, ifile->flags[FL_OPEN].value);
200         if (ifile->fd < 0) {
201                 fprintf(stderr,"%s: cannot open %s\n", Progname, ifile->path);
202                 perror(ifile->path);
203                 exit(2);
204         }
205
206
207         ofile->fd = open(ofile->path, ofile->flags[FL_OPEN].value, 0644);
208         if (ofile->fd < 0) {
209                 fprintf(stderr,"%s: cannot open %s\n", Progname, ofile->path);
210                 perror(ofile->path);
211                 exit(3);
212         }
213
214         if (print_flags_set) {
215                 print_flags("Input ", ifile);
216                 print_flags("Output", ofile);
217                 if (hack)
218                         print_flags("Hack  ", hfile);
219         }
220
221
222         ifile->p = mmap(NULL, len, ifile->flags[FL_PROT].value,
223                                 ifile->flags[FL_MAP].value, ifile->fd, 0);
224         if (ifile->p == MAP_FAILED) {
225                 fprintf(stderr,"%s: cannot mmap %s\n", Progname, ifile->path);
226                 perror(ifile->path);
227                 exit(2);
228         }
229
230         ofile->p = mmap(NULL, len, ofile->flags[FL_PROT].value,
231                                 ofile->flags[FL_MAP].value , ofile->fd, 0);
232                 if (ofile->p == MAP_FAILED) {
233                 fprintf(stderr,"%s: cannot mmap %s\n", Progname, ofile->path);
234                 perror(ofile->path);
235                 exit(3);
236         }
237
238         if (hack) {
239                 int     error;
240
241                 error = mprotect(ofile->p, len, hfile->flags[FL_PROT].value);
242                 if (error) {
243                         fprintf(stderr,"%s: mprotect call failed.\n", Progname);
244                         perror("mprotect");
245                         exit(3);
246                 }
247         }
248         
249         bcopy(ifile->p, ofile->p, len);
250
251         printf("%s complete.\n", Progname);
252         return 0;
253 }
254
255 static mfile_t *
256 new_mfile(void)
257 {
258         mfile_t *ptr = (mfile_t *)malloc(sizeof(*ptr));
259         if (ptr)
260                 bzero(ptr, sizeof *ptr);
261
262         return  ptr;
263 }
264
265
266 static  int
267 mfile_opt(char * s, mfile_t *f)
268 {
269         int     i;
270         ftype_t type;
271
272         for (i = 0; i < num_Flags; i++) {
273                 if(!strcasecmp(Flags[i].name, s)) {
274
275                         /* Zero value if this is 1st arg of this type */
276
277                         type = Flags[i].type;
278                         if (f->flags[type].arg++ == 0) 
279                                 f->flags[type].value = 0;
280                         f->flags[type].value |= Flags[i].value;
281                         return 0;
282                 }
283         }
284         return -1;      /* error - string not found */
285 }
286
287 static void
288 Usage(void)
289 {
290         int     i;
291
292         fprintf(stderr, 
293                 "Usage: %s [-d] [-i flag] [-i flag] [-o flag] ... file1 file2\n",
294                 Progname);
295         fprintf(stderr, "Valid flag values are:\n");
296
297         for (i = 0; i < num_Flags; i++) {
298                 fprintf(stderr,"%15s",Flags[i].name);
299                 if ((i+1)%4 == 0 || i == num_Flags-1)
300                         fprintf(stderr,"\n");
301                 else
302                         fprintf(stderr,",");
303         }
304         exit(1);
305 }
306
307 static  void
308 print_flags(char *s, mfile_t *f)
309 {
310         int             i;
311         ftype_t         type;
312
313         printf("DEBUG - %s flags:\n", s);
314         for (i = 0; i < num_Flags; i++) {
315                 type = Flags[i].type;
316                 if (type == FL_OPEN && Flags[i].value == O_RDONLY && 
317                         ((f->flags[type].value) & 3) == 0) 
318                                 /* Hack to print out O_RDONLY */
319                                 printf("\t%s\n", Flags[i].name);
320                 else if ((Flags[i].value & (f->flags[type].value)) != 0)
321                         printf("\t%s\n", Flags[i].name);
322         }
323 }