1 /* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $
2 * sys_sunos.c: SunOS specific syscall compatibility support.
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 * Based upon preliminary work which is:
9 * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/types.h>
16 #include <linux/mman.h>
18 #include <linux/swap.h>
20 #include <linux/file.h>
21 #include <linux/resource.h>
22 #include <linux/ipc.h>
23 #include <linux/shm.h>
24 #include <linux/msg.h>
25 #include <linux/sem.h>
26 #include <linux/signal.h>
27 #include <linux/uio.h>
28 #include <linux/utsname.h>
29 #include <linux/major.h>
30 #include <linux/stat.h>
31 #include <linux/slab.h>
32 #include <linux/pagemap.h>
33 #include <linux/capability.h>
34 #include <linux/errno.h>
35 #include <linux/smp.h>
36 #include <linux/smp_lock.h>
37 #include <linux/syscalls.h>
41 #include <asm/uaccess.h>
43 #include <linux/segment.h>
47 #include <asm/pgtable.h>
48 #include <asm/pconf.h>
49 #include <asm/idprom.h> /* for gethostid() */
50 #include <asm/unistd.h>
51 #include <asm/system.h>
53 /* For the nfs mount emulation */
54 #include <linux/socket.h>
56 #include <linux/nfs.h>
57 #include <linux/nfs2.h>
58 #include <linux/nfs_mount.h>
60 /* for sunos_select */
61 #include <linux/time.h>
62 #include <linux/personality.h>
64 /* NR_OPEN is now larger and dynamic in recent kernels. */
65 #define SUNOS_NR_OPEN 256
67 /* We use the SunOS mmap() semantics. */
68 asmlinkage
unsigned long sunos_mmap(unsigned long addr
, unsigned long len
,
69 unsigned long prot
, unsigned long flags
,
70 unsigned long fd
, unsigned long off
)
72 struct file
* file
= NULL
;
73 unsigned long retval
, ret_type
;
75 if (flags
& MAP_NORESERVE
) {
78 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
80 flags
&= ~MAP_NORESERVE
;
83 if (!(flags
& MAP_ANONYMOUS
)) {
84 if (fd
>= SUNOS_NR_OPEN
)
92 /* If this is ld.so or a shared library doing an mmap
93 * of /dev/zero, transform it into an anonymous mapping.
94 * SunOS is so stupid some times... hmph!
97 if (imajor(file
->f_dentry
->d_inode
) == MEM_MAJOR
&&
98 iminor(file
->f_dentry
->d_inode
) == 5) {
99 flags
|= MAP_ANONYMOUS
;
104 ret_type
= flags
& _MAP_NEW
;
107 if (!(flags
& MAP_FIXED
))
110 if (ARCH_SUN4C_SUN4
&&
112 ((flags
& MAP_FIXED
) &&
113 addr
< 0xe0000000 && addr
+ len
> 0x20000000)))
116 /* See asm-sparc/uaccess.h */
117 if (len
> TASK_SIZE
- PAGE_SIZE
||
118 addr
+ len
> TASK_SIZE
- PAGE_SIZE
)
122 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
123 down_write(¤t
->mm
->mmap_sem
);
124 retval
= do_mmap(file
, addr
, len
, prot
, flags
, off
);
125 up_write(¤t
->mm
->mmap_sem
);
127 retval
= ((retval
< PAGE_OFFSET
) ? 0 : retval
);
136 /* lmbench calls this, just say "yeah, ok" */
137 asmlinkage
int sunos_mctl(unsigned long addr
, unsigned long len
, int function
, char *arg
)
142 /* SunOS is completely broken... it returns 0 on success, otherwise
143 * ENOMEM. For sys_sbrk() it wants the old brk value as a return
144 * on success and ENOMEM as before on failure.
146 asmlinkage
int sunos_brk(unsigned long brk
)
148 int freepages
, retval
= -ENOMEM
;
150 unsigned long newbrk
, oldbrk
;
152 down_write(¤t
->mm
->mmap_sem
);
153 if (ARCH_SUN4C_SUN4
) {
154 if (brk
>= 0x20000000 && brk
< 0xe0000000) {
159 if (brk
< current
->mm
->end_code
)
162 newbrk
= PAGE_ALIGN(brk
);
163 oldbrk
= PAGE_ALIGN(current
->mm
->brk
);
165 if (oldbrk
== newbrk
) {
166 current
->mm
->brk
= brk
;
171 * Always allow shrinking brk
173 if (brk
<= current
->mm
->brk
) {
174 current
->mm
->brk
= brk
;
175 do_munmap(current
->mm
, newbrk
, oldbrk
-newbrk
);
179 * Check against rlimit and stack..
182 rlim
= current
->signal
->rlim
[RLIMIT_DATA
].rlim_cur
;
183 if (rlim
>= RLIM_INFINITY
)
185 if (brk
- current
->mm
->end_code
> rlim
)
189 * Check against existing mmap mappings.
191 if (find_vma_intersection(current
->mm
, oldbrk
, newbrk
+PAGE_SIZE
))
195 * stupid algorithm to decide if we have enough memory: while
196 * simple, it hopefully works in most obvious cases.. Easy to
197 * fool it, but this should catch most mistakes.
199 freepages
= global_page_state(NR_FILE_PAGES
);
201 freepages
+= nr_free_pages();
202 freepages
+= nr_swap_pages
;
203 freepages
-= num_physpages
>> 4;
204 freepages
-= (newbrk
-oldbrk
) >> PAGE_SHIFT
;
208 * Ok, we have probably got enough memory - let it rip.
210 current
->mm
->brk
= brk
;
211 do_brk(oldbrk
, newbrk
-oldbrk
);
214 up_write(¤t
->mm
->mmap_sem
);
218 asmlinkage
unsigned long sunos_sbrk(int increment
)
221 unsigned long oldbrk
;
223 /* This should do it hopefully... */
225 oldbrk
= current
->mm
->brk
;
226 error
= sunos_brk(((int) current
->mm
->brk
) + increment
);
233 /* XXX Completely undocumented, and completely magic...
234 * XXX I believe it is to increase the size of the stack by
235 * XXX argument 'increment' and return the new end of stack
238 asmlinkage
unsigned long sunos_sstk(int increment
)
241 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
242 current
->comm
, increment
);
247 /* Give hints to the kernel as to what paging strategy to use...
248 * Completely bogus, don't remind me.
250 #define VA_NORMAL 0 /* Normal vm usage expected */
251 #define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
252 #define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
253 #define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
254 static char *vstrings
[] = {
261 asmlinkage
void sunos_vadvise(unsigned long strategy
)
263 /* I wanna see who uses this... */
265 printk("%s: Advises us to use %s paging strategy\n",
267 strategy
<= 3 ? vstrings
[strategy
] : "BOGUS");
271 /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
272 * resource limit and is for backwards compatibility with older sunos
275 asmlinkage
long sunos_getdtablesize(void)
277 return SUNOS_NR_OPEN
;
280 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
282 asmlinkage
unsigned long sunos_sigblock(unsigned long blk_mask
)
286 spin_lock_irq(¤t
->sighand
->siglock
);
287 old
= current
->blocked
.sig
[0];
288 current
->blocked
.sig
[0] |= (blk_mask
& _BLOCKABLE
);
290 spin_unlock_irq(¤t
->sighand
->siglock
);
294 asmlinkage
unsigned long sunos_sigsetmask(unsigned long newmask
)
296 unsigned long retval
;
298 spin_lock_irq(¤t
->sighand
->siglock
);
299 retval
= current
->blocked
.sig
[0];
300 current
->blocked
.sig
[0] = (newmask
& _BLOCKABLE
);
302 spin_unlock_irq(¤t
->sighand
->siglock
);
306 /* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
307 /* getdents system call, the format of the structure just has a different */
308 /* layout (d_off+d_ino instead of d_ino+d_off) */
309 struct sunos_dirent
{
312 unsigned short d_reclen
;
313 unsigned short d_namlen
;
317 struct sunos_dirent_callback
{
318 struct sunos_dirent __user
*curr
;
319 struct sunos_dirent __user
*previous
;
324 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
325 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
327 static int sunos_filldir(void * __buf
, const char * name
, int namlen
,
328 loff_t offset
, ino_t ino
, unsigned int d_type
)
330 struct sunos_dirent __user
*dirent
;
331 struct sunos_dirent_callback
* buf
= __buf
;
332 int reclen
= ROUND_UP(NAME_OFFSET(dirent
) + namlen
+ 1);
334 buf
->error
= -EINVAL
; /* only used if we fail.. */
335 if (reclen
> buf
->count
)
337 dirent
= buf
->previous
;
339 put_user(offset
, &dirent
->d_off
);
341 buf
->previous
= dirent
;
342 put_user(ino
, &dirent
->d_ino
);
343 put_user(namlen
, &dirent
->d_namlen
);
344 put_user(reclen
, &dirent
->d_reclen
);
345 copy_to_user(dirent
->d_name
, name
, namlen
);
346 put_user(0, dirent
->d_name
+ namlen
);
347 dirent
= (void __user
*) dirent
+ reclen
;
349 buf
->count
-= reclen
;
353 asmlinkage
int sunos_getdents(unsigned int fd
, void __user
*dirent
, int cnt
)
356 struct sunos_dirent __user
*lastdirent
;
357 struct sunos_dirent_callback buf
;
360 if (fd
>= SUNOS_NR_OPEN
)
368 if (cnt
< (sizeof(struct sunos_dirent
) + 255))
371 buf
.curr
= (struct sunos_dirent __user
*) dirent
;
376 error
= vfs_readdir(file
, sunos_filldir
, &buf
);
380 lastdirent
= buf
.previous
;
383 put_user(file
->f_pos
, &lastdirent
->d_off
);
384 error
= cnt
- buf
.count
;
393 /* Old sunos getdirentries, severely broken compatibility stuff here. */
394 struct sunos_direntry
{
396 unsigned short d_reclen
;
397 unsigned short d_namlen
;
401 struct sunos_direntry_callback
{
402 struct sunos_direntry __user
*curr
;
403 struct sunos_direntry __user
*previous
;
408 static int sunos_filldirentry(void * __buf
, const char * name
, int namlen
,
409 loff_t offset
, ino_t ino
, unsigned int d_type
)
411 struct sunos_direntry __user
*dirent
;
412 struct sunos_direntry_callback
*buf
= __buf
;
413 int reclen
= ROUND_UP(NAME_OFFSET(dirent
) + namlen
+ 1);
415 buf
->error
= -EINVAL
; /* only used if we fail.. */
416 if (reclen
> buf
->count
)
418 dirent
= buf
->previous
;
420 buf
->previous
= dirent
;
421 put_user(ino
, &dirent
->d_ino
);
422 put_user(namlen
, &dirent
->d_namlen
);
423 put_user(reclen
, &dirent
->d_reclen
);
424 copy_to_user(dirent
->d_name
, name
, namlen
);
425 put_user(0, dirent
->d_name
+ namlen
);
426 dirent
= (void __user
*) dirent
+ reclen
;
428 buf
->count
-= reclen
;
432 asmlinkage
int sunos_getdirentries(unsigned int fd
, void __user
*dirent
,
433 int cnt
, unsigned int __user
*basep
)
436 struct sunos_direntry __user
*lastdirent
;
437 struct sunos_direntry_callback buf
;
440 if (fd
>= SUNOS_NR_OPEN
)
448 if (cnt
< (sizeof(struct sunos_direntry
) + 255))
451 buf
.curr
= (struct sunos_direntry __user
*) dirent
;
456 error
= vfs_readdir(file
, sunos_filldirentry
, &buf
);
460 lastdirent
= buf
.previous
;
463 put_user(file
->f_pos
, basep
);
464 error
= cnt
- buf
.count
;
473 struct sunos_utsname
{
482 asmlinkage
int sunos_uname(struct sunos_utsname __user
*name
)
486 ret
= copy_to_user(&name
->sname
[0], &system_utsname
.sysname
[0], sizeof(name
->sname
) - 1);
488 ret
|= __copy_to_user(&name
->nname
[0], &system_utsname
.nodename
[0], sizeof(name
->nname
) - 1);
489 ret
|= __put_user('\0', &name
->nname
[8]);
490 ret
|= __copy_to_user(&name
->rel
[0], &system_utsname
.release
[0], sizeof(name
->rel
) - 1);
491 ret
|= __copy_to_user(&name
->ver
[0], &system_utsname
.version
[0], sizeof(name
->ver
) - 1);
492 ret
|= __copy_to_user(&name
->mach
[0], &system_utsname
.machine
[0], sizeof(name
->mach
) - 1);
495 return ret
? -EFAULT
: 0;
498 asmlinkage
int sunos_nosys(void)
500 struct pt_regs
*regs
;
505 regs
= current
->thread
.kregs
;
506 info
.si_signo
= SIGSYS
;
508 info
.si_code
= __SI_FAULT
|0x100;
509 info
.si_addr
= (void __user
*)regs
->pc
;
510 info
.si_trapno
= regs
->u_regs
[UREG_G1
];
511 send_sig_info(SIGSYS
, &info
, current
);
513 printk("Process makes ni_syscall number %d, register dump:\n",
514 (int) regs
->u_regs
[UREG_G1
]);
521 /* This is not a real and complete implementation yet, just to keep
522 * the easy SunOS binaries happy.
524 asmlinkage
int sunos_fpathconf(int fd
, int name
)
547 case _PCONF_CHRESTRICT
: /* XXX Investigate XXX */
550 case _PCONF_NOTRUNC
: /* XXX Investigate XXX */
551 case _PCONF_VDISABLE
:
561 asmlinkage
int sunos_pathconf(char __user
*path
, int name
)
565 ret
= sunos_fpathconf(0, name
); /* XXX cheese XXX */
569 /* SunOS mount system call emulation */
571 asmlinkage
int sunos_select(int width
, fd_set __user
*inp
, fd_set __user
*outp
,
572 fd_set __user
*exp
, struct timeval __user
*tvp
)
576 /* SunOS binaries expect that select won't change the tvp contents */
577 ret
= sys_select (width
, inp
, outp
, exp
, tvp
);
578 if (ret
== -EINTR
&& tvp
) {
581 __get_user(sec
, &tvp
->tv_sec
);
582 __get_user(usec
, &tvp
->tv_usec
);
584 if (sec
== 0 && usec
== 0)
590 asmlinkage
void sunos_nop(void)
595 /* SunOS mount/umount. */
596 #define SMNT_RDONLY 1
597 #define SMNT_NOSUID 2
598 #define SMNT_NEWTYPE 4
600 #define SMNT_REMOUNT 16
601 #define SMNT_NOSUB 32
602 #define SMNT_MULTI 64
603 #define SMNT_SYS5 128
606 char fh_data
[NFS_FHSIZE
];
609 struct sunos_nfs_mount_args
{
610 struct sockaddr_in __user
*addr
; /* file server address */
611 struct nfs_fh __user
*fh
; /* File handle to be mounted */
612 int flags
; /* flags */
613 int wsize
; /* write size in bytes */
614 int rsize
; /* read size in bytes */
615 int timeo
; /* initial timeout in .1 secs */
616 int retrans
; /* times to retry send */
617 char __user
*hostname
; /* server's hostname */
618 int acregmin
; /* attr cache file min secs */
619 int acregmax
; /* attr cache file max secs */
620 int acdirmin
; /* attr cache dir min secs */
621 int acdirmax
; /* attr cache dir max secs */
622 char __user
*netname
; /* server's netname */
626 /* Bind the socket on a local reserved port and connect it to the
627 * remote server. This on Linux/i386 is done by the mount program,
631 sunos_nfs_get_server_fd (int fd
, struct sockaddr_in
*addr
)
633 struct sockaddr_in local
;
634 struct sockaddr_in server
;
636 struct socket
*socket
;
645 inode
= file
->f_dentry
->d_inode
;
647 socket
= SOCKET_I(inode
);
648 local
.sin_family
= AF_INET
;
649 local
.sin_addr
.s_addr
= INADDR_ANY
;
651 /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
654 local
.sin_port
= htons (--try_port
);
655 ret
= socket
->ops
->bind(socket
, (struct sockaddr
*)&local
,
657 } while (ret
&& try_port
> (1024 / 2));
662 server
.sin_family
= AF_INET
;
663 server
.sin_addr
= addr
->sin_addr
;
664 server
.sin_port
= NFS_PORT
;
666 /* Call sys_connect */
667 ret
= socket
->ops
->connect (socket
, (struct sockaddr
*) &server
,
668 sizeof (server
), file
->f_flags
);
678 static int get_default (int value
, int def_value
)
686 static int sunos_nfs_mount(char *dir_name
, int linux_flags
, void __user
*data
)
689 char *the_name
, *mount_page
;
690 struct nfs_mount_data linux_nfs_mount
;
691 struct sunos_nfs_mount_args sunos_mount
;
693 /* Ok, here comes the fun part: Linux's nfs mount needs a
694 * socket connection to the server, but SunOS mount does not
695 * require this, so we use the information on the destination
696 * address to create a socket and bind it to a reserved
697 * port on this system
699 if (copy_from_user(&sunos_mount
, data
, sizeof(sunos_mount
)))
702 server_fd
= sys_socket (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
706 if (copy_from_user(&linux_nfs_mount
.addr
,sunos_mount
.addr
,
707 sizeof(*sunos_mount
.addr
)) ||
708 copy_from_user(&linux_nfs_mount
.root
,sunos_mount
.fh
,
709 sizeof(*sunos_mount
.fh
))) {
710 sys_close (server_fd
);
714 if (!sunos_nfs_get_server_fd (server_fd
, &linux_nfs_mount
.addr
)){
715 sys_close (server_fd
);
719 /* Now, bind it to a locally reserved port */
720 linux_nfs_mount
.version
= NFS_MOUNT_VERSION
;
721 linux_nfs_mount
.flags
= sunos_mount
.flags
;
722 linux_nfs_mount
.fd
= server_fd
;
724 linux_nfs_mount
.rsize
= get_default (sunos_mount
.rsize
, 8192);
725 linux_nfs_mount
.wsize
= get_default (sunos_mount
.wsize
, 8192);
726 linux_nfs_mount
.timeo
= get_default (sunos_mount
.timeo
, 10);
727 linux_nfs_mount
.retrans
= sunos_mount
.retrans
;
729 linux_nfs_mount
.acregmin
= sunos_mount
.acregmin
;
730 linux_nfs_mount
.acregmax
= sunos_mount
.acregmax
;
731 linux_nfs_mount
.acdirmin
= sunos_mount
.acdirmin
;
732 linux_nfs_mount
.acdirmax
= sunos_mount
.acdirmax
;
734 the_name
= getname(sunos_mount
.hostname
);
735 if (IS_ERR(the_name
))
736 return PTR_ERR(the_name
);
738 strlcpy(linux_nfs_mount
.hostname
, the_name
,
739 sizeof(linux_nfs_mount
.hostname
));
742 mount_page
= (char *) get_zeroed_page(GFP_KERNEL
);
746 memcpy(mount_page
, &linux_nfs_mount
, sizeof(linux_nfs_mount
));
748 err
= do_mount("", dir_name
, "nfs", linux_flags
, mount_page
);
750 free_page((unsigned long) mount_page
);
755 sunos_mount(char __user
*type
, char __user
*dir
, int flags
, void __user
*data
)
759 char *dev_fname
= NULL
;
760 char *dir_page
, *type_page
;
762 if (!capable (CAP_SYS_ADMIN
))
766 /* We don't handle the integer fs type */
767 if ((flags
& SMNT_NEWTYPE
) == 0)
770 /* Do not allow for those flags we don't support */
771 if (flags
& (SMNT_GRPID
|SMNT_NOSUB
|SMNT_MULTI
|SMNT_SYS5
))
774 if (flags
& SMNT_REMOUNT
)
775 linux_flags
|= MS_REMOUNT
;
776 if (flags
& SMNT_RDONLY
)
777 linux_flags
|= MS_RDONLY
;
778 if (flags
& SMNT_NOSUID
)
779 linux_flags
|= MS_NOSUID
;
781 dir_page
= getname(dir
);
782 ret
= PTR_ERR(dir_page
);
783 if (IS_ERR(dir_page
))
786 type_page
= getname(type
);
787 ret
= PTR_ERR(type_page
);
788 if (IS_ERR(type_page
))
791 if (strcmp(type_page
, "ext2") == 0) {
792 dev_fname
= getname(data
);
793 } else if (strcmp(type_page
, "iso9660") == 0) {
794 dev_fname
= getname(data
);
795 } else if (strcmp(type_page
, "minix") == 0) {
796 dev_fname
= getname(data
);
797 } else if (strcmp(type_page
, "nfs") == 0) {
798 ret
= sunos_nfs_mount (dir_page
, flags
, data
);
800 } else if (strcmp(type_page
, "ufs") == 0) {
801 printk("Warning: UFS filesystem mounts unsupported.\n");
804 } else if (strcmp(type_page
, "proc")) {
808 ret
= PTR_ERR(dev_fname
);
809 if (IS_ERR(dev_fname
))
811 ret
= do_mount(dev_fname
, dir_page
, type_page
, linux_flags
, NULL
);
824 asmlinkage
int sunos_setpgrp(pid_t pid
, pid_t pgid
)
829 if ((!pid
|| pid
== current
->pid
) &&
834 ret
= sys_setpgid(pid
, pgid
);
840 asmlinkage
int sunos_wait4(pid_t pid
, unsigned int __user
*stat_addr
,
841 int options
, struct rusage __user
*ru
)
845 ret
= sys_wait4((pid
? pid
: -1), stat_addr
, options
, ru
);
849 extern int kill_pg(int, int, int);
850 asmlinkage
int sunos_killpg(int pgrp
, int sig
)
855 ret
= kill_pg(pgrp
, sig
, 0);
860 asmlinkage
int sunos_audit(void)
863 printk ("sys_audit\n");
868 asmlinkage
unsigned long sunos_gethostid(void)
873 ret
= ((unsigned long)idprom
->id_machtype
<< 24) |
874 (unsigned long)idprom
->id_sernum
;
879 /* sysconf options, for SunOS compatibility */
880 #define _SC_ARG_MAX 1
881 #define _SC_CHILD_MAX 2
882 #define _SC_CLK_TCK 3
883 #define _SC_NGROUPS_MAX 4
884 #define _SC_OPEN_MAX 5
885 #define _SC_JOB_CONTROL 6
886 #define _SC_SAVED_IDS 7
887 #define _SC_VERSION 8
889 asmlinkage
long sunos_sysconf (int name
)
898 ret
= -1; /* no limit */
903 case _SC_NGROUPS_MAX
:
909 case _SC_JOB_CONTROL
:
910 ret
= 1; /* yes, we do support job control */
913 ret
= 1; /* yes, we do support saved uids */
916 /* mhm, POSIX_VERSION is in /usr/include/unistd.h
917 * should it go on /usr/include/linux?
928 asmlinkage
int sunos_semsys(int op
, unsigned long arg1
, unsigned long arg2
,
929 unsigned long arg3
, void *ptr
)
936 /* Most arguments match on a 1:1 basis but cmd doesn't */
954 /* value to modify semaphore to */
955 arg4
.__pad
= (void __user
*) ptr
;
956 ret
= sys_semctl((int)arg1
, (int)arg2
, (int)arg3
, arg4
);
960 ret
= sys_semget((key_t
)arg1
, (int)arg2
, (int)arg3
);
964 ret
= sys_semop((int)arg1
, (struct sembuf __user
*)arg2
, (unsigned)arg3
);
973 asmlinkage
int sunos_msgsys(int op
, unsigned long arg1
, unsigned long arg2
,
974 unsigned long arg3
, unsigned long arg4
)
976 struct sparc_stackf
*sp
;
982 rval
= sys_msgget((key_t
)arg1
, (int)arg2
);
985 rval
= sys_msgctl((int)arg1
, (int)arg2
,
986 (struct msqid_ds __user
*)arg3
);
990 sp
= (struct sparc_stackf
*)current
->thread
.kregs
->u_regs
[UREG_FP
];
991 arg5
= sp
->xxargs
[0];
993 rval
= sys_msgrcv((int)arg1
, (struct msgbuf __user
*)arg2
,
994 (size_t)arg3
, (long)arg4
, (int)arg5
);
997 rval
= sys_msgsnd((int)arg1
, (struct msgbuf __user
*)arg2
,
998 (size_t)arg3
, (int)arg4
);
1007 asmlinkage
int sunos_shmsys(int op
, unsigned long arg1
, unsigned long arg2
,
1010 unsigned long raddr
;
1015 /* do_shmat(): attach a shared memory area */
1016 rval
= do_shmat((int)arg1
,(char __user
*)arg2
,(int)arg3
,&raddr
);
1021 /* sys_shmctl(): modify shared memory area attr. */
1022 rval
= sys_shmctl((int)arg1
,(int)arg2
,(struct shmid_ds __user
*)arg3
);
1025 /* sys_shmdt(): detach a shared memory area */
1026 rval
= sys_shmdt((char __user
*)arg1
);
1029 /* sys_shmget(): get a shared memory area */
1030 rval
= sys_shmget((key_t
)arg1
,(int)arg2
,(int)arg3
);
1039 #define SUNOS_EWOULDBLOCK 35
1041 /* see the sunos man page read(2v) for an explanation
1042 of this garbage. We use O_NDELAY to mark
1043 file descriptors that have been set non-blocking
1044 using 4.2BSD style calls. (tridge) */
1046 static inline int check_nonblock(int ret
, int fd
)
1048 if (ret
== -EAGAIN
) {
1049 struct file
* file
= fget(fd
);
1051 if (file
->f_flags
& O_NDELAY
)
1052 ret
= -SUNOS_EWOULDBLOCK
;
1059 asmlinkage
int sunos_read(unsigned int fd
, char __user
*buf
, int count
)
1063 ret
= check_nonblock(sys_read(fd
,buf
,count
),fd
);
1067 asmlinkage
int sunos_readv(unsigned long fd
, const struct iovec __user
*vector
,
1072 ret
= check_nonblock(sys_readv(fd
,vector
,count
),fd
);
1076 asmlinkage
int sunos_write(unsigned int fd
, char __user
*buf
, int count
)
1080 ret
= check_nonblock(sys_write(fd
,buf
,count
),fd
);
1084 asmlinkage
int sunos_writev(unsigned long fd
,
1085 const struct iovec __user
*vector
, long count
)
1089 ret
= check_nonblock(sys_writev(fd
,vector
,count
),fd
);
1093 asmlinkage
int sunos_recv(int fd
, void __user
*ubuf
, int size
, unsigned flags
)
1097 ret
= check_nonblock(sys_recv(fd
,ubuf
,size
,flags
),fd
);
1101 asmlinkage
int sunos_send(int fd
, void __user
*buff
, int len
, unsigned flags
)
1105 ret
= check_nonblock(sys_send(fd
,buff
,len
,flags
),fd
);
1109 asmlinkage
int sunos_accept(int fd
, struct sockaddr __user
*sa
,
1110 int __user
*addrlen
)
1115 ret
= check_nonblock(sys_accept(fd
,sa
,addrlen
),fd
);
1116 if (ret
!= -ENETUNREACH
&& ret
!= -EHOSTUNREACH
)
1123 #define SUNOS_SV_INTERRUPT 2
1126 sunos_sigaction(int sig
, const struct old_sigaction __user
*act
,
1127 struct old_sigaction __user
*oact
)
1129 struct k_sigaction new_ka
, old_ka
;
1135 if (!access_ok(VERIFY_READ
, act
, sizeof(*act
)) ||
1136 __get_user(new_ka
.sa
.sa_handler
, &act
->sa_handler
) ||
1137 __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
))
1139 __get_user(mask
, &act
->sa_mask
);
1140 new_ka
.sa
.sa_restorer
= NULL
;
1141 new_ka
.ka_restorer
= NULL
;
1142 siginitset(&new_ka
.sa
.sa_mask
, mask
);
1143 new_ka
.sa
.sa_flags
^= SUNOS_SV_INTERRUPT
;
1146 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
1149 /* In the clone() case we could copy half consistent
1150 * state to the user, however this could sleep and
1151 * deadlock us if we held the signal lock on SMP. So for
1152 * now I take the easy way out and do no locking.
1153 * But then again we don't support SunOS lwp's anyways ;-)
1155 old_ka
.sa
.sa_flags
^= SUNOS_SV_INTERRUPT
;
1156 if (!access_ok(VERIFY_WRITE
, oact
, sizeof(*oact
)) ||
1157 __put_user(old_ka
.sa
.sa_handler
, &oact
->sa_handler
) ||
1158 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
))
1160 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
);
1167 asmlinkage
int sunos_setsockopt(int fd
, int level
, int optname
,
1168 char __user
*optval
, int optlen
)
1170 int tr_opt
= optname
;
1173 if (level
== SOL_IP
) {
1174 /* Multicast socketopts (ttl, membership) */
1175 if (tr_opt
>=2 && tr_opt
<= 6)
1178 ret
= sys_setsockopt(fd
, level
, tr_opt
, optval
, optlen
);
1182 asmlinkage
int sunos_getsockopt(int fd
, int level
, int optname
,
1183 char __user
*optval
, int __user
*optlen
)
1185 int tr_opt
= optname
;
1188 if (level
== SOL_IP
) {
1189 /* Multicast socketopts (ttl, membership) */
1190 if (tr_opt
>=2 && tr_opt
<= 6)
1193 ret
= sys_getsockopt(fd
, level
, tr_opt
, optval
, optlen
);