blob: 84a6058bd1a2541d7bec1d856cd67acc3d4c050b [file] [log] [blame]
// Copyright 2012 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "file_stat.h"
#include <sys/stat.h>
#include <sstream>
#ifndef _WIN32
#include <sys/types.h>
#include <unistd.h>
#else
#include "filetime_win.h"
#endif
#include "counterz.h"
#include "glog/logging.h"
#ifdef _WIN32
namespace {
bool InitFromInfo(const WIN32_FILE_ATTRIBUTE_DATA& info,
devtools_goma::FileStat* file_stat) {
if (info.nFileSizeHigh != 0) {
LOG(ERROR) << "Goma won't handle a file whose size is larger than 4 GB.";
return false;
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
file_stat->is_directory = true;
}
file_stat->size = static_cast<off_t>(info.nFileSizeLow);
file_stat->mtime =
absl::ToTimeT(
devtools_goma::ConvertFiletimeToAbslTime(info.ftLastWriteTime));
return true;
}
} // namespace
#endif
namespace devtools_goma {
const off_t FileStat::kInvalidFileSize = -1;
FileStat::FileStat(const string& filename)
: mtime(0), size(kInvalidFileSize), is_directory(false) {
GOMA_COUNTERZ("FileStat");
#ifndef _WIN32
struct stat stat_buf;
if (stat(filename.c_str(), &stat_buf) == 0) {
InitFromStat(stat_buf);
}
#else
WIN32_FILE_ATTRIBUTE_DATA fileinfo;
if (GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
&fileinfo)) {
if (!InitFromInfo(fileinfo, this)) {
LOG(WARNING) << "Error in init file id."
<< " filename=" << filename;
}
}
#endif
}
#ifndef _WIN32
void FileStat::InitFromStat(const struct stat& stat_buf) {
mtime = stat_buf.st_mtime;
size = stat_buf.st_size;
is_directory = S_ISDIR(stat_buf.st_mode);
}
#endif
bool FileStat::IsValid() const {
return size != kInvalidFileSize;
}
bool FileStat::CanBeNewerThan(const FileStat& old, time_t last_checked) const {
// If mtime >= last_checked - 1, the file might be updated within
// the same second. We need to re-check the file for this case, too.
// The minus one is for VMs, where mtime can delay 1 second.
return mtime >= last_checked - 1 || *this != old;
}
std::string FileStat::DebugString() const {
std::stringstream ss;
ss << "{";
ss << " mtime=" << mtime;
ss << " size=" << size;
ss << " is_directory=" << is_directory;
ss << "}";
return ss.str();
}
std::ostream& operator<<(std::ostream& os, const FileStat& stat) {
return os << stat.DebugString();
}
} // namespace devtools_goma