syscall_kern.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  3. * Licensed under the GPL
  4. */
  5. #include "linux/sched.h"
  6. #include "linux/file.h"
  7. #include "linux/smp_lock.h"
  8. #include "linux/mm.h"
  9. #include "linux/utsname.h"
  10. #include "linux/msg.h"
  11. #include "linux/shm.h"
  12. #include "linux/sys.h"
  13. #include "linux/syscalls.h"
  14. #include "linux/unistd.h"
  15. #include "linux/slab.h"
  16. #include "linux/utime.h"
  17. #include "asm/mman.h"
  18. #include "asm/uaccess.h"
  19. #include "asm/ipc.h"
  20. #include "kern_util.h"
  21. #include "user_util.h"
  22. #include "sysdep/syscalls.h"
  23. #include "mode_kern.h"
  24. #include "choose-mode.h"
  25. /* Unlocked, I don't care if this is a bit off */
  26. int nsyscalls = 0;
  27. long sys_fork(void)
  28. {
  29. long ret;
  30. current->thread.forking = 1;
  31. ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
  32. current->thread.forking = 0;
  33. return(ret);
  34. }
  35. long sys_vfork(void)
  36. {
  37. long ret;
  38. current->thread.forking = 1;
  39. ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
  40. NULL);
  41. current->thread.forking = 0;
  42. return(ret);
  43. }
  44. /* common code for old and new mmaps */
  45. long sys_mmap2(unsigned long addr, unsigned long len,
  46. unsigned long prot, unsigned long flags,
  47. unsigned long fd, unsigned long pgoff)
  48. {
  49. long error = -EBADF;
  50. struct file * file = NULL;
  51. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  52. if (!(flags & MAP_ANONYMOUS)) {
  53. file = fget(fd);
  54. if (!file)
  55. goto out;
  56. }
  57. down_write(&current->mm->mmap_sem);
  58. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  59. up_write(&current->mm->mmap_sem);
  60. if (file)
  61. fput(file);
  62. out:
  63. return error;
  64. }
  65. long old_mmap(unsigned long addr, unsigned long len,
  66. unsigned long prot, unsigned long flags,
  67. unsigned long fd, unsigned long offset)
  68. {
  69. long err = -EINVAL;
  70. if (offset & ~PAGE_MASK)
  71. goto out;
  72. err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  73. out:
  74. return err;
  75. }
  76. /*
  77. * sys_pipe() is the normal C calling standard for creating
  78. * a pipe. It's not the way unix traditionally does this, though.
  79. */
  80. long sys_pipe(unsigned long __user * fildes)
  81. {
  82. int fd[2];
  83. long error;
  84. error = do_pipe(fd);
  85. if (!error) {
  86. if (copy_to_user(fildes, fd, sizeof(fd)))
  87. error = -EFAULT;
  88. }
  89. return error;
  90. }
  91. long sys_uname(struct old_utsname * name)
  92. {
  93. long err;
  94. if (!name)
  95. return -EFAULT;
  96. down_read(&uts_sem);
  97. err=copy_to_user(name, &system_utsname, sizeof (*name));
  98. up_read(&uts_sem);
  99. return err?-EFAULT:0;
  100. }
  101. long sys_olduname(struct oldold_utsname * name)
  102. {
  103. long error;
  104. if (!name)
  105. return -EFAULT;
  106. if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
  107. return -EFAULT;
  108. down_read(&uts_sem);
  109. error = __copy_to_user(&name->sysname,&system_utsname.sysname,
  110. __OLD_UTS_LEN);
  111. error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
  112. error |= __copy_to_user(&name->nodename,&system_utsname.nodename,
  113. __OLD_UTS_LEN);
  114. error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
  115. error |= __copy_to_user(&name->release,&system_utsname.release,
  116. __OLD_UTS_LEN);
  117. error |= __put_user(0,name->release+__OLD_UTS_LEN);
  118. error |= __copy_to_user(&name->version,&system_utsname.version,
  119. __OLD_UTS_LEN);
  120. error |= __put_user(0,name->version+__OLD_UTS_LEN);
  121. error |= __copy_to_user(&name->machine,&system_utsname.machine,
  122. __OLD_UTS_LEN);
  123. error |= __put_user(0,name->machine+__OLD_UTS_LEN);
  124. up_read(&uts_sem);
  125. error = error ? -EFAULT : 0;
  126. return error;
  127. }
  128. DEFINE_SPINLOCK(syscall_lock);
  129. static int syscall_index = 0;
  130. int next_syscall_index(int limit)
  131. {
  132. int ret;
  133. spin_lock(&syscall_lock);
  134. ret = syscall_index;
  135. if(++syscall_index == limit)
  136. syscall_index = 0;
  137. spin_unlock(&syscall_lock);
  138. return(ret);
  139. }
  140. /*
  141. * Overrides for Emacs so that we follow Linus's tabbing style.
  142. * Emacs will notice this stuff at the end of the file and automatically
  143. * adjust the settings for this buffer only. This must remain at the end
  144. * of the file.
  145. * ---------------------------------------------------------------------------
  146. * Local variables:
  147. * c-file-style: "linux"
  148. * End:
  149. */