root/src/kits/package/FetchUtils.cpp
/*
 * Copyright 2020, Haiku, Inc. All Rights Reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Stephan Aßmus <superstippi@gmx.de>
 */


#include "FetchUtils.h"
#include "string.h"

#include <Entry.h>
#include <Node.h>
#include <TypeConstants.h>

namespace BPackageKit {

namespace BPrivate {


#define DL_COMPLETE_ATTR "Meta:DownloadCompleted"


/*static*/ bool
FetchUtils::IsDownloadCompleted(const char* path)
{
        BEntry entry(path, true);
        BNode node(&entry);
        return IsDownloadCompleted(node);
}


/*static*/ bool
FetchUtils::IsDownloadCompleted(const BNode& node)
{
    bool isComplete;
    status_t status = _GetAttribute(node, DL_COMPLETE_ATTR,
        B_BOOL_TYPE, &isComplete, sizeof(isComplete));
    if (status != B_OK) {
        // Most likely cause is that the attribute was not written,
        // for example by previous versions of the Package Kit.
        // Worst outcome of assuming a partial download should be
        // a no-op range request.
        isComplete = false;
    }
    return isComplete;
}


/*static*/ status_t
FetchUtils::MarkDownloadComplete(BNode& node)
{
    bool isComplete = true;
    return _SetAttribute(node, DL_COMPLETE_ATTR,
        B_BOOL_TYPE, &isComplete, sizeof(isComplete));
}


/*static*/ status_t
FetchUtils::SetFileType(BNode& node, const char* type)
{
        return _SetAttribute(node, "BEOS:TYPE",
        B_MIME_STRING_TYPE, type, strlen(type) + 1);
}

status_t
FetchUtils::_SetAttribute(BNode& node, const char* attrName,
    type_code type, const void* data, size_t size)
{
        if (node.InitCheck() != B_OK)
                return node.InitCheck();

        ssize_t written = node.WriteAttr(attrName, type, 0, data, size);
        if (written != (ssize_t)size) {
                if (written < 0)
                        return (status_t)written;
                return B_IO_ERROR;
        }
        return B_OK;
}


status_t
FetchUtils::_GetAttribute(const BNode& node, const char* attrName,
    type_code type, void* data, size_t size)
{
        if (node.InitCheck() != B_OK)
                return node.InitCheck();

        ssize_t read = node.ReadAttr(attrName, type, 0, data, size);
        if (read != (ssize_t)size) {
                if (read < 0)
                        return (status_t)read;
                return B_IO_ERROR;
        }
        return B_OK;
}


}       // namespace BPrivate

}       // namespace BPackageKit