usercopy.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * User address space access functions.
  3.  *
  4.  * Copyright 1997 Andi Kleen <ak@muc.de>
  5.  * Copyright 1997 Linus Torvalds
  6.  * Copyright 2002 Andi Kleen <ak@suse.de>
  7.  */
  8. #include <asm/uaccess.h>
  9. /*
  10.  * Copy a null terminated string from userspace.
  11.  */
  12. #define __do_strncpy_from_user(dst,src,count,res)    
  13. do {    
  14. long __d0, __d1, __d2;    
  15. __asm__ __volatile__(    
  16. " testq %1,%1n"    
  17. " jz 2fn"    
  18. "0: lodsbn"    
  19. " stosbn"    
  20. " testb %%al,%%aln"    
  21. " jz 1fn"    
  22. " decq %1n"    
  23. " jnz 0bn"    
  24. "1: subq %1,%0n"    
  25. "2:n"    
  26. ".section .fixup,"ax"n"    
  27. "3: movq %5,%0n"    
  28. " jmp 2bn"    
  29. ".previousn"    
  30. ".section __ex_table,"a"n"    
  31. " .align 4n"    
  32. " .quad 0b,3bn"    
  33. ".previous"    
  34. : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),    
  35.   "=&D" (__d2)    
  36. : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) 
  37. : "memory");    
  38. } while (0)
  39. long
  40. __strncpy_from_user(char *dst, const char *src, long count)
  41. {
  42. long res;
  43. __do_strncpy_from_user(dst, src, count, res);
  44. return res;
  45. }
  46. long
  47. strncpy_from_user(char *dst, const char *src, long count)
  48. {
  49. long res = -EFAULT;
  50. if (access_ok(VERIFY_READ, src, 1))
  51. __do_strncpy_from_user(dst, src, count, res);
  52. return res;
  53. }
  54. /*
  55.  * Zero Userspace
  56.  */
  57. unsigned long __clear_user(void *addr, unsigned long size)
  58. {
  59. long __d0;
  60. /* no memory constraint because it doesn't change any memory gcc knows
  61.    about */
  62. asm volatile(
  63. " testq  %[size8],%[size8]n"
  64. " jz     4fn"
  65. "0: movnti %[zero],(%[dst])n"
  66. " addq   %[eight],%[dst]n"
  67. " decl %%ecx ; jnz   0bn"
  68. "4: movq  %[size1],%%rcxn"
  69. " testl %%ecx,%%ecxn"
  70. " jz     2fn"
  71. "1: movb   %b[zero],(%[dst])n"
  72. " incq   %[dst]n"
  73. " decl %%ecx ; jnz  1bn"
  74. "2: sfencen"
  75. ".section .fixup,"ax"n"
  76. "3: lea 0(%[size1],%[size8],8),%[size8]n"
  77. " jmp 2bn"
  78. ".previousn"
  79. ".section __ex_table,"a"n"
  80. "       .align 8n"
  81. " .quad 0b,3bn"
  82. " .quad 1b,2bn"
  83. ".previous"
  84. : [size8] "=c"(size), [dst] "=&D" (__d0)
  85. : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst] "(addr),
  86.   [zero] "r" (0UL), [eight] "r" (8UL));
  87. return size;
  88. }
  89. unsigned long clear_user(void *to, unsigned long n)
  90. {
  91. if (access_ok(VERIFY_WRITE, to, n))
  92. return __clear_user(to, n);
  93. return n;
  94. }
  95. /*
  96.  * Return the size of a string (including the ending 0)
  97.  *
  98.  * Return 0 on exception, a value greater than N if too long
  99.  */
  100. long strnlen_user(const char *s, long n)
  101. {
  102. unsigned long res = 0;
  103. char c;
  104. if (!access_ok(VERIFY_READ, s, n))
  105. return 0;
  106. while (1) {
  107. if (get_user(c, s))
  108. return 0;
  109. if (!c)
  110. return res+1;
  111. if (res>n)
  112. return n+1;
  113. res++;
  114. s++;
  115. }
  116. }