Add optional FD parameter to AddEntry()

If a FD is specified, instead of using the file with the given the FD is
used. Allows for adding entries without first copying them into the
directory structure.
This commit is contained in:
Ingo Weinhold
2011-11-25 06:18:45 +01:00
parent cd8f03a8cc
commit 0f9a98a419
4 changed files with 89 additions and 31 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ public:
~BPackageWriter();
status_t Init(const char* fileName);
status_t AddEntry(const char* fileName);
status_t AddEntry(const char* fileName, int fd = -1);
status_t Finish();
private:
@@ -38,7 +38,7 @@ public:
~PackageWriterImpl();
status_t Init(const char* fileName);
status_t AddEntry(const char* fileName);
status_t AddEntry(const char* fileName, int fd = -1);
status_t Finish();
private:
@@ -52,9 +52,9 @@ private:
status_t _Init(const char* fileName);
status_t _Finish();
status_t _RegisterEntry(const char* fileName);
status_t _RegisterEntry(const char* fileName, int fd);
Entry* _RegisterEntry(Entry* parent,
const char* name, size_t nameLength,
const char* name, size_t nameLength, int fd,
bool isImplicit);
status_t _CheckLicenses();
+2 -2
View File
@@ -40,12 +40,12 @@ BPackageWriter::Init(const char* fileName)
status_t
BPackageWriter::AddEntry(const char* fileName)
BPackageWriter::AddEntry(const char* fileName, int fd)
{
if (fImpl == NULL)
return B_NO_INIT;
return fImpl->AddEntry(fileName);
return fImpl->AddEntry(fileName, fd);
}
+83 -25
View File
@@ -91,10 +91,11 @@ struct PackageWriterImpl::Attribute
struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
Entry(char* name, size_t nameLength, bool isImplicit)
Entry(char* name, size_t nameLength, int fd, bool isImplicit)
:
fName(name),
fNameLength(nameLength),
fFD(fd),
fIsImplicit(isImplicit)
{
}
@@ -105,7 +106,8 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
free(fName);
}
static Entry* Create(const char* name, size_t nameLength, bool isImplicit)
static Entry* Create(const char* name, size_t nameLength, int fd,
bool isImplicit)
{
char* clonedName = (char*)malloc(nameLength + 1);
if (clonedName == NULL)
@@ -113,7 +115,7 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
memcpy(clonedName, name, nameLength);
clonedName[nameLength] = '\0';
Entry* entry = new(std::nothrow) Entry(clonedName, nameLength,
Entry* entry = new(std::nothrow) Entry(clonedName, nameLength, fd,
isImplicit);
if (entry == NULL) {
free(clonedName);
@@ -128,6 +130,16 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
return fName;
}
int FD() const
{
return fFD;
}
void SetFD(int fd)
{
fFD = fd;
}
bool IsImplicit() const
{
return fIsImplicit;
@@ -174,6 +186,7 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
private:
char* fName;
size_t fNameLength;
int fFD;
bool fIsImplicit;
EntryList fChildren;
};
@@ -253,7 +266,7 @@ PackageWriterImpl::Init(const char* fileName)
status_t
PackageWriterImpl::AddEntry(const char* fileName)
PackageWriterImpl::AddEntry(const char* fileName, int fd)
{
try {
// if it's ".PackageInfo", parse it
@@ -267,15 +280,48 @@ PackageWriterImpl::AddEntry(const char* fileName)
}
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;
if (fd >= 0) {
// a file descriptor is given -- read the config from there
// stat the file to get the file size
struct stat st;
if (fstat(fd, &st) != 0)
return errno;
BString packageInfoString;
char* buffer = packageInfoString.LockBuffer(st.st_size);
if (buffer == NULL)
return B_NO_MEMORY;
ssize_t result = read_pos(fd, 0, buffer, st.st_size);
if (result < 0) {
packageInfoString.UnlockBuffer(0);
return errno;
}
buffer[st.st_size] = '\0';
packageInfoString.UnlockBuffer(st.st_size);
result = fPackageInfo.ReadFromConfigString(packageInfoString,
&errorListener);
if (result != B_OK)
return result;
} else {
printf(" reading by name...\n");
// use the file name
BEntry packageInfoEntry(fileName);
status_t result = fPackageInfo.ReadFromConfigFile(
packageInfoEntry, &errorListener);
if (result != B_OK
|| (result = fPackageInfo.InitCheck()) != B_OK) {
return result;
}
}
RegisterPackageInfo(PackageAttributes(), fPackageInfo);
}
return _RegisterEntry(fileName);
return _RegisterEntry(fileName, fd);
} catch (status_t error) {
return error;
} catch (std::bad_alloc) {
@@ -325,7 +371,7 @@ PackageWriterImpl::_Init(const char* fileName)
throw std::bad_alloc();
// create entry list
fRootEntry = new Entry(NULL, 0, true);
fRootEntry = new Entry(NULL, 0, -1, true);
fRootAttribute = new Attribute();
@@ -425,7 +471,7 @@ PackageWriterImpl::_Finish()
status_t
PackageWriterImpl::_RegisterEntry(const char* fileName)
PackageWriterImpl::_RegisterEntry(const char* fileName, int fd)
{
if (*fileName == '\0') {
fListener->PrintError("Invalid empty file name\n");
@@ -438,7 +484,8 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
const char* nextSlash = strchr(fileName, '/');
// no slash, just add the file name
if (nextSlash == NULL) {
entry = _RegisterEntry(entry, fileName, strlen(fileName), false);
entry = _RegisterEntry(entry, fileName, strlen(fileName), fd,
false);
break;
}
@@ -447,13 +494,15 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
while (*nextComponent == '/')
nextComponent++;
bool lastComponent = *nextComponent != '\0';
if (nextSlash == fileName) {
// the FS root
entry = _RegisterEntry(entry, fileName, 1,
*nextComponent != '\0');
entry = _RegisterEntry(entry, fileName, 1, lastComponent ? fd : -1,
lastComponent);
} else {
entry = _RegisterEntry(entry, fileName, nextSlash - fileName,
*nextComponent != '\0');
lastComponent ? fd : -1, lastComponent);
}
fileName = nextComponent;
@@ -465,7 +514,7 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
PackageWriterImpl::Entry*
PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
size_t nameLength, bool isImplicit)
size_t nameLength, int fd, bool isImplicit)
{
// check the component name -- don't allow "." or ".."
if (name[0] == '.'
@@ -483,10 +532,11 @@ PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
if (entry->IsImplicit() && !isImplicit) {
entry->DeleteChildren();
entry->SetImplicit(false);
entry->SetFD(fd);
}
} else {
// nope -- create it
entry = Entry::Create(name, nameLength, isImplicit);
entry = Entry::Create(name, nameLength, fd, isImplicit);
parent->AddChild(entry);
}
@@ -626,14 +676,22 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName,
}
// open the node
int fd = openat(dirFD, fileName,
O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
if (fd < 0) {
fListener->PrintError("Failed to open entry \"%s\": %s\n", fileName,
strerror(errno));
throw status_t(errno);
int fd;
FileDescriptorCloser fdCloser;
if (entry != NULL && entry->FD() >= 0) {
// a file descriptor is already given -- use that
fd = entry->FD();
} else {
fd = openat(dirFD, fileName,
O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
if (fd < 0) {
fListener->PrintError("Failed to open entry \"%s\": %s\n", fileName,
strerror(errno));
throw status_t(errno);
}
fdCloser.SetTo(fd);
}
FileDescriptorCloser fdCloser(fd);
// stat the node
struct stat st;