This source file includes following definitions.
- get_sparc_unmapped_area
- sunos_mmap
- sunos_mctl
- sunos_msync
- sunos_brk
- sunos_sbrk
- sunos_sstk
- sunos_vadvise
- sunos_madvise
- sunos_mincore
- sunos_getdtablesize
- sunos_sigblock
- sunos_filldir
- sunos_getdents
- sunos_getdomainname
- sunos_uname
- sunos_nosys
- sunos_fpathconf
- sunos_pathconf
- sunos_select
- sunos_nop
- sunos_nfs_get_server_fd
- get_default
- sunos_nfs_mount
- sunos_mount
- sunos_setpgrp
- sunos_wait4
- sunos_killpg
- sunos_audit
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/types.h>
15 #include <linux/mman.h>
16 #include <linux/errno.h>
17 #include <linux/mm.h>
18 #include <linux/fs.h>
19 #include <linux/resource.h>
20 #include <linux/signal.h>
21 #include <linux/uio.h>
22 #include <linux/utsname.h>
23 #include <linux/fs.h>
24 #include <linux/major.h>
25
26 #include <asm/page.h>
27 #include <asm/pgtable.h>
28 #include <asm/pconf.h>
29
30
31 #include <linux/socket.h>
32 #include <linux/in.h>
33 #include <linux/nfs.h>
34 #include <linux/nfs_mount.h>
35
36
37 #include <linux/time.h>
38 #include <linux/personality.h>
39
40 static unsigned long get_sparc_unmapped_area(unsigned long len)
41 {
42 unsigned long addr;
43 struct vm_area_struct * vmm;
44
45 if (len > TASK_SIZE)
46 return 0;
47 addr = 0xE8000000UL;
48 for (vmm = current->mm->mmap; ; vmm = vmm->vm_next) {
49 if (TASK_SIZE - len < addr)
50 return 0;
51 if (!vmm)
52 return addr;
53 if (addr > vmm->vm_end)
54 continue;
55 if (addr + len > vmm->vm_start) {
56 addr = vmm->vm_end;
57 continue;
58 }
59 return addr;
60 }
61 }
62
63
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 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
73 current->comm);
74 flags &= ~MAP_NORESERVE;
75 }
76 if(!(flags & MAP_ANONYMOUS))
77 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
78 return -EBADF;
79 if(!(flags & MAP_FIXED) && !addr) {
80 addr = get_sparc_unmapped_area(len);
81 if(!addr)
82 return -ENOMEM;
83 }
84
85
86
87
88 if(MAJOR(file->f_inode->i_rdev) == MEM_MAJOR &&
89 MINOR(file->f_inode->i_rdev) == 5) {
90 flags |= MAP_ANONYMOUS;
91 file = 0;
92 }
93 ret_type = flags & _MAP_NEW;
94 flags &= ~_MAP_NEW;
95 retval = do_mmap(file, addr, len, prot, flags, off);
96 if(ret_type)
97 return retval;
98 else
99 return ((retval < KERNBASE) ? 0 : retval);
100 }
101
102
103 asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
104 {
105 printk("%s: Call to sunos_mctl(addr<%08lx>, len<%08lx>, function<%d>, arg<%p>) "
106 "is unsupported\n", current->comm, addr, len, function, arg);
107 return -EAGAIN;
108 }
109
110
111
112
113 asmlinkage int sunos_msync(unsigned long addr, unsigned long len, unsigned long flags)
114 {
115 printk("%s: Call to sunos_msync(addr<%08lx>, len<%08lx>, flags<%08lx>) "
116 "is unsupported\n", current->comm, addr, len, flags);
117 return -EINVAL;
118 }
119
120
121
122
123
124 asmlinkage int sunos_brk(unsigned long brk)
125 {
126 int freepages;
127 unsigned long rlim;
128 unsigned long newbrk, oldbrk;
129
130 if (brk < current->mm->end_code)
131 return -ENOMEM;
132
133 newbrk = PAGE_ALIGN(brk);
134 oldbrk = PAGE_ALIGN(current->mm->brk);
135 if (oldbrk == newbrk) {
136 current->mm->brk = brk;
137 return 0;
138 }
139
140
141
142
143 if (brk <= current->mm->brk) {
144 current->mm->brk = brk;
145 do_munmap(newbrk, oldbrk-newbrk);
146 return 0;
147 }
148
149
150
151 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
152 if (rlim >= RLIM_INFINITY)
153 rlim = ~0;
154 if (brk - current->mm->end_code > rlim)
155 return -ENOMEM;
156
157
158
159
160 if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
161 return -ENOMEM;
162
163
164
165
166
167
168 freepages = buffermem >> 12;
169 freepages += nr_free_pages;
170 freepages += nr_swap_pages;
171 freepages -= MAP_NR(high_memory) >> 4;
172 freepages -= (newbrk-oldbrk) >> 12;
173 if (freepages < 0)
174 return -ENOMEM;
175
176
177
178 current->mm->brk = brk;
179 do_mmap(NULL, oldbrk, newbrk-oldbrk,
180 PROT_READ|PROT_WRITE|PROT_EXEC,
181 MAP_FIXED|MAP_PRIVATE, 0);
182 return 0;
183 }
184
185 asmlinkage unsigned long sunos_sbrk(int increment)
186 {
187 int error;
188
189
190 error = sunos_brk(((int) current->mm->brk) + increment);
191 if(error == 0)
192 return current->mm->brk;
193 else
194 return error;
195 }
196
197
198
199
200
201
202 asmlinkage unsigned long sunos_sstk(int increment)
203 {
204 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
205 current->comm, increment);
206 return -1;
207 }
208
209
210
211
212 #define VA_NORMAL 0
213 #define VA_ABNORMAL 1
214 #define VA_SEQUENTIAL 2
215 #define VA_INVALIDATE 3
216 static char *vstrings[] = {
217 "VA_NORMAL",
218 "VA_ABNORMAL",
219 "VA_SEQUENTIAL",
220 "VA_INVALIDATE",
221 };
222
223 asmlinkage void sunos_vadvise(unsigned long strategy)
224 {
225
226 printk("%s: Advises us to use %s paging strategy\n",
227 current->comm,
228 strategy <= 3 ? vstrings[strategy] : "BOGUS");
229 return;
230 }
231
232
233
234
235 #define MADV_NORMAL 0
236 #define MADV_RANDOM 1
237 #define MADV_SEQUENTIAL 2
238 #define MADV_WILLNEED 3
239 #define MADV_DONTNEED 4
240
241 static char *mstrings[] = {
242 "MADV_NORMAL",
243 "MADV_RANDOM",
244 "MADV_SEQUENTIAL",
245 "MADV_WILLNEED",
246 "MADV_DONTNEED",
247 };
248
249 asmlinkage void sunos_madvise(unsigned long address, unsigned long len,
250 unsigned long strategy)
251 {
252
253 printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
254 current->comm,
255 strategy <= 4 ? mstrings[strategy] : "BOGUS",
256 address, len);
257 return;
258 }
259
260
261
262
263
264
265
266
267
268
269
270 asmlinkage int sunos_mincore(unsigned long addr, unsigned long len, char *array)
271 {
272 pgd_t *pgdp;
273 pmd_t *pmdp;
274 pte_t *ptep;
275 unsigned long limit;
276 int num_pages, pnum;
277
278 if(addr & (PAGE_SIZE - 1))
279 return -EINVAL;
280
281 num_pages = (len / PAGE_SIZE);
282 if(verify_area(VERIFY_WRITE, array, num_pages))
283 return -EFAULT;
284 if((addr >= KERNBASE) || ((addr + len) > KERNBASE))
285 return -ENOMEM;
286
287
288 pnum = 0;
289 for(limit = addr + len; addr < limit; addr += PAGE_SIZE, pnum++) {
290 pgdp = pgd_offset(current->mm, addr);
291 if(pgd_none(*pgdp))
292 return -ENOMEM;
293 pmdp = pmd_offset(pgdp, addr);
294 if(pmd_none(*pmdp))
295 return -ENOMEM;
296 ptep = pte_offset(pmdp, addr);
297 if(pte_none(*ptep))
298 return -ENOMEM;
299
300 array[pnum] = pte_present(*ptep) ? 1 : 0;
301 }
302 return 0;
303 }
304
305
306
307
308
309 asmlinkage long sunos_getdtablesize(void)
310 {
311 return NR_OPEN;
312 }
313 #define _S(nr) (1<<((nr)-1))
314
315 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
316
317 asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
318 {
319 unsigned long old = current->blocked;
320
321 current->blocked |= (blk_mask & _BLOCKABLE);
322 return old;
323 }
324
325
326
327
328 struct sunos_dirent {
329 long d_off;
330 unsigned long d_ino;
331 unsigned short d_reclen;
332 unsigned short d_namlen;
333 char d_name[1];
334 };
335
336 struct sunos_dirent_callback {
337 struct sunos_dirent *curr;
338 struct sunos_dirent *previous;
339 int count;
340 int error;
341 };
342
343 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
344 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
345
346 static int sunos_filldir(void * __buf, const char * name, int namlen,
347 off_t offset, ino_t ino)
348 {
349 struct sunos_dirent * dirent;
350 struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
351 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
352
353 buf->error = -EINVAL;
354 if (reclen > buf->count)
355 return -EINVAL;
356 dirent = buf->previous;
357 if (dirent)
358 put_user(offset, &dirent->d_off);
359 dirent = buf->curr;
360 buf->previous = dirent;
361 put_user(ino, &dirent->d_ino);
362 put_user((strlen(name)), &dirent->d_namlen);
363 put_user(reclen, &dirent->d_reclen);
364 memcpy_tofs(dirent->d_name, name, namlen);
365 put_user(0, dirent->d_name + namlen);
366 ((char *) dirent) += reclen;
367 buf->curr = dirent;
368 buf->count -= reclen;
369 return 0;
370 }
371
372 asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt)
373 {
374 struct file * file;
375 struct sunos_dirent * lastdirent;
376 struct sunos_dirent_callback buf;
377 int error;
378
379 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
380 return -EBADF;
381 if (!file->f_op || !file->f_op->readdir)
382 return -ENOTDIR;
383 if(verify_area(VERIFY_WRITE, dirent, cnt))
384 return -EFAULT;
385 if(cnt < (sizeof(struct sunos_dirent) + 255))
386 return -EINVAL;
387
388 buf.curr = (struct sunos_dirent *) dirent;
389 buf.previous = NULL;
390 buf.count = cnt;
391 buf.error = 0;
392 error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
393 if (error < 0)
394 return error;
395 lastdirent = buf.previous;
396 if (!lastdirent)
397 return buf.error;
398 put_user(file->f_pos, &lastdirent->d_off);
399 return cnt - buf.count;
400 }
401
402 asmlinkage int sunos_getdomainname(char *name, int len)
403 {
404 int error;
405
406 if(len > __NEW_UTS_LEN)
407 return -EFAULT;
408 error = verify_area(VERIFY_WRITE, name, len);
409 if(error)
410 return -EFAULT;
411 memcpy_tofs(name, system_utsname.domainname, len);
412 return 0;
413 }
414
415 struct sunos_utsname {
416 char sname[9];
417 char nname[9];
418 char nnext[56];
419 char rel[9];
420 char ver[9];
421 char mach[9];
422 };
423
424 asmlinkage int sunos_uname(struct sunos_utsname *name)
425 {
426 int error;
427 if(!name)
428 return -EFAULT;
429 error = verify_area(VERIFY_WRITE, name, sizeof *name);
430 if(error)
431 return error;
432 memcpy_tofs(&name->sname[0], &system_utsname.sysname[0],
433 sizeof(name->sname));
434 memcpy_tofs(&name->nname[0], &system_utsname.nodename[0],
435 sizeof(name->nname));
436 name->nname[8] = '\0';
437 memcpy_tofs(&name->nnext[0], &system_utsname.nodename[9],
438 sizeof(name->nnext));
439 memcpy_tofs(&name->rel[0], &system_utsname.release[0],
440 sizeof(name->rel));
441 memcpy_tofs(&name->ver[0], &system_utsname.version[0],
442 sizeof(name->ver));
443 memcpy_tofs(&name->mach[0], &system_utsname.machine[0],
444 sizeof(name->mach));
445 return 0;
446 }
447
448 asmlinkage int sunos_nosys(void)
449 {
450 struct pt_regs *regs;
451
452 regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
453 (PAGE_SIZE - TRACEREG_SZ));
454 current->tss.sig_address = regs->pc;
455 current->tss.sig_desc = regs->u_regs[UREG_G1];
456 send_sig(SIGSYS, current, 1);
457 printk("Process makes ni_syscall number %d, register dump:\n",
458 (int) regs->u_regs[UREG_G1]);
459 show_regs(regs);
460 return -ENOSYS;
461 }
462
463
464
465
466 asmlinkage int sunos_fpathconf(int fd, int name)
467 {
468 switch(name) {
469 case _PCONF_LINK:
470 return LINK_MAX;
471 case _PCONF_CANON:
472 return MAX_CANON;
473 case _PCONF_INPUT:
474 return MAX_INPUT;
475 case _PCONF_NAME:
476 return NAME_MAX;
477 case _PCONF_PATH:
478 return PATH_MAX;
479 case _PCONF_PIPE:
480 return PIPE_BUF;
481 case _PCONF_CHRESTRICT:
482 return 1;
483 case _PCONF_NOTRUNC:
484 return 0;
485 case _PCONF_VDISABLE:
486 return 30;
487 default:
488 return -EINVAL;
489 }
490 }
491
492 asmlinkage int sunos_pathconf(char *path, int name)
493 {
494 return sunos_fpathconf(0, name);
495 }
496
497
498 extern asmlinkage int
499 sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
500
501 asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
502 {
503
504 current->personality |= STICKY_TIMEOUTS;
505 return sys_select (width, inp, outp, exp, tvp);
506 }
507
508 asmlinkage void sunos_nop(void)
509 {
510 return;
511 }
512
513
514 #define SMNT_RDONLY 1
515 #define SMNT_NOSUID 2
516 #define SMNT_NEWTYPE 4
517 #define SMNT_GRPID 8
518 #define SMNT_REMOUNT 16
519 #define SMNT_NOSUB 32
520 #define SMNT_MULTI 64
521 #define SMNT_SYS5 128
522
523 struct ufs_mntargs {
524 char *dev_name;
525 };
526
527 struct lo_mntargs {
528 char *dev_name;
529 };
530
531 struct ext2_mntargs {
532 char *dev_name;
533 };
534
535 struct iso9660_mntargs {
536 char *dev_name;
537 };
538
539 struct minix_mntargs {
540 char *dev_name;
541 };
542
543 struct ext_mntargs {
544 char *dev_name;
545 };
546
547 struct msdos_mntargs {
548 char *dev_name;
549 };
550
551 struct xiafs_mntargs {
552 char *dev_name;
553 };
554
555 struct sunos_fh_t {
556 char fh_data [NFS_FHSIZE];
557 };
558
559 struct sunos_nfs_mount_args {
560 struct sockaddr_in *addr;
561 struct nfs_fh *fh;
562 int flags;
563 int wsize;
564 int rsize;
565 int timeo;
566 int retrans;
567 char *hostname;
568 int acregmin;
569 int acregmax;
570 int acdirmin;
571 int acdirmax;
572 char *netname;
573 };
574
575 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
576
577 extern int do_mount(dev_t, const char *, char *, int, void *);
578 extern dev_t get_unnamed_dev(void);
579 extern void put_unnamed_dev(dev_t);
580
581 extern sys_mount (char * dev_name, char * dir_name, char * type,
582 unsigned long new_flags, void * data);
583
584 extern asmlinkage int
585 sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
586
587 extern asmlinkage int
588 sys_socket(int family, int type, int protocol);
589
590 asmlinkage int
591 sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
592
593
594
595
596
597
598 static int
599 sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
600 {
601 struct sockaddr_in local;
602 struct sockaddr_in server;
603 int try_port;
604 int ret;
605 struct socket *socket;
606 struct inode *inode;
607 struct file *file;
608
609 file = current->files->fd [fd];
610 inode = file->f_inode;
611 if (!inode || !inode->i_sock)
612 return 0;
613
614 socket = &inode->u.socket_i;
615 local.sin_family = AF_INET;
616 local.sin_addr.s_addr = INADDR_ANY;
617
618
619 try_port = 1024;
620 do {
621 local.sin_port = htons (--try_port);
622 ret = socket->ops->bind(socket, (struct sockaddr*)&local,
623 sizeof(local));
624 } while (ret && try_port > (1024 / 2));
625
626 if (ret)
627 return 0;
628
629 server.sin_family = AF_INET;
630 server.sin_addr = addr->sin_addr;
631 server.sin_port = NFS_PORT;
632
633
634 ret = socket->ops->connect (socket, (struct sockaddr *) &server,
635 sizeof (server), file->f_flags);
636 if (ret < 0)
637 return 0;
638 return 1;
639 }
640
641 static int get_default (int value, int def_value)
642 {
643 if (value)
644 return value;
645 else
646 return def_value;
647 }
648
649 asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
650 {
651 int ret = -ENODEV, error;
652 int server_fd;
653 char *the_name;
654 struct nfs_mount_data linux_nfs_mount;
655 struct sunos_nfs_mount_args *sunos_mount = data;
656 dev_t dev;
657 struct pt_regs *regs;
658
659 error = verify_area(VERIFY_READ, data, sizeof (struct sunos_nfs_mount_args));
660 if (error)
661 return error;
662
663
664
665
666
667
668 server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
669 if (server_fd < 0)
670 return -ENXIO;
671
672 if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
673 sys_close (server_fd);
674 return -ENXIO;
675 }
676
677
678 linux_nfs_mount.version = NFS_MOUNT_VERSION;
679 linux_nfs_mount.flags = sunos_mount->flags;
680 linux_nfs_mount.addr = *sunos_mount->addr;
681 linux_nfs_mount.root = *sunos_mount->fh;
682 linux_nfs_mount.fd = server_fd;
683
684 linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192);
685 linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192);
686 linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10);
687 linux_nfs_mount.retrans = sunos_mount->retrans;
688
689 linux_nfs_mount.acregmin = sunos_mount->acregmin;
690 linux_nfs_mount.acregmax = sunos_mount->acregmax;
691 linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
692 linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
693
694 if (getname (sunos_mount->hostname, &the_name))
695 return -EFAULT;
696
697 strncpy (linux_nfs_mount.hostname, the_name, 254);
698 linux_nfs_mount.hostname [255] = 0;
699 putname (the_name);
700
701 dev = get_unnamed_dev ();
702
703 ret = do_mount (dev, dir_name, "nfs", linux_flags, &linux_nfs_mount);
704 if (ret)
705 put_unnamed_dev(dev);
706
707 #if 0
708
709 regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
710 (PAGE_SIZE - TRACEREG_SZ));
711 current->tss.sig_address = regs->pc;
712 current->tss.sig_desc = regs->u_regs[UREG_G1];
713 send_sig(SIGSYS, current, 1);
714 #endif
715 return ret;
716 }
717
718 asmlinkage int
719 sunos_mount(char *type, char *dir, int flags, void *data)
720 {
721 int linux_flags = MS_MGC_MSK;
722 int error;
723 char *dev_fname = 0;
724
725
726 if ((flags & SMNT_NEWTYPE) == 0)
727 return -EINVAL;
728
729
730 if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
731 return -EINVAL;
732
733 if(flags & SMNT_REMOUNT)
734 linux_flags |= MS_REMOUNT;
735 if(flags & SMNT_RDONLY)
736 linux_flags |= MS_RDONLY;
737 if(flags & SMNT_NOSUID)
738 linux_flags |= MS_NOSUID;
739 error = verify_area(VERIFY_READ, type, 16);
740 if(error)
741 return error;
742 if(strcmp(type, "ext2") == 0) {
743 dev_fname = (char *) data;;
744 } else if(strcmp(type, "iso9660") == 0) {
745 dev_fname = (char *) data;
746 } else if(strcmp(type, "minix") == 0) {
747 dev_fname = (char *) data;
748 } else if(strcmp(type, "ext") == 0) {
749 dev_fname = (char *) data;
750 } else if(strcmp(type, "xiafs") == 0) {
751 dev_fname = (char *) data;
752 } else if(strcmp(type, "nfs") == 0) {
753 error = sunos_nfs_mount (dir, flags, data);
754 return error;
755 } else if(strcmp(type, "ufs") == 0) {
756 printk("Warning: UFS filesystem mounts unsupported.\n");
757 return -ENODEV;
758 } else if(strcmp(type, "proc")) {
759 return -ENODEV;
760 }
761 if(error)
762 return error;
763 error = sys_mount(dev_fname, dir, type, linux_flags, NULL);
764 printk("sys_mount(type<%s>, device<%s>) returns %d\n",
765 type, dev_fname, error);
766 return error;
767 }
768
769 extern asmlinkage int sys_setsid(void);
770 extern asmlinkage int sys_setpgid(pid_t, pid_t);
771
772 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
773 {
774
775 if((!pid || pid == current->pid) &&
776 !pgid) {
777 sys_setsid();
778 return 0;
779 } else {
780 return sys_setpgid(pid, pgid);
781 }
782 }
783
784
785 extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
786 asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
787 {
788 return sys_wait4((pid ? pid : -1), stat_addr, options, ru);
789 }
790
791 extern int kill_pg(int, int, int);
792 asmlinkage int sunos_killpg(int pgrp, int sig)
793 {
794 return kill_pg(pgrp, sig, 0);
795 }
796
797 extern asmlinkage sunos_audit ()
798 {
799 printk ("sys_audit\n");
800 return -1;
801 }