From 80e500c6efaf6ecb0b89d2c182cfad8925e7b680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Wed, 30 Sep 2015 09:35:17 +0200 Subject: [PATCH] Protected against opendir reinitialization in lownfs-3g Under some condition (probably interference with another process), the directory list gets reinitialized by releasedir() and opendir() at the beginning of a partial buffer. So in readdir() skip to the requested offset. This is a step towards implementing seekdir(). --- src/lowntfs-3g.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index c68a49b7..ec94a33c 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -1190,6 +1190,7 @@ static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, } if (!fill->filled) { /* initial call : build the full list */ + current = (ntfs_fuse_fill_item_t*)NULL; first = (ntfs_fuse_fill_item_t*)ntfs_malloc (sizeof(ntfs_fuse_fill_item_t) + size); if (first) { @@ -1214,12 +1215,23 @@ static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, if (ntfs_inode_close(ni)) set_fuse_error(&err); } - if (!err) - fuse_reply_buf(req, first->buf, - first->off); - /* reply sent, now must exit with no error */ - fill->first = first->next; - free(first); + if (!err) { + off_t loc = 0; + /* + * In some circumstances, the queue gets + * reinitialized by releasedir() + opendir(), + * apparently always on end of partial buffer. + * Files may be missing or duplicated. + */ + while (first + && ((loc < off) || !first->off)) { + loc += first->off; + fill->first = first->next; + free(first); + first = fill->first; + } + current = first; + } } else err = -errno; } else { @@ -1230,6 +1242,8 @@ static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, free(fill->first); fill->first = current; } + } + if (!err) { if (current) { fuse_reply_buf(req, current->buf, current->off); fill->first = current->next;