#include "ServerIconExportUpdateProcess.h"
#include <sys/stat.h>
#include <time.h>
#include <AutoDeleter.h>
#include <BufferIO.h>
#include <Catalog.h>
#include <FileIO.h>
#include "DataIOUtils.h"
#include "HaikuDepotConstants.h"
#include "Logger.h"
#include "PackageIconTarRepository.h"
#include "ServerHelper.h"
#include "StandardMetaDataJsonEventListener.h"
#include "StorageUtils.h"
#include "TarArchiveService.h"
#define ENTRY_PATH_METADATA "hicn/info.json"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ServerIconExportUpdateProcess"
class InfoJsonExtractEntryListener : public TarEntryListener
{
public:
InfoJsonExtractEntryListener();
virtual ~InfoJsonExtractEntryListener();
virtual status_t Handle(
const TarArchiveHeader& header,
size_t offset,
BDataIO *data);
BPositionIO& GetInfoJsonData();
private:
BMallocIO fInfoJsonData;
};
InfoJsonExtractEntryListener::InfoJsonExtractEntryListener()
{
}
InfoJsonExtractEntryListener::~InfoJsonExtractEntryListener()
{
}
BPositionIO&
InfoJsonExtractEntryListener::GetInfoJsonData()
{
return fInfoJsonData;
}
status_t
InfoJsonExtractEntryListener::Handle(const TarArchiveHeader& header, size_t offset, BDataIO* data)
{
if (header.Length() > 0 && header.FileName() == ENTRY_PATH_METADATA) {
status_t copyResult = DataIOUtils::CopyAll(&fInfoJsonData, data);
if (copyResult == B_OK) {
HDINFO("[InfoJsonExtractEntryListener] did extract [%s]", ENTRY_PATH_METADATA);
fInfoJsonData.Seek(0, SEEK_SET);
return B_CANCELED;
}
return copyResult;
}
return B_OK;
}
ServerIconExportUpdateProcess::ServerIconExportUpdateProcess(Model* model,
uint32 serverProcessOptions)
:
AbstractSingleFileServerProcess(serverProcessOptions),
fModel(model)
{
}
ServerIconExportUpdateProcess::~ServerIconExportUpdateProcess()
{
}
const char*
ServerIconExportUpdateProcess::Name() const
{
return "ServerIconExportUpdateProcess";
}
const char*
ServerIconExportUpdateProcess::Description() const
{
return B_TRANSLATE("Synchronizing icons");
}
status_t
ServerIconExportUpdateProcess::ProcessLocalData()
{
BPath tarPath;
status_t result = GetLocalPath(tarPath);
if (result == B_OK) {
PackageIconTarRepository* tarRepository = new PackageIconTarRepository(tarPath);
result = tarRepository->Init();
if (result == B_OK)
fModel->SetIconRepository(PackageIconRepositoryRef(tarRepository, true));
else
delete tarRepository;
}
return result;
}
status_t
ServerIconExportUpdateProcess::GetLocalPath(BPath& path) const
{
return StorageUtils::IconTarPath(path);
}
status_t
ServerIconExportUpdateProcess::IfModifiedSinceHeaderValue(BString& headerValue)
{
headerValue.SetTo("");
BPath tarPath;
status_t result = GetLocalPath(tarPath);
if (result == B_OK) {
off_t size;
bool hasFile;
result = StorageUtils::ExistsObject(tarPath, &hasFile, NULL, &size);
if (result == B_OK && (!hasFile || size == 0))
return result;
}
if (result == B_OK) {
BFile* tarIo = new BFile(tarPath.Path(), O_RDONLY);
BBufferIO* bufferTarIo = new BBufferIO(tarIo, 10 * 1024, true);
ObjectDeleter<BBufferIO> tarIoDeleter(bufferTarIo);
InfoJsonExtractEntryListener* extractDataListener = new InfoJsonExtractEntryListener();
ObjectDeleter<InfoJsonExtractEntryListener> extractDataListenerDeleter(extractDataListener);
result = TarArchiveService::ForEachEntry(*bufferTarIo, extractDataListener);
if (result == B_CANCELED) {
result = B_OK;
StandardMetaData metaData;
BString metaDataJsonPath;
GetStandardMetaDataJsonPath(metaDataJsonPath);
StandardMetaDataJsonEventListener parseInfoJsonListener(metaDataJsonPath, metaData);
BPrivate::BJson::Parse(&(extractDataListener->GetInfoJsonData()),
&parseInfoJsonListener);
result = parseInfoJsonListener.ErrorStatus();
if (result == B_OK)
SetIfModifiedSinceHeaderValueFromMetaData(headerValue, metaData);
else
HDERROR("[%s] unable to parse the meta data from the tar file", Name());
} else {
HDERROR("[%s] did not find the metadata [%s] in the tar", Name(), ENTRY_PATH_METADATA);
result = B_BAD_DATA;
}
}
return result;
}
status_t
ServerIconExportUpdateProcess::GetStandardMetaDataPath(BPath& path) const
{
return B_ERROR;
}
void
ServerIconExportUpdateProcess::GetStandardMetaDataJsonPath(BString& jsonPath) const
{
jsonPath.SetTo("$");
}
BString
ServerIconExportUpdateProcess::UrlPathComponent()
{
return "/__pkgicon/all.tar.gz";
}