* 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:
Oliver Tappe
2011-01-31 15:43:33 +00:00
parent 2eb4032d55
commit 7fd711ef99
5 changed files with 261 additions and 91 deletions
+26 -1
View File
@@ -8,6 +8,8 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#include <package/hpkg/ErrorOutput.h>
namespace BPackageKit { namespace BPackageKit {
@@ -20,9 +22,32 @@ namespace BPrivate {
using BPrivate::PackageWriterImpl; 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 { class BPackageWriter {
public: public:
BPackageWriter(); public:
BPackageWriter(
BPackageWriterListener* listener);
~BPackageWriter(); ~BPackageWriter();
status_t Init(const char* fileName); status_t Init(const char* fileName);
@@ -9,19 +9,19 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
#include <package/PackageInfo.h>
#include <package/hpkg/PackageWriter.h>
#include <package/hpkg/Strings.h> #include <package/hpkg/Strings.h>
namespace BPackageKit { namespace BPackageKit {
class BPackageInfo;
namespace BHPKG { namespace BHPKG {
class BDataReader; class BDataReader;
class BErrorOutput;
namespace BPrivate { namespace BPrivate {
@@ -31,7 +31,8 @@ struct hpkg_header;
class PackageWriterImpl { class PackageWriterImpl {
public: public:
PackageWriterImpl(); PackageWriterImpl(
BPackageWriterListener* listener);
~PackageWriterImpl(); ~PackageWriterImpl();
status_t Init(const char* fileName); status_t Init(const char* fileName);
@@ -49,6 +50,7 @@ private:
struct DataWriter; struct DataWriter;
struct DummyDataWriter; struct DummyDataWriter;
struct FDDataWriter; struct FDDataWriter;
struct SubPathAdder;
struct ZlibDataWriter; struct ZlibDataWriter;
typedef BOpenHashTable<AttributeTypeHashDefinition> typedef BOpenHashTable<AttributeTypeHashDefinition>
@@ -86,7 +88,7 @@ private:
off_t offset); off_t offset);
void _AddEntry(int dirFD, Entry* entry, void _AddEntry(int dirFD, Entry* entry,
const char* fileName); const char* fileName, char* pathBuffer);
Attribute* _AddAttribute(const char* attributeName, Attribute* _AddAttribute(const char* attributeName,
const AttributeValue& value); const AttributeValue& value);
@@ -114,6 +116,8 @@ private:
uint64& _compressedSize); uint64& _compressedSize);
private: private:
BPackageWriterListener* fListener;
const char* fFileName; const char* fFileName;
int fFD; int fFD;
bool fFinished; bool fFinished;
@@ -122,6 +126,8 @@ private:
void* fDataBuffer; void* fDataBuffer;
size_t fDataBufferSize; size_t fDataBufferSize;
BPackageInfo fPackageInfo;
DataWriter* fDataWriter; DataWriter* fDataWriter;
Entry* fRootEntry; Entry* fRootEntry;
+103 -21
View File
@@ -18,25 +18,99 @@
#include <package/hpkg/PackageWriter.h> #include <package/hpkg/PackageWriter.h>
#include "package.h" #include "package.h"
#include "StandardErrorOutput.h"
using BPackageKit::BPackageInfo; using BPackageKit::BHPKG::BPackageWriterListener;
using BPackageKit::BHPKG::BPackageWriter; 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 int
command_create(int argc, const char* const* argv) command_create(int argc, const char* const* argv)
{ {
const char* changeToDirectory = NULL; const char* changeToDirectory = NULL;
bool quiet = false;
bool verbose = false;
while (true) { while (true) {
static struct option sLongOptions[] = { static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ "quiet", no_argument, 0, 'q' },
{ "verbose", no_argument, 0, 'v' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
opterr = 0; // don't print errors 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) if (c == -1)
break; break;
@@ -49,6 +123,14 @@ command_create(int argc, const char* const* argv)
print_usage_and_exit(false); print_usage_and_exit(false);
break; break;
case 'q':
quiet = true;
break;
case 'v':
verbose = true;
break;
default: default:
print_usage_and_exit(true); print_usage_and_exit(true);
break; break;
@@ -65,27 +147,27 @@ command_create(int argc, const char* const* argv)
int fileNameCount = argc - optind; int fileNameCount = argc - optind;
// create package // create package
BPackageWriter packageWriter; PackageWriterListener listener(verbose, quiet);
status_t error = packageWriter.Init(packageFileName); BPackageWriter packageWriter(&listener);
printf("Init(): %s\n", strerror(error)); status_t result = packageWriter.Init(packageFileName);
if (error != B_OK) if (result != B_OK)
return 1; return 1;
// change directory, if requested // change directory, if requested
if (changeToDirectory != NULL) { if (changeToDirectory != NULL) {
if (chdir(changeToDirectory) != 0) { if (chdir(changeToDirectory) != 0) {
fprintf(stderr, "Error: Failed to change the current working " listener.PrintError(
"directory to \"%s\": %s\n", changeToDirectory, "Error: Failed to change the current working directory to "
strerror(errno)); "\"%s\": %s\n", changeToDirectory, strerror(errno));
} }
} }
// add files // add files
for (int i = 0; i < fileNameCount; i++) { for (int i = 0; i < fileNameCount; i++) {
if (strcmp(fileNames[i], ".") == 0) { if (strcmp(fileNames[i], ".") == 0) {
DIR* dir = opendir ("."); DIR* dir = opendir(".");
if (dir == NULL) { if (dir == NULL) {
fprintf(stderr, "Error: Failed to opendir '.': %s\n", listener.PrintError("Error: Failed to opendir '.': %s\n",
strerror(errno)); strerror(errno));
return 1; return 1;
} }
@@ -94,26 +176,26 @@ printf("Init(): %s\n", strerror(error));
|| strcmp(entry->d_name, "..") == 0) || strcmp(entry->d_name, "..") == 0)
continue; continue;
error = packageWriter.AddEntry(entry->d_name); result = packageWriter.AddEntry(entry->d_name);
printf("AddEntry(\"%s\"): %s\n", entry->d_name, strerror(error)); if (result != B_OK)
if (error != B_OK)
return 1; return 1;
} }
closedir (dir); closedir(dir);
} else { } else {
error = packageWriter.AddEntry(fileNames[i]); result = packageWriter.AddEntry(fileNames[i]);
printf("AddEntry(\"%s\"): %s\n", fileNames[i], strerror(error)); if (result != B_OK)
if (error != B_OK)
return 1; return 1;
} }
} }
// write the package // write the package
error = packageWriter.Finish(); result = packageWriter.Finish();
printf("Finish(): %s\n", strerror(error)); if (result != B_OK)
if (error != B_OK)
return 1; return 1;
if (verbose)
printf("\nsuccessfully created package '%s'\n", packageFileName);
return 0; return 0;
} }
+2 -2
View File
@@ -16,9 +16,9 @@ namespace BPackageKit {
namespace BHPKG { namespace BHPKG {
BPackageWriter::BPackageWriter() BPackageWriter::BPackageWriter(BPackageWriterListener* listener)
: :
fImpl(new (std::nothrow) PackageWriterImpl()) fImpl(new (std::nothrow) PackageWriterImpl(listener))
{ {
} }
+119 -62
View File
@@ -19,6 +19,7 @@
#include <new> #include <new>
#include <ByteOrder.h> #include <ByteOrder.h>
#include <Entry.h>
#include <fs_attr.h> #include <fs_attr.h>
#include <AutoDeleter.h> #include <AutoDeleter.h>
@@ -301,7 +302,6 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
fNameLength(nameLength), fNameLength(nameLength),
fIsImplicit(isImplicit) fIsImplicit(isImplicit)
{ {
printf("%p->Entry::Entry(\"%s\", %lu, %d)\n", this, name, nameLength, isImplicit);
} }
~Entry() ~Entry()
@@ -431,10 +431,11 @@ struct PackageWriterImpl::DummyDataWriter : DataWriter {
struct PackageWriterImpl::FDDataWriter : DataWriter { struct PackageWriterImpl::FDDataWriter : DataWriter {
FDDataWriter(int fd, off_t offset) FDDataWriter(int fd, off_t offset, BPackageWriterListener* listener)
: :
fFD(fd), fFD(fd),
fOffset(offset) fOffset(offset),
fListener(listener)
{ {
} }
@@ -442,13 +443,15 @@ struct PackageWriterImpl::FDDataWriter : DataWriter {
{ {
ssize_t bytesWritten = pwrite(fFD, buffer, size, fOffset); ssize_t bytesWritten = pwrite(fFD, buffer, size, fOffset);
if (bytesWritten < 0) { 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)); buffer, size, strerror(errno));
return errno; return errno;
} }
if ((size_t)bytesWritten != size) { if ((size_t)bytesWritten != size) {
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write all data\n", fListener->PrintError(
buffer, size); "_WriteBuffer(%p, %lu) failed to write all data\n", buffer,
size);
return B_ERROR; return B_ERROR;
} }
@@ -463,11 +466,31 @@ struct PackageWriterImpl::FDDataWriter : DataWriter {
} }
private: private:
int fFD; int fFD;
off_t fOffset; 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 { struct PackageWriterImpl::ZlibDataWriter : DataWriter, private BDataOutput {
ZlibDataWriter(DataWriter* dataWriter) ZlibDataWriter(DataWriter* dataWriter)
: :
@@ -542,8 +565,9 @@ PackageWriterImpl::_AddAttribute(const char* attributeName, Type value)
// #pragma mark - PackageWriterImpl // #pragma mark - PackageWriterImpl
PackageWriterImpl::PackageWriterImpl() PackageWriterImpl::PackageWriterImpl(BPackageWriterListener* listener)
: :
fListener(listener),
fFileName(NULL), fFileName(NULL),
fFD(-1), fFD(-1),
fFinished(false), fFinished(false),
@@ -600,7 +624,7 @@ PackageWriterImpl::Init(const char* fileName)
} catch (status_t error) { } catch (status_t error) {
return error; return error;
} catch (std::bad_alloc) { } catch (std::bad_alloc) {
fprintf(stderr, "Out of memory!\n"); fListener->PrintError("Out of memory!\n");
return B_NO_MEMORY; return B_NO_MEMORY;
} }
} }
@@ -610,11 +634,29 @@ status_t
PackageWriterImpl::AddEntry(const char* fileName) PackageWriterImpl::AddEntry(const char* fileName)
{ {
try { 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); return _RegisterEntry(fileName);
} catch (status_t error) { } catch (status_t error) {
return error; return error;
} catch (std::bad_alloc) { } catch (std::bad_alloc) {
fprintf(stderr, "Out of memory!\n"); fListener->PrintError("Out of memory!\n");
return B_NO_MEMORY; return B_NO_MEMORY;
} }
} }
@@ -624,11 +666,16 @@ status_t
PackageWriterImpl::Finish() PackageWriterImpl::Finish()
{ {
try { 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(); return _Finish();
} catch (status_t error) { } catch (status_t error) {
return error; return error;
} catch (std::bad_alloc) { } catch (std::bad_alloc) {
fprintf(stderr, "Out of memory!\n"); fListener->PrintError("Out of memory!\n");
return B_NO_MEMORY; return B_NO_MEMORY;
} }
} }
@@ -659,7 +706,7 @@ PackageWriterImpl::_Init(const char* fileName)
fFD = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, fFD = open(fileName, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fFD < 0) { 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)); fileName, strerror(errno));
return errno; return errno;
} }
@@ -680,11 +727,12 @@ PackageWriterImpl::_Finish()
// write entries // write entries
for (EntryList::ConstIterator it = fRootEntry->ChildIterator(); for (EntryList::ConstIterator it = fRootEntry->ChildIterator();
Entry* entry = it.Next();) { 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)); off_t heapSize = fHeapEnd - sizeof(hpkg_header);
printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
hpkg_header header; hpkg_header header;
@@ -693,7 +741,11 @@ printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
_WritePackageAttributes(header); _WritePackageAttributes(header);
off_t totalSize = fHeapEnd; 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 // prepare the header
@@ -716,7 +768,7 @@ status_t
PackageWriterImpl::_RegisterEntry(const char* fileName) PackageWriterImpl::_RegisterEntry(const char* fileName)
{ {
if (*fileName == '\0') { if (*fileName == '\0') {
fprintf(stderr, "Error: Invalid empty file name\n"); fListener->PrintError("Invalid empty file name\n");
return B_BAD_VALUE; return B_BAD_VALUE;
} }
@@ -758,7 +810,7 @@ PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
// check the component name -- don't allow "." or ".." // check the component name -- don't allow "." or ".."
if (name[0] == '.' if (name[0] == '.'
&& (nameLength == 1 || (nameLength == 2 && name[1] == '.'))) { && (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"); "are not allowed as path components\n");
throw status_t(B_BAD_VALUE); 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) // prepare the writer (zlib writer on top of a file writer)
off_t startOffset = fHeapEnd; off_t startOffset = fHeapEnd;
FDDataWriter realWriter(fFD, startOffset); FDDataWriter realWriter(fFD, startOffset, fListener);
ZlibDataWriter zlibWriter(&realWriter); ZlibDataWriter zlibWriter(&realWriter);
fDataWriter = &zlibWriter; fDataWriter = &zlibWriter;
zlibWriter.Init(); zlibWriter.Init();
@@ -805,11 +857,11 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header)
fHeapEnd = realWriter.Offset(); fHeapEnd = realWriter.Offset();
fDataWriter = NULL; 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; 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 // update the header
@@ -956,7 +1008,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
{ {
// write the package attributes // write the package attributes
off_t startOffset = fHeapEnd; off_t startOffset = fHeapEnd;
FDDataWriter realWriter(fFD, startOffset); FDDataWriter realWriter(fFD, startOffset, fListener);
fDataWriter = &realWriter; fDataWriter = &realWriter;
_Write<uint8>(0); _Write<uint8>(0);
@@ -966,7 +1018,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
off_t endOffset = fHeapEnd; off_t endOffset = fHeapEnd;
printf("package attributes size: %lld\n", endOffset - startOffset); fListener->OnPackageAttributesSizeInfo(endOffset - startOffset);
// update the header // update the header
header.attributes_compression = B_HOST_TO_BENDIAN_INT32( header.attributes_compression = B_HOST_TO_BENDIAN_INT32(
@@ -1008,7 +1060,7 @@ PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
break; break;
default: default:
{ {
fprintf(stderr, "_WriteAttributeValue(): invalid " fListener->PrintError("_WriteAttributeValue(): invalid "
"encoding %d for int value type %d\n", encoding, "encoding %d for int value type %d\n", encoding,
value.type); value.type);
throw status_t(B_BAD_VALUE); throw status_t(B_BAD_VALUE);
@@ -1038,7 +1090,7 @@ PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
} }
default: default:
fprintf(stderr, "_WriteAttributeValue(): invalid value type: " fListener->PrintError("_WriteAttributeValue(): invalid value type: "
"%d\n", value.type); "%d\n", value.type);
throw status_t(B_BAD_VALUE); 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); ssize_t bytesWritten = pwrite(fFD, buffer, size, offset);
if (bytesWritten < 0) { if (bytesWritten < 0) {
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write data: %s\n", fListener->PrintError(
buffer, size, strerror(errno)); "_WriteBuffer(%p, %lu) failed to write data: %s\n", buffer, size,
strerror(errno));
throw status_t(errno); throw status_t(errno);
} }
if ((size_t)bytesWritten != size) { if ((size_t)bytesWritten != size) {
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write all data\n", fListener->PrintError(
buffer, size); "_WriteBuffer(%p, %lu) failed to write all data\n", buffer, size);
throw status_t(B_ERROR); throw status_t(B_ERROR);
} }
} }
void 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(); 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 // open the node
int fd = openat(dirFD, fileName, int fd = openat(dirFD, fileName,
O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE)); O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "Error: Failed to open entry \"%s\": %s\n", fListener->PrintError("Failed to open entry \"%s\": %s\n", fileName,
fileName, strerror(errno)); strerror(errno));
throw status_t(errno); throw status_t(errno);
} }
FileDescriptorCloser fdCloser(fd); FileDescriptorCloser fdCloser(fd);
@@ -1096,14 +1155,14 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
// stat the node // stat the node
struct stat st; struct stat st;
if (fstat(fd, &st) < 0) { if (fstat(fd, &st) < 0) {
fprintf(stderr, "Error: Failed to fstat() file \"%s\": %s\n", fListener->PrintError("Failed to fstat() file \"%s\": %s\n", fileName,
fileName, strerror(errno)); strerror(errno));
throw status_t(errno); throw status_t(errno);
} }
// implicit entries must be directories // implicit entries must be directories
if (isImplicitEntry && !S_ISDIR(st.st_mode)) { 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); "directory\n", fileName);
throw status_t(B_BAD_VALUE); 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; defaultPermissions = B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS;
} else { } else {
// unsupported node type // unsupported node type
fprintf(stderr, "Error: Unsupported node type, entry: \"%s\"\n", fListener->PrintError("Unsupported node type, entry: \"%s\"\n",
fileName); fileName);
throw status_t(B_UNSUPPORTED); 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, ssize_t bytesRead = readlinkat(dirFD, fileName, path,
B_PATH_NAME_LENGTH); B_PATH_NAME_LENGTH);
if (bytesRead < 0) { 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)); fileName, strerror(errno));
throw status_t(errno); throw status_t(errno);
} }
@@ -1175,9 +1234,9 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
while (dirent* entry = readdir(attrDir)) { while (dirent* entry = readdir(attrDir)) {
attr_info attrInfo; attr_info attrInfo;
if (fs_stat_attr(fd, entry->d_name, &attrInfo) < 0) { if (fs_stat_attr(fd, entry->d_name, &attrInfo) < 0) {
fprintf(stderr, "Error: Failed to stat attribute \"%s\" of " fListener->PrintError(
"file \"%s\": %s\n", entry->d_name, fileName, "Failed to stat attribute \"%s\" of file \"%s\": %s\n",
strerror(errno)); entry->d_name, fileName, strerror(errno));
throw status_t(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 // this is an implicit entry -- just add it's children
for (EntryList::ConstIterator it = entry->ChildIterator(); for (EntryList::ConstIterator it = entry->ChildIterator();
Entry* child = it.Next();) { Entry* child = it.Next();) {
_AddEntry(fd, child, child->Name()); _AddEntry(fd, child, child->Name(), pathBuffer);
} }
} else { } else {
// we need to clone the directory FD for fdopendir() // we need to clone the directory FD for fdopendir()
int clonedFD = dup(fd); int clonedFD = dup(fd);
if (clonedFD < 0) { if (clonedFD < 0) {
fprintf(stderr, "Error: Failed to dup() directory FD: %s\n", fListener->PrintError(
strerror(errno)); "Failed to dup() directory FD: %s\n", strerror(errno));
throw status_t(errno); throw status_t(errno);
} }
DIR* dir = fdopendir(clonedFD); DIR* dir = fdopendir(clonedFD);
if (dir == NULL) { if (dir == NULL) {
fprintf(stderr, "Error: Failed to open directory \"%s\": %s\n", fListener->PrintError(
fileName, strerror(errno)); "Failed to open directory \"%s\": %s\n", fileName,
strerror(errno));
close(clonedFD); close(clonedFD);
throw status_t(errno); throw status_t(errno);
} }
@@ -1232,7 +1292,7 @@ printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
continue; 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]; uint8 buffer[B_HPKG_MAX_INLINE_DATA_SIZE];
status_t error = dataReader.ReadData(0, buffer, size); status_t error = dataReader.ReadData(0, buffer, size);
if (error != B_OK) { if (error != B_OK) {
fprintf(stderr, "Error: Failed to read data: %s\n", fListener->PrintError("Failed to read data: %s\n", strerror(error));
strerror(error));
return error; return error;
} }
@@ -1388,20 +1447,19 @@ PackageWriterImpl::_WriteUncompressedData(BDataReader& dataReader, off_t size,
size_t toCopy = std::min(remainingSize, (off_t)fDataBufferSize); size_t toCopy = std::min(remainingSize, (off_t)fDataBufferSize);
status_t error = dataReader.ReadData(readOffset, fDataBuffer, toCopy); status_t error = dataReader.ReadData(readOffset, fDataBuffer, toCopy);
if (error != B_OK) { if (error != B_OK) {
fprintf(stderr, "Error: Failed to read data: %s\n", fListener->PrintError("Failed to read data: %s\n", strerror(error));
strerror(error));
return error; return error;
} }
// write to heap // write to heap
ssize_t bytesWritten = pwrite(fFD, fDataBuffer, toCopy, writeOffset); ssize_t bytesWritten = pwrite(fFD, fDataBuffer, toCopy, writeOffset);
if (bytesWritten < 0) { if (bytesWritten < 0) {
fprintf(stderr, "Error: Failed to write data: %s\n", fListener->PrintError("Failed to write data: %s\n",
strerror(errno)); strerror(errno));
return errno; return errno;
} }
if ((size_t)bytesWritten != toCopy) { 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; return B_ERROR;
} }
@@ -1450,8 +1508,7 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
size_t toCopy = std::min(remainingSize, (off_t)chunkSize); size_t toCopy = std::min(remainingSize, (off_t)chunkSize);
status_t error = dataReader.ReadData(readOffset, inputBuffer, toCopy); status_t error = dataReader.ReadData(readOffset, inputBuffer, toCopy);
if (error != B_OK) { if (error != B_OK) {
fprintf(stderr, "Error: Failed to read data: %s\n", fListener->PrintError("Failed to read data: %s\n", strerror(error));
strerror(error));
return error; return error;
} }
@@ -1483,12 +1540,12 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
ssize_t bytesWritten = pwrite(fFD, writeBuffer, bytesToWrite, ssize_t bytesWritten = pwrite(fFD, writeBuffer, bytesToWrite,
writeOffset); writeOffset);
if (bytesWritten < 0) { if (bytesWritten < 0) {
fprintf(stderr, "Error: Failed to write data: %s\n", fListener->PrintError("Failed to write data: %s\n",
strerror(errno)); strerror(errno));
return errno; return errno;
} }
if ((size_t)bytesWritten != bytesToWrite) { 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; return B_ERROR;
} }
@@ -1504,12 +1561,12 @@ PackageWriterImpl::_WriteZlibCompressedData(BDataReader& dataReader, off_t size,
ssize_t bytesWritten = pwrite(fFD, offsetTable, bytesToWrite, ssize_t bytesWritten = pwrite(fFD, offsetTable, bytesToWrite,
offsetTableOffset); offsetTableOffset);
if (bytesWritten < 0) { if (bytesWritten < 0) {
fprintf(stderr, "Error: Failed to write data: %s\n", fListener->PrintError("Failed to write data: %s\n",
strerror(errno)); strerror(errno));
return errno; return errno;
} }
if ((size_t)bytesWritten != bytesToWrite) { 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; return B_ERROR;
} }
} }