Messages in this thread Patch in this message | | | Date | Fri, 20 Aug 1999 16:37:23 -0400 | From | Jason Rappleye <> | Subject | [PATCH] solaris/sparc emul improvements against 2.2.11 |
| |
Hi,
Enclosed is a patch against kernel 2.2.11 that offers some improvements to the solaris emulation. This patch was tested on a Sun Ultra 5 workstation.
-implemented F_FREESP (truncate) fcntl op -socketpair seems to take just one arg on solairs, emul code was taking three -converted solaris socket options to linux equivalents (for setsockopt and getsockopt). SO_STATE isn't emulated correctly, but for the app I was working with it worked fine. If SO_STATE were documented.... -added MTIO (magnetic tape) ioctls -added openprom ioctls (solaris eeprom works as expected)
The way I fixed socketpair is certainly not the right way to do it, but I haven't figured out how change the number of arguments a syscall takes...if someone would point me in the right direction I'd be happy to fix it...I'm just not sure where to start.
Jason
--- v2.2.11/arch/sparc64/solaris/fs.c Wed Jun 2 12:55:38 1999 +++ linux/arch/sparc64/solaris/fs.c Thu Aug 19 16:50:29 1999 @@ -2,6 +2,9 @@ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * 1999-08-19 Implemented solaris F_FREESP (truncate) + * fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu) */ #include <linux/types.h> @@ -19,6 +22,8 @@ #include <asm/string.h> #include <asm/ptrace.h> +#include <sys/syscall.h> + #include "conv.h" extern char * getname32(u32 filename); @@ -635,7 +640,7 @@ case SOL_F_GETLK: case SOL_F_SETLK: case SOL_F_SETLKW: - { + { struct flock f; mm_segment_t old_fs = get_fs(); @@ -660,6 +665,15 @@ __put_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_pid, -EFAULT); __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT); return ret; + } + case SOL_F_FREESP: + { + int length; + int (*sys_newftruncate)(unsigned int, unsigned long)= + (int (*)(unsigned int, unsigned long))SYS(ftruncate); + + get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, -EFAULT); + return sys_newftruncate(fd, length); } } return -EINVAL; --- v2.2.11/arch/sparc64/solaris/ioctl.c Tue Apr 14 20:44:21 1998 +++ linux/arch/sparc64/solaris/ioctl.c Thu Aug 19 16:50:46 1999 @@ -7,6 +7,9 @@ * Streams & timod emulation based on code * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) * + * 1999-08-19 Implemented solaris 'm' (mag tape) and + * 'O' (openprom) ioctls, by Jason Rappleye + * (rappleye@ccr.buffalo.edu) */ #include <linux/types.h> @@ -18,9 +21,12 @@ #include <linux/fs.h> #include <linux/file.h> #include <linux/netdevice.h> +#include <linux/mtio.h> +#include <linux/time.h> #include <asm/uaccess.h> #include <asm/termios.h> +#include <asm/openpromio.h> #include "conv.h" #include "socksys.h" @@ -675,7 +681,7 @@ case 87: /* SIOCGIFNUM */ { struct device *d; - int i = 0; + int i = 0; for (d = dev_base; d; d = d->next) i++; if (put_user (i, (int *)A(arg))) @@ -688,6 +694,72 @@ /* }}} */ +static inline int solaris_m(unsigned int fd, unsigned int cmd, u32 arg) +{ + + struct file * flip; + flip=fget(fd); + + switch (cmd & 0xff) { + case 1: /* MTIOCTOP */ + return sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg); + case 2: /* MTIOCGET */ + return sys_ioctl(fd, MTIOCGET, (unsigned long)&arg); + case 3: /* MTIOCGETDRIVETYPE */ + case 4: /* MTIOCPERSISTENT */ + case 5: /* MTIOCPERSISTENTSTATUS */ + case 6: /* MTIOCLRERR */ + case 7: /* MTIOCGUARANTEEDORDER */ + case 8: /* MTIOCRESERVE */ + case 9: /* MTIOCRELEASE */ + case 10: /* MTIOCFORCERESERVE */ + case 13: /* MTIOCSTATE */ + case 14: /* MTIOCREADIGNOREILI */ + case 15: /* MTIOCREADIGNOREEOFS */ + case 16: /* MTIOCSHORTFMK */ + return -ENOSYS; /* linux doesn't support these */ + } + + return -ENOSYS; +} + +static inline int solaris_O(unsigned int fd, unsigned int cmd, u32 arg) +{ + switch (cmd & 0xff) { + case 1: /* OPROMGETOPT */ + return sys_ioctl(fd, OPROMGETOPT, arg); + case 2: /* OPROMSETOPT */ + return sys_ioctl(fd, OPROMSETOPT, arg); + case 3: /* OPROMNXTOPT */ + return sys_ioctl(fd, OPROMNXTOPT, arg); + case 4: /* OPROMSETOPT2 */ + return sys_ioctl(fd, OPROMSETOPT2, arg); + case 5: /* OPROMNEXT */ + return sys_ioctl(fd, OPROMNEXT, arg); + case 6: /* OPROMCHILD */ + return sys_ioctl(fd, OPROMCHILD, arg); + case 7: /* OPROMGETPROP */ + return sys_ioctl(fd, OPROMGETPROP, arg); + case 8: /* OPROMNXTPROP */ + return sys_ioctl(fd, OPROMNXTPROP, arg); + case 9: /* OPROMU2P */ + return sys_ioctl(fd, OPROMU2P, arg); + case 10: /* OPROMGETCONS */ + return sys_ioctl(fd, OPROMGETCONS, arg); + case 11: /* OPROMGETFBNAME */ + return sys_ioctl(fd, OPROMGETFBNAME, arg); + case 12: /* OPROMGETBOOTARGS */ + return sys_ioctl(fd, OPROMGETBOOTARGS, arg); + case 13: /* OPROMGETVERSION */ + case 14: /* OPROMPATH2DRV */ + case 15: /* OPROMDEV2PROMNAME */ + case 16: /* OPROMPROM2DEVNAME */ + case 17: /* OPROMGETPROPLEN */ + return -EINVAL; + } + return -EINVAL; +} + asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg) { struct file *filp; @@ -695,6 +767,7 @@ lock_kernel(); filp = fcheck(fd); + if (!filp) goto out; @@ -707,19 +780,24 @@ case 's': error = solaris_s(fd, cmd, arg); break; case 't': error = solaris_t(fd, cmd, arg); break; case 'f': error = sys_ioctl(fd, cmd, arg); break; + case 'm': error = solaris_m(fd, cmd, arg); break; + case 'O': error = solaris_O(fd, cmd, arg); break; default: error = -ENOSYS; break; } + out: if (error == -ENOSYS) { unsigned char c = cmd>>8; - + if (c < ' ' || c > 126) c = '.'; printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n", (int)fd, (unsigned int)cmd, c, (unsigned int)arg); error = -EINVAL; } + unlock_kernel(); return error; } + --- v2.2.11/arch/sparc64/solaris/socket.c Mon Nov 16 13:37:28 1998 +++ linux/arch/sparc64/solaris/socket.c Thu Aug 19 16:50:58 1999 @@ -2,6 +2,9 @@ * socket.c: Socket syscall emulation for Solaris 2.6+ * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) + * + * 1999-08-19 Fixed socketpair code + * Jason Rappleye (rappleye@ccr.buffalo.edu) */ #include <linux/types.h> @@ -25,6 +28,18 @@ #define SOCK_SOL_RDM 5 #define SOCK_SOL_SEQPACKET 6 +#define SOL_SO_SNDLOWAT 0x1003 +#define SOL_SO_RCVLOWAT 0x1004 +#define SOL_SO_SNDTIMEO 0x1005 +#define SOL_SO_RCVTIMEO 0x1006 +#define SOL_SO_STATE 0x2000 + +#define SOL_SS_NDELAY 0x040 +#define SOL_SS_NONBLOCK 0x080 +#define SOL_SS_ASYNC 0x100 + +#define SO_STATE 0x000e + static int socket_check(int family, int type) { if (family != PF_UNIX && family != PF_INET) @@ -40,6 +55,19 @@ return type; } +static int solaris_to_linux_sockopt(int optname) +{ + switch (optname) { + case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break; + case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break; + case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; + case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break; + case SOL_SO_STATE: optname = SO_STATE; break; + } + + return optname; +} + asmlinkage int solaris_socket(int family, int type, int protocol) { int (*sys_socket)(int, int, int) = @@ -55,9 +83,12 @@ int (*sys_socketpair)(int, int, int, int *) = (int (*)(int, int, int, int *))SYS(socketpair); - type = socket_check (family, type); - if (type < 0) return type; - return sys_socketpair(family, type, protocol, usockvec); + /* solaris socketpair really only takes one arg at the syscall + level, int * usockvec. The libs apparently take care of + making sure that family==AF_UNIX and type==SOCK_STREAM. The + pointer we really want ends up residing in family */ + + return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)family); } asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen) @@ -68,10 +99,19 @@ return sys_bind(fd, addr, addrlen); } + asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen) { int (*sunos_setsockopt)(int, int, int, u32, int) = (int (*)(int, int, int, u32, int))SUNOS(105); + int val; + + optname = solaris_to_linux_sockopt(optname); + get_user_ret(val, (int *)A(optval), -EFAULT); + printk("solaris_setsockopt: optname (%#x) optval (%#x)\n", optname, val); + + if (optname < 0) return optname; + if (optname == SO_STATE) return 0; return sunos_setsockopt(fd, level, optname, optval, optlen); } @@ -80,6 +120,11 @@ { int (*sunos_getsockopt)(int, int, int, u32, u32) = (int (*)(int, int, int, u32, u32))SUNOS(118); + + optname = solaris_to_linux_sockopt(optname); + if (optname < 0) return optname; + + if (optname == SO_STATE) optname = SOL_SO_STATE; return sunos_getsockopt(fd, level, optname, optval, optlen); } --- v2.2.11/drivers/sbus/char/openprom.c Mon Aug 24 16:14:09 1998 +++ linux/drivers/sbus/char/openprom.c Thu Aug 19 15:55:12 1999 @@ -70,10 +70,22 @@ return -EFAULT; get_user_ret(bufsize, &info->oprom_size, -EFAULT); - - if (bufsize == 0 || bufsize > OPROMMAXPARAM) +#if 0 + if (bufsize == 0 || bufsize > OPROMMAXPARAM) + return -EINVAL; +#endif + if (bufsize == 0) return -EINVAL; + /* max buf size is higher on solaris...maybe the right way to + do this is to change the value of OPROMMAXPARAM in the + header file ? */ + + if (bufsize > OPROMMAXPARAM) { + /* printk(KERN_DEBUG "openprom.c: bufsize hack\n"); */ + bufsize = OPROMMAXPARAM; + } + if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) return -ENOMEM; memset(*opp_p, 0, sizeof(int) + bufsize + 1); @@ -144,7 +156,7 @@ else bufsize = copyin((void *)arg, &opp); - if (bufsize < 0) + if (bufsize < 0) return bufsize; switch (cmd) {
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |