Skip to content

Commit 037c9e5

Browse files
authored
Merge pull request #119 from bbockelm/fix_posc_autostat
[POSC] Fix implementation of autostat protocol
2 parents ae960e8 + 820897c commit 037c9e5

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

src/Posc.cc

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -568,12 +568,22 @@ int PoscDir::Opendir(const char *path, XrdOucEnv &env) {
568568
}
569569

570570
int PoscDir::Readdir(char *buff, int blen) {
571-
m_stat_avail = false;
572571
while (true) {
573572
auto rc = wrapDF.Readdir(buff, blen);
574573
if (rc) {
574+
if (m_stat_external) {
575+
memset(m_stat_external, '\0', sizeof(*m_stat_external));
576+
}
575577
return rc;
576578
}
579+
// If the auto-stat protocol is supported, then the Readdir will have
580+
// populated the stat buffer. Copy it over to the user-provided one.
581+
// Note that we have our internal `struct stat` to prevent potential
582+
// bugs where ignored / invisible directory entries are leaked out
583+
// to the caller.
584+
if (m_stat_external) {
585+
memcpy(m_stat_external, &m_stat, sizeof(*m_stat_external));
586+
}
577587
if (*buff == '\0') {
578588
return 0;
579589
} else if (!strcmp(buff, ".") || !strcmp(buff, "..")) {
@@ -593,27 +603,21 @@ int PoscDir::Readdir(char *buff, int blen) {
593603
"directory",
594604
path.string().c_str());
595605
}
606+
if (m_stat_external) {
607+
memset(m_stat_external, '\0', sizeof(*m_stat_external));
608+
}
596609
} else {
597610
return 0;
598611
}
599612
}
600613
}
601614

602-
// Returns the struct stat corresponding to the current
603-
// directory entry name.
615+
// Saves the provided pointer to internal memory if the
616+
// wrapped directory supports the "auto stat" protocol.
604617
//
605-
// If `Readdir` required a stat of the path to determine
606-
// if its visible, the cached copy may be served here.
607618
int PoscDir::StatRet(struct stat *buff) {
608-
if (m_stat_avail) {
609-
memcpy(buff, &m_stat, sizeof(m_stat));
610-
return 0;
611-
}
612619
auto rc = wrapDF.StatRet(&m_stat);
613-
if (!rc) {
614-
m_stat_avail = true;
615-
memcpy(buff, &m_stat, sizeof(m_stat));
616-
}
620+
m_stat_external = rc ? nullptr : buff;
617621
return rc;
618622
}
619623

src/Posc.hh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ class PoscDir final : public XrdOssWrapDF {
241241
virtual int Close(long long *retsz = 0) override;
242242

243243
private:
244-
bool m_stat_avail{false};
244+
// The stat object provided by the caller which must be filled during
245+
// the Readdir on success.
246+
struct stat *m_stat_external{nullptr};
245247
struct stat m_stat;
246248
std::unique_ptr<XrdOssDF> m_wrapped;
247249
XrdSysError &m_log;

0 commit comments

Comments
 (0)