diff --git a/configure.ac b/configure.ac index df86ebc..ae9fef2 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,12 @@ AC_ARG_ENABLE([sigterm-handler], ]) AM_CONDITIONAL([SIGTERM_HANDLER], [test x$enable_sigterm_handler = xyes]) +AC_ARG_ENABLE([broken-directory-offsets], + AS_HELP_STRING([--enable-broken-directory-offsets], [handle broken directory offsets, for implementations like FUSE-T]), + [broken_dir_offsets="yes"]) +AS_IF([test x$broken_dir_offsets = xyes], + [AC_DEFINE(SQFS_BROKEN_DIR_OFFSETS, 1, [Handle broken directory offsets])]) + AC_SUBST([sq_decompressors]) AC_SUBST([sq_high_level]) AC_SUBST([sq_low_level]) diff --git a/hl.c b/hl.c index ea65c19..3144eb4 100644 --- a/hl.c +++ b/hl.c @@ -142,13 +142,20 @@ static int sqfs_hl_op_readdir(const char *path, void *buf, sqfs_hl_lookup(&fs, NULL, NULL); inode = (sqfs_inode*)(intptr_t)fi->fh; +#ifdef SQFS_BROKEN_DIR_OFFSETS + offset = 0; +#endif if (sqfs_dir_open(fs, inode, &dir, offset)) return -EINVAL; memset(&st, 0, sizeof(st)); sqfs_dentry_init(&entry, namebuf); while (sqfs_dir_next(fs, &dir, &entry, &err)) { +#ifdef SQFS_BROKEN_DIR_OFFSETS + sqfs_off_t doff = 0; +#else sqfs_off_t doff = sqfs_dentry_next_offset(&entry); +#endif st.st_mode = sqfs_dentry_mode(&entry); if (filler(buf, sqfs_dentry_name(&entry), &st, doff #if FUSE_USE_VERSION >= 30 diff --git a/ll.c b/ll.c index fd328fa..b374b48 100644 --- a/ll.c +++ b/ll.c @@ -172,7 +172,14 @@ void sqfs_ll_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, int err = 0; update_access_time(); - if (sqfs_dir_open(&lli->ll->fs, &lli->inode, &dir, off)) + +#ifdef SQFS_BROKEN_DIR_OFFSETS + off_t dir_offset = 0; +#else + off_t dir_offset = off; +#endif + + if (sqfs_dir_open(&lli->ll->fs, &lli->inode, &dir, dir_offset)) err = EINVAL; if (!err && !(bufpos = buf = malloc(size))) err = ENOMEM; @@ -186,6 +193,15 @@ void sqfs_ll_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, esize = sqfs_ll_add_direntry(req, bufpos, size, sqfs_dentry_name(&entry), &st, sqfs_dentry_next_offset(&entry)); + +#ifdef SQFS_BROKEN_DIR_OFFSETS + /* We couldn't fast-forwards earlier, so manually skip entries instead */ + if (off > 0) { + off -= esize; + continue; + } +#endif + if (esize > size) break;