David, easier done than said: this is the first quick hack to get OSF/1
"xeyes" working. I haven't tried anything else yet, but at least xeyes
seems happy. Readv/writev was the only thing it wanted.
Note that a _real_ readv/writev has some atomicity guarantees that this
doesn't have, so this will fail at least for packetized stuff (UDP), but
it seems to be ok for TCP (in fact, xeyes stared working at the first
try ;-)
Also, please note that the only testing this has gotten is that single
Xeyes up in the left corner of my screen right now, and I wouldn't
exactly trust that as the definitive last word on the issue. Larger X
packages might need more (or might be less happy with this emulation).
Linus
----------
diff -u --recursive uni-version/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- uni-version/linux/arch/alpha/kernel/entry.S Sat Sep 23 17:01:28 1995
+++ linux/arch/alpha/kernel/entry.S Fri Sep 29 12:20:33 1995
@@ -590,7 +590,7 @@
.quad sys_setsockopt, sys_listen, do_entSys, do_entSys, do_entSys
.quad do_entSys, sys_sigsuspend, do_entSys, do_entSys, do_entSys
.quad do_entSys, sys_gettimeofday, sys_getrusage, sys_getsockopt, do_entSys
- .quad do_entSys, do_entSys, sys_settimeofday, sys_fchown, sys_fchmod
+ .quad osf_readv, osf_writev, sys_settimeofday, sys_fchown, sys_fchmod
.quad sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
.quad sys_ftruncate, do_entSys, sys_setgid, sys_sendto, sys_shutdown
.quad sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, do_entSys
diff -u --recursive uni-version/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- uni-version/linux/arch/alpha/kernel/osf_sys.c Sat Sep 23 17:05:39 1995
+++ linux/arch/alpha/kernel/osf_sys.c Fri Sep 29 12:30:51 1995
@@ -27,6 +27,7 @@
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/shm.h>
+#include <linux/uio.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -43,6 +44,95 @@
extern asmlinkage int sys_umount(char *);
extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
+
+/*
+ * OSF/1 readv/writev emulation.
+ *
+ * NOTE! This is not really the way it should be done,
+ * but it should be good enough for TCP connections,
+ * notably X11 ;-)
+ */
+int osf_readv(unsigned long fd, const struct iovec * vector, long count)
+{
+ int retval;
+ struct file * file;
+ struct inode * inode;
+
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
+ return -EBADF;
+ if (!(file->f_mode & 1))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->read)
+ return -EINVAL;
+ if (!count)
+ return 0;
+ retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
+ if (retval)
+ return retval;
+
+ while (count > 0) {
+ void * base;
+ int len, nr;
+
+ base = get_user(&vector->iov_base);
+ len = get_user(&vector->iov_len);
+ vector++;
+ count--;
+ nr = verify_area(VERIFY_WRITE, base, len);
+ if (!nr)
+ nr = file->f_op->read(inode, file, base, len);
+ if (nr < 0) {
+ if (retval)
+ return retval;
+ return nr;
+ }
+ retval += nr;
+ if (nr != len)
+ break;
+ }
+ return retval;
+}
+
+int osf_writev(unsigned long fd, const struct iovec * vector, long count)
+{
+ int retval;
+ struct file * file;
+ struct inode * inode;
+
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
+ return -EBADF;
+ if (!(file->f_mode & 2))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->write)
+ return -EINVAL;
+ if (!count)
+ return 0;
+ retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
+ if (retval)
+ return retval;
+
+ while (count > 0) {
+ void * base;
+ int len, nr;
+
+ base = get_user(&vector->iov_base);
+ len = get_user(&vector->iov_len);
+ vector++;
+ count--;
+ nr = verify_area(VERIFY_READ, base, len);
+ if (!nr)
+ nr = file->f_op->write(inode, file, base, len);
+ if (nr < 0) {
+ if (retval)
+ return retval;
+ return nr;
+ }
+ retval += nr;
+ if (nr != len)
+ break;
+ }
+ return retval;
+}
/*
* OSF/1 directory handling functions...
----------