* refactored PackageWriter(Impl) to no longer print anything itself,
but publish that info through a BPackageWriterListener * adjusted 'package create' to print a package summary by default and more verbose info upon request. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40332 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <package/hpkg/ErrorOutput.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
@@ -20,9 +22,32 @@ namespace BPrivate {
|
||||
using BPrivate::PackageWriterImpl;
|
||||
|
||||
|
||||
class BPackageWriterListener : public BErrorOutput {
|
||||
public:
|
||||
virtual void PrintErrorVarArgs(const char* format,
|
||||
va_list args) = 0;
|
||||
|
||||
virtual void OnEntryAdded(const char* path) = 0;
|
||||
|
||||
virtual void OnTOCSizeInfo(
|
||||
uint64 uncompressedAttributeTypesSize,
|
||||
uint64 uncompressedStringsSize,
|
||||
uint64 uncompressedMainSize,
|
||||
uint64 uncompressedTOCSize) = 0;
|
||||
virtual void OnPackageAttributesSizeInfo(
|
||||
uint32 uncompressedSize) = 0;
|
||||
virtual void OnPackageSizeInfo(uint32 headerSize,
|
||||
uint64 heapSize, uint64 tocSize,
|
||||
uint32 packageAttributesSize,
|
||||
uint64 totalSize) = 0;
|
||||
};
|
||||
|
||||
|
||||
class BPackageWriter {
|
||||
public:
|
||||
BPackageWriter();
|
||||
public:
|
||||
BPackageWriter(
|
||||
BPackageWriterListener* listener);
|
||||
~BPackageWriter();
|
||||
|
||||
status_t Init(const char* fileName);
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
#include <util/DoublyLinkedList.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include <package/PackageInfo.h>
|
||||
#include <package/hpkg/PackageWriter.h>
|
||||
#include <package/hpkg/Strings.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
class BPackageInfo;
|
||||
|
||||
|
||||
namespace BHPKG {
|
||||
|
||||
|
||||
class BDataReader;
|
||||
class BErrorOutput;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -31,7 +31,8 @@ struct hpkg_header;
|
||||
|
||||
class PackageWriterImpl {
|
||||
public:
|
||||
PackageWriterImpl();
|
||||
PackageWriterImpl(
|
||||
BPackageWriterListener* listener);
|
||||
~PackageWriterImpl();
|
||||
|
||||
status_t Init(const char* fileName);
|
||||
@@ -49,6 +50,7 @@ private:
|
||||
struct DataWriter;
|
||||
struct DummyDataWriter;
|
||||
struct FDDataWriter;
|
||||
struct SubPathAdder;
|
||||
struct ZlibDataWriter;
|
||||
|
||||
typedef BOpenHashTable<AttributeTypeHashDefinition>
|
||||
@@ -86,7 +88,7 @@ private:
|
||||
off_t offset);
|
||||
|
||||
void _AddEntry(int dirFD, Entry* entry,
|
||||
const char* fileName);
|
||||
const char* fileName, char* pathBuffer);
|
||||
|
||||
Attribute* _AddAttribute(const char* attributeName,
|
||||
const AttributeValue& value);
|
||||
@@ -114,6 +116,8 @@ private:
|
||||
uint64& _compressedSize);
|
||||
|
||||
private:
|
||||
BPackageWriterListener* fListener;
|
||||
|
||||
const char* fFileName;
|
||||
int fFD;
|
||||
bool fFinished;
|
||||
@@ -122,6 +126,8 @@ private:
|
||||
void* fDataBuffer;
|
||||
size_t fDataBufferSize;
|
||||
|
||||
BPackageInfo fPackageInfo;
|
||||
|
||||
DataWriter* fDataWriter;
|
||||
|
||||
Entry* fRootEntry;
|
||||
|
||||
@@ -18,25 +18,99 @@
|
||||
#include <package/hpkg/PackageWriter.h>
|
||||
|
||||
#include "package.h"
|
||||
#include "StandardErrorOutput.h"
|
||||
|
||||
|
||||
using BPackageKit::BPackageInfo;
|
||||
using BPackageKit::BHPKG::BPackageWriterListener;
|
||||
using BPackageKit::BHPKG::BPackageWriter;
|
||||
|
||||
|
||||
class PackageWriterListener : public BPackageWriterListener {
|
||||
public:
|
||||
PackageWriterListener(bool verbose, bool quiet)
|
||||
: fVerbose(verbose), fQuiet(quiet)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void PrintErrorVarArgs(const char* format, va_list args)
|
||||
{
|
||||
vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
virtual void OnEntryAdded(const char* path)
|
||||
{
|
||||
if (fQuiet || !fVerbose)
|
||||
return;
|
||||
|
||||
printf("\t%s\n", path);
|
||||
}
|
||||
|
||||
virtual void OnTOCSizeInfo(uint64 uncompressedAttributeTypesSize,
|
||||
uint64 uncompressedStringsSize, uint64 uncompressedMainSize,
|
||||
uint64 uncompressedTOCSize)
|
||||
{
|
||||
if (fQuiet || !fVerbose)
|
||||
return;
|
||||
|
||||
printf("----- TOC Info -----\n");
|
||||
printf("attribute types size: %10llu (uncompressed)\n",
|
||||
uncompressedAttributeTypesSize);
|
||||
printf("cached strings size: %10llu (uncompressed)\n",
|
||||
uncompressedStringsSize);
|
||||
printf("TOC main size: %10llu (uncompressed)\n",
|
||||
uncompressedMainSize);
|
||||
printf("total TOC size: %10llu (uncompressed)\n",
|
||||
uncompressedTOCSize);
|
||||
}
|
||||
|
||||
virtual void OnPackageAttributesSizeInfo(uint32 uncompressedSize)
|
||||
{
|
||||
if (fQuiet || !fVerbose)
|
||||
return;
|
||||
|
||||
printf("----- Package Attribute Info -----\n");
|
||||
printf("package attributes size: %10ld (uncompressed)\n",
|
||||
uncompressedSize);
|
||||
}
|
||||
|
||||
virtual void OnPackageSizeInfo(uint32 headerSize, uint64 heapSize,
|
||||
uint64 tocSize, uint32 packageAttributesSize, uint64 totalSize)
|
||||
{
|
||||
if (fQuiet)
|
||||
return;
|
||||
|
||||
printf("----- Package Info -----\n");
|
||||
printf("header size: %10lu\n", headerSize);
|
||||
printf("heap size: %10lld\n", heapSize);
|
||||
printf("TOC size: %10lld\n", tocSize);
|
||||
printf("package attributes size: %10ld\n", packageAttributesSize);
|
||||
printf("total size: %10lld\n", totalSize);
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
bool fVerbose;
|
||||
bool fQuiet;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
command_create(int argc, const char* const* argv)
|
||||
{
|
||||
const char* changeToDirectory = NULL;
|
||||
bool quiet = false;
|
||||
bool verbose = false;
|
||||
|
||||
while (true) {
|
||||
static struct option sLongOptions[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "quiet", no_argument, 0, 'q' },
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "+C:h", sLongOptions, NULL);
|
||||
int c = getopt_long(argc, (char**)argv, "+C:hqv", sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
@@ -49,6 +123,14 @@ command_create(int argc, const char* const* argv)
|
||||
print_usage_and_exit(false);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage_and_exit(true);
|
||||
break;
|
||||
@@ -65,27 +147,27 @@ command_create(int argc, const char* const* argv)
|
||||
int fileNameCount = argc - optind;
|
||||
|
||||
// create package
|
||||
BPackageWriter packageWriter;
|
||||
status_t error = packageWriter.Init(packageFileName);
|
||||
printf("Init(): %s\n", strerror(error));
|
||||
if (error != B_OK)
|
||||
PackageWriterListener listener(verbose, quiet);
|
||||
BPackageWriter packageWriter(&listener);
|
||||
status_t result = packageWriter.Init(packageFileName);
|
||||
if (result != B_OK)
|
||||
return 1;
|
||||
|
||||
// change directory, if requested
|
||||
if (changeToDirectory != NULL) {
|
||||
if (chdir(changeToDirectory) != 0) {
|
||||
fprintf(stderr, "Error: Failed to change the current working "
|
||||
"directory to \"%s\": %s\n", changeToDirectory,
|
||||
strerror(errno));
|
||||
listener.PrintError(
|
||||
"Error: Failed to change the current working directory to "
|
||||
"\"%s\": %s\n", changeToDirectory, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// add files
|
||||
for (int i = 0; i < fileNameCount; i++) {
|
||||
if (strcmp(fileNames[i], ".") == 0) {
|
||||
DIR* dir = opendir (".");
|
||||
DIR* dir = opendir(".");
|
||||
if (dir == NULL) {
|
||||
fprintf(stderr, "Error: Failed to opendir '.': %s\n",
|
||||
listener.PrintError("Error: Failed to opendir '.': %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
@@ -94,26 +176,26 @@ printf("Init(): %s\n", strerror(error));
|
||||
|| strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
error = packageWriter.AddEntry(entry->d_name);
|
||||
printf("AddEntry(\"%s\"): %s\n", entry->d_name, strerror(error));
|
||||
if (error != B_OK)
|
||||
result = packageWriter.AddEntry(entry->d_name);
|
||||
if (result != B_OK)
|
||||
return 1;
|
||||
}
|
||||
closedir (dir);
|
||||
closedir(dir);
|
||||
|
||||
} else {
|
||||
error = packageWriter.AddEntry(fileNames[i]);
|
||||
printf("AddEntry(\"%s\"): %s\n", fileNames[i], strerror(error));
|
||||
if (error != B_OK)
|
||||
result = packageWriter.AddEntry(fileNames[i]);
|
||||
if (result != B_OK)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// write the package
|
||||
error = packageWriter.Finish();
|
||||
printf("Finish(): %s\n", strerror(error));
|
||||
if (error != B_OK)
|
||||
result = packageWriter.Finish();
|
||||
if (result != B_OK)
|
||||
return 1;
|
||||
|
||||
if (verbose)
|
||||
printf("\nsuccessfully created package '%s'\n", packageFileName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace BPackageKit {
|
||||
namespace BHPKG {
|
||||
|
||||
|
||||
BPackageWriter::BPackageWriter()
|
||||
BPackageWriter::BPackageWriter(BPackageWriterListener* listener)
|
||||
:
|
||||
fImpl(new (std::nothrow) PackageWriterImpl())
|
||||
fImpl(new (std::nothrow) PackageWriterImpl(listener))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <new>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <Entry.h>
|
||||
#include <fs_attr.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
@@ -301,7 +302,6 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
||||
fNameLength(nameLength),
|
||||
fIsImplicit(isImplicit)
|
||||
{
|
||||
printf("%p->Entry::Entry(\"%s\", %lu, %d)\n", this, name, nameLength, isImplicit);
|
||||
}
|
||||
|
||||
~Entry()
|
||||
@@ -431,10 +431,11 @@ struct PackageWriterImpl::DummyDataWriter : DataWriter {
|
||||
|
||||
|
||||
struct PackageWriterImpl::FDDataWriter : DataWriter {
|
||||
FDDataWriter(int fd, off_t offset)
|
||||
FDDataWriter(int fd, off_t offset, BPackageWriterListener* listener)
|
||||
:
|
||||
fFD(fd),
|
||||
fOffset(offset)
|
||||
fOffset(offset),
|
||||
fListener(listener)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -442,13 +443,15 @@ struct PackageWriterImpl::FDDataWriter : DataWriter {
|
||||
{
|
||||
ssize_t bytesWritten = pwrite(fFD, buffer, size, fOffset);
|
||||
if (bytesWritten < 0) {
|
||||
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write data: %s\n",
|
||||
fListener->PrintError(
|
||||
"_WriteBuffer(%p, %lu) failed to write data: %s\n",
|
||||
buffer, size, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
if ((size_t)bytesWritten != size) {
|
||||
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write all data\n",
|
||||
buffer, size);
|
||||
fListener->PrintError(
|
||||
"_WriteBuffer(%p, %lu) failed to write all data\n", buffer,
|
||||
size);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -463,11 +466,31 @@ struct PackageWriterImpl::FDDataWriter : DataWriter {
|
||||
}
|
||||
|
||||
private:
|
||||
int fFD;
|
||||
off_t fOffset;
|
||||
int fFD;
|
||||
off_t fOffset;
|
||||
BPackageWriterListener* fListener;
|
||||
};
|
||||
|
||||
|
||||
struct PackageWriterImpl::SubPathAdder {
|
||||
SubPathAdder(char* pathBuffer, const char* subPath)
|
||||
: fOriginalPathEnd(pathBuffer + strlen(pathBuffer))
|
||||
{
|
||||
strcat(pathBuffer, "/");
|
||||
strcat(pathBuffer, subPath);
|
||||
}
|
||||
|
||||
~SubPathAdder()
|
||||
{
|
||||
*fOriginalPathEnd = '\0';
|
||||
}
|
||||
private:
|
||||
char* fOriginalPathEnd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct PackageWriterImpl::ZlibDataWriter : DataWriter, private BDataOutput {
|
||||
ZlibDataWriter(DataWriter* dataWriter)
|
||||
:
|
||||
@@ -542,8 +565,9 @@ PackageWriterImpl::_AddAttribute(const char* attributeName, Type value)
|
||||
// #pragma mark - PackageWriterImpl
|
||||
|
||||
|
||||
PackageWriterImpl::PackageWriterImpl()
|
||||
PackageWriterImpl::PackageWriterImpl(BPackageWriterListener* listener)
|
||||
:
|
||||
fListener(listener),
|
||||
fFileName(NULL),
|
||||
fFD(-1),
|
||||
fFinished(false),
|
||||
@@ -600,7 +624,7 @@ PackageWriterImpl::Init(const char* fileName)
|
||||
} catch (status_t error) {
|
||||
return error;
|
||||
} catch (std::bad_alloc) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
fListener->PrintError("Out of memory!\n");
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -610,11 +634,29 @@ status_t
|
||||
PackageWriterImpl::AddEntry(const char* fileName)
|
||||
{
|
||||
try {
|
||||
// if it's ".PackageInfo", parse it
|
||||
if (strcmp(fileName, B_HPKG_PACKAGE_INFO_FILE_NAME) == 0) {
|
||||
struct ErrorListener : public BPackageInfo::ParseErrorListener {
|
||||
ErrorListener(BPackageWriterListener* _listener)
|
||||
: listener(_listener) {}
|
||||
virtual void OnError(const BString& msg, int line, int col) {
|
||||
listener->PrintError("Parse error in %s(%d:%d) -> %s\n",
|
||||
B_HPKG_PACKAGE_INFO_FILE_NAME, line, col, msg.String());
|
||||
}
|
||||
BPackageWriterListener* listener;
|
||||
} errorListener(fListener);
|
||||
BEntry packageInfoEntry(fileName);
|
||||
status_t result = fPackageInfo.ReadFromConfigFile(packageInfoEntry,
|
||||
&errorListener);
|
||||
if (result != B_OK || (result = fPackageInfo.InitCheck()) != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
return _RegisterEntry(fileName);
|
||||
} catch (status_t error) {
|
||||
return error;
|
||||
} catch (std::bad_alloc) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
fListener->PrintError("Out of memory!\n");
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -624,11 +666,16 @@ status_t
|
||||
PackageWriterImpl::Finish()
|
||||
{
|
||||
try {
|
||||
if (fPackageInfo.InitCheck() != B_OK) {
|
||||
fListener->PrintError("No package-info file found (%s)!\n",
|
||||
B_HPKG_PACKAGE_INFO_FILE_NAME);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
return _Finish();
|
||||
} catch (status_t error) {
|
||||
return error;
|
||||
} catch (std::bad_alloc) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
fListener->PrintError("Out of memory!\n");
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -659,7 +706,7 @@ PackageWriterImpl::_Init(const char* fileName)
|
||||
fFD = open(fileName, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fFD < 0) {
|
||||
fprintf(stderr, "Error: Failed to open package file \"%s\": %s\n",
|
||||
fListener->PrintError("Failed to open package file \"%s\": %s\n",
|
||||
fileName, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
@@ -680,11 +727,12 @@ PackageWriterImpl::_Finish()
|
||||
// write entries
|
||||
for (EntryList::ConstIterator it = fRootEntry->ChildIterator();
|
||||
Entry* entry = it.Next();) {
|
||||
_AddEntry(AT_FDCWD, entry, entry->Name());
|
||||
char pathBuffer[B_PATH_NAME_LENGTH];
|
||||
pathBuffer[0] = '\0';
|
||||
_AddEntry(AT_FDCWD, entry, entry->Name(), pathBuffer);
|
||||
}
|
||||
|
||||
printf("header size: %lu\n", sizeof(hpkg_header));
|
||||
printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
|
||||
off_t heapSize = fHeapEnd - sizeof(hpkg_header);
|
||||
|
||||
hpkg_header header;
|
||||
|
||||
@@ -693,7 +741,11 @@ printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
|
||||
_WritePackageAttributes(header);
|
||||
|
||||
off_t totalSize = fHeapEnd;
|
||||
printf("total size: %lld\n", totalSize);
|
||||
|
||||
fListener->OnPackageSizeInfo(sizeof(hpkg_header), heapSize,
|
||||
B_BENDIAN_TO_HOST_INT64(header.toc_length_compressed),
|
||||
B_BENDIAN_TO_HOST_INT32(header.attributes_length_compressed),
|
||||
totalSize);
|
||||
|
||||
// prepare the header
|
||||
|
||||
@@ -716,7 +768,7 @@ status_t
|
||||
PackageWriterImpl::_RegisterEntry(const char* fileName)
|
||||
{
|
||||
if (*fileName == '\0') {
|
||||
fprintf(stderr, "Error: Invalid empty file name\n");
|
||||
fListener->PrintError("Invalid empty file name\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
@@ -758,7 +810,7 @@ PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
|
||||
// check the component name -- don't allow "." or ".."
|
||||
if (name[0] == '.'
|
||||
&& (nameLength == 1 || (nameLength == 2 && name[1] == '.'))) {
|
||||
fprintf(stderr, "Error: Invalid file name: \".\" and \"..\" "
|
||||
fListener->PrintError("Invalid file name: \".\" and \"..\" "
|
||||
"are not allowed as path components\n");
|
||||
throw status_t(B_BAD_VALUE);
|
||||
}
|
||||
@@ -787,7 +839,7 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header)
|
||||
{
|
||||
// prepare the writer (zlib writer on top of a file writer)
|
||||
off_t startOffset = fHeapEnd;
|
||||
FDDataWriter realWriter(fFD, startOffset);
|
||||
FDDataWriter realWriter(fFD, startOffset, fListener);
|
||||
ZlibDataWriter zlibWriter(&realWriter);
|
||||
fDataWriter = &zlibWriter;
|
||||
zlibWriter.Init();
|
||||
@@ -805,11 +857,11 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header)
|
||||
fHeapEnd = realWriter.Offset();
|
||||
fDataWriter = NULL;
|
||||
|
||||
printf("attributes types size: %llu\n", uncompressedAttributeTypesSize);
|
||||
printf("cached strings size: %llu\n", uncompressedStringsSize);
|
||||
printf("TOC main size: %llu\n", uncompressedMainSize);
|
||||
off_t endOffset = fHeapEnd;
|
||||
printf("total TOC size: %llu (%llu)\n", endOffset - startOffset, zlibWriter.BytesWritten());
|
||||
|
||||
fListener->OnTOCSizeInfo(uncompressedAttributeTypesSize,
|
||||
uncompressedStringsSize, uncompressedMainSize,
|
||||
zlibWriter.BytesWritten());
|
||||
|
||||
// update the header
|
||||
|
||||
@@ -956,7 +1008,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
|
||||
{
|
||||
// write the package attributes
|
||||
off_t startOffset = fHeapEnd;
|
||||
FDDataWriter realWriter(fFD, startOffset);
|
||||
FDDataWriter realWriter(fFD, startOffset, fListener);
|
||||
fDataWriter = &realWriter;
|
||||
|
||||
_Write<uint8>(0);
|
||||
@@ -966,7 +1018,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
|
||||
|
||||
off_t endOffset = fHeapEnd;
|
||||
|
||||
printf("package attributes size: %lld\n", endOffset - startOffset);
|
||||
fListener->OnPackageAttributesSizeInfo(endOffset - startOffset);
|
||||
|
||||
// update the header
|
||||
header.attributes_compression = B_HOST_TO_BENDIAN_INT32(
|
||||
@@ -1008,7 +1060,7 @@ PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
|
||||
break;
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "_WriteAttributeValue(): invalid "
|
||||
fListener->PrintError("_WriteAttributeValue(): invalid "
|
||||
"encoding %d for int value type %d\n", encoding,
|
||||
value.type);
|
||||
throw status_t(B_BAD_VALUE);
|
||||
@@ -1038,7 +1090,7 @@ PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "_WriteAttributeValue(): invalid value type: "
|
||||
fListener->PrintError("_WriteAttributeValue(): invalid value type: "
|
||||
"%d\n", value.type);
|
||||
throw status_t(B_BAD_VALUE);
|
||||
}
|
||||
@@ -1065,30 +1117,37 @@ PackageWriterImpl::_WriteBuffer(const void* buffer, size_t size, off_t offset)
|
||||
{
|
||||
ssize_t bytesWritten = pwrite(fFD, buffer, size, offset);
|
||||
if (bytesWritten < 0) {
|
||||
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write data: %s\n",
|
||||
buffer, size, strerror(errno));
|
||||
fListener->PrintError(
|
||||
"_WriteBuffer(%p, %lu) failed to write data: %s\n", buffer, size,
|
||||
strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
if ((size_t)bytesWritten != size) {
|
||||
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write all data\n",
|
||||
buffer, size);
|
||||
fListener->PrintError(
|
||||
"_WriteBuffer(%p, %lu) failed to write all data\n", buffer, size);
|
||||
throw status_t(B_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName)
|
||||
PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName,
|
||||
char* pathBuffer)
|
||||
{
|
||||
printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
bool isImplicitEntry = entry != NULL && entry->IsImplicit();
|
||||
|
||||
SubPathAdder pathAdder(pathBuffer, fileName);
|
||||
if (!isImplicitEntry) {
|
||||
fListener->OnEntryAdded(pathBuffer + 1);
|
||||
// pathBuffer + 1 in order to skip leading slash
|
||||
}
|
||||
|
||||
// open the node
|
||||
int fd = openat(dirFD, fileName,
|
||||
O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error: Failed to open entry \"%s\": %s\n",
|
||||
fileName, strerror(errno));
|
||||
fListener->PrintError("Failed to open entry \"%s\": %s\n", fileName,
|
||||
strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
FileDescriptorCloser fdCloser(fd);
|
||||
@@ -1096,14 +1155,14 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
// stat the node
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
fprintf(stderr, "Error: Failed to fstat() file \"%s\": %s\n",
|
||||
fileName, strerror(errno));
|
||||
fListener->PrintError("Failed to fstat() file \"%s\": %s\n", fileName,
|
||||
strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
|
||||
// implicit entries must be directories
|
||||
if (isImplicitEntry && !S_ISDIR(st.st_mode)) {
|
||||
fprintf(stderr, "Error: Non-leaf path component \"%s\" is not a "
|
||||
fListener->PrintError("Non-leaf path component \"%s\" is not a "
|
||||
"directory\n", fileName);
|
||||
throw status_t(B_BAD_VALUE);
|
||||
}
|
||||
@@ -1122,7 +1181,7 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
defaultPermissions = B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS;
|
||||
} else {
|
||||
// unsupported node type
|
||||
fprintf(stderr, "Error: Unsupported node type, entry: \"%s\"\n",
|
||||
fListener->PrintError("Unsupported node type, entry: \"%s\"\n",
|
||||
fileName);
|
||||
throw status_t(B_UNSUPPORTED);
|
||||
}
|
||||
@@ -1159,7 +1218,7 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
ssize_t bytesRead = readlinkat(dirFD, fileName, path,
|
||||
B_PATH_NAME_LENGTH);
|
||||
if (bytesRead < 0) {
|
||||
fprintf(stderr, "Error: Failed to read symlink \"%s\": %s\n",
|
||||
fListener->PrintError("Failed to read symlink \"%s\": %s\n",
|
||||
fileName, strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
@@ -1175,9 +1234,9 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
while (dirent* entry = readdir(attrDir)) {
|
||||
attr_info attrInfo;
|
||||
if (fs_stat_attr(fd, entry->d_name, &attrInfo) < 0) {
|
||||
fprintf(stderr, "Error: Failed to stat attribute \"%s\" of "
|
||||
"file \"%s\": %s\n", entry->d_name, fileName,
|
||||
strerror(errno));
|
||||
fListener->PrintError(
|
||||
"Failed to stat attribute \"%s\" of file \"%s\": %s\n",
|
||||
entry->d_name, fileName, strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
|
||||
@@ -1205,21 +1264,22 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
// this is an implicit entry -- just add it's children
|
||||
for (EntryList::ConstIterator it = entry->ChildIterator();
|
||||
Entry* child = it.Next();) {
|
||||
_AddEntry(fd, child, child->Name());
|
||||
_AddEntry(fd, child, child->Name(), pathBuffer);
|
||||
}
|
||||
} else {
|
||||
// we need to clone the directory FD for fdopendir()
|
||||
int clonedFD = dup(fd);
|
||||
if (clonedFD < 0) {
|
||||
fprintf(stderr, "Error: Failed to dup() directory FD: %s\n",
|
||||
strerror(errno));
|
||||
fListener->PrintError(
|
||||
"Failed to dup() directory FD: %s\n", strerror(errno));
|
||||
throw status_t(errno);
|
||||
}
|
||||
|
||||
DIR* dir = fdopendir(clonedFD);
|
||||
if (dir == NULL) {
|
||||
fprintf(stderr, "Error: Failed to open directory \"%s\": %s\n",
|
||||
fileName, strerror(errno));
|
||||
fListener->PrintError(
|
||||
"Failed to open directory \"%s\": %s\n", fileName,
|
||||
strerror(errno));
|
||||
close(clonedFD);
|
||||
throw status_t(errno);
|
||||
}
|
||||
@@ -1232,7 +1292,7 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
_AddEntry(fd, NULL, entry->d_name);
|
||||
_AddEntry(fd, NULL, entry->d_name, pathBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1332,8 +1392,7 @@ PackageWriterImpl::_AddData(BDataReader& dataReader, off_t size)
|
||||
uint8 buffer[B_HPKG_MAX_INLINE_DATA_SIZE];
|
||||
status_t error = dataReader.ReadData(0, buffer, size);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to read data: %s\n",
|
||||
strerror(error));
|
||||
fListener->PrintError("Failed to read data: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1388,20 +1447,19 @@ PackageWriterImpl::_WriteUncompressedData(BDataReader& dataReader, off_t size,
|
||||
size_t toCopy = std::min(remainingSize, (off_t)fDataBufferSize);
|
||||
status_t error = dataReader.ReadData(readOffset, fDataBuffer, toCopy);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to read data: %s\n",
|
||||
strerror(error));
|
||||
fListener->PrintError("Failed to read data: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
// write to heap
|
||||
ssize_t bytesWritten = pwrite(fFD, fDataBuffer, toCopy, writeOffset);
|
||||
if (bytesWritten < 0) {
|
||||
fprintf(stderr, "Error: Failed to write data: %s\n",
|
||||
fListener->PrintError("Failed to write data: %s\n",
|
||||
strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
if ((size_t)bytesWritten != toCopy) {
|
||||
fprintf(stderr, "Error: Failed to write all data\n");
|
||||
fListener->PrintError("Failed to write all data\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -1450,8 +1508,7 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
|
||||
size_t toCopy = std::min(remainingSize, (off_t)chunkSize);
|
||||
status_t error = dataReader.ReadData(readOffset, inputBuffer, toCopy);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to read data: %s\n",
|
||||
strerror(error));
|
||||
fListener->PrintError("Failed to read data: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1483,12 +1540,12 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
|
||||
ssize_t bytesWritten = pwrite(fFD, writeBuffer, bytesToWrite,
|
||||
writeOffset);
|
||||
if (bytesWritten < 0) {
|
||||
fprintf(stderr, "Error: Failed to write data: %s\n",
|
||||
fListener->PrintError("Failed to write data: %s\n",
|
||||
strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
if ((size_t)bytesWritten != bytesToWrite) {
|
||||
fprintf(stderr, "Error: Failed to write all data\n");
|
||||
fListener->PrintError("Failed to write all data\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -1504,12 +1561,12 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
|
||||
ssize_t bytesWritten = pwrite(fFD, offsetTable, bytesToWrite,
|
||||
offsetTableOffset);
|
||||
if (bytesWritten < 0) {
|
||||
fprintf(stderr, "Error: Failed to write data: %s\n",
|
||||
fListener->PrintError("Failed to write data: %s\n",
|
||||
strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
if ((size_t)bytesWritten != bytesToWrite) {
|
||||
fprintf(stderr, "Error: Failed to write all data\n");
|
||||
fListener->PrintError("Failed to write all data\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user