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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc/] [kernel/] [sys_sunos.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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