mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
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().
This commit is contained in:
parent
2f373dee56
commit
80e500c6ef
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user