|
@@ -907,97 +907,6 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
|
|
|
|
-
|
|
|
|
-struct compat_getdents_callback64 {
|
|
|
|
- struct dir_context ctx;
|
|
|
|
- struct linux_dirent64 __user *current_dir;
|
|
|
|
- struct linux_dirent64 __user *previous;
|
|
|
|
- int count;
|
|
|
|
- int error;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static int compat_filldir64(struct dir_context *ctx, const char *name,
|
|
|
|
- int namlen, loff_t offset, u64 ino,
|
|
|
|
- unsigned int d_type)
|
|
|
|
-{
|
|
|
|
- struct linux_dirent64 __user *dirent;
|
|
|
|
- struct compat_getdents_callback64 *buf =
|
|
|
|
- container_of(ctx, struct compat_getdents_callback64, ctx);
|
|
|
|
- int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
|
|
|
|
- sizeof(u64));
|
|
|
|
- u64 off;
|
|
|
|
-
|
|
|
|
- buf->error = -EINVAL; /* only used if we fail.. */
|
|
|
|
- if (reclen > buf->count)
|
|
|
|
- return -EINVAL;
|
|
|
|
- dirent = buf->previous;
|
|
|
|
-
|
|
|
|
- if (dirent) {
|
|
|
|
- if (signal_pending(current))
|
|
|
|
- return -EINTR;
|
|
|
|
- if (__put_user_unaligned(offset, &dirent->d_off))
|
|
|
|
- goto efault;
|
|
|
|
- }
|
|
|
|
- dirent = buf->current_dir;
|
|
|
|
- if (__put_user_unaligned(ino, &dirent->d_ino))
|
|
|
|
- goto efault;
|
|
|
|
- off = 0;
|
|
|
|
- if (__put_user_unaligned(off, &dirent->d_off))
|
|
|
|
- goto efault;
|
|
|
|
- if (__put_user(reclen, &dirent->d_reclen))
|
|
|
|
- goto efault;
|
|
|
|
- if (__put_user(d_type, &dirent->d_type))
|
|
|
|
- goto efault;
|
|
|
|
- if (copy_to_user(dirent->d_name, name, namlen))
|
|
|
|
- goto efault;
|
|
|
|
- if (__put_user(0, dirent->d_name + namlen))
|
|
|
|
- goto efault;
|
|
|
|
- buf->previous = dirent;
|
|
|
|
- dirent = (void __user *)dirent + reclen;
|
|
|
|
- buf->current_dir = dirent;
|
|
|
|
- buf->count -= reclen;
|
|
|
|
- return 0;
|
|
|
|
-efault:
|
|
|
|
- buf->error = -EFAULT;
|
|
|
|
- return -EFAULT;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
|
|
|
- struct linux_dirent64 __user *, dirent, unsigned int, count)
|
|
|
|
-{
|
|
|
|
- struct fd f;
|
|
|
|
- struct linux_dirent64 __user * lastdirent;
|
|
|
|
- struct compat_getdents_callback64 buf = {
|
|
|
|
- .ctx.actor = compat_filldir64,
|
|
|
|
- .current_dir = dirent,
|
|
|
|
- .count = count
|
|
|
|
- };
|
|
|
|
- int error;
|
|
|
|
-
|
|
|
|
- if (!access_ok(VERIFY_WRITE, dirent, count))
|
|
|
|
- return -EFAULT;
|
|
|
|
-
|
|
|
|
- f = fdget_pos(fd);
|
|
|
|
- if (!f.file)
|
|
|
|
- return -EBADF;
|
|
|
|
-
|
|
|
|
- error = iterate_dir(f.file, &buf.ctx);
|
|
|
|
- if (error >= 0)
|
|
|
|
- error = buf.error;
|
|
|
|
- lastdirent = buf.previous;
|
|
|
|
- if (lastdirent) {
|
|
|
|
- typeof(lastdirent->d_off) d_off = buf.ctx.pos;
|
|
|
|
- if (__put_user_unaligned(d_off, &lastdirent->d_off))
|
|
|
|
- error = -EFAULT;
|
|
|
|
- else
|
|
|
|
- error = count - buf.count;
|
|
|
|
- }
|
|
|
|
- fdput_pos(f);
|
|
|
|
- return error;
|
|
|
|
-}
|
|
|
|
-#endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Exactly like fs/open.c:sys_open(), except that it doesn't set the
|
|
* Exactly like fs/open.c:sys_open(), except that it doesn't set the
|
|
* O_LARGEFILE flag.
|
|
* O_LARGEFILE flag.
|