Home | History | Annotate | Download | only in mmap
      1 /*
      2  * Copyright (C) 2000 Juan Quintela <quintela (at) fi.udc.es>
      3  *                    Aaron Laffin <alaffin (at) sgi.com>
      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
      7  * as published by the Free Software Foundation; either version 2
      8  * of the License, or (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18  *
     19  * mmap001.c - Tests mmapping a big file and writing it once
     20  */
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 #include <fcntl.h>
     24 #include <sys/mman.h>
     25 #include <stdlib.h>
     26 #include <stdio.h>
     27 #include <unistd.h>
     28 #include <errno.h>
     29 #include <string.h>
     30 
     31 #include "test.h"
     32 
     33 char *TCID = "mmap001";
     34 int TST_TOTAL = 5;
     35 static char *filename = NULL;
     36 static int m_opt = 0;
     37 static char *m_copt;
     38 
     39 static void cleanup(void)
     40 {
     41 	free(filename);
     42 
     43 	tst_rmdir();
     44 }
     45 
     46 static void setup(void)
     47 {
     48 	char buf[1024];
     49 	/*
     50 	 * setup a default signal hander and a
     51 	 * temporary working directory.
     52 	 */
     53 	tst_sig(FORK, DEF_HANDLER, cleanup);
     54 
     55 	TEST_PAUSE;
     56 
     57 	tst_tmpdir();
     58 
     59 	snprintf(buf, 1024, "testfile.%d", getpid());
     60 
     61 	if ((filename = strdup(buf)) == NULL) {
     62 		tst_brkm(TBROK | TERRNO, cleanup, "strdup failed");
     63 	}
     64 
     65 }
     66 
     67 static void help(void)
     68 {
     69 	printf("  -m x    size of mmap in pages (default 1000)\n");
     70 }
     71 
     72 /*
     73  * add the -m option whose parameter is the
     74  * pages that should be mapped.
     75  */
     76 option_t options[] = {
     77 	{"m:", &m_opt, &m_copt},
     78 	{NULL, NULL, NULL}
     79 };
     80 
     81 int main(int argc, char *argv[])
     82 {
     83 	char *array;
     84 	int i, lc;
     85 	int fd;
     86 	unsigned int pages, memsize;
     87 
     88 	tst_parse_opts(argc, argv, options, help);
     89 
     90 	if (m_opt) {
     91 		memsize = pages = atoi(m_copt);
     92 
     93 		if (memsize < 1) {
     94 			tst_brkm(TBROK, cleanup, "Invalid arg for -m: %s",
     95 				 m_copt);
     96 		}
     97 
     98 		memsize *= getpagesize();	/* N PAGES */
     99 
    100 	} else {
    101 		/*
    102 		 * default size 1000 pages;
    103 		 */
    104 		memsize = pages = 1000;
    105 		memsize *= getpagesize();
    106 	}
    107 
    108 	tst_resm(TINFO, "mmap()ing file of %u pages or %u bytes", pages,
    109 		 memsize);
    110 
    111 	setup();
    112 
    113 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    114 		tst_count = 0;
    115 
    116 		fd = open(filename, O_RDWR | O_CREAT, 0666);
    117 		if ((fd == -1))
    118 			tst_brkm(TBROK | TERRNO, cleanup,
    119 				 "opening %s failed", filename);
    120 
    121 		if (lseek(fd, memsize, SEEK_SET) != memsize) {
    122 			TEST_ERRNO = errno;
    123 			close(fd);
    124 			tst_brkm(TBROK | TTERRNO, cleanup, "lseek failed");
    125 		}
    126 
    127 		if (write(fd, "\0", 1) != 1) {
    128 			TEST_ERRNO = errno;
    129 			close(fd);
    130 			tst_brkm(TBROK | TTERRNO, cleanup,
    131 				 "writing to %s failed", filename);
    132 		}
    133 
    134 		array = mmap(0, memsize, PROT_WRITE, MAP_SHARED, fd, 0);
    135 		if (array == MAP_FAILED) {
    136 			TEST_ERRNO = errno;
    137 			close(fd);
    138 			tst_brkm(TBROK | TTERRNO, cleanup,
    139 				 "mmapping %s failed", filename);
    140 		} else {
    141 			tst_resm(TPASS, "mmap() completed successfully.");
    142 		}
    143 
    144 		tst_resm(TINFO, "touching mmaped memory");
    145 
    146 		for (i = 0; i < memsize; i++) {
    147 			array[i] = (char)i;
    148 		}
    149 
    150 		/*
    151 		 * seems that if the map area was bad, we'd get SEGV,
    152 		 * hence we can indicate a PASS.
    153 		 */
    154 		tst_resm(TPASS,
    155 			 "we're still here, mmaped area must be good");
    156 
    157 		TEST(msync(array, memsize, MS_SYNC));
    158 
    159 		if (TEST_RETURN == -1) {
    160 			tst_resm(TFAIL | TTERRNO,
    161 				 "synchronizing mmapped page failed");
    162 		} else {
    163 			tst_resm(TPASS,
    164 				 "synchronizing mmapped page passed");
    165 		}
    166 
    167 		TEST(munmap(array, memsize));
    168 
    169 		if (TEST_RETURN == -1) {
    170 			tst_resm(TFAIL | TTERRNO,
    171 				 "munmapping %s failed", filename);
    172 		} else {
    173 			tst_resm(TPASS, "munmapping %s successful", filename);
    174 		}
    175 
    176 		close(fd);
    177 		unlink(filename);
    178 
    179 	}
    180 	cleanup();
    181 	tst_exit();
    182 }
    183