patch-2.1.5 linux/fs/namei.c
Next file: linux/include/asm-alpha/segment.h
Previous file: linux/fs/ext2/symlink.c
Back to the patch index
Back to the overall index
- Lines: 97
- Date:
Fri Oct 18 14:45:57 1996
- Orig file:
v2.1.4/linux/fs/namei.c
- Orig date:
Wed Oct 16 10:48:28 1996
diff -u --recursive --new-file v2.1.4/linux/fs/namei.c linux/fs/namei.c
@@ -21,66 +21,47 @@
#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).
*/
+static inline int do_getname(const char *filename, char *page)
+{
+ int retval;
+ unsigned long len = PAGE_SIZE;
+
+ if ((unsigned long) filename >= TASK_SIZE) {
+ if (get_fs() != KERNEL_DS)
+ return -EFAULT;
+ } else if (TASK_SIZE - (unsigned long) filename < PAGE_SIZE)
+ len = TASK_SIZE - (unsigned long) filename;
+
+ retval = strncpy_from_user((char *)page, filename, len);
+ if (retval > 0) {
+ if (retval < len)
+ return 0;
+ return -ENAMETOOLONG;
+ } else if (!retval)
+ retval = -ENOENT;
+ return retval;
+}
+
int getname(const char * filename, char **result)
{
- int i, error;
unsigned long page;
- char * tmp, c;
+ int retval;
- i = get_max_filename((unsigned long) filename);
- if (i < 0)
- return i;
- error = -EFAULT;
- if (!i) {
- error = -ENAMETOOLONG;
- i = PAGE_SIZE;
- }
- get_user(c, filename++);
- if (!c)
- return -ENOENT;
- if(!(page = __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- *result = tmp = (char *) page;
- while (--i) {
- *(tmp++) = c;
- get_user(c, filename++);
- if (!c) {
- *tmp = '\0';
- return 0;
- }
+ page = __get_free_page(GFP_KERNEL);
+ retval = -ENOMEM;
+ if (page) {
+ *result = (char *)page;
+ retval = do_getname(filename, (char *) page);
+ if (retval < 0)
+ free_page(page);
}
- free_page(page);
- return error;
+ return retval;
}
void putname(char * name)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov