diff -Naur linux-2.4.22-5um.orig/arch/um/include/filemap.h linux-2.4.22-5um.new/arch/um/include/filemap.h
--- linux-2.4.22-5um.orig/arch/um/include/filemap.h	Wed Dec 31 19:00:00 1969
+++ linux-2.4.22-5um.new/arch/um/include/filemap.h	Thu Sep 25 20:29:17 2003
@@ -0,0 +1,13 @@
+/* 
+ * Copyright (C) 2003 Steve Schmidtke 
+ * Licensed under the GPL
+ */
+
+#ifndef __FILEMAP_H__
+#define __FILEMAP_H__
+
+extern int filemap_access(const char* table_name, const char* file_name);
+extern int filemap_aquire(const char* table_name, const char* file_name);
+extern int filemap_release(const char* table_name, int fd);
+
+#endif
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/Makefile linux-2.4.22-5um.new/arch/um/kernel/Makefile
--- linux-2.4.22-5um.orig/arch/um/kernel/Makefile	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/Makefile	Thu Sep 25 20:29:17 2003
@@ -11,7 +11,7 @@
 	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
 	syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
 	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
-	um_arch.o umid.o user_syms.o user_util.o
+	um_arch.o umid.o user_syms.o user_util.o filemap.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -29,7 +29,7 @@
 # building anything in export-objs
 
 USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
-	process.o tempfile.o time.o umid.o user_util.o 
+	process.o tempfile.o time.o umid.o user_util.o filemap.o
 
 DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
 DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/filemap.c linux-2.4.22-5um.new/arch/um/kernel/filemap.c
--- linux-2.4.22-5um.orig/arch/um/kernel/filemap.c	Wed Dec 31 19:00:00 1969
+++ linux-2.4.22-5um.new/arch/um/kernel/filemap.c	Thu Sep 25 20:29:17 2003
@@ -0,0 +1,655 @@
+/* 
+ * Copyright (C) 2003 Steve Schmidtke 
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h> 
+#include <string.h> 
+#include <unistd.h> 
+#include <errno.h> 
+#include "init.h"
+#include "sys/types.h"
+#include "unistd.h"
+#include "fcntl.h"
+
+#define STRFD_ISEND(c)  ((c == '\0') || (c == ',') || (c == '-'))
+
+struct filemap_entry {
+	struct filemap_entry* next;
+	char* name;
+	int fd;
+	int count;
+	int cf; /* initial close on exec flag */
+};  
+
+struct filemap_ops {
+	int (*parse)(void* table, char* str);
+	int (*access)(void* table, char* filename);
+	int (*aquire)(void* table, char* filename);
+	int (*release)(void* table, int fd);
+	int (*shutdown)(void* table);
+};
+
+struct filemap_table {
+	char* name;
+	struct filemap_entry* entries;
+	struct filemap_ops* ops;
+};
+
+static struct filemap_entry* filemap_entry_alloc(void)
+{
+	return(malloc(sizeof(struct filemap_entry)));
+}
+
+/* FIXME: the os_* versions of these routines below may recurse? */
+
+static void seek_file(int fd, off_t offset)
+{
+	lseek(fd, offset, SEEK_SET);
+}
+
+static int get_close_on_exec(int fd, int* close_on_exec)
+{
+	int ret;
+
+	do {
+		ret = fcntl(fd, F_GETFD);
+	} while(ret<0 && errno==EINTR) ;
+
+	if(ret < 0)
+		return(-errno);
+
+	*close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+
+	return(ret);
+}
+
+static int set_close_on_exec(int fd, int close_on_exec)
+{
+	int flag, err;
+
+	if(close_on_exec) flag = FD_CLOEXEC;
+	else flag = 0;
+
+	do {
+		err = fcntl(fd, F_SETFD, flag);
+	} while(err<0 && errno==EINTR) ;
+
+	if(err < 0)
+		return(-errno);
+
+	return(err);
+}
+
+/*
+ * Add a fd (and filename) to a table in the db.
+ */
+static int filemap_add_entry(struct filemap_table* table,
+    int fdesc, char* file_name)
+{
+	struct filemap_entry* entry;
+	struct filemap_entry* dup;
+	int coeflag;
+	int err;
+
+	if((table == NULL) || (fdesc < 0)) {
+		return(-EINVAL);
+	}
+
+	dup = NULL;
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(!dup && (fdesc == entry->fd)) {
+			dup = entry;
+		}
+	}
+
+	if(dup) {
+		coeflag = dup->cf;
+	} else {
+		err = get_close_on_exec(fdesc, &coeflag);
+		if(err < 0) {
+			printk("filemap_add_entry: get close-on-exec flag"
+				" failed errno=%d fd=%d name=%s\n",
+				err, fdesc, file_name);
+			return(err);
+		}
+
+		/* by default, exec calls should close filemaps */ 
+		err = set_close_on_exec(fdesc, 1);
+		if(err < 0) {
+			printk("filemap_add_entry: set close-on-exec flag"
+				" failed errno=%d fd=%d name=%s\n",
+				err, fdesc, file_name);
+			return(err);
+		}
+	}
+
+	entry = filemap_entry_alloc();
+	if(entry == NULL) {
+		printk("filemap_add_entry: alloc failed fd=%d, name=%s\n",
+			fdesc, file_name);
+		return(-ENOMEM);
+	}
+
+	printk("installing filemap: table=%s fd=%d, c-o-e=%d name=%s\n",
+		table->name, fdesc, coeflag, file_name);
+
+	*entry = ((struct filemap_entry) {
+			.next	= table->entries,
+			.name	= file_name,
+			.fd	= fdesc,
+			.count	= 0,
+			.cf	= coeflag
+	});
+
+	table->entries = entry;
+
+	return(0);
+}
+
+/*
+ * Find the matching filename in the db and return the filemap entry. 
+ */
+static struct filemap_entry* filemap_lookup_name(struct filemap_table* table,
+    const char* file_name)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(strcmp(file_name, entry->name) == 0) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * Find a fresh file descriptor in a file pool
+ */
+static struct filemap_entry* filemap_lookup_unused(struct filemap_table* table)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(entry->count == 0) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * Find a matching fd in the db and return a filemap entry. 
+ */
+static struct filemap_entry* filemap_lookup_fd(struct filemap_table* table,
+    const int fd)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(fd == entry->fd) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * set the filemapped file as pristine as possible
+ */
+static int filemap_scrub(struct filemap_entry* entry)
+{
+	int err;
+
+	err = set_close_on_exec(entry->fd, entry->cf);
+	if(err < 0) {
+		printk("filemap_scrub: reset close-on-exec flag failed"
+			" err=%d fd=%d c-o-e=%d name=%s\n",
+			err, entry->fd, entry->cf, entry->name);
+		return(err);
+	}
+
+	return(0);
+}
+
+/* 
+ * Return a disposable file descriptor for the one provided.
+ * dup() is used to guard against a close of the fd that was passed
+ * in.  This is not ideal as concurrent uses of the same file may
+ * wreak havoc with the shared position pointer, etc. between the
+ * duplicated file descriptors.
+ */ 
+static int filemap_newfd(int oldfd)
+{
+	int newfd, err;
+
+	if(oldfd < 0)
+		return(-EINVAL);
+
+	do {
+		newfd = dup(oldfd);
+	} while(newfd<0 && errno==EINTR) ;
+
+	if(newfd < 0)
+		return(-errno);
+
+	err = set_close_on_exec(newfd, 0);
+	if(err < 0) {
+		printk("filemap_newfd: clear close-on-exec flag failed"
+			" err=%d fd=%d\n", err, newfd);
+		return(err);
+	}
+
+	return(newfd);
+}
+
+/*
+ * parse the setup string for a file descriptor (number) and
+ * return * a pointer on the next argument in the setup string.
+ */
+static __init char* set_fdesc(char* str, int* fd)
+{
+	char* end;
+	int num;
+
+	if((str==NULL) || (*str=='\0'))
+		return(NULL);
+
+	if(*str == ',')
+		return(str);
+
+	num = strtoul(str, &end, 10);
+	if((end == str) || !STRFD_ISEND(*end)) {
+		printk("filemap: set_fd - invalid value '%s'\n", str);
+		goto endout;
+	}
+
+	*fd = num;
+
+endout:
+	while(!STRFD_ISEND(*end)) end++;
+	if(*end == '\0')
+		 return(NULL);
+
+	return(end);
+}
+
+
+/************************************************
+ *** Routines to support 'pool' type filemaps ***
+ ************************************************/
+
+static int fm_pool_parse(void* data, char* str)
+{
+	struct filemap_table* table = data;
+	char* end;
+	unsigned int count;
+	int fdfirst, fdlast, err;
+
+	end = set_fdesc(str, &fdfirst);
+	if(*end == '-') {
+		end = set_fdesc(end+1, &fdlast);
+	} else {
+		fdlast = fdfirst;
+	}
+
+	/* NOTE: add_entry loop must interate first -> last *inclusive* */
+
+	if(fdfirst < fdlast) count = fdlast - fdfirst;
+	else count = fdfirst - fdlast;
+
+	do { 
+		err = filemap_add_entry(table, fdfirst, NULL);
+		if(err < 0) {
+			printk("WARNING: filemap error %d on '%s':'%s'\n",
+			    err, table->name, str);
+			return(err);
+		}
+
+		if(fdfirst < fdlast) fdfirst++;
+		else fdfirst--;
+	} while(count--) ;
+
+	return(0);
+}
+
+static int fm_pool_access(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	entry = filemap_lookup_unused(table);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	entry->count++;
+
+	return(entry->fd);
+}
+
+static int fm_pool_aquire(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+	int fd;
+
+	entry = filemap_lookup_unused(table);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	fd = filemap_newfd(entry->fd);
+	if(fd < 0)
+		return(fd);
+
+	entry->count++;
+
+	/* make sure this "new" file is rewound */
+	seek_file(fd, 0);
+
+	return(fd);
+}
+
+static int fm_pool_release(void* data, int fd)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	/* the lookup_fd will always fail if the returned fd from _aquire is
+	 * a dup of the real fd.  This is OK: the caller will close the dup */
+	entry=filemap_lookup_fd(table, fd); 
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	if(entry->count > 0)
+		entry->count--;
+
+	return(0);
+}
+
+static int fm_pool_shutdown(void* data)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		filemap_scrub(entry);
+	}
+
+	return(0);
+}
+
+static struct filemap_ops fm_ops_pool = {
+	.parse        = fm_pool_parse,
+	.access       = fm_pool_access,
+	.aquire       = fm_pool_aquire,
+	.release      = fm_pool_release,
+	.shutdown     = fm_pool_shutdown,
+};
+
+
+/************************************************
+ *** Routines to support 'file' type filemaps ***
+ ************************************************/
+
+static int fm_file_parse(void* data, char* str)
+{
+	struct filemap_table* table = data;
+	char* file_name;
+	int fd, err;
+
+	file_name = set_fdesc(str, &fd);
+	if(*file_name == ',')
+		file_name++;
+
+	err = filemap_add_entry(table, fd, file_name);
+	if(err < 0) {
+		printk("WARNING: filemap error %d on '%s':'%s'\n",
+		    err, table->name, str);
+		return(err);
+	}
+
+	return(0);
+}
+
+static int fm_file_access(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	entry = filemap_lookup_name(table, file_name);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	return(entry->fd);
+}
+
+static int fm_file_aquire(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+	int fd;
+
+	entry = filemap_lookup_name(table, file_name);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	fd = filemap_newfd(entry->fd);
+	if(fd < 0)
+		return(fd);
+
+	/* make sure this "new" file is rewound */
+	seek_file(fd, 0);
+
+	return(fd);
+}
+
+static int fm_file_release(void* data, int fd)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	/* the lookup_fd will always fail if the returned fd from _aquire is
+	 * a dup of the real fd.  This is OK: the caller will close the dup */
+	entry = filemap_lookup_fd(table, fd);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	return(0);
+}
+
+static int fm_file_shutdown(void* data)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		filemap_scrub(entry);
+	}
+
+	return(0);
+}
+
+static struct filemap_ops fm_ops_file = {
+	.parse        = fm_file_parse,
+	.access       = fm_file_access,
+	.aquire       = fm_file_aquire,
+	.release      = fm_file_release,
+	.shutdown     = fm_file_shutdown,
+};
+
+
+/***********************
+ *** Filemap Tables  ***
+ ***********************/
+
+static struct filemap_table filemap_tables[] = {
+	{
+		.name    = "file",
+		.entries = NULL,
+		.ops     = &fm_ops_file,
+	},
+	{
+		.name    = "vm",
+		.entries = NULL,
+		.ops     = &fm_ops_pool,
+	},
+};
+
+static struct filemap_table* filemap_get_table(const char* table_name)
+{
+	struct filemap_table* table;
+	int i;
+
+	i = 0;
+
+	while(i < sizeof(filemap_tables)/sizeof(filemap_tables[0])) {
+		table = &filemap_tables[i];
+
+		if(strcmp(table_name, table->name) == 0)
+			return(table);
+
+		i++;
+	}
+
+	return(NULL);
+}
+
+
+/**********************************
+ *** Filemap Interface Routines ***
+ **********************************/
+
+/*
+ * Return THE file descriptor for the given filename from the db table.
+ * This is a raw interface for functions, like stat() wrappers that promise
+ * not to do IO, close the fd, or otherwise fiddle with the file state.
+ */
+int filemap_access(const char* table_name, char* file_name)
+{
+	struct filemap_table* table;
+	int fd;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	fd = table->ops->access(table, file_name);
+
+	return(fd);
+}
+
+/*
+ * Return A NEW file descriptor for the given filename from the db.
+ * Assume the modes of the file descriptor was set up to match what is
+ * being asked for.
+ */
+int filemap_aquire(const char* table_name, char* file_name)
+{
+	struct filemap_table* table;
+	int fd;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	fd = table->ops->aquire(table, file_name);
+
+	return(fd);
+}
+
+/*
+ * "Release" the file descriptor.  Do nothing - if not in the db,
+ * return -ENOENT.  The caller would want to use the close() system
+ * call on the fd in that event.
+ */
+int filemap_release(const char* table_name, const int fd)
+{
+	struct filemap_table* table;
+	int err;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(-ENOENT); /* the caller expects ENOENT */ 
+	}
+
+	err = table->ops->release(table, fd);
+
+	return(err);
+}
+
+/*
+ * Do any table cleanup necessary before power cycle
+ */
+static void filemap_shutdown(void)
+{
+	struct filemap_table* table;
+	int i;
+
+	i = 0;
+
+	while(i < sizeof(filemap_tables)/sizeof(filemap_tables[0]))
+	{
+		table = &filemap_tables[i];
+
+		table->ops->shutdown(table);
+
+		i++;
+	}
+}
+
+__uml_exitcall(filemap_shutdown);
+
+static int __init parse_filemap(char* str, int* add)
+{
+	struct filemap_table* table;
+	char* table_name;
+	int err;
+
+	*add = 0;
+
+	table_name = str;
+	while(*str && *str != ',') str++;
+	if(*str == ',') *str++ = '\0';
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	err = table->ops->parse(table, str);
+	if(err < 0) {
+		printk("ERROR: filemap parse error %d on '%s':'%s'\n",
+		    err, table_name, str);
+		return(0);
+	}
+
+	return(0);
+}
+
+__uml_setup("filemap=", parse_filemap,
+"filemap=<table>,<fd>[-<fd>][,<filename>]\n"
+"    Map <filename> to <fd> (already opened) into db table named <table>.\n"
+"    Common tables: file=normal files, vm=virtual memory. Examples for bash:\n"
+"    ./linux ubd0=fs.cow,fs.dat filemap=file,10,fs.dat 10</cdrom2/fs.dat\n"
+"    ./linux filemap=file,11,/proc/cpuinfo 11</proc/cpuinfo\n"
+"    ./linux filemap=vm,20-21 20<>/dev/shm/vm-$$.1 21<>/dev/shm/vm-$$.2\n"
+);
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/mem_user.c linux-2.4.22-5um.new/arch/um/kernel/mem_user.c
--- linux-2.4.22-5um.orig/arch/um/kernel/mem_user.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/mem_user.c	Thu Sep 25 20:29:17 2003
@@ -47,6 +47,8 @@
 #include "tempfile.h"
 #include "kern_constants.h"
 
+#include "filemap.h"
+
 extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -56,6 +58,12 @@
 	int fd, err;
 	char zero;
 
+	fd = filemap_aquire("vm",NULL);
+	if(fd >= 0) {
+		ftruncate(fd, len); /* use 0 instead of len to zero contents */
+		goto sizefile;
+	}
+
 	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
 	if(fd < 0) {
 		os_print_error(fd, "make_tempfile");
@@ -66,6 +74,8 @@
 		os_print_error(err, "change_mode");
 		exit(1);
 	}
+
+sizefile:
 	err = os_seek_file(fd, len);
 	if(err < 0){
 		os_print_error(err, "seek_file");
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/umid.c linux-2.4.22-5um.new/arch/um/kernel/umid.c
--- linux-2.4.22-5um.orig/arch/um/kernel/umid.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/umid.c	Thu Sep 25 20:29:17 2003
@@ -19,6 +19,8 @@
 #include "user_util.h"
 #include "choose-mode.h"
 
+#include "filemap.h"
+
 #define UMID_LEN 64
 #define UML_DIR "~/.uml/"
 
@@ -68,8 +70,24 @@
 {
 	int n;
 
-	if(!umid_inited && make_umid(printk)) return(-1);
+	if(umid_inited) {
+		char path[MAXPATHLEN + 1];   /* XXX use buf instead? */
+
+		n = snprintf(path, sizeof(path), "%s%s/%s",
+			     uml_dir, umid, name);
+		if((n < 0) || (n >= sizeof(path)))
+			return(-1);
+
+		/* just test for existence in the filemap file table */
+		if(filemap_access("file", path) >= 0) {
+			goto handle_name;
+		}
+	} 
+
+	if(make_umid(printk))
+		return(-1);
 
+handle_name:
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
 		printk("umid_file_name : buffer too short\n");
diff -Naur linux-2.4.22-5um.orig/arch/um/os-Linux/file.c linux-2.4.22-5um.new/arch/um/os-Linux/file.c
--- linux-2.4.22-5um.orig/arch/um/os-Linux/file.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/os-Linux/file.c	Thu Sep 25 20:29:17 2003
@@ -19,6 +19,8 @@
 #include "user.h"
 #include "kern_util.h"
 
+#include "filemap.h"
+
 static void copy_stat(struct uml_stat *dst, struct stat64 *src)
 {
 	*dst = ((struct uml_stat) {
@@ -57,12 +59,22 @@
 int os_stat_file(const char *file_name, struct uml_stat *ubuf)
 {
 	struct stat64 sbuf;
-	int err;
+	int fd, err;
+
+	fd = filemap_access("file", file_name);
+	if(fd >= 0) {
+		do {
+			err = fstat64(fd, &sbuf);
+		} while((err < 0) && (errno == EINTR)) ;
+
+		goto did_stat;
+	}
 
 	do {
 		err = stat64(file_name, &sbuf);
 	} while((err < 0) && (errno == EINTR)) ;
 
+did_stat:
 	if(err < 0) 
 		return(-errno);
 
@@ -74,6 +86,26 @@
 int os_access(const char* file, int mode)
 {
 	int amode, err;
+	int fd, flags;
+
+	fd = filemap_access("file", file);
+	if(fd >= 0) {
+		do {
+			flags = fcntl(fd, F_GETFL);
+		} while((flags < 0) && (errno == EINTR)) ;
+	
+		if(flags < 0)
+			return(-errno);
+
+		if(mode & OS_ACC_X_OK)
+			return(-EACCES); /* XXX not executable not true? */
+		if((mode & OS_ACC_W_OK) && !(flags&O_RDWR || flags&O_WRONLY))
+			return(-EACCES);
+		if((mode & OS_ACC_R_OK) && (flags&O_WRONLY))
+			return(-EACCES);
+
+		return(0);
+	}
 
 	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
 	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
@@ -257,6 +289,12 @@
 {
 	int fd, f = 0;
 
+	fd = filemap_aquire("file", file);
+	if(fd >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n", fd, file);
+		goto setfd;
+	}
+
 	if(flags.r && flags.w) f = O_RDWR;
 	else if(flags.r) f = O_RDONLY;
 	else if(flags.w) f = O_WRONLY;
@@ -271,6 +309,7 @@
 	if(fd < 0)
 		return(-errno);
 
+setfd:
 	if(flags.cl && fcntl(fd, F_SETFD, 1)){
 		os_close_file(fd);
 		return(-errno);
@@ -300,6 +339,13 @@
 
 void os_close_file(int fd)
 {
+#if 0
+	/* filemapped files will return something other than -ENOENT */
+	if(filemap_release("file", fd) != -ENOENT) {
+		return;
+	}
+#endif
+
 	close(fd);
 }
 
@@ -574,6 +620,12 @@
 	struct sockaddr_un addr;
 	int sock, err;
 
+	sock = filemap_aquire("file", file);
+	if(sock >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n", sock, file);
+		goto setfd;
+	}
+
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0){
 		printk("create_unix_socket - socket failed, errno = %d\n",
@@ -581,13 +633,6 @@
 		return(-errno);
 	}
 
-	if(close_on_exec) {
-		err = os_set_exec_close(sock, 1);
-		if(err < 0)
-			printk("create_unix_socket : close_on_exec failed, "
-		       "err = %d", -err);
-	}
-
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -598,6 +643,14 @@
 		printk("create_listening_socket - bind failed, errno = %d\n",
 		       errno);
 		return(-errno);
+	}
+
+setfd:
+	if(close_on_exec) {
+		err = os_set_exec_close(sock, 1);
+		if(err < 0)
+			printk("create_unix_socket : close_on_exec failed, "
+		       "err = %d", -err);
 	}
 
 	return(sock);
diff -Naur linux-2.4.22-5um.orig/arch/um/drivers/daemon_user.c linux-2.4.22-5um.new/arch/um/drivers/daemon_user.c
--- linux-2.4.22-5um.orig/arch/um/drivers/daemon_user.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/drivers/daemon_user.c	Thu Sep 25 20:29:17 2003
@@ -18,6 +18,8 @@
 #include "user.h"
 #include "os.h"
 
+#include "filemap.h"
+
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
 enum request_type { REQ_NEW_CONTROL };
@@ -53,6 +55,13 @@
 	struct request_v3 req;
 	int fd, n, err;
 
+	pri->control = filemap_aquire("file", ctl_addr->sun_path);
+	if(pri->control >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n",
+		       pri->control, ctl_addr->sun_path);
+		goto have_control;
+	}
+
 	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
 	if(pri->control < 0){
 		printk("daemon_open : control socket failed, errno = %d\n", 
@@ -68,6 +77,7 @@
 		goto out;
 	}
 
+have_control:
 	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
 	if(fd < 0){
 		printk("daemon_open : data socket failed, errno = %d\n", 
