1 /* $Id: sys_sunos32.c,v 1.28 1999/06/29 12:34:04 davem Exp $
2 * sys_sunos32.c: SunOS binary compatability layer on sparc64.
4 * Copyright (C) 1995, 1996, 1997 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)
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/types.h>
15 #include <linux/mman.h>
17 #include <linux/swap.h>
19 #include <linux/file.h>
20 #include <linux/resource.h>
21 #include <linux/ipc.h>
22 #include <linux/shm.h>
23 #include <linux/msg.h>
24 #include <linux/sem.h>
25 #include <linux/signal.h>
26 #include <linux/uio.h>
27 #include <linux/utsname.h>
28 #include <linux/major.h>
29 #include <linux/stat.h>
30 #include <linux/malloc.h>
31 #include <linux/pagemap.h>
32 #include <linux/errno.h>
33 #include <linux/smp.h>
34 #include <linux/smp_lock.h>
36 #include <asm/uaccess.h>
38 #include <asm/pgtable.h>
39 #include <asm/pconf.h>
40 #include <asm/idprom.h> /* for gethostid() */
41 #include <asm/unistd.h>
42 #include <asm/system.h>
44 /* For the nfs mount emulation */
45 #include <linux/socket.h>
47 #include <linux/nfs.h>
48 #include <linux/nfs_mount.h>
50 /* for sunos_select */
51 #include <linux/time.h>
52 #include <linux/personality.h>
54 /* Use this to get at 32-bit user passed pointers. */
56 ({ unsigned long __ret; \
57 __asm__ ("srl %0, 0, %0" \
63 #define SUNOS_NR_OPEN 256
65 asmlinkage u32
sunos_mmap(u32 addr
, u32 len
, u32 prot
, u32 flags
, u32 fd
, u32 off
)
67 struct file
*file
= NULL
;
68 unsigned long retval
, ret_type
;
70 down(¤t
->mm
->mmap_sem
);
72 current
->personality
|= PER_BSD
;
73 if(flags
& MAP_NORESERVE
) {
74 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
76 flags
&= ~MAP_NORESERVE
;
79 if(!(flags
& MAP_ANONYMOUS
)) {
80 if(fd
>= SUNOS_NR_OPEN
)
85 if (file
->f_dentry
&& file
->f_dentry
->d_inode
) {
86 struct inode
* inode
= file
->f_dentry
->d_inode
;
87 if(MAJOR(inode
->i_rdev
) == MEM_MAJOR
&&
88 MINOR(inode
->i_rdev
) == 5) {
89 flags
|= MAP_ANONYMOUS
;
97 if(!(flags
& MAP_FIXED
) && !addr
) {
98 unsigned long attempt
= get_unmapped_area(addr
, len
);
99 if(!attempt
|| (attempt
>= 0xf0000000UL
))
101 addr
= (u32
) attempt
;
103 if(!(flags
& MAP_FIXED
))
105 ret_type
= flags
& _MAP_NEW
;
108 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
109 retval
= do_mmap(file
,
110 (unsigned long) addr
, (unsigned long) len
,
111 (unsigned long) prot
, (unsigned long) flags
,
112 (unsigned long) off
);
114 retval
= ((retval
< 0xf0000000) ? 0 : retval
);
120 up(¤t
->mm
->mmap_sem
);
124 asmlinkage
int sunos_mctl(u32 addr
, u32 len
, int function
, u32 arg
)
129 asmlinkage
int sunos_brk(u32 baddr
)
131 int freepages
, retval
= -ENOMEM
;
133 unsigned long newbrk
, oldbrk
, brk
= (unsigned long) baddr
;
135 down(¤t
->mm
->mmap_sem
);
136 if (brk
< current
->mm
->end_code
)
138 newbrk
= PAGE_ALIGN(brk
);
139 oldbrk
= PAGE_ALIGN(current
->mm
->brk
);
141 if (oldbrk
== newbrk
) {
142 current
->mm
->brk
= brk
;
145 /* Always allow shrinking brk. */
146 if (brk
<= current
->mm
->brk
) {
147 current
->mm
->brk
= brk
;
148 do_munmap(newbrk
, oldbrk
-newbrk
);
151 /* Check against rlimit and stack.. */
153 rlim
= current
->rlim
[RLIMIT_DATA
].rlim_cur
;
154 if (rlim
>= RLIM_INFINITY
)
156 if (brk
- current
->mm
->end_code
> rlim
)
158 /* Check against existing mmap mappings. */
159 if (find_vma_intersection(current
->mm
, oldbrk
, newbrk
+PAGE_SIZE
))
161 /* stupid algorithm to decide if we have enough memory: while
162 * simple, it hopefully works in most obvious cases.. Easy to
163 * fool it, but this should catch most mistakes.
165 freepages
= atomic_read(&buffermem
) >> PAGE_SHIFT
;
166 freepages
+= atomic_read(&page_cache_size
);
168 freepages
+= nr_free_pages
;
169 freepages
+= nr_swap_pages
;
170 freepages
-= num_physpages
>> 4;
171 freepages
-= (newbrk
-oldbrk
) >> PAGE_SHIFT
;
174 /* Ok, we have probably got enough memory - let it rip. */
175 current
->mm
->brk
= brk
;
176 do_brk(oldbrk
, newbrk
-oldbrk
);
179 up(¤t
->mm
->mmap_sem
);
183 asmlinkage u32
sunos_sbrk(int increment
)
187 /* This should do it hopefully... */
189 oldbrk
= (int)current
->mm
->brk
;
190 error
= sunos_brk(((int) current
->mm
->brk
) + increment
);
197 asmlinkage u32
sunos_sstk(int increment
)
200 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
201 current
->comm
, increment
);
206 /* Give hints to the kernel as to what paging strategy to use...
207 * Completely bogus, don't remind me.
209 #define VA_NORMAL 0 /* Normal vm usage expected */
210 #define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
211 #define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
212 #define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
213 static char *vstrings
[] = {
220 asmlinkage
void sunos_vadvise(u32 strategy
)
222 /* I wanna see who uses this... */
224 printk("%s: Advises us to use %s paging strategy\n",
226 strategy
<= 3 ? vstrings
[strategy
] : "BOGUS");
230 /* Same as vadvise, and just as bogus, but for a range of virtual
231 * process address space.
233 #define MADV_NORMAL 0 /* Nothing special... */
234 #define MADV_RANDOM 1 /* I am emacs... */
235 #define MADV_SEQUENTIAL 2 /* I am researcher code... */
236 #define MADV_WILLNEED 3 /* Pages in this range will be needed */
237 #define MADV_DONTNEED 4 /* Pages in this range won't be needed */
239 static char *mstrings
[] = {
247 asmlinkage
void sunos_madvise(u32 address
, u32 len
, u32 strategy
)
249 /* I wanna see who uses this... */
251 printk("%s: Advises us to use %s paging strategy for addr<%08x> len<%08x>\n",
252 current
->comm
, strategy
<= 4 ? mstrings
[strategy
] : "BOGUS",
257 /* Places into character array, the status of all the pages in the passed
258 * range from 'addr' to 'addr + len'. -1 on failure, 0 on success...
259 * The encoding in each character is:
260 * low-bit is zero == Page is not in physical ram right now
261 * low-bit is one == Page is currently residing in core
262 * All other bits are undefined within the character so there...
263 * Also, if you try to get stats on an area outside of the user vm area
264 * *or* the passed base address is not aligned on a page boundary you
267 asmlinkage
int sunos_mincore(u32 __addr
, u32 len
, u32 u_array
)
272 unsigned long limit
, addr
= (unsigned long)__addr
;
273 int num_pages
, pnum
, retval
= -EINVAL
;
274 char *array
= (char *)A(u_array
);
279 num_pages
= (len
/ 4096);
281 if(verify_area(VERIFY_WRITE
, array
, num_pages
))
284 if((addr
>= 0xf0000000) || ((addr
+ len
) > 0xf0000000))
285 goto out
; /* I'm sure you're curious about kernel mappings.. */
286 /* Wheee, go through pte's */
288 for(limit
= addr
+ len
; addr
< limit
; addr
+= 4096, pnum
++) {
289 pgdp
= pgd_offset(current
->mm
, addr
);
291 goto out
; /* As per SunOS manpage */
292 pmdp
= pmd_offset(pgdp
, addr
);
294 goto out
; /* As per SunOS manpage */
295 ptep
= pte_offset(pmdp
, addr
);
297 goto out
; /* As per SunOS manpage */
298 /* Page in core or Swapped page? */
299 __put_user((pte_present(*ptep
) ? 1 : 0), &array
[pnum
]);
301 retval
= 0; /* Success... I think... */
307 /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
308 * resource limit and is for backwards compatibility with older sunos
311 asmlinkage
int sunos_getdtablesize(void)
313 return SUNOS_NR_OPEN
;
317 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
319 asmlinkage u32
sunos_sigblock(u32 blk_mask
)
323 spin_lock_irq(¤t
->sigmask_lock
);
324 old
= (u32
) current
->blocked
.sig
[0];
325 current
->blocked
.sig
[0] |= (blk_mask
& _BLOCKABLE
);
326 spin_unlock_irq(¤t
->sigmask_lock
);
330 asmlinkage u32
sunos_sigsetmask(u32 newmask
)
334 spin_lock_irq(¤t
->sigmask_lock
);
335 retval
= (u32
) current
->blocked
.sig
[0];
336 current
->blocked
.sig
[0] = (newmask
& _BLOCKABLE
);
337 spin_unlock_irq(¤t
->sigmask_lock
);
341 /* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
342 /* getdents system call, the format of the structure just has a different */
343 /* layout (d_off+d_ino instead of d_ino+d_off) */
344 struct sunos_dirent
{
352 struct sunos_dirent_callback
{
353 struct sunos_dirent
*curr
;
354 struct sunos_dirent
*previous
;
359 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
360 #define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
362 static int sunos_filldir(void * __buf
, const char * name
, int namlen
,
363 off_t offset
, ino_t ino
)
365 struct sunos_dirent
* dirent
;
366 struct sunos_dirent_callback
* buf
= (struct sunos_dirent_callback
*) __buf
;
367 int reclen
= ROUND_UP(NAME_OFFSET(dirent
) + namlen
+ 1);
369 buf
->error
= -EINVAL
; /* only used if we fail.. */
370 if (reclen
> buf
->count
)
372 dirent
= buf
->previous
;
374 put_user(offset
, &dirent
->d_off
);
376 buf
->previous
= dirent
;
377 put_user(ino
, &dirent
->d_ino
);
378 put_user(namlen
, &dirent
->d_namlen
);
379 put_user(reclen
, &dirent
->d_reclen
);
380 copy_to_user(dirent
->d_name
, name
, namlen
);
381 put_user(0, dirent
->d_name
+ namlen
);
382 ((char *) dirent
) += reclen
;
384 buf
->count
-= reclen
;
388 asmlinkage
int sunos_getdents(unsigned int fd
, u32 u_dirent
, int cnt
)
391 struct inode
* inode
;
392 struct sunos_dirent
* lastdirent
;
393 struct sunos_dirent_callback buf
;
395 void *dirent
= (void *)A(u_dirent
);
398 if(fd
>= SUNOS_NR_OPEN
)
406 if (!file
->f_op
|| !file
->f_op
->readdir
)
410 if(cnt
< (sizeof(struct sunos_dirent
) + 255))
413 buf
.curr
= (struct sunos_dirent
*) dirent
;
418 inode
= file
->f_dentry
->d_inode
;
420 error
= file
->f_op
->readdir(file
, &buf
, sunos_filldir
);
425 lastdirent
= buf
.previous
;
428 put_user(file
->f_pos
, &lastdirent
->d_off
);
429 error
= cnt
- buf
.count
;
439 /* Old sunos getdirentries, severely broken compatibility stuff here. */
440 struct sunos_direntry
{
447 struct sunos_direntry_callback
{
448 struct sunos_direntry
*curr
;
449 struct sunos_direntry
*previous
;
454 static int sunos_filldirentry(void * __buf
, const char * name
, int namlen
,
455 off_t offset
, ino_t ino
)
457 struct sunos_direntry
* dirent
;
458 struct sunos_direntry_callback
* buf
= (struct sunos_direntry_callback
*) __buf
;
459 int reclen
= ROUND_UP(NAME_OFFSET(dirent
) + namlen
+ 1);
461 buf
->error
= -EINVAL
; /* only used if we fail.. */
462 if (reclen
> buf
->count
)
464 dirent
= buf
->previous
;
466 buf
->previous
= dirent
;
467 put_user(ino
, &dirent
->d_ino
);
468 put_user(namlen
, &dirent
->d_namlen
);
469 put_user(reclen
, &dirent
->d_reclen
);
470 copy_to_user(dirent
->d_name
, name
, namlen
);
471 put_user(0, dirent
->d_name
+ namlen
);
472 ((char *) dirent
) += reclen
;
474 buf
->count
-= reclen
;
478 asmlinkage
int sunos_getdirentries(unsigned int fd
, u32 u_dirent
,
479 int cnt
, u32 u_basep
)
481 void *dirent
= (void *) A(u_dirent
);
482 unsigned int *basep
= (unsigned int *)A(u_basep
);
484 struct inode
* inode
;
485 struct sunos_direntry
* lastdirent
;
487 struct sunos_direntry_callback buf
;
490 if(fd
>= SUNOS_NR_OPEN
)
498 if (!file
->f_op
|| !file
->f_op
->readdir
)
502 if(cnt
< (sizeof(struct sunos_direntry
) + 255))
505 buf
.curr
= (struct sunos_direntry
*) dirent
;
510 inode
= file
->f_dentry
->d_inode
;
512 error
= file
->f_op
->readdir(file
, &buf
, sunos_filldirentry
);
517 lastdirent
= buf
.previous
;
520 put_user(file
->f_pos
, basep
);
521 error
= cnt
- buf
.count
;
531 struct sunos_utsname
{
540 asmlinkage
int sunos_uname(struct sunos_utsname
*name
)
545 ret
= copy_to_user(&name
->sname
[0], &system_utsname
.sysname
[0], sizeof(name
->sname
) - 1);
546 ret
|= copy_to_user(&name
->nname
[0], &system_utsname
.nodename
[0], sizeof(name
->nname
) - 1);
547 ret
|= put_user('\0', &name
->nname
[8]);
548 ret
|= copy_to_user(&name
->rel
[0], &system_utsname
.release
[0], sizeof(name
->rel
) - 1);
549 ret
|= copy_to_user(&name
->ver
[0], &system_utsname
.version
[0], sizeof(name
->ver
) - 1);
550 ret
|= copy_to_user(&name
->mach
[0], &system_utsname
.machine
[0], sizeof(name
->mach
) - 1);
555 asmlinkage
int sunos_nosys(void)
557 struct pt_regs
*regs
;
560 regs
= current
->tss
.kregs
;
561 current
->tss
.sig_address
= regs
->tpc
;
562 current
->tss
.sig_desc
= regs
->u_regs
[UREG_G1
];
563 send_sig(SIGSYS
, current
, 1);
564 printk("Process makes ni_syscall number %d, register dump:\n",
565 (int) regs
->u_regs
[UREG_G1
]);
571 /* This is not a real and complete implementation yet, just to keep
572 * the easy SunOS binaries happy.
574 asmlinkage
int sunos_fpathconf(int fd
, int name
)
598 case _PCONF_CHRESTRICT
: /* XXX Investigate XXX */
601 case _PCONF_NOTRUNC
: /* XXX Investigate XXX */
602 case _PCONF_VDISABLE
:
613 asmlinkage
int sunos_pathconf(u32 u_path
, int name
)
618 ret
= sunos_fpathconf(0, name
); /* XXX cheese XXX */
623 /* SunOS mount system call emulation */
624 extern asmlinkage
int
625 sys32_select(int n
, u32 inp
, u32 outp
, u32 exp
, u32 tvp
);
632 asmlinkage
int sunos_select(int width
, u32 inp
, u32 outp
, u32 exp
, u32 tvp_x
)
636 /* SunOS binaries expect that select won't change the tvp contents */
638 current
->personality
|= STICKY_TIMEOUTS
;
639 ret
= sys32_select (width
, inp
, outp
, exp
, tvp_x
);
640 if (ret
== -EINTR
&& tvp_x
) {
641 struct timeval32
*tvp
= (struct timeval32
*)A(tvp_x
);
644 __get_user(sec
, &tvp
->tv_sec
);
645 __get_user(usec
, &tvp
->tv_usec
);
646 if (sec
== 0 && usec
== 0)
653 asmlinkage
void sunos_nop(void)
658 /* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
659 #define SMNT_RDONLY 1
660 #define SMNT_NOSUID 2
661 #define SMNT_NEWTYPE 4
663 #define SMNT_REMOUNT 16
664 #define SMNT_NOSUB 32
665 #define SMNT_MULTI 64
666 #define SMNT_SYS5 128
669 char fh_data
[NFS_FHSIZE
];
672 struct sunos_nfs_mount_args
{
673 struct sockaddr_in
*addr
; /* file server address */
674 struct nfs_fh
*fh
; /* File handle to be mounted */
675 int flags
; /* flags */
676 int wsize
; /* write size in bytes */
677 int rsize
; /* read size in bytes */
678 int timeo
; /* initial timeout in .1 secs */
679 int retrans
; /* times to retry send */
680 char *hostname
; /* server's hostname */
681 int acregmin
; /* attr cache file min secs */
682 int acregmax
; /* attr cache file max secs */
683 int acdirmin
; /* attr cache dir min secs */
684 int acdirmax
; /* attr cache dir max secs */
685 char *netname
; /* server's netname */
688 extern int do_mount(kdev_t
, const char *, const char *, char *, int, void *);
689 extern dev_t
get_unnamed_dev(void);
690 extern void put_unnamed_dev(dev_t
);
691 extern asmlinkage
int sys_mount(char *, char *, char *, unsigned long, void *);
692 extern asmlinkage
int sys_connect(int fd
, struct sockaddr
*uservaddr
, int addrlen
);
693 extern asmlinkage
int sys_socket(int family
, int type
, int protocol
);
694 extern asmlinkage
int sys_bind(int fd
, struct sockaddr
*umyaddr
, int addrlen
);
697 /* Bind the socket on a local reserved port and connect it to the
698 * remote server. This on Linux/i386 is done by the mount program,
701 /* XXXXXXXXXXXXXXXXXXXX */
703 sunos_nfs_get_server_fd (int fd
, struct sockaddr_in
*addr
)
705 struct sockaddr_in local
;
706 struct sockaddr_in server
;
709 struct socket
*socket
;
710 struct dentry
*dentry
;
718 dentry
= file
->f_dentry
;
722 inode
= dentry
->d_inode
;
726 socket
= &inode
->u
.socket_i
;
727 local
.sin_family
= AF_INET
;
728 local
.sin_addr
.s_addr
= INADDR_ANY
;
730 /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
733 local
.sin_port
= htons (--try_port
);
734 ret
= socket
->ops
->bind(socket
, (struct sockaddr
*)&local
,
736 } while (ret
&& try_port
> (1024 / 2));
741 server
.sin_family
= AF_INET
;
742 server
.sin_addr
= addr
->sin_addr
;
743 server
.sin_port
= NFS_PORT
;
745 /* Call sys_connect */
746 ret
= socket
->ops
->connect (socket
, (struct sockaddr
*) &server
,
747 sizeof (server
), file
->f_flags
);
753 /* XXXXXXXXXXXXXXXXXXXX */
754 static int get_default (int value
, int def_value
)
762 /* XXXXXXXXXXXXXXXXXXXX */
763 asmlinkage
int sunos_nfs_mount(char *dir_name
, int linux_flags
, void *data
)
768 struct nfs_mount_data linux_nfs_mount
;
769 struct sunos_nfs_mount_args
*sunos_mount
= data
;
772 /* Ok, here comes the fun part: Linux's nfs mount needs a
773 * socket connection to the server, but SunOS mount does not
774 * require this, so we use the information on the destination
775 * address to create a socket and bind it to a reserved
776 * port on this system
778 server_fd
= sys_socket (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
782 if (!sunos_nfs_get_server_fd (server_fd
, sunos_mount
->addr
)){
783 sys_close (server_fd
);
787 /* Now, bind it to a locally reserved port */
788 linux_nfs_mount
.version
= NFS_MOUNT_VERSION
;
789 linux_nfs_mount
.flags
= sunos_mount
->flags
;
790 linux_nfs_mount
.addr
= *sunos_mount
->addr
;
791 linux_nfs_mount
.root
= *sunos_mount
->fh
;
792 linux_nfs_mount
.fd
= server_fd
;
794 linux_nfs_mount
.rsize
= get_default (sunos_mount
->rsize
, 8192);
795 linux_nfs_mount
.wsize
= get_default (sunos_mount
->wsize
, 8192);
796 linux_nfs_mount
.timeo
= get_default (sunos_mount
->timeo
, 10);
797 linux_nfs_mount
.retrans
= sunos_mount
->retrans
;
799 linux_nfs_mount
.acregmin
= sunos_mount
->acregmin
;
800 linux_nfs_mount
.acregmax
= sunos_mount
->acregmax
;
801 linux_nfs_mount
.acdirmin
= sunos_mount
->acdirmin
;
802 linux_nfs_mount
.acdirmax
= sunos_mount
->acdirmax
;
804 the_name
= getname(sunos_mount
->hostname
);
808 strncpy (linux_nfs_mount
.hostname
, the_name
, 254);
809 linux_nfs_mount
.hostname
[255] = 0;
812 dev
= get_unnamed_dev ();
814 ret
= do_mount (dev
, "", dir_name
, "nfs", linux_flags
, &linux_nfs_mount
);
816 put_unnamed_dev(dev
);
821 /* XXXXXXXXXXXXXXXXXXXX */
823 sunos_mount(char *type
, char *dir
, int flags
, void *data
)
825 int linux_flags
= MS_MGC_MSK
; /* new semantics */
829 if (!capable (CAP_SYS_ADMIN
))
832 /* We don't handle the integer fs type */
833 if ((flags
& SMNT_NEWTYPE
) == 0)
836 /* Do not allow for those flags we don't support */
837 if (flags
& (SMNT_GRPID
|SMNT_NOSUB
|SMNT_MULTI
|SMNT_SYS5
))
840 if(flags
& SMNT_REMOUNT
)
841 linux_flags
|= MS_REMOUNT
;
842 if(flags
& SMNT_RDONLY
)
843 linux_flags
|= MS_RDONLY
;
844 if(flags
& SMNT_NOSUID
)
845 linux_flags
|= MS_NOSUID
;
846 if(strcmp(type
, "ext2") == 0) {
847 dev_fname
= (char *) data
;
848 } else if(strcmp(type
, "iso9660") == 0) {
849 dev_fname
= (char *) data
;
850 } else if(strcmp(type
, "minix") == 0) {
851 dev_fname
= (char *) data
;
852 } else if(strcmp(type
, "nfs") == 0) {
853 ret
= sunos_nfs_mount (dir
, flags
, data
);
855 } else if(strcmp(type
, "ufs") == 0) {
856 printk("Warning: UFS filesystem mounts unsupported.\n");
859 } else if(strcmp(type
, "proc")) {
863 ret
= sys_mount(dev_fname
, dir
, type
, linux_flags
, NULL
);
869 extern asmlinkage
int sys_setsid(void);
870 extern asmlinkage
int sys_setpgid(pid_t
, pid_t
);
872 asmlinkage
int sunos_setpgrp(pid_t pid
, pid_t pgid
)
878 if((!pid
|| pid
== current
->pid
) &&
883 ret
= sys_setpgid(pid
, pgid
);
890 extern asmlinkage
int sys32_wait4(__kernel_pid_t32 pid
,
891 u32 stat_addr
, int options
, u32 ru
);
893 asmlinkage
int sunos_wait4(__kernel_pid_t32 pid
, u32 stat_addr
, int options
, u32 ru
)
898 ret
= sys32_wait4((pid
? pid
: ((__kernel_pid_t32
)-1)),
899 stat_addr
, options
, ru
);
904 extern int kill_pg(int, int, int);
905 asmlinkage
int sunos_killpg(int pgrp
, int sig
)
910 ret
= kill_pg(pgrp
, sig
, 0);
915 asmlinkage
int sunos_audit(void)
918 printk ("sys_audit\n");
923 extern asmlinkage u32
sunos_gethostid(void)
928 ret
= (((u32
)idprom
->id_machtype
<< 24) | ((u32
)idprom
->id_sernum
));
933 /* sysconf options, for SunOS compatibility */
934 #define _SC_ARG_MAX 1
935 #define _SC_CHILD_MAX 2
936 #define _SC_CLK_TCK 3
937 #define _SC_NGROUPS_MAX 4
938 #define _SC_OPEN_MAX 5
939 #define _SC_JOB_CONTROL 6
940 #define _SC_SAVED_IDS 7
941 #define _SC_VERSION 8
943 extern asmlinkage s32
sunos_sysconf (int name
)
958 case _SC_NGROUPS_MAX
:
964 case _SC_JOB_CONTROL
:
965 ret
= 1; /* yes, we do support job control */
968 ret
= 1; /* yes, we do support saved uids */
971 /* mhm, POSIX_VERSION is in /usr/include/unistd.h
972 * should it go on /usr/include/linux?
984 extern asmlinkage
int sys_semctl (int semid
, int semnum
, int cmd
, union semun arg
);
985 extern asmlinkage
int sys_semget (key_t key
, int nsems
, int semflg
);
986 extern asmlinkage
int sys_semop (int semid
, struct sembuf
*tsops
, unsigned nsops
);
988 asmlinkage
int sunos_semsys(int op
, u32 arg1
, u32 arg2
, u32 arg3
, u32 ptr
)
996 /* Most arguments match on a 1:1 basis but cmd doesn't */
1005 arg3
=GETNCNT
; break;
1007 arg3
=GETZCNT
; break;
1014 arg4
.__pad
=(void *)A(ptr
); /* value to modify semaphore to */
1015 ret
= sys_semctl((int)arg1
, (int)arg2
, (int)arg3
, arg4
);
1019 ret
= sys_semget((key_t
)arg1
, (int)arg2
, (int)arg3
);
1023 ret
= sys_semop((int)arg1
, (struct sembuf
*)A(arg2
), (unsigned)arg3
);
1041 __kernel_uid_t32 uid
;
1042 __kernel_gid_t32 gid
;
1043 __kernel_uid_t32 cuid
;
1044 __kernel_gid_t32 cgid
;
1045 __kernel_mode_t32 mode
;
1051 struct ipc_perm32 msg_perm
;
1054 __kernel_time_t32 msg_stime
;
1055 __kernel_time_t32 msg_rtime
;
1056 __kernel_time_t32 msg_ctime
;
1059 unsigned short msg_cbytes
;
1060 unsigned short msg_qnum
;
1061 unsigned short msg_qbytes
;
1062 __kernel_ipc_pid_t32 msg_lspid
;
1063 __kernel_ipc_pid_t32 msg_lrpid
;
1066 static inline int sunos_msqid_get(struct msqid_ds32
*user
,
1067 struct msqid_ds
*kern
)
1069 if(get_user(kern
->msg_perm
.key
, &user
->msg_perm
.key
) ||
1070 __get_user(kern
->msg_perm
.uid
, &user
->msg_perm
.uid
) ||
1071 __get_user(kern
->msg_perm
.gid
, &user
->msg_perm
.gid
) ||
1072 __get_user(kern
->msg_perm
.cuid
, &user
->msg_perm
.cuid
) ||
1073 __get_user(kern
->msg_perm
.cgid
, &user
->msg_perm
.cgid
) ||
1074 __get_user(kern
->msg_stime
, &user
->msg_stime
) ||
1075 __get_user(kern
->msg_rtime
, &user
->msg_rtime
) ||
1076 __get_user(kern
->msg_ctime
, &user
->msg_ctime
) ||
1077 __get_user(kern
->msg_ctime
, &user
->msg_cbytes
) ||
1078 __get_user(kern
->msg_ctime
, &user
->msg_qnum
) ||
1079 __get_user(kern
->msg_ctime
, &user
->msg_qbytes
) ||
1080 __get_user(kern
->msg_ctime
, &user
->msg_lspid
) ||
1081 __get_user(kern
->msg_ctime
, &user
->msg_lrpid
))
1086 static inline int sunos_msqid_put(struct msqid_ds32
*user
,
1087 struct msqid_ds
*kern
)
1089 if(put_user(kern
->msg_perm
.key
, &user
->msg_perm
.key
) ||
1090 __put_user(kern
->msg_perm
.uid
, &user
->msg_perm
.uid
) ||
1091 __put_user(kern
->msg_perm
.gid
, &user
->msg_perm
.gid
) ||
1092 __put_user(kern
->msg_perm
.cuid
, &user
->msg_perm
.cuid
) ||
1093 __put_user(kern
->msg_perm
.cgid
, &user
->msg_perm
.cgid
) ||
1094 __put_user(kern
->msg_stime
, &user
->msg_stime
) ||
1095 __put_user(kern
->msg_rtime
, &user
->msg_rtime
) ||
1096 __put_user(kern
->msg_ctime
, &user
->msg_ctime
) ||
1097 __put_user(kern
->msg_ctime
, &user
->msg_cbytes
) ||
1098 __put_user(kern
->msg_ctime
, &user
->msg_qnum
) ||
1099 __put_user(kern
->msg_ctime
, &user
->msg_qbytes
) ||
1100 __put_user(kern
->msg_ctime
, &user
->msg_lspid
) ||
1101 __put_user(kern
->msg_ctime
, &user
->msg_lrpid
))
1106 static inline int sunos_msgbuf_get(struct msgbuf32
*user
, struct msgbuf
*kern
, int len
)
1108 if(get_user(kern
->mtype
, &user
->mtype
) ||
1109 __copy_from_user(kern
->mtext
, &user
->mtext
, len
))
1114 static inline int sunos_msgbuf_put(struct msgbuf32
*user
, struct msgbuf
*kern
, int len
)
1116 if(put_user(kern
->mtype
, &user
->mtype
) ||
1117 __copy_to_user(user
->mtext
, kern
->mtext
, len
))
1122 extern asmlinkage
int sys_msgget (key_t key
, int msgflg
);
1123 extern asmlinkage
int sys_msgrcv (int msqid
, struct msgbuf
*msgp
,
1124 size_t msgsz
, long msgtyp
, int msgflg
);
1125 extern asmlinkage
int sys_msgsnd (int msqid
, struct msgbuf
*msgp
,
1126 size_t msgsz
, int msgflg
);
1127 extern asmlinkage
int sys_msgctl (int msqid
, int cmd
, struct msqid_ds
*buf
);
1129 asmlinkage
int sunos_msgsys(int op
, u32 arg1
, u32 arg2
, u32 arg3
, u32 arg4
)
1131 struct sparc_stackf32
*sp
;
1132 struct msqid_ds kds
;
1133 struct msgbuf
*kmbuf
;
1134 mm_segment_t old_fs
= get_fs();
1141 rval
= sys_msgget((key_t
)arg1
, (int)arg2
);
1144 if(!sunos_msqid_get((struct msqid_ds32
*)A(arg3
), &kds
)) {
1146 rval
= sys_msgctl((int)arg1
, (int)arg2
,
1147 (struct msqid_ds
*)A(arg3
));
1150 rval
= sunos_msqid_put((struct msqid_ds32
*)A(arg3
),
1157 kmbuf
= (struct msgbuf
*)kmalloc(sizeof(struct msgbuf
) + arg3
,
1161 sp
= (struct sparc_stackf32
*)
1162 (current
->tss
.kregs
->u_regs
[UREG_FP
] & 0xffffffffUL
);
1163 if(get_user(arg5
, &sp
->xxargs
[0])) {
1168 rval
= sys_msgrcv((int)arg1
, kmbuf
, (size_t)arg3
,
1169 (long)arg4
, (int)arg5
);
1172 rval
= sunos_msgbuf_put((struct msgbuf32
*)A(arg2
),
1178 kmbuf
= (struct msgbuf
*)kmalloc(sizeof(struct msgbuf
) + arg3
,
1180 if(!kmbuf
|| sunos_msgbuf_get((struct msgbuf32
*)A(arg2
),
1184 rval
= sys_msgsnd((int)arg1
, kmbuf
, (size_t)arg3
, (int)arg4
);
1197 struct ipc_perm32 shm_perm
;
1199 __kernel_time_t32 shm_atime
;
1200 __kernel_time_t32 shm_dtime
;
1201 __kernel_time_t32 shm_ctime
;
1202 __kernel_ipc_pid_t32 shm_cpid
;
1203 __kernel_ipc_pid_t32 shm_lpid
;
1204 unsigned short shm_nattch
;
1207 static inline int sunos_shmid_get(struct shmid_ds32
*user
,
1208 struct shmid_ds
*kern
)
1210 if(get_user(kern
->shm_perm
.key
, &user
->shm_perm
.key
) ||
1211 __get_user(kern
->shm_perm
.uid
, &user
->shm_perm
.uid
) ||
1212 __get_user(kern
->shm_perm
.gid
, &user
->shm_perm
.gid
) ||
1213 __get_user(kern
->shm_perm
.cuid
, &user
->shm_perm
.cuid
) ||
1214 __get_user(kern
->shm_perm
.cgid
, &user
->shm_perm
.cgid
) ||
1215 __get_user(kern
->shm_segsz
, &user
->shm_segsz
) ||
1216 __get_user(kern
->shm_atime
, &user
->shm_atime
) ||
1217 __get_user(kern
->shm_dtime
, &user
->shm_dtime
) ||
1218 __get_user(kern
->shm_ctime
, &user
->shm_ctime
) ||
1219 __get_user(kern
->shm_cpid
, &user
->shm_cpid
) ||
1220 __get_user(kern
->shm_lpid
, &user
->shm_lpid
) ||
1221 __get_user(kern
->shm_nattch
, &user
->shm_nattch
))
1226 static inline int sunos_shmid_put(struct shmid_ds32
*user
,
1227 struct shmid_ds
*kern
)
1229 if(put_user(kern
->shm_perm
.key
, &user
->shm_perm
.key
) ||
1230 __put_user(kern
->shm_perm
.uid
, &user
->shm_perm
.uid
) ||
1231 __put_user(kern
->shm_perm
.gid
, &user
->shm_perm
.gid
) ||
1232 __put_user(kern
->shm_perm
.cuid
, &user
->shm_perm
.cuid
) ||
1233 __put_user(kern
->shm_perm
.cgid
, &user
->shm_perm
.cgid
) ||
1234 __put_user(kern
->shm_segsz
, &user
->shm_segsz
) ||
1235 __put_user(kern
->shm_atime
, &user
->shm_atime
) ||
1236 __put_user(kern
->shm_dtime
, &user
->shm_dtime
) ||
1237 __put_user(kern
->shm_ctime
, &user
->shm_ctime
) ||
1238 __put_user(kern
->shm_cpid
, &user
->shm_cpid
) ||
1239 __put_user(kern
->shm_lpid
, &user
->shm_lpid
) ||
1240 __put_user(kern
->shm_nattch
, &user
->shm_nattch
))
1245 extern asmlinkage
int sys_shmat (int shmid
, char *shmaddr
, int shmflg
, ulong
*raddr
);
1246 extern asmlinkage
int sys_shmctl (int shmid
, int cmd
, struct shmid_ds
*buf
);
1247 extern asmlinkage
int sys_shmdt (char *shmaddr
);
1248 extern asmlinkage
int sys_shmget (key_t key
, int size
, int shmflg
);
1250 asmlinkage
int sunos_shmsys(int op
, u32 arg1
, u32 arg2
, u32 arg3
)
1252 struct shmid_ds ksds
;
1253 unsigned long raddr
;
1254 mm_segment_t old_fs
= get_fs();
1260 /* sys_shmat(): attach a shared memory area */
1261 rval
= sys_shmat((int)arg1
,(char *)A(arg2
),(int)arg3
,&raddr
);
1266 /* sys_shmctl(): modify shared memory area attr. */
1267 if(!sunos_shmid_get((struct shmid_ds32
*)A(arg3
), &ksds
)) {
1269 rval
= sys_shmctl((int)arg1
,(int)arg2
, &ksds
);
1272 rval
= sunos_shmid_put((struct shmid_ds32
*)A(arg3
),
1278 /* sys_shmdt(): detach a shared memory area */
1279 rval
= sys_shmdt((char *)A(arg1
));
1282 /* sys_shmget(): get a shared memory area */
1283 rval
= sys_shmget((key_t
)arg1
,(int)arg2
,(int)arg3
);
1293 asmlinkage
int sunos_open(u32 filename
, int flags
, int mode
)
1298 current
->personality
|= PER_BSD
;
1299 ret
= sys_open ((char *)A(filename
), flags
, mode
);
1304 #define SUNOS_EWOULDBLOCK 35
1306 /* see the sunos man page read(2v) for an explanation
1307 of this garbage. We use O_NDELAY to mark
1308 file descriptors that have been set non-blocking
1309 using 4.2BSD style calls. (tridge) */
1311 static inline int check_nonblock(int ret
, int fd
)
1313 if (ret
== -EAGAIN
) {
1314 struct file
* file
= fcheck(fd
);
1315 if (file
&& (file
->f_flags
& O_NDELAY
))
1316 ret
= -SUNOS_EWOULDBLOCK
;
1321 extern asmlinkage
int sys_read(unsigned int fd
, char *buf
, unsigned long count
);
1322 extern asmlinkage
int sys_write(unsigned int fd
, char *buf
, unsigned long count
);
1323 extern asmlinkage
int sys_recv(int fd
, void *ubuf
, size_t size
, unsigned flags
);
1324 extern asmlinkage
int sys_send(int fd
, void *buff
, size_t len
, unsigned flags
);
1325 extern asmlinkage
int sys_accept(int fd
, struct sockaddr
*sa
, int *addrlen
);
1326 extern asmlinkage
int sys32_readv(u32 fd
, u32 vector
, s32 count
);
1327 extern asmlinkage
int sys32_writev(u32 fd
, u32 vector
, s32 count
);
1329 asmlinkage
int sunos_read(unsigned int fd
, u32 buf
, u32 count
)
1334 ret
= check_nonblock(sys_read(fd
, (char *)A(buf
), count
), fd
);
1339 asmlinkage
int sunos_readv(u32 fd
, u32 vector
, s32 count
)
1344 ret
= check_nonblock(sys32_readv(fd
, vector
, count
), fd
);
1349 asmlinkage
int sunos_write(unsigned int fd
, u32 buf
, u32 count
)
1354 ret
= check_nonblock(sys_write(fd
, (char *)A(buf
), count
), fd
);
1359 asmlinkage
int sunos_writev(u32 fd
, u32 vector
, s32 count
)
1364 ret
= check_nonblock(sys32_writev(fd
, vector
, count
), fd
);
1369 asmlinkage
int sunos_recv(int fd
, u32 ubuf
, int size
, unsigned flags
)
1374 ret
= check_nonblock(sys_recv(fd
, (void *)A(ubuf
), size
, flags
), fd
);
1379 asmlinkage
int sunos_send(int fd
, u32 buff
, int len
, unsigned flags
)
1384 ret
= check_nonblock(sys_send(fd
, (void *)A(buff
), len
, flags
), fd
);
1389 extern asmlinkage
int sys_setsockopt(int fd
, int level
, int optname
,
1390 char *optval
, int optlen
);
1392 asmlinkage
int sunos_socket(int family
, int type
, int protocol
)
1397 ret
= sys_socket(family
, type
, protocol
);
1401 sys_setsockopt(ret
, SOL_SOCKET
, SO_BSDCOMPAT
,
1402 (char *)&one
, sizeof(one
));
1408 asmlinkage
int sunos_accept(int fd
, u32 sa
, u32 addrlen
)
1414 ret
= check_nonblock(sys_accept(fd
, (struct sockaddr
*)A(sa
),
1415 (int *)A(addrlen
)), fd
);
1416 if (ret
!= -ENETUNREACH
&& ret
!= -EHOSTUNREACH
)
1422 sys_setsockopt(ret
, SOL_SOCKET
, SO_BSDCOMPAT
,
1423 (char *)&one
, sizeof(one
));
1429 #define SUNOS_SV_INTERRUPT 2
1431 asmlinkage
int sunos_sigaction (int sig
, u32 act
, u32 oact
)
1433 struct k_sigaction new_ka
, old_ka
;
1436 current
->personality
|= PER_BSD
;
1439 old_sigset_t32 mask
;
1441 if (get_user((long)new_ka
.sa
.sa_handler
, &((struct old_sigaction32
*)A(act
))->sa_handler
) ||
1442 __get_user(new_ka
.sa
.sa_flags
, &((struct old_sigaction32
*)A(act
))->sa_flags
))
1444 __get_user(mask
, &((struct old_sigaction32
*)A(act
))->sa_mask
);
1445 new_ka
.sa
.sa_restorer
= NULL
;
1446 new_ka
.ka_restorer
= NULL
;
1447 siginitset(&new_ka
.sa
.sa_mask
, mask
);
1448 new_ka
.sa
.sa_flags
^= SUNOS_SV_INTERRUPT
;
1451 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
1454 old_ka
.sa
.sa_flags
^= SUNOS_SV_INTERRUPT
;
1455 if (put_user((long)old_ka
.sa
.sa_handler
, &((struct old_sigaction32
*)A(oact
))->sa_handler
) ||
1456 __put_user(old_ka
.sa
.sa_flags
, &((struct old_sigaction32
*)A(oact
))->sa_flags
))
1458 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &((struct old_sigaction32
*)A(oact
))->sa_mask
);
1464 extern asmlinkage
int sys_setsockopt(int fd
, int level
, int optname
,
1465 char *optval
, int optlen
);
1466 extern asmlinkage
int sys32_getsockopt(int fd
, int level
, int optname
,
1467 u32 optval
, u32 optlen
);
1469 asmlinkage
int sunos_setsockopt(int fd
, int level
, int optname
, u32 optval
,
1472 int tr_opt
= optname
;
1476 if (level
== SOL_IP
) {
1477 /* Multicast socketopts (ttl, membership) */
1478 if (tr_opt
>=2 && tr_opt
<= 6)
1481 ret
= sys_setsockopt(fd
, level
, tr_opt
, (char *)A(optval
), optlen
);
1486 asmlinkage
int sunos_getsockopt(int fd
, int level
, int optname
,
1487 u32 optval
, u32 optlen
)
1489 int tr_opt
= optname
;
1493 if (level
== SOL_IP
) {
1494 /* Multicast socketopts (ttl, membership) */
1495 if (tr_opt
>=2 && tr_opt
<= 6)
1498 ret
= sys32_getsockopt(fd
, level
, tr_opt
, optval
, optlen
);