/** * This function behaves exactly like mtcp_sys_open(), except that you are * guaranteed to receive a file descriptor that is not one of the standard 3. * This is useful if, for instance, you have no fd 0, receive one through * open(), dup2 it to stdin, and close the original (therefore closing stdin). * * @param filename the file to open * @param flags the flags that indicate how to open it * @param mode if O_CREAT is in flags and the file gets created, mode indicates * the permissions * * @return a file descriptor to filename, opened according to flags and mode, * that is guaranteed to not be one of the standard 3 */ int mtcp_safe_open(char const *filename, int flags, mode_t mode) { int fds[3]; int i, j, fd; for(i = 0; i < 4; i++) { fd = mtcp_sys_open(filename, flags, mode); if((fd != STDIN_FILENO) && (fd != STDOUT_FILENO) && (fd != STDERR_FILENO)) break; fds[i] = fd; } for(j = 0; j < i; j++) mtcp_sys_close(fds[j]); return fd; }
/** * This function will return the first character of the given file. If the * file is not readable, we will abort. * * @param filename the name of the file to read * @return the first character of the given file */ static char first_char(char *filename) { int fd, rc; char c; fd = mtcp_sys_open(filename, O_RDONLY, 0); if(fd < 0) { MTCP_PRINTF("ERROR: Cannot open file %s\n", filename); mtcp_abort(); } rc = mtcp_sys_read(fd, &c, 1); if(rc != 1) { MTCP_PRINTF("ERROR: Error reading from file %s\n", filename); mtcp_abort(); } mtcp_sys_close(fd); return c; }
int mtcp_selfmap_open() { return mtcp_sys_open ("/proc/self/maps", O_RDONLY, 0); }
void mtcp_get_memory_region_of_this_library(VA *startaddr, VA *endaddr) { struct { VA start_addr; VA end_addr; } text, guard, rodata, rwdata, bssdata; Area area; VA thislib_fnc = (void*) &mtcp_get_memory_region_of_this_library; VA thislib_static_var = (VA) &dummy_uninitialized_static_var; char filename[PATH_MAX] = {0}; text.start_addr = guard.start_addr = rodata.start_addr = NULL; rwdata.start_addr = bssdata.start_addr = bssdata.end_addr = NULL; int mapsfd = mtcp_sys_open("/proc/self/maps", O_RDONLY, 0); MTCP_ASSERT(mapsfd != -1); while (mtcp_readmapsline (mapsfd, &area, NULL)) { VA start_addr = area.addr; VA end_addr = area.addr + area.size; if (thislib_fnc >= start_addr && thislib_fnc < end_addr) { MTCP_ASSERT(text.start_addr == NULL); text.start_addr = start_addr; text.end_addr = end_addr; mtcp_strcpy(filename, area.name); continue; } if (text.start_addr != NULL && guard.start_addr == NULL && mtcp_strcmp(filename, area.name) == 0) { MTCP_ASSERT(area.addr == text.end_addr); if (area.prot == 0) { /* The guard pages are unreadable due to the "---p" protection. Even if * the protection is changed to "r--p", a read will result in a SIGSEGV * as the pages are not backed by the kernel. A better way to handle * this is to remap these pages with anonymous memory. */ MTCP_ASSERT(mtcp_sys_mmap(start_addr, area.size, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0) == start_addr); guard.start_addr = start_addr; guard.end_addr = end_addr; continue; } else { // No guard pages found. This is probably the ROData section. guard.start_addr = start_addr; guard.end_addr = start_addr; } } if (guard.start_addr != NULL && rodata.start_addr == NULL && mtcp_strcmp(filename, area.name) == 0) { MTCP_ASSERT(area.addr == guard.end_addr); if (area.prot == PROT_READ || // On some systems, all sections of the library have exec // permissions. area.prot == (PROT_READ|PROT_EXEC)) { rodata.start_addr = start_addr; rodata.end_addr = end_addr; continue; } else { // No ROData section. This is probably the RWData section. rodata.start_addr = start_addr; rodata.end_addr = start_addr; } } if (rodata.start_addr != NULL && rwdata.start_addr == NULL && mtcp_strcmp(filename, area.name) == 0) { MTCP_ASSERT(area.addr == rodata.end_addr); MTCP_ASSERT(area.prot == (PROT_READ|PROT_WRITE) || // On some systems, all sections of the library have exec // permissions. area.prot == (PROT_READ|PROT_WRITE|PROT_EXEC)); rwdata.start_addr = start_addr; rwdata.end_addr = end_addr; continue; } if (rwdata.start_addr != NULL && bssdata.start_addr == NULL && area.name[0] == '\0') { /* /proc/PID/maps does not label the filename for memory region holding * static variables in a library. But that is also part of this * library (libmtcp.so). * So, find the meory region for static memory variables and add it. */ MTCP_ASSERT(area.addr == rwdata.end_addr); MTCP_ASSERT(area.prot == (PROT_READ|PROT_WRITE) || // On some systems, all sections of the library have exec // permissions. area.prot == (PROT_READ|PROT_WRITE|PROT_EXEC)); MTCP_ASSERT(thislib_static_var >= start_addr && thislib_static_var < end_addr); bssdata.start_addr = start_addr; bssdata.end_addr = end_addr; break; } } mtcp_sys_close(mapsfd); MTCP_ASSERT(text.start_addr != NULL); MTCP_ASSERT(bssdata.end_addr != NULL); *startaddr = text.start_addr; *endaddr = bssdata.end_addr; }
/** * This function will open the checkpoint file stored at the given filename. * It will check the magic number and take the appropriate action. If the * magic number is unknown, we will abort. The fd returned points to the * beginning of the uncompressed data. * NOTE: related code in ../dmtcp/src/connectionmanager.cpp:open_ckpt_to_read() * * @param filename the name of the checkpoint file * @return the fd to use */ static int open_ckpt_to_read(char *filename, char *envp[]) { int fd; int fds[2]; char fc; char *gzip_cmd = "gzip"; static char *gzip_args[] = { "gzip", "-d", "-", NULL }; #ifdef HBICT_DELTACOMP char *hbict_cmd = "hbict"; static char *hbict_args[] = { "hbict", "-r", NULL }; #endif char decomp_path[PATH_MAX]; static char **decomp_args; pid_t cpid; fc = first_char(filename); fd = mtcp_sys_open(filename, O_RDONLY, 0); if(fd < 0) { MTCP_PRINTF("ERROR: Cannot open checkpoint file %s\n", filename); mtcp_abort(); } if (fc == MAGIC_FIRST || fc == 'D') /* no compression ('D' from DMTCP) */ return fd; else if (fc == GZIP_FIRST #ifdef HBICT_DELTACOMP || fc == HBICT_FIRST #endif ) { /* Set prog_path */ if( fc == GZIP_FIRST ){ decomp_args = gzip_args; if( mtcp_find_executable(gzip_cmd, getenv("PATH"), decomp_path) == NULL ) { MTCP_PRINTF("ERROR: Cannot find gunzip to decompress ckpt file!\n"); mtcp_abort(); } } #ifdef HBICT_DELTACOMP if( fc == HBICT_FIRST ){ decomp_args = hbict_args; if( mtcp_find_executable(hbict_cmd, getenv("PATH"), decomp_path) == NULL ) { MTCP_PRINTF("ERROR: Cannot find hbict to decompress ckpt file!\n"); mtcp_abort(); } } #endif if (mtcp_sys_pipe(fds) == -1) { MTCP_PRINTF("ERROR: Cannot create pipe to execute gunzip to decompress" " checkpoint file!\n"); mtcp_abort(); } cpid = mtcp_sys_fork(); if(cpid == -1) { MTCP_PRINTF("ERROR: Cannot fork to execute gunzip to decompress" " checkpoint file!\n"); mtcp_abort(); } else if(cpid > 0) /* parent process */ { decomp_child_pid = cpid; mtcp_sys_close(fd); mtcp_sys_close(fds[1]); return fds[0]; } else /* child process */ { fd = mtcp_sys_dup(mtcp_sys_dup(mtcp_sys_dup(fd))); if (fd == -1) { MTCP_PRINTF("ERROR: dup() failed! No restoration will be performed!" " Cancel now!\n"); mtcp_abort(); } fds[1] = mtcp_sys_dup(fds[1]); mtcp_sys_close(fds[0]); if (mtcp_sys_dup2(fd, STDIN_FILENO) != STDIN_FILENO) { MTCP_PRINTF("ERROR: dup2() failed! No restoration will be performed!" " Cancel now!\n"); mtcp_abort(); } mtcp_sys_close(fd); mtcp_sys_dup2(fds[1], STDOUT_FILENO); mtcp_sys_close(fds[1]); mtcp_sys_execve(decomp_path, decomp_args, envp); /* should not get here */ MTCP_PRINTF("ERROR: Decompression failed! No restoration will be" " performed! Cancel now!\n"); mtcp_abort(); } } else /* invalid magic number */ { MTCP_PRINTF("ERROR: Invalid magic number in this checkpoint file!\n"); mtcp_abort(); } }