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