OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc64/] [kernel/] [sys_sunos32.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $
2
 * sys_sunos32.c: SunOS binary compatibility layer on sparc64.
3
 *
4
 * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
5
 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
6
 *
7
 * Based upon preliminary work which is:
8
 *
9
 * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
10
 */
11
 
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/types.h>
15
#include <linux/capability.h>
16
#include <linux/compat.h>
17
#include <linux/mman.h>
18
#include <linux/mm.h>
19
#include <linux/swap.h>
20
#include <linux/fs.h>
21
#include <linux/file.h>
22
#include <linux/resource.h>
23
#include <linux/ipc.h>
24
#include <linux/shm.h>
25
#include <linux/msg.h>
26
#include <linux/sem.h>
27
#include <linux/signal.h>
28
#include <linux/uio.h>
29
#include <linux/utsname.h>
30
#include <linux/major.h>
31
#include <linux/stat.h>
32
#include <linux/slab.h>
33
#include <linux/pagemap.h>
34
#include <linux/errno.h>
35
#include <linux/smp.h>
36
#include <linux/smp_lock.h>
37
#include <linux/syscalls.h>
38
 
39
#include <asm/uaccess.h>
40
#include <asm/page.h>
41
#include <asm/pgtable.h>
42
#include <asm/pconf.h>
43
#include <asm/idprom.h> /* for gethostid() */
44
#include <asm/unistd.h>
45
#include <asm/system.h>
46
#include <asm/compat_signal.h>
47
 
48
/* For the nfs mount emulation */
49
#include <linux/socket.h>
50
#include <linux/in.h>
51
#include <linux/nfs.h>
52
#include <linux/nfs2.h>
53
#include <linux/nfs_mount.h>
54
 
55
/* for sunos_select */
56
#include <linux/time.h>
57
#include <linux/personality.h>
58
 
59
/* For SOCKET_I */
60
#include <net/sock.h>
61
#include <net/compat.h>
62
 
63
#define SUNOS_NR_OPEN   256
64
 
65
asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
66
{
67
        struct file *file = NULL;
68
        unsigned long retval, ret_type;
69
 
70
        if (flags & MAP_NORESERVE) {
71
                static int cnt;
72
                if (cnt++ < 10)
73
                        printk("%s:  unimplemented SunOS MAP_NORESERVE mmap() flag\n",
74
                               current->comm);
75
                flags &= ~MAP_NORESERVE;
76
        }
77
        retval = -EBADF;
78
        if (!(flags & MAP_ANONYMOUS)) {
79
                struct inode * inode;
80
                if (fd >= SUNOS_NR_OPEN)
81
                        goto out;
82
                file = fget(fd);
83
                if (!file)
84
                        goto out;
85
                inode = file->f_path.dentry->d_inode;
86
                if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
87
                        flags |= MAP_ANONYMOUS;
88
                        fput(file);
89
                        file = NULL;
90
                }
91
        }
92
 
93
        retval = -EINVAL;
94
        if (!(flags & MAP_FIXED))
95
                addr = 0;
96
        else if (len > 0xf0000000 || addr > 0xf0000000 - len)
97
                goto out_putf;
98
        ret_type = flags & _MAP_NEW;
99
        flags &= ~_MAP_NEW;
100
 
101
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
102
        down_write(&current->mm->mmap_sem);
103
        retval = do_mmap(file,
104
                         (unsigned long) addr, (unsigned long) len,
105
                         (unsigned long) prot, (unsigned long) flags,
106
                         (unsigned long) off);
107
        up_write(&current->mm->mmap_sem);
108
        if (!ret_type)
109
                retval = ((retval < 0xf0000000) ? 0 : retval);
110
out_putf:
111
        if (file)
112
                fput(file);
113
out:
114
        return (u32) retval;
115
}
116
 
117
asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
118
{
119
        return 0;
120
}
121
 
122
asmlinkage int sunos_brk(u32 baddr)
123
{
124
        int freepages, retval = -ENOMEM;
125
        unsigned long rlim;
126
        unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
127
 
128
        down_write(&current->mm->mmap_sem);
129
        if (brk < current->mm->end_code)
130
                goto out;
131
        newbrk = PAGE_ALIGN(brk);
132
        oldbrk = PAGE_ALIGN(current->mm->brk);
133
        retval = 0;
134
        if (oldbrk == newbrk) {
135
                current->mm->brk = brk;
136
                goto out;
137
        }
138
        /* Always allow shrinking brk. */
139
        if (brk <= current->mm->brk) {
140
                current->mm->brk = brk;
141
                do_munmap(current->mm, newbrk, oldbrk-newbrk);
142
                goto out;
143
        }
144
        /* Check against rlimit and stack.. */
145
        retval = -ENOMEM;
146
        rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
147
        if (rlim >= RLIM_INFINITY)
148
                rlim = ~0;
149
        if (brk - current->mm->end_code > rlim)
150
                goto out;
151
        /* Check against existing mmap mappings. */
152
        if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
153
                goto out;
154
        /* stupid algorithm to decide if we have enough memory: while
155
         * simple, it hopefully works in most obvious cases.. Easy to
156
         * fool it, but this should catch most mistakes.
157
         */
158
        freepages = global_page_state(NR_FILE_PAGES);
159
        freepages >>= 1;
160
        freepages += nr_free_pages();
161
        freepages += nr_swap_pages;
162
        freepages -= num_physpages >> 4;
163
        freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
164
        if (freepages < 0)
165
                goto out;
166
        /* Ok, we have probably got enough memory - let it rip. */
167
        current->mm->brk = brk;
168
        do_brk(oldbrk, newbrk-oldbrk);
169
        retval = 0;
170
out:
171
        up_write(&current->mm->mmap_sem);
172
        return retval;
173
}
174
 
175
asmlinkage u32 sunos_sbrk(int increment)
176
{
177
        int error, oldbrk;
178
 
179
        /* This should do it hopefully... */
180
        oldbrk = (int)current->mm->brk;
181
        error = sunos_brk(((int) current->mm->brk) + increment);
182
        if (!error)
183
                error = oldbrk;
184
        return error;
185
}
186
 
187
asmlinkage u32 sunos_sstk(int increment)
188
{
189
        printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
190
               current->comm, increment);
191
 
192
        return (u32)-1;
193
}
194
 
195
/* Give hints to the kernel as to what paging strategy to use...
196
 * Completely bogus, don't remind me.
197
 */
198
#define VA_NORMAL     0 /* Normal vm usage expected */
199
#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
200
#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
201
#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
202
static char *vstrings[] = {
203
        "VA_NORMAL",
204
        "VA_ABNORMAL",
205
        "VA_SEQUENTIAL",
206
        "VA_INVALIDATE",
207
};
208
 
209
asmlinkage void sunos_vadvise(u32 strategy)
210
{
211
        static int count;
212
 
213
        /* I wanna see who uses this... */
214
        if (count++ < 5)
215
                printk("%s: Advises us to use %s paging strategy\n",
216
                       current->comm,
217
                       strategy <= 3 ? vstrings[strategy] : "BOGUS");
218
}
219
 
220
/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
221
 * resource limit and is for backwards compatibility with older sunos
222
 * revs.
223
 */
224
asmlinkage int sunos_getdtablesize(void)
225
{
226
        return SUNOS_NR_OPEN;
227
}
228
 
229
 
230
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
231
 
232
asmlinkage u32 sunos_sigblock(u32 blk_mask)
233
{
234
        u32 old;
235
 
236
        spin_lock_irq(&current->sighand->siglock);
237
        old = (u32) current->blocked.sig[0];
238
        current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
239
        recalc_sigpending();
240
        spin_unlock_irq(&current->sighand->siglock);
241
        return old;
242
}
243
 
244
asmlinkage u32 sunos_sigsetmask(u32 newmask)
245
{
246
        u32 retval;
247
 
248
        spin_lock_irq(&current->sighand->siglock);
249
        retval = (u32) current->blocked.sig[0];
250
        current->blocked.sig[0] = (newmask & _BLOCKABLE);
251
        recalc_sigpending();
252
        spin_unlock_irq(&current->sighand->siglock);
253
        return retval;
254
}
255
 
256
/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
257
/* getdents system call, the format of the structure just has a different */
258
/* layout (d_off+d_ino instead of d_ino+d_off) */
259
struct sunos_dirent {
260
    s32         d_off;
261
    u32         d_ino;
262
    u16         d_reclen;
263
    u16         d_namlen;
264
    char        d_name[1];
265
};
266
 
267
struct sunos_dirent_callback {
268
    struct sunos_dirent __user *curr;
269
    struct sunos_dirent __user *previous;
270
    int count;
271
    int error;
272
};
273
 
274
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
275
#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
276
 
277
static int sunos_filldir(void * __buf, const char * name, int namlen,
278
                         loff_t offset, ino_t ino, unsigned int d_type)
279
{
280
        struct sunos_dirent __user *dirent;
281
        struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
282
        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
283
        u32 d_ino;
284
 
285
        buf->error = -EINVAL;   /* only used if we fail.. */
286
        if (reclen > buf->count)
287
                return -EINVAL;
288
        d_ino = ino;
289
        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
290
                return -EOVERFLOW;
291
        dirent = buf->previous;
292
        if (dirent)
293
                put_user(offset, &dirent->d_off);
294
        dirent = buf->curr;
295
        buf->previous = dirent;
296
        put_user(d_ino, &dirent->d_ino);
297
        put_user(namlen, &dirent->d_namlen);
298
        put_user(reclen, &dirent->d_reclen);
299
        if (copy_to_user(dirent->d_name, name, namlen))
300
                return -EFAULT;
301
        put_user(0, dirent->d_name + namlen);
302
        dirent = (void __user *) dirent + reclen;
303
        buf->curr = dirent;
304
        buf->count -= reclen;
305
        return 0;
306
}
307
 
308
asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
309
{
310
        struct file * file;
311
        struct sunos_dirent __user *lastdirent;
312
        struct sunos_dirent_callback buf;
313
        int error = -EBADF;
314
 
315
        if (fd >= SUNOS_NR_OPEN)
316
                goto out;
317
 
318
        file = fget(fd);
319
        if (!file)
320
                goto out;
321
 
322
        error = -EINVAL;
323
        if (cnt < (sizeof(struct sunos_dirent) + 255))
324
                goto out_putf;
325
 
326
        buf.curr = (struct sunos_dirent __user *) dirent;
327
        buf.previous = NULL;
328
        buf.count = cnt;
329
        buf.error = 0;
330
 
331
        error = vfs_readdir(file, sunos_filldir, &buf);
332
        if (error < 0)
333
                goto out_putf;
334
 
335
        lastdirent = buf.previous;
336
        error = buf.error;
337
        if (lastdirent) {
338
                put_user(file->f_pos, &lastdirent->d_off);
339
                error = cnt - buf.count;
340
        }
341
 
342
out_putf:
343
        fput(file);
344
out:
345
        return error;
346
}
347
 
348
/* Old sunos getdirentries, severely broken compatibility stuff here. */
349
struct sunos_direntry {
350
    u32         d_ino;
351
    u16         d_reclen;
352
    u16         d_namlen;
353
    char        d_name[1];
354
};
355
 
356
struct sunos_direntry_callback {
357
    struct sunos_direntry __user *curr;
358
    struct sunos_direntry __user *previous;
359
    int count;
360
    int error;
361
};
362
 
363
static int sunos_filldirentry(void * __buf, const char * name, int namlen,
364
                              loff_t offset, ino_t ino, unsigned int d_type)
365
{
366
        struct sunos_direntry __user *dirent;
367
        struct sunos_direntry_callback * buf =
368
                (struct sunos_direntry_callback *) __buf;
369
        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
370
        u32 d_ino;
371
 
372
        buf->error = -EINVAL;   /* only used if we fail.. */
373
        if (reclen > buf->count)
374
                return -EINVAL;
375
        d_ino = ino;
376
        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
377
                return -EOVERFLOW;
378
        dirent = buf->previous;
379
        dirent = buf->curr;
380
        buf->previous = dirent;
381
        put_user(d_ino, &dirent->d_ino);
382
        put_user(namlen, &dirent->d_namlen);
383
        put_user(reclen, &dirent->d_reclen);
384
        if (copy_to_user(dirent->d_name, name, namlen))
385
                return -EFAULT;
386
        put_user(0, dirent->d_name + namlen);
387
        dirent = (void __user *) dirent + reclen;
388
        buf->curr = dirent;
389
        buf->count -= reclen;
390
        return 0;
391
}
392
 
393
asmlinkage int sunos_getdirentries(unsigned int fd,
394
                                   void __user *dirent,
395
                                   int cnt,
396
                                   unsigned int __user *basep)
397
{
398
        struct file * file;
399
        struct sunos_direntry __user *lastdirent;
400
        int error = -EBADF;
401
        struct sunos_direntry_callback buf;
402
 
403
        if (fd >= SUNOS_NR_OPEN)
404
                goto out;
405
 
406
        file = fget(fd);
407
        if (!file)
408
                goto out;
409
 
410
        error = -EINVAL;
411
        if (cnt < (sizeof(struct sunos_direntry) + 255))
412
                goto out_putf;
413
 
414
        buf.curr = (struct sunos_direntry __user *) dirent;
415
        buf.previous = NULL;
416
        buf.count = cnt;
417
        buf.error = 0;
418
 
419
        error = vfs_readdir(file, sunos_filldirentry, &buf);
420
        if (error < 0)
421
                goto out_putf;
422
 
423
        lastdirent = buf.previous;
424
        error = buf.error;
425
        if (lastdirent) {
426
                put_user(file->f_pos, basep);
427
                error = cnt - buf.count;
428
        }
429
 
430
out_putf:
431
        fput(file);
432
out:
433
        return error;
434
}
435
 
436
struct sunos_utsname {
437
        char sname[9];
438
        char nname[9];
439
        char nnext[56];
440
        char rel[9];
441
        char ver[9];
442
        char mach[9];
443
};
444
 
445
asmlinkage int sunos_uname(struct sunos_utsname __user *name)
446
{
447
        int ret;
448
 
449
        down_read(&uts_sem);
450
        ret = copy_to_user(&name->sname[0], &utsname()->sysname[0],
451
                           sizeof(name->sname) - 1);
452
        ret |= copy_to_user(&name->nname[0], &utsname()->nodename[0],
453
                            sizeof(name->nname) - 1);
454
        ret |= put_user('\0', &name->nname[8]);
455
        ret |= copy_to_user(&name->rel[0], &utsname()->release[0],
456
                            sizeof(name->rel) - 1);
457
        ret |= copy_to_user(&name->ver[0], &utsname()->version[0],
458
                            sizeof(name->ver) - 1);
459
        ret |= copy_to_user(&name->mach[0], &utsname()->machine[0],
460
                            sizeof(name->mach) - 1);
461
        up_read(&uts_sem);
462
        return (ret ? -EFAULT : 0);
463
}
464
 
465
asmlinkage int sunos_nosys(void)
466
{
467
        struct pt_regs *regs;
468
        siginfo_t info;
469
        static int cnt;
470
 
471
        regs = current_thread_info()->kregs;
472
        if (test_thread_flag(TIF_32BIT)) {
473
                regs->tpc &= 0xffffffff;
474
                regs->tnpc &= 0xffffffff;
475
        }
476
        info.si_signo = SIGSYS;
477
        info.si_errno = 0;
478
        info.si_code = __SI_FAULT|0x100;
479
        info.si_addr = (void __user *)regs->tpc;
480
        info.si_trapno = regs->u_regs[UREG_G1];
481
        send_sig_info(SIGSYS, &info, current);
482
        if (cnt++ < 4) {
483
                printk("Process makes ni_syscall number %d, register dump:\n",
484
                       (int) regs->u_regs[UREG_G1]);
485
                show_regs(regs);
486
        }
487
        return -ENOSYS;
488
}
489
 
490
/* This is not a real and complete implementation yet, just to keep
491
 * the easy SunOS binaries happy.
492
 */
493
asmlinkage int sunos_fpathconf(int fd, int name)
494
{
495
        int ret;
496
 
497
        switch(name) {
498
        case _PCONF_LINK:
499
                ret = LINK_MAX;
500
                break;
501
        case _PCONF_CANON:
502
                ret = MAX_CANON;
503
                break;
504
        case _PCONF_INPUT:
505
                ret = MAX_INPUT;
506
                break;
507
        case _PCONF_NAME:
508
                ret = NAME_MAX;
509
                break;
510
        case _PCONF_PATH:
511
                ret = PATH_MAX;
512
                break;
513
        case _PCONF_PIPE:
514
                ret = PIPE_BUF;
515
                break;
516
        case _PCONF_CHRESTRICT:         /* XXX Investigate XXX */
517
                ret = 1;
518
                break;
519
        case _PCONF_NOTRUNC:            /* XXX Investigate XXX */
520
        case _PCONF_VDISABLE:
521
                ret = 0;
522
                break;
523
        default:
524
                ret = -EINVAL;
525
                break;
526
        }
527
        return ret;
528
}
529
 
530
asmlinkage int sunos_pathconf(u32 u_path, int name)
531
{
532
        int ret;
533
 
534
        ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
535
        return ret;
536
}
537
 
538
asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x)
539
{
540
        int ret;
541
 
542
        /* SunOS binaries expect that select won't change the tvp contents */
543
        ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp),
544
                                compat_ptr(exp), compat_ptr(tvp_x));
545
        if (ret == -EINTR && tvp_x) {
546
                struct compat_timeval __user *tvp = compat_ptr(tvp_x);
547
                time_t sec, usec;
548
 
549
                __get_user(sec, &tvp->tv_sec);
550
                __get_user(usec, &tvp->tv_usec);
551
                if (sec == 0 && usec == 0)
552
                        ret = 0;
553
        }
554
        return ret;
555
}
556
 
557
asmlinkage void sunos_nop(void)
558
{
559
        return;
560
}
561
 
562
#if 0 /* This code doesn't translate user pointers correctly,
563
       * disable for now. -DaveM
564
       */
565
 
566
/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
567
#define SMNT_RDONLY       1
568
#define SMNT_NOSUID       2
569
#define SMNT_NEWTYPE      4
570
#define SMNT_GRPID        8
571
#define SMNT_REMOUNT      16
572
#define SMNT_NOSUB        32
573
#define SMNT_MULTI        64
574
#define SMNT_SYS5         128
575
 
576
struct sunos_fh_t {
577
        char fh_data [NFS_FHSIZE];
578
};
579
 
580
struct sunos_nfs_mount_args {
581
        struct sockaddr_in  *addr; /* file server address */
582
        struct nfs_fh *fh;     /* File handle to be mounted */
583
        int        flags;      /* flags */
584
        int        wsize;      /* write size in bytes */
585
        int        rsize;      /* read size in bytes */
586
        int        timeo;      /* initial timeout in .1 secs */
587
        int        retrans;    /* times to retry send */
588
        char       *hostname;  /* server's hostname */
589
        int        acregmin;   /* attr cache file min secs */
590
        int        acregmax;   /* attr cache file max secs */
591
        int        acdirmin;   /* attr cache dir min secs */
592
        int        acdirmax;   /* attr cache dir max secs */
593
        char       *netname;   /* server's netname */
594
};
595
 
596
 
597
/* Bind the socket on a local reserved port and connect it to the
598
 * remote server.  This on Linux/i386 is done by the mount program,
599
 * not by the kernel.
600
 */
601
/* XXXXXXXXXXXXXXXXXXXX */
602
static int
603
sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
604
{
605
        struct sockaddr_in local;
606
        struct sockaddr_in server;
607
        int    try_port;
608
        int    ret;
609
        struct socket *socket;
610
        struct inode  *inode;
611
        struct file   *file;
612
 
613
        file = fget(fd);
614
        if (!file)
615
                return 0;
616
 
617
        inode = file->f_path.dentry->d_inode;
618
 
619
        socket = SOCKET_I(inode);
620
        local.sin_family = AF_INET;
621
        local.sin_addr.s_addr = INADDR_ANY;
622
 
623
        /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
624
        try_port = 1024;
625
        do {
626
                local.sin_port = htons (--try_port);
627
                ret = socket->ops->bind(socket, (struct sockaddr*)&local,
628
                                        sizeof(local));
629
        } while (ret && try_port > (1024 / 2));
630
 
631
        if (ret) {
632
                fput(file);
633
                return 0;
634
        }
635
 
636
        server.sin_family = AF_INET;
637
        server.sin_addr = addr->sin_addr;
638
        server.sin_port = NFS_PORT;
639
 
640
        /* Call sys_connect */
641
        ret = socket->ops->connect (socket, (struct sockaddr *) &server,
642
                                    sizeof (server), file->f_flags);
643
        fput(file);
644
        if (ret < 0)
645
                return 0;
646
        return 1;
647
}
648
 
649
/* XXXXXXXXXXXXXXXXXXXX */
650
static int get_default (int value, int def_value)
651
{
652
    if (value)
653
        return value;
654
    else
655
        return def_value;
656
}
657
 
658
/* XXXXXXXXXXXXXXXXXXXX */
659
static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data)
660
{
661
        int  server_fd, err;
662
        char *the_name, *mount_page;
663
        struct nfs_mount_data linux_nfs_mount;
664
        struct sunos_nfs_mount_args sunos_mount;
665
 
666
        /* Ok, here comes the fun part: Linux's nfs mount needs a
667
         * socket connection to the server, but SunOS mount does not
668
         * require this, so we use the information on the destination
669
         * address to create a socket and bind it to a reserved
670
         * port on this system
671
         */
672
        if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
673
                return -EFAULT;
674
 
675
        server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
676
        if (server_fd < 0)
677
                return -ENXIO;
678
 
679
        if (copy_from_user(&linux_nfs_mount.addr, sunos_mount.addr,
680
                           sizeof(*sunos_mount.addr)) ||
681
            copy_from_user(&linux_nfs_mount.root, sunos_mount.fh,
682
                           sizeof(*sunos_mount.fh))) {
683
                sys_close (server_fd);
684
                return -EFAULT;
685
        }
686
 
687
        if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
688
                sys_close (server_fd);
689
                return -ENXIO;
690
        }
691
 
692
        /* Now, bind it to a locally reserved port */
693
        linux_nfs_mount.version  = NFS_MOUNT_VERSION;
694
        linux_nfs_mount.flags    = sunos_mount.flags;
695
        linux_nfs_mount.fd       = server_fd;
696
 
697
        linux_nfs_mount.rsize    = get_default (sunos_mount.rsize, 8192);
698
        linux_nfs_mount.wsize    = get_default (sunos_mount.wsize, 8192);
699
        linux_nfs_mount.timeo    = get_default (sunos_mount.timeo, 10);
700
        linux_nfs_mount.retrans  = sunos_mount.retrans;
701
 
702
        linux_nfs_mount.acregmin = sunos_mount.acregmin;
703
        linux_nfs_mount.acregmax = sunos_mount.acregmax;
704
        linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
705
        linux_nfs_mount.acdirmax = sunos_mount.acdirmax;
706
 
707
        the_name = getname(sunos_mount.hostname);
708
        if (IS_ERR(the_name))
709
                return PTR_ERR(the_name);
710
 
711
        strlcpy(linux_nfs_mount.hostname, the_name,
712
                sizeof(linux_nfs_mount.hostname));
713
        putname (the_name);
714
 
715
        mount_page = (char *) get_zeroed_page(GFP_KERNEL);
716
        if (!mount_page)
717
                return -ENOMEM;
718
 
719
        memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
720
 
721
        err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
722
 
723
        free_page((unsigned long) mount_page);
724
        return err;
725
}
726
 
727
/* XXXXXXXXXXXXXXXXXXXX */
728
asmlinkage int
729
sunos_mount(char *type, char *dir, int flags, void *data)
730
{
731
        int linux_flags = 0;
732
        int ret = -EINVAL;
733
        char *dev_fname = 0;
734
        char *dir_page, *type_page;
735
 
736
        if (!capable (CAP_SYS_ADMIN))
737
                return -EPERM;
738
 
739
        /* We don't handle the integer fs type */
740
        if ((flags & SMNT_NEWTYPE) == 0)
741
                goto out;
742
 
743
        /* Do not allow for those flags we don't support */
744
        if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
745
                goto out;
746
 
747
        if (flags & SMNT_REMOUNT)
748
                linux_flags |= MS_REMOUNT;
749
        if (flags & SMNT_RDONLY)
750
                linux_flags |= MS_RDONLY;
751
        if (flags & SMNT_NOSUID)
752
                linux_flags |= MS_NOSUID;
753
 
754
        dir_page = getname(dir);
755
        ret = PTR_ERR(dir_page);
756
        if (IS_ERR(dir_page))
757
                goto out;
758
 
759
        type_page = getname(type);
760
        ret = PTR_ERR(type_page);
761
        if (IS_ERR(type_page))
762
                goto out1;
763
 
764
        if (strcmp(type_page, "ext2") == 0) {
765
                dev_fname = getname(data);
766
        } else if (strcmp(type_page, "iso9660") == 0) {
767
                dev_fname = getname(data);
768
        } else if (strcmp(type_page, "minix") == 0) {
769
                dev_fname = getname(data);
770
        } else if (strcmp(type_page, "nfs") == 0) {
771
                ret = sunos_nfs_mount (dir_page, flags, data);
772
                goto out2;
773
        } else if (strcmp(type_page, "ufs") == 0) {
774
                printk("Warning: UFS filesystem mounts unsupported.\n");
775
                ret = -ENODEV;
776
                goto out2;
777
        } else if (strcmp(type_page, "proc")) {
778
                ret = -ENODEV;
779
                goto out2;
780
        }
781
        ret = PTR_ERR(dev_fname);
782
        if (IS_ERR(dev_fname))
783
                goto out2;
784
        lock_kernel();
785
        ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
786
        unlock_kernel();
787
        if (dev_fname)
788
                putname(dev_fname);
789
out2:
790
        putname(type_page);
791
out1:
792
        putname(dir_page);
793
out:
794
        return ret;
795
}
796
#endif
797
 
798
asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
799
{
800
        int ret;
801
 
802
        /* So stupid... */
803
        if ((!pid || pid == current->pid) &&
804
            !pgid) {
805
                sys_setsid();
806
                ret = 0;
807
        } else {
808
                ret = sys_setpgid(pid, pgid);
809
        }
810
        return ret;
811
}
812
 
813
/* So stupid... */
814
extern long compat_sys_wait4(compat_pid_t, compat_uint_t __user *, int,
815
                             struct compat_rusage __user *);
816
 
817
asmlinkage int sunos_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru)
818
{
819
        int ret;
820
 
821
        ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)),
822
                               stat_addr, options, ru);
823
        return ret;
824
}
825
 
826
asmlinkage int sunos_killpg(int pgrp, int sig)
827
{
828
        int ret;
829
 
830
        rcu_read_lock();
831
        ret = -EINVAL;
832
        if (pgrp > 0)
833
                ret = kill_pgrp(find_vpid(pgrp), sig, 0);
834
        rcu_read_unlock();
835
 
836
        return ret;
837
}
838
 
839
asmlinkage int sunos_audit(void)
840
{
841
        printk ("sys_audit\n");
842
        return -1;
843
}
844
 
845
asmlinkage u32 sunos_gethostid(void)
846
{
847
        u32 ret;
848
 
849
        ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum));
850
 
851
        return ret;
852
}
853
 
854
/* sysconf options, for SunOS compatibility */
855
#define   _SC_ARG_MAX             1
856
#define   _SC_CHILD_MAX           2
857
#define   _SC_CLK_TCK             3
858
#define   _SC_NGROUPS_MAX         4
859
#define   _SC_OPEN_MAX            5
860
#define   _SC_JOB_CONTROL         6
861
#define   _SC_SAVED_IDS           7
862
#define   _SC_VERSION             8
863
 
864
asmlinkage s32 sunos_sysconf (int name)
865
{
866
        s32 ret;
867
 
868
        switch (name){
869
        case _SC_ARG_MAX:
870
                ret = ARG_MAX;
871
                break;
872
        case _SC_CHILD_MAX:
873
                ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur;
874
                break;
875
        case _SC_CLK_TCK:
876
                ret = HZ;
877
                break;
878
        case _SC_NGROUPS_MAX:
879
                ret = NGROUPS_MAX;
880
                break;
881
        case _SC_OPEN_MAX:
882
                ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
883
                break;
884
        case _SC_JOB_CONTROL:
885
                ret = 1;        /* yes, we do support job control */
886
                break;
887
        case _SC_SAVED_IDS:
888
                ret = 1;        /* yes, we do support saved uids  */
889
                break;
890
        case _SC_VERSION:
891
                /* mhm, POSIX_VERSION is in /usr/include/unistd.h
892
                 * should it go on /usr/include/linux?
893
                 */
894
                ret = 199009;
895
                break;
896
        default:
897
                ret = -1;
898
                break;
899
        };
900
        return ret;
901
}
902
 
903
asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, void __user *ptr)
904
{
905
        union semun arg4;
906
        int ret;
907
 
908
        switch (op) {
909
        case 0:
910
                /* Most arguments match on a 1:1 basis but cmd doesn't */
911
                switch(arg3) {
912
                case 4:
913
                        arg3=GETPID; break;
914
                case 5:
915
                        arg3=GETVAL; break;
916
                case 6:
917
                        arg3=GETALL; break;
918
                case 3:
919
                        arg3=GETNCNT; break;
920
                case 7:
921
                        arg3=GETZCNT; break;
922
                case 8:
923
                        arg3=SETVAL; break;
924
                case 9:
925
                        arg3=SETALL; break;
926
                }
927
                /* sys_semctl(): */
928
                /* value to modify semaphore to */
929
                arg4.__pad = ptr;
930
                ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4);
931
                break;
932
        case 1:
933
                /* sys_semget(): */
934
                ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
935
                break;
936
        case 2:
937
                /* sys_semop(): */
938
                ret = sys_semop((int)arg1, (struct sembuf __user *)(unsigned long)arg2,
939
                                (unsigned int) arg3);
940
                break;
941
        default:
942
                ret = -EINVAL;
943
                break;
944
        };
945
        return ret;
946
}
947
 
948
struct msgbuf32 {
949
        s32 mtype;
950
        char mtext[1];
951
};
952
 
953
struct ipc_perm32
954
{
955
        key_t             key;
956
        compat_uid_t  uid;
957
        compat_gid_t  gid;
958
        compat_uid_t  cuid;
959
        compat_gid_t  cgid;
960
        compat_mode_t mode;
961
        unsigned short  seq;
962
};
963
 
964
struct msqid_ds32
965
{
966
        struct ipc_perm32 msg_perm;
967
        u32 msg_first;
968
        u32 msg_last;
969
        compat_time_t msg_stime;
970
        compat_time_t msg_rtime;
971
        compat_time_t msg_ctime;
972
        u32 wwait;
973
        u32 rwait;
974
        unsigned short msg_cbytes;
975
        unsigned short msg_qnum;
976
        unsigned short msg_qbytes;
977
        compat_ipc_pid_t msg_lspid;
978
        compat_ipc_pid_t msg_lrpid;
979
};
980
 
981
static inline int sunos_msqid_get(struct msqid_ds32 __user *user,
982
                                  struct msqid_ds *kern)
983
{
984
        if (get_user(kern->msg_perm.key, &user->msg_perm.key)           ||
985
            __get_user(kern->msg_perm.uid, &user->msg_perm.uid)         ||
986
            __get_user(kern->msg_perm.gid, &user->msg_perm.gid)         ||
987
            __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid)       ||
988
            __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid)       ||
989
            __get_user(kern->msg_stime, &user->msg_stime)               ||
990
            __get_user(kern->msg_rtime, &user->msg_rtime)               ||
991
            __get_user(kern->msg_ctime, &user->msg_ctime)               ||
992
            __get_user(kern->msg_ctime, &user->msg_cbytes)              ||
993
            __get_user(kern->msg_ctime, &user->msg_qnum)                ||
994
            __get_user(kern->msg_ctime, &user->msg_qbytes)              ||
995
            __get_user(kern->msg_ctime, &user->msg_lspid)               ||
996
            __get_user(kern->msg_ctime, &user->msg_lrpid))
997
                return -EFAULT;
998
        return 0;
999
}
1000
 
1001
static inline int sunos_msqid_put(struct msqid_ds32 __user *user,
1002
                                  struct msqid_ds *kern)
1003
{
1004
        if (put_user(kern->msg_perm.key, &user->msg_perm.key)           ||
1005
            __put_user(kern->msg_perm.uid, &user->msg_perm.uid)         ||
1006
            __put_user(kern->msg_perm.gid, &user->msg_perm.gid)         ||
1007
            __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid)       ||
1008
            __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid)       ||
1009
            __put_user(kern->msg_stime, &user->msg_stime)               ||
1010
            __put_user(kern->msg_rtime, &user->msg_rtime)               ||
1011
            __put_user(kern->msg_ctime, &user->msg_ctime)               ||
1012
            __put_user(kern->msg_ctime, &user->msg_cbytes)              ||
1013
            __put_user(kern->msg_ctime, &user->msg_qnum)                ||
1014
            __put_user(kern->msg_ctime, &user->msg_qbytes)              ||
1015
            __put_user(kern->msg_ctime, &user->msg_lspid)               ||
1016
            __put_user(kern->msg_ctime, &user->msg_lrpid))
1017
                return -EFAULT;
1018
        return 0;
1019
}
1020
 
1021
static inline int sunos_msgbuf_get(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
1022
{
1023
        if (get_user(kern->mtype, &user->mtype) ||
1024
            __copy_from_user(kern->mtext, &user->mtext, len))
1025
                return -EFAULT;
1026
        return 0;
1027
}
1028
 
1029
static inline int sunos_msgbuf_put(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
1030
{
1031
        if (put_user(kern->mtype, &user->mtype) ||
1032
            __copy_to_user(user->mtext, kern->mtext, len))
1033
                return -EFAULT;
1034
        return 0;
1035
}
1036
 
1037
asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
1038
{
1039
        struct sparc_stackf32 __user *sp;
1040
        struct msqid_ds kds;
1041
        struct msgbuf *kmbuf;
1042
        mm_segment_t old_fs = get_fs();
1043
        u32 arg5;
1044
        int rval;
1045
 
1046
        switch(op) {
1047
        case 0:
1048
                rval = sys_msgget((key_t)arg1, (int)arg2);
1049
                break;
1050
        case 1:
1051
                if (!sunos_msqid_get((struct msqid_ds32 __user *)(unsigned long)arg3, &kds)) {
1052
                        set_fs(KERNEL_DS);
1053
                        rval = sys_msgctl((int)arg1, (int)arg2,
1054
                                          (struct msqid_ds __user *)(unsigned long)arg3);
1055
                        set_fs(old_fs);
1056
                        if (!rval)
1057
                                rval = sunos_msqid_put((struct msqid_ds32 __user *)(unsigned long)arg3,
1058
                                                       &kds);
1059
                } else
1060
                        rval = -EFAULT;
1061
                break;
1062
        case 2:
1063
                rval = -EFAULT;
1064
                kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
1065
                                                 GFP_KERNEL);
1066
                if (!kmbuf)
1067
                        break;
1068
                sp = (struct sparc_stackf32 __user *)
1069
                        (current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL);
1070
                if (get_user(arg5, &sp->xxargs[0])) {
1071
                        rval = -EFAULT;
1072
                        kfree(kmbuf);
1073
                        break;
1074
                }
1075
                set_fs(KERNEL_DS);
1076
                rval = sys_msgrcv((int)arg1, (struct msgbuf __user *) kmbuf,
1077
                                  (size_t)arg3,
1078
                                  (long)arg4, (int)arg5);
1079
                set_fs(old_fs);
1080
                if (!rval)
1081
                        rval = sunos_msgbuf_put((struct msgbuf32 __user *)(unsigned long)arg2,
1082
                                                kmbuf, arg3);
1083
                kfree(kmbuf);
1084
                break;
1085
        case 3:
1086
                rval = -EFAULT;
1087
                kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
1088
                                                 GFP_KERNEL);
1089
                if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
1090
                                               kmbuf, arg3))
1091
                        break;
1092
                set_fs(KERNEL_DS);
1093
                rval = sys_msgsnd((int)arg1, (struct msgbuf __user *) kmbuf,
1094
                                  (size_t)arg3, (int)arg4);
1095
                set_fs(old_fs);
1096
                kfree(kmbuf);
1097
                break;
1098
        default:
1099
                rval = -EINVAL;
1100
                break;
1101
        }
1102
        return rval;
1103
}
1104
 
1105
struct shmid_ds32 {
1106
        struct ipc_perm32       shm_perm;
1107
        int                     shm_segsz;
1108
        compat_time_t         shm_atime;
1109
        compat_time_t         shm_dtime;
1110
        compat_time_t         shm_ctime;
1111
        compat_ipc_pid_t    shm_cpid;
1112
        compat_ipc_pid_t    shm_lpid;
1113
        unsigned short          shm_nattch;
1114
};
1115
 
1116
static inline int sunos_shmid_get(struct shmid_ds32 __user *user,
1117
                                  struct shmid_ds *kern)
1118
{
1119
        if (get_user(kern->shm_perm.key, &user->shm_perm.key)           ||
1120
            __get_user(kern->shm_perm.uid, &user->shm_perm.uid)         ||
1121
            __get_user(kern->shm_perm.gid, &user->shm_perm.gid)         ||
1122
            __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid)       ||
1123
            __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid)       ||
1124
            __get_user(kern->shm_segsz, &user->shm_segsz)               ||
1125
            __get_user(kern->shm_atime, &user->shm_atime)               ||
1126
            __get_user(kern->shm_dtime, &user->shm_dtime)               ||
1127
            __get_user(kern->shm_ctime, &user->shm_ctime)               ||
1128
            __get_user(kern->shm_cpid, &user->shm_cpid)                 ||
1129
            __get_user(kern->shm_lpid, &user->shm_lpid)                 ||
1130
            __get_user(kern->shm_nattch, &user->shm_nattch))
1131
                return -EFAULT;
1132
        return 0;
1133
}
1134
 
1135
static inline int sunos_shmid_put(struct shmid_ds32 __user *user,
1136
                                  struct shmid_ds *kern)
1137
{
1138
        if (put_user(kern->shm_perm.key, &user->shm_perm.key)           ||
1139
            __put_user(kern->shm_perm.uid, &user->shm_perm.uid)         ||
1140
            __put_user(kern->shm_perm.gid, &user->shm_perm.gid)         ||
1141
            __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid)       ||
1142
            __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid)       ||
1143
            __put_user(kern->shm_segsz, &user->shm_segsz)               ||
1144
            __put_user(kern->shm_atime, &user->shm_atime)               ||
1145
            __put_user(kern->shm_dtime, &user->shm_dtime)               ||
1146
            __put_user(kern->shm_ctime, &user->shm_ctime)               ||
1147
            __put_user(kern->shm_cpid, &user->shm_cpid)                 ||
1148
            __put_user(kern->shm_lpid, &user->shm_lpid)                 ||
1149
            __put_user(kern->shm_nattch, &user->shm_nattch))
1150
                return -EFAULT;
1151
        return 0;
1152
}
1153
 
1154
asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
1155
{
1156
        struct shmid_ds ksds;
1157
        unsigned long raddr;
1158
        mm_segment_t old_fs = get_fs();
1159
        int rval;
1160
 
1161
        switch(op) {
1162
        case 0:
1163
                /* do_shmat(): attach a shared memory area */
1164
                rval = do_shmat((int)arg1,(char __user *)(unsigned long)arg2,(int)arg3,&raddr);
1165
                if (!rval)
1166
                        rval = (int) raddr;
1167
                break;
1168
        case 1:
1169
                /* sys_shmctl(): modify shared memory area attr. */
1170
                if (!sunos_shmid_get((struct shmid_ds32 __user *)(unsigned long)arg3, &ksds)) {
1171
                        set_fs(KERNEL_DS);
1172
                        rval = sys_shmctl((int) arg1,(int) arg2,
1173
                                          (struct shmid_ds __user *) &ksds);
1174
                        set_fs(old_fs);
1175
                        if (!rval)
1176
                                rval = sunos_shmid_put((struct shmid_ds32 __user *)(unsigned long)arg3,
1177
                                                       &ksds);
1178
                } else
1179
                        rval = -EFAULT;
1180
                break;
1181
        case 2:
1182
                /* sys_shmdt(): detach a shared memory area */
1183
                rval = sys_shmdt((char __user *)(unsigned long)arg1);
1184
                break;
1185
        case 3:
1186
                /* sys_shmget(): get a shared memory area */
1187
                rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
1188
                break;
1189
        default:
1190
                rval = -EINVAL;
1191
                break;
1192
        };
1193
        return rval;
1194
}
1195
 
1196
extern asmlinkage long sparc32_open(const char __user * filename, int flags, int mode);
1197
 
1198
asmlinkage int sunos_open(u32 fname, int flags, int mode)
1199
{
1200
        const char __user *filename = compat_ptr(fname);
1201
 
1202
        return sparc32_open(filename, flags, mode);
1203
}
1204
 
1205
#define SUNOS_EWOULDBLOCK 35
1206
 
1207
/* see the sunos man page read(2v) for an explanation
1208
   of this garbage. We use O_NDELAY to mark
1209
   file descriptors that have been set non-blocking
1210
   using 4.2BSD style calls. (tridge) */
1211
 
1212
static inline int check_nonblock(int ret, int fd)
1213
{
1214
        if (ret == -EAGAIN) {
1215
                struct file * file = fget(fd);
1216
                if (file) {
1217
                        if (file->f_flags & O_NDELAY)
1218
                                ret = -SUNOS_EWOULDBLOCK;
1219
                        fput(file);
1220
                }
1221
        }
1222
        return ret;
1223
}
1224
 
1225
asmlinkage int sunos_read(unsigned int fd, char __user *buf, u32 count)
1226
{
1227
        int ret;
1228
 
1229
        ret = check_nonblock(sys_read(fd, buf, count), fd);
1230
        return ret;
1231
}
1232
 
1233
asmlinkage int sunos_readv(u32 fd, void __user *vector, s32 count)
1234
{
1235
        int ret;
1236
 
1237
        ret = check_nonblock(compat_sys_readv(fd, vector, count), fd);
1238
        return ret;
1239
}
1240
 
1241
asmlinkage int sunos_write(unsigned int fd, char __user *buf, u32 count)
1242
{
1243
        int ret;
1244
 
1245
        ret = check_nonblock(sys_write(fd, buf, count), fd);
1246
        return ret;
1247
}
1248
 
1249
asmlinkage int sunos_writev(u32 fd, void __user *vector, s32 count)
1250
{
1251
        int ret;
1252
 
1253
        ret = check_nonblock(compat_sys_writev(fd, vector, count), fd);
1254
        return ret;
1255
}
1256
 
1257
asmlinkage int sunos_recv(u32 __fd, void __user *ubuf, int size, unsigned flags)
1258
{
1259
        int ret, fd = (int) __fd;
1260
 
1261
        ret = check_nonblock(sys_recv(fd, ubuf, size, flags), fd);
1262
        return ret;
1263
}
1264
 
1265
asmlinkage int sunos_send(u32 __fd, void __user *buff, int len, unsigned flags)
1266
{
1267
        int ret, fd = (int) __fd;
1268
 
1269
        ret = check_nonblock(sys_send(fd, buff, len, flags), fd);
1270
        return ret;
1271
}
1272
 
1273
asmlinkage int sunos_accept(u32 __fd, struct sockaddr __user *sa, int __user *addrlen)
1274
{
1275
        int ret, fd = (int) __fd;
1276
 
1277
        while (1) {
1278
                ret = check_nonblock(sys_accept(fd, sa, addrlen), fd);
1279
                if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
1280
                        break;
1281
        }
1282
        return ret;
1283
}
1284
 
1285
#define SUNOS_SV_INTERRUPT 2
1286
 
1287
asmlinkage int sunos_sigaction (int sig,
1288
                                struct old_sigaction32 __user *act,
1289
                                struct old_sigaction32 __user *oact)
1290
{
1291
        struct k_sigaction new_ka, old_ka;
1292
        int ret;
1293
 
1294
        if (act) {
1295
                compat_old_sigset_t mask;
1296
                u32 u_handler;
1297
 
1298
                if (get_user(u_handler, &act->sa_handler) ||
1299
                    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
1300
                        return -EFAULT;
1301
                new_ka.sa.sa_handler = compat_ptr(u_handler);
1302
                __get_user(mask, &act->sa_mask);
1303
                new_ka.sa.sa_restorer = NULL;
1304
                new_ka.ka_restorer = NULL;
1305
                siginitset(&new_ka.sa.sa_mask, mask);
1306
                new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
1307
        }
1308
 
1309
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1310
 
1311
        if (!ret && oact) {
1312
                old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
1313
                if (put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||
1314
                    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
1315
                        return -EFAULT;
1316
                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
1317
        }
1318
 
1319
        return ret;
1320
}
1321
 
1322
asmlinkage int sunos_setsockopt(u32 __fd, u32 __level, u32 __optname,
1323
                                char __user *optval, u32 __optlen)
1324
{
1325
        int fd = (int) __fd;
1326
        int level = (int) __level;
1327
        int optname = (int) __optname;
1328
        int optlen = (int) __optlen;
1329
        int tr_opt = optname;
1330
        int ret;
1331
 
1332
        if (level == SOL_IP) {
1333
                /* Multicast socketopts (ttl, membership) */
1334
                if (tr_opt >=2 && tr_opt <= 6)
1335
                        tr_opt += 30;
1336
        }
1337
        ret = sys_setsockopt(fd, level, tr_opt,
1338
                             optval, optlen);
1339
        return ret;
1340
}
1341
 
1342
asmlinkage int sunos_getsockopt(u32 __fd, u32 __level, u32 __optname,
1343
                                char __user *optval, int __user *optlen)
1344
{
1345
        int fd = (int) __fd;
1346
        int level = (int) __level;
1347
        int optname = (int) __optname;
1348
        int tr_opt = optname;
1349
        int ret;
1350
 
1351
        if (level == SOL_IP) {
1352
                /* Multicast socketopts (ttl, membership) */
1353
                if (tr_opt >=2 && tr_opt <= 6)
1354
                        tr_opt += 30;
1355
        }
1356
        ret = compat_sys_getsockopt(fd, level, tr_opt,
1357
                                    optval, optlen);
1358
        return ret;
1359
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.