patch-2.1.3 linux/fs/namei.c
Next file: linux/fs/proc/base.c
Previous file: linux/fs/buffer.c
Back to the patch index
Back to the overall index
- Lines: 110
- Date:
Wed Oct 9 10:43:24 1996
- Orig file:
v2.1.2/linux/fs/namei.c
- Orig date:
Fri Sep 20 13:17:18 1996
diff -u --recursive --new-file v2.1.2/linux/fs/namei.c linux/fs/namei.c
@@ -21,68 +21,66 @@
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
/*
- * How long a filename can we get from user space?
- * -EFAULT if invalid area
- * 0 if ok (ENAMETOOLONG before EFAULT)
- * >0 EFAULT after xx bytes
- */
-static inline int get_max_filename(unsigned long address)
-{
- struct vm_area_struct * vma;
-
- if (get_fs() == KERNEL_DS)
- return 0;
- vma = find_vma(current->mm, address);
- if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
- return -EFAULT;
- address = vma->vm_end - address;
- if (address > PAGE_SIZE)
- return 0;
- if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
- (vma->vm_next->vm_flags & VM_READ))
- return 0;
- return address;
-}
-
-/*
* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
*
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
*/
-int getname(const char * filename, char **result)
+static inline int do_getname(const char * filename, char *buf)
{
- int i, error;
- unsigned long page;
- char * tmp, c;
+ int error, maxlen = PAGE_SIZE;
+ int c;
- i = get_max_filename((unsigned long) filename);
- if (i < 0)
- return i;
- error = -EFAULT;
- if (!i) {
- error = -ENAMETOOLONG;
- i = PAGE_SIZE;
+ error = -ENAMETOOLONG;
+ if (get_fs() != KERNEL_DS) {
+ error = -EFAULT;
+ if (TASK_SIZE <= (unsigned long) filename)
+ return error;
+ maxlen = TASK_SIZE - (unsigned long) filename;
+ if (maxlen >= PAGE_SIZE) {
+ maxlen = PAGE_SIZE;
+ error = -ENAMETOOLONG;
+ }
}
- c = get_user(filename++);
+
+ c = (unsigned char) get_user(filename++);
if (!c)
return -ENOENT;
- if(!(page = __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- *result = tmp = (char *) page;
- while (--i) {
- *(tmp++) = c;
+
+ while (--maxlen) {
+ *(buf++) = c;
c = get_user(filename++);
if (!c) {
- *tmp = '\0';
+ *buf = '\0';
return 0;
}
}
- free_page(page);
return error;
}
+int getname(const char *filename, char **result)
+{
+ int error;
+ unsigned long page = __get_free_page(GFP_KERNEL);
+
+ error = -ENOMEM;
+ if (page) {
+ error = -EFAULT;
+ if (!exception()) {
+ int retval = do_getname(filename, (char *) page);
+ end_exception();
+ if (!retval) {
+ *result = (char *) page;
+ return 0;
+ }
+ error = retval;
+ }
+ free_page(page);
+ }
+ return error;
+}
+
void putname(char * name)
{
free_page((unsigned long) name);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov