port to linux
[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 #ifdef linux
43 #ifndef _GNU_SOURCE
44 #define _GNU_SOURCE
45 #endif
46 #endif
47
48 #include <unistd.h>
49 #include <stddef.h>
50 #include <stdio.h>
51 #include <sys/types.h>
52 #include <sys/mman.h>
53 #include <sys/fcntl.h>
54 #include <sys/stat.h>
55 #include <string.h>
56 #include <errno.h>
57 #include <getopt.h>
58
59
60 char * Progname;
61 off_t   len;                    /* length of file 1 */
62 off_t   offset = 0;
63 int     print_flags_set = 1;
64
65 typedef struct  fflag {
66         int     arg;            /* != 0 if ars specified */
67         int     value;          /* flags value */
68 } fflag_t;
69
70
71 typedef enum ftype {    /* flag bit types */
72         FL_MAP, FL_PROT, FL_OPEN, FL_MAX
73 } ftype_t;
74
75 typedef struct  mfile   {
76         fflag_t flags[FL_MAX];
77         char    *path;
78         int     fd;
79         struct  stat    st;
80 #ifdef linux
81         void *p;
82 #else
83         addr_t  p;
84 #endif
85 } mfile_t;
86
87
88 #define FLAG(symbol,type) { # symbol , symbol, type }
89 #define MAP_NONE        0
90
91 static  struct  {
92         char    *name;
93         int     value;
94         ftype_t type;
95 } Flags[] = {
96         FLAG(O_RDONLY, FL_OPEN),
97         FLAG(O_WRONLY, FL_OPEN),
98         FLAG(O_RDWR, FL_OPEN),
99         FLAG(O_NDELAY, FL_OPEN),
100         FLAG(O_NONBLOCK, FL_OPEN),
101         FLAG(O_APPEND, FL_OPEN),
102         FLAG(O_SYNC, FL_OPEN),
103         FLAG(O_TRUNC, FL_OPEN),
104         FLAG(O_CREAT, FL_OPEN),
105         FLAG(O_DIRECT, FL_OPEN),
106         FLAG(PROT_NONE, FL_PROT),
107         FLAG(PROT_READ, FL_PROT),
108         FLAG(PROT_WRITE, FL_PROT),
109         FLAG(PROT_EXEC, FL_PROT),
110 #ifdef __sgi
111         FLAG(PROT_EXECUTE, FL_PROT),
112 #endif
113         FLAG(MAP_SHARED, FL_MAP),
114         FLAG(MAP_PRIVATE, FL_MAP),
115         FLAG(MAP_FIXED, FL_MAP),
116 #ifdef __sgi
117         FLAG(MAP_RENAME, FL_MAP),
118         FLAG(MAP_AUTOGROW, FL_MAP),
119         FLAG(MAP_LOCAL, FL_MAP),
120         FLAG(MAP_AUTORESRV, FL_MAP),
121 #endif
122         FLAG(MAP_NONE, FL_MAP),
123 };
124
125 int     num_Flags = sizeof(Flags)/sizeof(Flags[0]);
126
127
128 mfile_t *ifile, *ofile;
129 mfile_t *hfile; /* Hack job */
130 static int      hack = 0;
131         
132 static  mfile_t *new_mfile(void);
133 static int mfile_opt(char * s, mfile_t * f);
134 static  void print_flags(char *s, mfile_t *f);
135 static void Usage(void);
136
137 main(int argc, char * argv[])
138 {
139         int     opt;
140
141         if ((Progname = strrchr(argv[0], '/')) == NULL)
142                 Progname = argv[0];
143         else
144                 Progname++;
145
146         ifile = new_mfile();
147         ofile = new_mfile();
148         hfile = new_mfile();
149         if (ifile == NULL || ofile == NULL || hfile == NULL) {
150                 fprintf(stderr,"%s: malloc failure.\n", Progname);
151                 exit (1);
152         }
153
154         /* Set default flags */
155         ifile->flags[FL_MAP].value = MAP_PRIVATE;
156         ifile->flags[FL_PROT].value = PROT_READ;
157         ifile->flags[FL_OPEN].value = O_RDONLY;
158         ofile->flags[FL_MAP].value = MAP_SHARED;
159 #ifdef __sgi
160         ofile->flags[FL_MAP].value = MAP_AUTOGROW;
161 #endif
162         ofile->flags[FL_PROT].value = PROT_WRITE;
163         ofile->flags[FL_OPEN].value = O_RDWR|O_CREAT;
164
165         while ((opt = getopt(argc, argv, "i:o:h:d")) != EOF) {
166                 switch(opt) {
167                 case 'i':
168                         if (mfile_opt(optarg, ifile) != 0) {
169                                 fprintf(stderr, "%s: Invalid -i option %s\n",
170                                         Progname, optarg);
171                                 Usage();
172                         }
173                         break;
174
175                 case 'o':
176                         if (mfile_opt(optarg, ofile) != 0) {
177                                 fprintf(stderr, "%s: Invalid -o option %s\n",
178                                         Progname, optarg);
179                                 Usage();
180                         }
181                         break;
182
183                 case 'h':
184                         if (mfile_opt(optarg, hfile) != 0) {
185                                 fprintf(stderr, "%s: Invalid -h option %s\n",
186                                         Progname, optarg);
187                                 Usage();
188                         }
189                         hack = 1;
190                         break;
191
192                 case 'd':
193                         print_flags_set ^= 1;
194                         break;
195                 case '?':
196                         Usage();
197                 }
198         }
199
200         if (optind+1 > argc)
201                 Usage();
202
203         ifile->path = argv[optind++];
204         ofile->path = argv[optind++];
205
206         if (optind != argc)     /* Extra args on command line */
207                 Usage();
208
209         if (stat(ifile->path, &(ifile->st)) < 0) {
210                 fprintf(stderr,"%s: stat of %s failed.\n",
211                                                 Progname, ifile->path);
212                 perror(ifile->path);
213                 exit(2);
214         }
215
216         len = ifile->st.st_size;
217
218         ifile->fd = open(ifile->path, ifile->flags[FL_OPEN].value);
219         if (ifile->fd < 0) {
220                 fprintf(stderr,"%s: cannot open %s\n", Progname, ifile->path);
221                 perror(ifile->path);
222                 exit(2);
223         }
224
225
226         ofile->fd = open(ofile->path, ofile->flags[FL_OPEN].value, 0644);
227         if (ofile->fd < 0) {
228                 fprintf(stderr,"%s: cannot open %s\n", Progname, ofile->path);
229                 perror(ofile->path);
230                 exit(3);
231         }
232
233         if (print_flags_set) {
234                 print_flags("Input ", ifile);
235                 print_flags("Output", ofile);
236                 if (hack)
237                         print_flags("Hack  ", hfile);
238         }
239
240
241         ifile->p = mmap(NULL, len, ifile->flags[FL_PROT].value,
242                                 ifile->flags[FL_MAP].value, ifile->fd, 0);
243         if (ifile->p == MAP_FAILED) {
244                 fprintf(stderr,"%s: cannot mmap %s\n", Progname, ifile->path);
245                 perror(ifile->path);
246                 exit(2);
247         }
248
249         ofile->p = mmap(NULL, len, ofile->flags[FL_PROT].value,
250                                 ofile->flags[FL_MAP].value , ofile->fd, 0);
251                 if (ofile->p == MAP_FAILED) {
252                 fprintf(stderr,"%s: cannot mmap %s\n", Progname, ofile->path);
253                 perror(ofile->path);
254                 exit(3);
255         }
256
257         if (hack) {
258                 int     error;
259
260                 error = mprotect(ofile->p, len, hfile->flags[FL_PROT].value);
261                 if (error) {
262                         fprintf(stderr,"%s: mprotect call failed.\n", Progname);
263                         perror("mprotect");
264                         exit(3);
265                 }
266         }
267         
268         bcopy(ifile->p, ofile->p, len);
269
270         printf("%s complete.\n", Progname);
271         return 0;
272 }
273
274 static mfile_t *
275 new_mfile(void)
276 {
277         mfile_t *ptr = (mfile_t *)malloc(sizeof(*ptr));
278         if (ptr)
279                 bzero(ptr, sizeof *ptr);
280
281         return  ptr;
282 }
283
284
285 static  int
286 mfile_opt(char * s, mfile_t *f)
287 {
288         int     i;
289         ftype_t type;
290
291         for (i = 0; i < num_Flags; i++) {
292                 if(!strcasecmp(Flags[i].name, s)) {
293
294                         /* Zero value if this is 1st arg of this type */
295
296                         type = Flags[i].type;
297                         if (f->flags[type].arg++ == 0) 
298                                 f->flags[type].value = 0;
299                         f->flags[type].value |= Flags[i].value;
300                         return 0;
301                 }
302         }
303         return -1;      /* error - string not found */
304 }
305
306 static void
307 Usage(void)
308 {
309         int     i;
310
311         fprintf(stderr, 
312                 "Usage: %s [-d] [-i flag] [-i flag] [-o flag] ... file1 file2\n",
313                 Progname);
314         fprintf(stderr, "Valid flag values are:\n");
315
316         for (i = 0; i < num_Flags; i++) {
317                 fprintf(stderr,"%15s",Flags[i].name);
318                 if ((i+1)%4 == 0 || i == num_Flags-1)
319                         fprintf(stderr,"\n");
320                 else
321                         fprintf(stderr,",");
322         }
323         exit(1);
324 }
325
326 static  void
327 print_flags(char *s, mfile_t *f)
328 {
329         int             i;
330         ftype_t         type;
331
332         printf("DEBUG - %s flags:\n", s);
333         for (i = 0; i < num_Flags; i++) {
334                 type = Flags[i].type;
335                 if (type == FL_OPEN && Flags[i].value == O_RDONLY && 
336                         ((f->flags[type].value) & 3) == 0) 
337                                 /* Hack to print out O_RDONLY */
338                                 printf("\t%s\n", Flags[i].name);
339                 else if ((Flags[i].value & (f->flags[type].value)) != 0)
340                         printf("\t%s\n", Flags[i].name);
341         }
342 }