Skip to content

Commit

Permalink
Merge pull request #65 from rw2/stat-fix
Browse files Browse the repository at this point in the history
Correct handling of `Stat` on pseudo-directories.
  • Loading branch information
bbockelm authored Dec 14, 2024
2 parents d82504a + 6668ca2 commit ab22c54
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 102 deletions.
41 changes: 41 additions & 0 deletions src/S3Commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,47 @@ bool AmazonS3Head::SendRequest() {
return SendS3Request(noPayloadAllowed, 0, true);
}

void AmazonS3Head::parseResponse() {
if (m_parsedResponse) {
return;
}
m_parsedResponse = true;

const std::string &headers = getResultString();
std::string line;
size_t current_newline = 0;
size_t next_newline = std::string::npos;
size_t last_character = headers.size();
while (current_newline != std::string::npos &&
current_newline != last_character - 1) {
next_newline = headers.find("\r\n", current_newline + 2);
line = substring(headers, current_newline + 2, next_newline);

size_t colon = line.find(":");
if (colon != std::string::npos && colon != line.size()) {
auto attr = substring(line, 0, colon);
auto value = substring(line, colon + 1);
trim(value);
toLower(attr);

if (attr == "content-length") {
m_size = std::stol(value);
} else if (attr == "last-modified") {
struct tm t;
char *eos = strptime(value.c_str(), "%a, %d %b %Y %T %Z", &t);
if (eos == &value.c_str()[value.size()]) {
auto epoch = timegm(&t);
if (epoch != -1) {
m_last_modified = epoch;
}
}
}
}

current_newline = next_newline;
}
}

// ---------------------------------------------------------------------------

bool AmazonS3List::SendRequest(const std::string &continuationToken) {
Expand Down
13 changes: 12 additions & 1 deletion src/S3Commands.hh
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,21 @@ class AmazonS3Head final : public AmazonRequest {

virtual bool SendRequest();

off_t getSize() const { return m_size; }
off_t getSize() {
parseResponse();
return m_size;
}
time_t getLastModified() {
parseResponse();
return m_last_modified;
}

private:
void parseResponse();

bool m_parsedResponse{false};
off_t m_size{0};
time_t m_last_modified{0};
};

struct S3ObjectInfo {
Expand Down
61 changes: 17 additions & 44 deletions src/S3File.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ int S3File::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &env) {
if (ai->getS3BucketName().empty()) {
return -EINVAL;
}
if (object == "") {
return -ENOENT;
}

m_ai = *ai;
m_object = object;
Expand Down Expand Up @@ -167,53 +170,23 @@ int S3File::Fstat(struct stat *buff) {
}
}

std::string headers = head.getResultString();

std::string line;
size_t current_newline = 0;
size_t next_newline = std::string::npos;
size_t last_character = headers.size();
while (current_newline != std::string::npos &&
current_newline != last_character - 1) {
next_newline = headers.find("\r\n", current_newline + 2);
line = substring(headers, current_newline + 2, next_newline);

size_t colon = line.find(":");
if (colon != std::string::npos && colon != line.size()) {
std::string attr = substring(line, 0, colon);
std::string value = substring(line, colon + 1);
trim(value);
toLower(attr);

if (attr == "content-length") {
this->content_length = std::stol(value);
} else if (attr == "last-modified") {
struct tm t;
char *eos = strptime(value.c_str(), "%a, %d %b %Y %T %Z", &t);
if (eos == &value.c_str()[value.size()]) {
time_t epoch = timegm(&t);
if (epoch != -1) {
this->last_modified = epoch;
}
}
}
}
content_length = head.getSize();
last_modified = head.getLastModified();

current_newline = next_newline;
if (buff) {
memset(buff, '\0', sizeof(struct stat));
buff->st_mode = 0600 | S_IFREG;
buff->st_nlink = 1;
buff->st_uid = 1;
buff->st_gid = 1;
buff->st_size = content_length;
buff->st_mtime = last_modified;
buff->st_atime = 0;
buff->st_ctime = 0;
buff->st_dev = 0;
buff->st_ino = 0;
}

memset(buff, '\0', sizeof(struct stat));
buff->st_mode = 0600 | S_IFREG;
buff->st_nlink = 1;
buff->st_uid = 1;
buff->st_gid = 1;
buff->st_size = this->content_length;
buff->st_mtime = this->last_modified;
buff->st_atime = 0;
buff->st_ctime = 0;
buff->st_dev = 0;
buff->st_ino = 0;

return 0;
}

Expand Down
Loading

0 comments on commit ab22c54

Please sign in to comment.