/* create a temp file for anonymous mappings */ struct file *create_temp_file( int access ) { char tmpfn[16]; int fd; sprintf( tmpfn, "anonmap.XXXXXX" ); /* create it in the server directory */ fd = mkstemps( tmpfn, 0 ); if (fd == -1) { file_set_error(); return NULL; } unlink( tmpfn ); return create_file_for_fd( fd, access, 0 ); }
/* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { struct shared_map *shared; struct file *file; unsigned int i; mem_size_t total_size; size_t file_size, map_size, max_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; long toread; /* compute the total size of the shared mapping */ total_size = max_size = 0; for (i = 0; i < nb_sec; i++) { if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); if (file_size > max_size) max_size = file_size; total_size += map_size; } } if (!total_size) return 1; /* nothing to do */ if ((mapping->shared = get_shared_file( mapping->fd ))) return 1; /* create a temp file for the mapping */ if ((shared_fd = create_temp_file( total_size )) == -1) return 0; if (!(file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) return 0; if (!(buffer = malloc( max_size ))) goto error; /* copy the shared sections data into the temp file */ shared_pos = 0; for (i = 0; i < nb_sec; i++) { if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); write_pos = shared_pos; shared_pos += map_size; if (!sec[i].PointerToRawData || !file_size) continue; toread = file_size; while (toread) { long res = pread( fd, buffer + file_size - toread, toread, read_pos ); if (!res && toread < 0x200) /* partial sector at EOF is not an error */ { file_size -= toread; break; } if (res <= 0) goto error; toread -= res; read_pos += res; } if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error; } if (!(shared = alloc_object( &shared_map_ops ))) goto error; shared->fd = (struct fd *)grab_object( mapping->fd ); shared->file = file; list_add_head( &shared_map_list, &shared->entry ); mapping->shared = shared; free( buffer ); return 1; error: release_object( file ); free( buffer ); return 0; }