|
@@ -285,147 +285,6 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-struct linux32_dirent {
|
|
|
- u32 d_ino;
|
|
|
- compat_off_t d_off;
|
|
|
- u16 d_reclen;
|
|
|
- char d_name[1];
|
|
|
-};
|
|
|
-
|
|
|
-struct old_linux32_dirent {
|
|
|
- u32 d_ino;
|
|
|
- u32 d_offset;
|
|
|
- u16 d_namlen;
|
|
|
- char d_name[1];
|
|
|
-};
|
|
|
-
|
|
|
-struct getdents32_callback {
|
|
|
- struct linux32_dirent __user * current_dir;
|
|
|
- struct linux32_dirent __user * previous;
|
|
|
- int count;
|
|
|
- int error;
|
|
|
-};
|
|
|
-
|
|
|
-struct readdir32_callback {
|
|
|
- struct old_linux32_dirent __user * dirent;
|
|
|
- int count;
|
|
|
-};
|
|
|
-
|
|
|
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
|
|
|
-static int filldir32 (void *__buf, const char *name, int namlen,
|
|
|
- loff_t offset, u64 ino, unsigned int d_type)
|
|
|
-{
|
|
|
- struct linux32_dirent __user * dirent;
|
|
|
- struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
|
|
|
- int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, 4);
|
|
|
- u32 d_ino;
|
|
|
-
|
|
|
- buf->error = -EINVAL; /* only used if we fail.. */
|
|
|
- if (reclen > buf->count)
|
|
|
- return -EINVAL;
|
|
|
- d_ino = ino;
|
|
|
- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
|
|
|
- return -EOVERFLOW;
|
|
|
- dirent = buf->previous;
|
|
|
- if (dirent)
|
|
|
- put_user(offset, &dirent->d_off);
|
|
|
- dirent = buf->current_dir;
|
|
|
- buf->previous = dirent;
|
|
|
- put_user(d_ino, &dirent->d_ino);
|
|
|
- put_user(reclen, &dirent->d_reclen);
|
|
|
- copy_to_user(dirent->d_name, name, namlen);
|
|
|
- put_user(0, dirent->d_name + namlen);
|
|
|
- dirent = ((void __user *)dirent) + reclen;
|
|
|
- buf->current_dir = dirent;
|
|
|
- buf->count -= reclen;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-asmlinkage long
|
|
|
-sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
|
|
|
-{
|
|
|
- struct file * file;
|
|
|
- struct linux32_dirent __user * lastdirent;
|
|
|
- struct getdents32_callback buf;
|
|
|
- int error;
|
|
|
-
|
|
|
- error = -EFAULT;
|
|
|
- if (!access_ok(VERIFY_WRITE, dirent, count))
|
|
|
- goto out;
|
|
|
-
|
|
|
- error = -EBADF;
|
|
|
- file = fget(fd);
|
|
|
- if (!file)
|
|
|
- goto out;
|
|
|
-
|
|
|
- buf.current_dir = (struct linux32_dirent __user *) dirent;
|
|
|
- buf.previous = NULL;
|
|
|
- buf.count = count;
|
|
|
- buf.error = 0;
|
|
|
-
|
|
|
- error = vfs_readdir(file, filldir32, &buf);
|
|
|
- if (error < 0)
|
|
|
- goto out_putf;
|
|
|
- error = buf.error;
|
|
|
- lastdirent = buf.previous;
|
|
|
- if (lastdirent) {
|
|
|
- if (put_user(file->f_pos, &lastdirent->d_off))
|
|
|
- error = -EFAULT;
|
|
|
- else
|
|
|
- error = count - buf.count;
|
|
|
- }
|
|
|
-
|
|
|
-out_putf:
|
|
|
- fput(file);
|
|
|
-out:
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
-static int fillonedir32(void * __buf, const char * name, int namlen,
|
|
|
- loff_t offset, u64 ino, unsigned int d_type)
|
|
|
-{
|
|
|
- struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
|
|
|
- struct old_linux32_dirent __user * dirent;
|
|
|
- u32 d_ino;
|
|
|
-
|
|
|
- if (buf->count)
|
|
|
- return -EINVAL;
|
|
|
- d_ino = ino;
|
|
|
- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
|
|
|
- return -EOVERFLOW;
|
|
|
- buf->count++;
|
|
|
- dirent = buf->dirent;
|
|
|
- put_user(d_ino, &dirent->d_ino);
|
|
|
- put_user(offset, &dirent->d_offset);
|
|
|
- put_user(namlen, &dirent->d_namlen);
|
|
|
- copy_to_user(dirent->d_name, name, namlen);
|
|
|
- put_user(0, dirent->d_name + namlen);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-asmlinkage long
|
|
|
-sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
|
|
|
-{
|
|
|
- int error;
|
|
|
- struct file * file;
|
|
|
- struct readdir32_callback buf;
|
|
|
-
|
|
|
- error = -EBADF;
|
|
|
- file = fget(fd);
|
|
|
- if (!file)
|
|
|
- goto out;
|
|
|
-
|
|
|
- buf.count = 0;
|
|
|
- buf.dirent = dirent;
|
|
|
-
|
|
|
- error = vfs_readdir(file, fillonedir32, &buf);
|
|
|
- if (error >= 0)
|
|
|
- error = buf.count;
|
|
|
- fput(file);
|
|
|
-out:
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
/*** copied from mips64 ***/
|
|
|
/*
|
|
|
* Ooo, nasty. We need here to frob 32-bit unsigned longs to
|