@@ -19,7 +19,8 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
unsigned long p = *ppos;
void *src;
int err = 0;
- unsigned long total_size;
+ unsigned long total_size, c;
+ ssize_t ret;
if (info->state != FBINFO_STATE_RUNNING)
return -EPERM;
@@ -43,13 +44,14 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (copy_to_user(buf, src, count))
+ c = copy_to_user(buf, src, count);
+ if (c)
err = -EFAULT;
+ ret = count - c;
- if (!err)
- *ppos += count;
+ *ppos += ret;
- return (err) ? err : count;
+ return ret ? ret : err;
}
EXPORT_SYMBOL_GPL(fb_sys_read);
@@ -59,7 +61,8 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
unsigned long p = *ppos;
void *dst;
int err = 0;
- unsigned long total_size;
+ unsigned long total_size, c;
+ size_t ret;
if (info->state != FBINFO_STATE_RUNNING)
return -EPERM;
@@ -89,13 +92,14 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (copy_from_user(dst, buf, count))
+ c = copy_from_user(dst, buf, count);
+ if (c)
err = -EFAULT;
+ ret = count - c;
- if (!err)
- *ppos += count;
+ *ppos += ret;
- return (err) ? err : count;
+ return ret ? ret : err;
}
EXPORT_SYMBOL_GPL(fb_sys_write);
@@ -766,7 +766,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
u8 *buffer, *dst;
u8 __iomem *src;
int c, cnt = 0, err = 0;
- unsigned long total_size;
+ unsigned long total_size, trailing;
if (!info || ! info->screen_base)
return -ENODEV;
@@ -808,10 +808,13 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
dst += c;
src += c;
- if (copy_to_user(buf, buffer, c)) {
+ trailing = copy_to_user(buf, buffer, c);
+ if (trailing == c) {
err = -EFAULT;
break;
}
+ c -= trailing;
+
*ppos += c;
buf += c;
cnt += c;
@@ -820,7 +823,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
kfree(buffer);
- return (err) ? err : cnt;
+ return cnt ? cnt : err;
}
static ssize_t
@@ -831,7 +834,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
u8 *buffer, *src;
u8 __iomem *dst;
int c, cnt = 0, err = 0;
- unsigned long total_size;
+ unsigned long total_size, trailing;
if (!info || !info->screen_base)
return -ENODEV;
@@ -876,10 +879,12 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
src = buffer;
- if (copy_from_user(src, buf, c)) {
+ trailing = copy_from_user(src, buf, c);
+ if (trailing == c) {
err = -EFAULT;
break;
}
+ c -= trailing;
fb_memcpy_tofb(dst, src, c);
dst += c;