/* * * Copyright (c) International Business Machines Corp., 2001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Test Name: mmap01 * * Test Description: * Verify that, mmap() succeeds when used to map a file where size of the * file is not a multiple of the page size, the memory area beyond the end * of the file to the end of the page is accessible. Also, verify that * this area is all zeroed and the modifications done to this area are * not written to the file. * * Expected Result: * mmap() should succeed returning the address of the mapped region. * The memory area beyond the end of file to the end of page should be * filled with zero. * The changes beyond the end of file should not get written to the file. * * Algorithm: * Setup: * Setup signal handling. * Pause for SIGUSR1 if option specified. * Create temporary directory. * * Test: * Loop if the proper options are given. * Execute system call * Check return code, if system call failed (return=-1) * Log the errno and Issue a FAIL message. * Otherwise, * Verify the Functionality of system call * if successful, * Issue Functionality-Pass message. * Otherwise, * Issue Functionality-Fail message. * Cleanup: * Print timing stats if options given * Delete the temporary directory created. * * Usage: * mmap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t] * where, -c n : Run n copies concurrently. * -f : Turn off functionality Testing. * -i n : Execute test n times. * -I x : Execute test for x seconds. * -P x : Pause for x seconds between iterations. * -t : Turn on syscall timing. * * HISTORY * 07/2001 Ported by Wayne Boyer * * RESTRICTIONS: * None. */ #include #include #include #include #include #include #include #include #include #include #include #include #define TEMPFILE "mmapfile" char *TCID = "mmap01"; /* Test program identifier. */ int TST_TOTAL = 1; /* Total number of test cases. */ extern int Tst_count; /* Test Case counter for tst_* routines */ char *addr; /* addr of memory mapped region */ char *dummy; /* dummy string */ size_t page_sz; /* system page size */ size_t file_sz; /* mapped file size */ int fildes; /* file descriptor for tempfile */ char Cmd_buffer[BUFSIZ]; /* command buffer to hold test command */ void setup(); /* Main setup function of test */ void cleanup(); /* cleanup function for the test */ int main(int ac, char **av) { int lc; /* loop counter */ char *msg; /* message returned from parse_opts */ int i; /* Perform global setup for test */ struct stat stat_buf; char write_buf[] = "ABCD\n EFGH\n"; //41424344 /* Creat a temporary file used for mapping */ if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { printf( "open() on %s Failed, errno=%d : %s", TEMPFILE, errno, strerror(errno)); cleanup(); } /* Write some data into temporary file */ if (write(fildes, write_buf, strlen(write_buf)) != strlen(write_buf)) { printf("write() on %s Failed, errno=%d : %s", TEMPFILE, errno, strerror(errno)); cleanup(); } /* Get the size of temporary file */ if (stat(TEMPFILE, &stat_buf) < 0) { printf( "stat() on %s Failed, errno=%d : %s", TEMPFILE, errno, strerror(errno)); cleanup(); } file_sz = stat_buf.st_size; /* Get the system page size */ if ((page_sz = getpagesize()) < 0) { printf("getpagesize() fails to get system page size"); cleanup(); } /* Allocate and initialize dummy string of system page size bytes */ if ((dummy = (char *)calloc(page_sz, sizeof(char))) == NULL) { printf("calloc() failed to allocate space"); cleanup(); } /* * Initialize addr to align with the first segment boundary address * above the break address of the process. */ addr = (void *)(((intptr_t) sbrk(0) + (SHMLBA - 1)) & ~(SHMLBA - 1)); printf("dummy 0x%x, addr 0x%x, sbrk 0x%x 0x%x\n", dummy, addr, sbrk, SHMLBA); /* Set the break address of the process to the addr plus one * page size. */ if ((intptr_t) sbrk(SHMLBA + page_sz) == -1) { printf("sbrk(SHMLBA + page_sz) failed"); cleanup(); } /* Initialize one page region from addr with 'A' */ memset(addr, 'A', page_sz); #if 0 /* delayed loops */ /* Hera is one loop which read all data which are in addr -> all are 0x41414141 which is correct */ int *test = (int *)addr; /* +1 caused that I read one word after allocated space */ for( i = 0; i<(page_sz/4 + 1); i++) { printf("0x%x: 0x%x\n", test, *test); test++; } /* test with printf - on nfs works, on initramfs sometimes failed */ printf("hello\n"); /* test with syscall */ sync(); #endif /* * Call mmap to map the temporary file beyond EOF * with write access. */ errno = 0; addr = mmap(addr, page_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED | MAP_FIXED, fildes, 0); /* Check for the return value of mmap() */ if (addr == MAP_FAILED) { printf("mmap() Failed on %s, errno=%d : %s", TEMPFILE, errno, strerror(errno)); } printf("file size=0x%x, first writing addr=0x%x\n", file_sz, &addr[file_sz]); /* 1. checking loop after mmap */ /* read fist 15 words mmap memory */ int *file = (int *)addr; for( i = 0; i<(15); i++) { printf("0x%x: 0x%08x\n", file, *file); file++; } /* * Initialize memory beyond file size */ addr[file_sz] = 0x11; addr[file_sz + 1] = 0x12; addr[file_sz + 2] = 0x13; /* 2. checking after writing - always is correct */ printf("------------\n"); file = (int *)addr; for( i = 0; i<(15); i++) { printf("0x%x: 0x%08x\n", file, *file); file++; } /* * Synchronize the mapped memory region * with the file. */ if (msync(addr, page_sz, MS_SYNC) != 0) { printf("msync() failed to " "synchronize mapped file, error:%d", errno); cleanup(); } /* Create the command which will be executed in the test */ sprintf(Cmd_buffer, "grep XYZ %s > /dev/null", TEMPFILE); /* * Now, Search for the pattern 'XYZ' in the * temporary file. The pattern should not be * found and the return value should be 1. */ if (system(Cmd_buffer) != 0) { printf("Functionality of mmap() successful"); } else { printf("Specified pattern found in file"); } /* Clean up things in case we are looping */ /* Unmap the mapped memory */ if (munmap(addr, page_sz) != 0) { printf("munmap() fails to unmap the " "memory, errno=%d", errno); } /* Call cleanup() to undo setup done for the test. */ cleanup(); /*NOTREACHED*/ return 0; } /* End main */ /* * cleanup() - performs all ONE TIME cleanup for this test at * completion or premature exit. * Free the memory allocated to variable. * Remove the temporary directory created. */ void cleanup() { /* * print timing stats if that option was specified. */ close(fildes); /* Free the memory allocated for dummy string */ if (dummy) { free(dummy); } }