diff options
author | jdike <jdike> | 2003-12-16 16:22:26 +0000 |
---|---|---|
committer | jdike <jdike> | 2003-12-16 16:22:26 +0000 |
commit | c9d8c123fdca02c3d20587050e27fc3fd70741bd (patch) | |
tree | 05b1393b5cf352dd046247bea10c99b6d8555549 | |
parent | 347ab1686e44a845d7472d3c53494b5f3d1a4a60 (diff) | |
download | uml-history-c9d8c123fdca02c3d20587050e27fc3fd70741bd.tar.gz |
os_{read,write}_file now make sure their buffers are present before calling
{read,write} on the host.
-rw-r--r-- | arch/um/os-Linux/file.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index eabdf9a..1b9924e 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -312,20 +312,37 @@ int os_seek_file(int fd, __u64 offset) return(0); } -int os_read_file(int fd, void *buf, int len) +static int fault_buffer(void *start, int len, + int (*copy_proc)(void *addr, void *buf, int len)) { - int n; + int page = getpagesize(), i; + char c; - /* Force buf into memory if it's not already. */ + for(i = 0; i < len; i += page){ + if((*copy_proc)(start + i, &c, sizeof(c))) + return(-EFAULT); + } + if((len % page) != 0){ + if((*copy_proc)(start + len - 1, &c, sizeof(c))) + return(-EFAULT); + } + return(0); +} - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, &c, sizeof(c))) - return(-EFAULT); -#endif +static int file_io(int fd, void *buf, int len, + int (*io_proc)(int fd, void *buf, int len), + int (*copy_user_proc)(void *addr, void *buf, int len)) +{ + int n, err; do { - n = read(fd, buf, len); + n = (*io_proc)(fd, buf, len); + if((n < 0) && (errno == EFAULT)){ + err = fault_buffer(buf, len, copy_user_proc); + if(err) + return(err); + n = (*io_proc)(fd, buf, len); + } } while((n < 0) && (errno == EINTR)); if(n < 0) @@ -333,25 +350,16 @@ int os_read_file(int fd, void *buf, int len) return(n); } -int os_write_file(int fd, const void *buf, int count) +int os_read_file(int fd, void *buf, int len) { - int n; - - /* Force buf into memory if it's not already. */ - - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, buf, buf[0])) - return(-EFAULT); -#endif - - do { - n = write(fd, buf, count); - } while((n < 0) && (errno == EINTR)); + return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, + copy_from_user_proc)); +} - if(n < 0) - return(-errno); - return(n); +int os_write_file(int fd, const void *buf, int len) +{ + return(file_io(fd, (void *) buf, len, + (int (*)(int, void *, int)) write, copy_to_user_proc)); } int os_file_size(char *file, long long *size_out) @@ -610,8 +618,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0){ - printk("create_listening_socket - bind failed, errno = %d\n", - errno); + printk("create_listening_socket at '%s' - bind failed, " + "errno = %d\n", file, errno); return(-errno); } |