diff options
Diffstat (limited to 'arch/frv/kernel/uaccess.c')
-rw-r--r-- | arch/frv/kernel/uaccess.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c new file mode 100644 index 00000000000..f3fd58a5bc4 --- /dev/null +++ b/arch/frv/kernel/uaccess.c @@ -0,0 +1,95 @@ +/* uaccess.c: userspace access functions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/mm.h> +#include <asm/uaccess.h> + +/*****************************************************************************/ +/* + * copy a null terminated string from userspace + */ +long strncpy_from_user(char *dst, const char *src, long count) +{ + unsigned long max; + char *p, ch; + long err = -EFAULT; + + if (count < 0) + BUG(); + + p = dst; + +#ifndef CONFIG_MMU + if ((unsigned long) src < memory_start) + goto error; +#endif + + if ((unsigned long) src >= get_addr_limit()) + goto error; + + max = get_addr_limit() - (unsigned long) src; + if ((unsigned long) count > max) { + memset(dst + max, 0, count - max); + count = max; + } + + err = 0; + for (; count > 0; count--, p++, src++) { + __get_user_asm(err, ch, src, "ub", "=r"); + if (err < 0) + goto error; + if (!ch) + break; + *p = ch; + } + + err = p - dst; /* return length excluding NUL */ + + error: + if (count > 0) + memset(p, 0, count); /* clear remainder of buffer [security] */ + + return err; +} /* end strncpy_from_user() */ + +/*****************************************************************************/ +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char *src, long count) +{ + const char *p; + long err = 0; + char ch; + + if (count < 0) + BUG(); + +#ifndef CONFIG_MMU + if ((unsigned long) src < memory_start) + return 0; +#endif + + if ((unsigned long) src >= get_addr_limit()) + return 0; + + for (p = src; count > 0; count--, p++) { + __get_user_asm(err, ch, p, "ub", "=r"); + if (err < 0) + return 0; + if (!ch) + break; + } + + return p - src + 1; /* return length including NUL */ +} /* end strnlen_user() */ |