diff --git a/sdbfs/kernel/sdbfs-core.c b/sdbfs/kernel/sdbfs-core.c index e9cf836e3b93e30ce8d57dcda85eca53a3472599..04c3fe097f624792f45f801fc240c291b5b9c499 100644 --- a/sdbfs/kernel/sdbfs-core.c +++ b/sdbfs/kernel/sdbfs-core.c @@ -32,13 +32,11 @@ static int sdbfs_readdir(struct file * filp, int i, j, n; printk("%s\n", __func__); - if (file_off != 0) - return 0; inode = container_of(ino, struct sdbfs_inode, ino); n = be16_to_cpu(inode->s_i.sdb_records) - 1; - /* FIXME: use file_off */ - for (i = 0; i < n; i++) { + + for (i = file_off; i < n; i++) { char s[20]; offset += SDB_SIZE; @@ -71,30 +69,39 @@ static ssize_t sdbfs_read(struct file *f, char __user *buf, size_t count, struct sdbfs_inode *inode; char kbuf[16]; unsigned long start, size; - ssize_t ret; + ssize_t i, done; inode = container_of(ino, struct sdbfs_inode, ino); start = be64_to_cpu(inode->s_d.sdb_component.addr_first); size = be64_to_cpu(inode->s_d.sdb_component.addr_last) + 1 - start; - /* Horribly inefficient, who cares... */ if (*offp > size) return 0; if (*offp + count > size) count = size - *offp; - ret = count; - while (count) { + done = 0; + while (done < count) { + /* Horribly inefficient, just copy a few bytes at a time */ int n = sizeof(kbuf) > count ? count : sizeof(kbuf); /* FIXME: error checking */ - sd->ops->read(sd, start + *offp, kbuf, n); - if (copy_to_user(buf, kbuf, n)) + i = sd->ops->read(sd, start + *offp, kbuf, n); + if (i < 0) { + if (done) + return done; + return i; + } + if (copy_to_user(buf, kbuf, i)) return -EFAULT; - count -= n; - buf += n; - *offp += n; + buf += i; + done += i; + if (i != n) { + /* Partial read: done for this time */ + break; + } } - return ret; + *offp += done; + return done; } static const struct file_operations sdbfs_fops = {