Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

copy.c

Go to the documentation of this file.
00001 #ifndef _COPY_C_
00002 #define _COPY_C_
00003 
00004 /* -*- linux-c -*- */
00005 /** @file copy.c
00006  * @brief Functions to copy from user space.
00007  */
00008 
00009 /** @addtogroup copy Functions to copy from user space.
00010  * Functions to copy from user space.
00011  * None of these functions will sleep (for example to allow pages
00012  * to be swapped in). It is possible (although rare) that the data
00013  * in user space will not present and these functions will return an error.
00014  * @{
00015  */
00016 
00017 long _stp_strncpy_from_user(char *dst, const char __user *src, long count);
00018 //static long __stp_strncpy_from_user(char *dst, const char __user *src, long count);
00019 
00020 #if defined (__i386__)
00021 #define __stp_strncpy_from_user(dst,src,count,res)                         \
00022 do {                                                                       \
00023         int __d0, __d1, __d2;                                              \
00024         __asm__ __volatile__(                                              \
00025                 "       testl %1,%1\n"                                     \
00026                 "       jz 2f\n"                                           \
00027                 "0:     lodsb\n"                                           \
00028                 "       stosb\n"                                           \
00029                 "       testb %%al,%%al\n"                                 \
00030                 "       jz 1f\n"                                           \
00031                 "       decl %1\n"                                         \
00032                 "       jnz 0b\n"                                          \
00033                 "1:     subl %1,%0\n"                                      \
00034                 "2:\n"                                                     \
00035                 ".section .fixup,\"ax\"\n"                                 \
00036                 "3:     movl %5,%0\n"                                      \
00037                 "       jmp 2b\n"                                          \
00038                 ".previous\n"                                              \
00039                 ".section __ex_table,\"a\"\n"                              \
00040                 "       .align 4\n"                                        \
00041                 "       .long 0b,3b\n"                                     \
00042                 ".previous"                                                \
00043                 : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
00044                   "=&D" (__d2)                                             \
00045                 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
00046                 : "memory");                                               \
00047 } while (0)
00048 #elif defined (__x86_64__)
00049 #define __stp_strncpy_from_user(dst,src,count,res)                         \
00050 do {                                                                       \
00051         long __d0, __d1, __d2;                                             \
00052         __asm__ __volatile__(                                              \
00053                 "       testq %1,%1\n"                                     \
00054                 "       jz 2f\n"                                           \
00055                 "0:     lodsb\n"                                           \
00056                 "       stosb\n"                                           \
00057                 "       testb %%al,%%al\n"                                 \
00058                 "       jz 1f\n"                                           \
00059                 "       decq %1\n"                                         \
00060                 "       jnz 0b\n"                                          \
00061                 "1:     subq %1,%0\n"                                      \
00062                 "2:\n"                                                     \
00063                 ".section .fixup,\"ax\"\n"                                 \
00064                 "3:     movq %5,%0\n"                                      \
00065                 "       jmp 2b\n"                                          \
00066                 ".previous\n"                                              \
00067                 ".section __ex_table,\"a\"\n"                              \
00068                 "       .align 8\n"                                        \
00069                 "       .quad 0b,3b\n"                                     \
00070                 ".previous"                                                \
00071                 : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
00072                   "=&D" (__d2)                                             \
00073                 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
00074                 : "memory");                                               \
00075 } while (0)
00076 #endif
00077 
00078 /** Copy a NULL-terminated string from userspace.
00079  * On success, returns the length of the string (not including the trailing
00080  * NULL).
00081  *
00082  * If access to userspace fails, returns -EFAULT (some data may have been
00083  * copied).
00084  * @param dst Destination address, in kernel space.  This buffer must be at
00085  *         least <i>count</i> bytes long.
00086  * @param src Source address, in user space.
00087  * @param count Maximum number of bytes to copy, including the trailing NULL.
00088  * 
00089  * If <i>count</i> is smaller than the length of the string, copies 
00090  * <i>count</i> bytes and returns <i>count</i>.
00091  */
00092 
00093 long
00094 _stp_strncpy_from_user(char *dst, const char __user *src, long count)
00095 {
00096         long res;
00097         __stp_strncpy_from_user(dst, src, count, res);
00098         return res;
00099 }
00100 
00101 /** Copy a block of data from user space.
00102  *
00103  * If some data could not be copied, this function will pad the copied
00104  * data to the requested size using zero bytes.
00105 
00106  * @param dst Destination address, in kernel space.
00107  * @param src Source address, in user space.
00108  * @param count Number of bytes to copy.
00109  * @return number of bytes that could not be copied. On success, 
00110  * this will be zero.
00111  *
00112  */
00113 
00114 unsigned long inline
00115 _stp_copy_from_user (char *dst, const char __user *src, unsigned long count)
00116 {
00117         return __copy_from_user_inatomic(dst, src, count);
00118 }
00119 
00120 /** Copy an argv from user space to a List.
00121  *
00122  * @param list A list.
00123  * @param argv Source argv, in user space.
00124  * @return number of elements in <i>list</i>
00125  *
00126  * @b Example:
00127  * @include argv.c
00128  */
00129 
00130 int _stp_copy_argv_from_user (MAP list, char __user *__user *argv)
00131 {
00132         char str[128];
00133         char __user *vstr;
00134         int len;
00135 
00136         if (argv)
00137                 argv++;
00138 
00139         while (argv != NULL) {
00140                 if (get_user (vstr, argv))
00141                         break;
00142                 
00143                 if (vstr == NULL)
00144                         break;
00145                 
00146                 len = _stp_strncpy_from_user(str, vstr, 128);
00147                 str[len] = 0;
00148                 _stp_list_add_str (list, str);
00149                 argv++;
00150         }
00151         return list->num;
00152 }
00153 /** @} */
00154 #endif /* _COPY_C_ */