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:
@@ -48,7 +48,7 @@ public:
|
|||||||
~BPackageWriter();
|
~BPackageWriter();
|
||||||
|
|
||||||
status_t Init(const char* fileName);
|
status_t Init(const char* fileName);
|
||||||
status_t AddEntry(const char* fileName);
|
status_t AddEntry(const char* fileName, int fd = -1);
|
||||||
status_t Finish();
|
status_t Finish();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
~PackageWriterImpl();
|
~PackageWriterImpl();
|
||||||
|
|
||||||
status_t Init(const char* fileName);
|
status_t Init(const char* fileName);
|
||||||
status_t AddEntry(const char* fileName);
|
status_t AddEntry(const char* fileName, int fd = -1);
|
||||||
status_t Finish();
|
status_t Finish();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -52,9 +52,9 @@ private:
|
|||||||
status_t _Init(const char* fileName);
|
status_t _Init(const char* fileName);
|
||||||
status_t _Finish();
|
status_t _Finish();
|
||||||
|
|
||||||
status_t _RegisterEntry(const char* fileName);
|
status_t _RegisterEntry(const char* fileName, int fd);
|
||||||
Entry* _RegisterEntry(Entry* parent,
|
Entry* _RegisterEntry(Entry* parent,
|
||||||
const char* name, size_t nameLength,
|
const char* name, size_t nameLength, int fd,
|
||||||
bool isImplicit);
|
bool isImplicit);
|
||||||
|
|
||||||
status_t _CheckLicenses();
|
status_t _CheckLicenses();
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ BPackageWriter::Init(const char* fileName)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPackageWriter::AddEntry(const char* fileName)
|
BPackageWriter::AddEntry(const char* fileName, int fd)
|
||||||
{
|
{
|
||||||
if (fImpl == NULL)
|
if (fImpl == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
return fImpl->AddEntry(fileName);
|
return fImpl->AddEntry(fileName, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,10 +91,11 @@ struct PackageWriterImpl::Attribute
|
|||||||
|
|
||||||
|
|
||||||
struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
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),
|
fName(name),
|
||||||
fNameLength(nameLength),
|
fNameLength(nameLength),
|
||||||
|
fFD(fd),
|
||||||
fIsImplicit(isImplicit)
|
fIsImplicit(isImplicit)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,8 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
|||||||
free(fName);
|
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);
|
char* clonedName = (char*)malloc(nameLength + 1);
|
||||||
if (clonedName == NULL)
|
if (clonedName == NULL)
|
||||||
@@ -113,7 +115,7 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
|||||||
memcpy(clonedName, name, nameLength);
|
memcpy(clonedName, name, nameLength);
|
||||||
clonedName[nameLength] = '\0';
|
clonedName[nameLength] = '\0';
|
||||||
|
|
||||||
Entry* entry = new(std::nothrow) Entry(clonedName, nameLength,
|
Entry* entry = new(std::nothrow) Entry(clonedName, nameLength, fd,
|
||||||
isImplicit);
|
isImplicit);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
free(clonedName);
|
free(clonedName);
|
||||||
@@ -128,6 +130,16 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
|||||||
return fName;
|
return fName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FD() const
|
||||||
|
{
|
||||||
|
return fFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFD(int fd)
|
||||||
|
{
|
||||||
|
fFD = fd;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsImplicit() const
|
bool IsImplicit() const
|
||||||
{
|
{
|
||||||
return fIsImplicit;
|
return fIsImplicit;
|
||||||
@@ -174,6 +186,7 @@ struct PackageWriterImpl::Entry : DoublyLinkedListLinkImpl<Entry> {
|
|||||||
private:
|
private:
|
||||||
char* fName;
|
char* fName;
|
||||||
size_t fNameLength;
|
size_t fNameLength;
|
||||||
|
int fFD;
|
||||||
bool fIsImplicit;
|
bool fIsImplicit;
|
||||||
EntryList fChildren;
|
EntryList fChildren;
|
||||||
};
|
};
|
||||||
@@ -253,7 +266,7 @@ PackageWriterImpl::Init(const char* fileName)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageWriterImpl::AddEntry(const char* fileName)
|
PackageWriterImpl::AddEntry(const char* fileName, int fd)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// if it's ".PackageInfo", parse it
|
// if it's ".PackageInfo", parse it
|
||||||
@@ -267,15 +280,48 @@ PackageWriterImpl::AddEntry(const char* fileName)
|
|||||||
}
|
}
|
||||||
BPackageWriterListener* listener;
|
BPackageWriterListener* listener;
|
||||||
} errorListener(fListener);
|
} errorListener(fListener);
|
||||||
BEntry packageInfoEntry(fileName);
|
|
||||||
status_t result = fPackageInfo.ReadFromConfigFile(packageInfoEntry,
|
if (fd >= 0) {
|
||||||
&errorListener);
|
// a file descriptor is given -- read the config from there
|
||||||
if (result != B_OK || (result = fPackageInfo.InitCheck()) != B_OK)
|
// stat the file to get the file size
|
||||||
return result;
|
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);
|
RegisterPackageInfo(PackageAttributes(), fPackageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _RegisterEntry(fileName);
|
return _RegisterEntry(fileName, fd);
|
||||||
} catch (status_t error) {
|
} catch (status_t error) {
|
||||||
return error;
|
return error;
|
||||||
} catch (std::bad_alloc) {
|
} catch (std::bad_alloc) {
|
||||||
@@ -325,7 +371,7 @@ PackageWriterImpl::_Init(const char* fileName)
|
|||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
|
|
||||||
// create entry list
|
// create entry list
|
||||||
fRootEntry = new Entry(NULL, 0, true);
|
fRootEntry = new Entry(NULL, 0, -1, true);
|
||||||
|
|
||||||
fRootAttribute = new Attribute();
|
fRootAttribute = new Attribute();
|
||||||
|
|
||||||
@@ -425,7 +471,7 @@ PackageWriterImpl::_Finish()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageWriterImpl::_RegisterEntry(const char* fileName)
|
PackageWriterImpl::_RegisterEntry(const char* fileName, int fd)
|
||||||
{
|
{
|
||||||
if (*fileName == '\0') {
|
if (*fileName == '\0') {
|
||||||
fListener->PrintError("Invalid empty file name\n");
|
fListener->PrintError("Invalid empty file name\n");
|
||||||
@@ -438,7 +484,8 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
|
|||||||
const char* nextSlash = strchr(fileName, '/');
|
const char* nextSlash = strchr(fileName, '/');
|
||||||
// no slash, just add the file name
|
// no slash, just add the file name
|
||||||
if (nextSlash == NULL) {
|
if (nextSlash == NULL) {
|
||||||
entry = _RegisterEntry(entry, fileName, strlen(fileName), false);
|
entry = _RegisterEntry(entry, fileName, strlen(fileName), fd,
|
||||||
|
false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,13 +494,15 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
|
|||||||
while (*nextComponent == '/')
|
while (*nextComponent == '/')
|
||||||
nextComponent++;
|
nextComponent++;
|
||||||
|
|
||||||
|
bool lastComponent = *nextComponent != '\0';
|
||||||
|
|
||||||
if (nextSlash == fileName) {
|
if (nextSlash == fileName) {
|
||||||
// the FS root
|
// the FS root
|
||||||
entry = _RegisterEntry(entry, fileName, 1,
|
entry = _RegisterEntry(entry, fileName, 1, lastComponent ? fd : -1,
|
||||||
*nextComponent != '\0');
|
lastComponent);
|
||||||
} else {
|
} else {
|
||||||
entry = _RegisterEntry(entry, fileName, nextSlash - fileName,
|
entry = _RegisterEntry(entry, fileName, nextSlash - fileName,
|
||||||
*nextComponent != '\0');
|
lastComponent ? fd : -1, lastComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = nextComponent;
|
fileName = nextComponent;
|
||||||
@@ -465,7 +514,7 @@ PackageWriterImpl::_RegisterEntry(const char* fileName)
|
|||||||
|
|
||||||
PackageWriterImpl::Entry*
|
PackageWriterImpl::Entry*
|
||||||
PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
|
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 ".."
|
// check the component name -- don't allow "." or ".."
|
||||||
if (name[0] == '.'
|
if (name[0] == '.'
|
||||||
@@ -483,10 +532,11 @@ PackageWriterImpl::_RegisterEntry(Entry* parent, const char* name,
|
|||||||
if (entry->IsImplicit() && !isImplicit) {
|
if (entry->IsImplicit() && !isImplicit) {
|
||||||
entry->DeleteChildren();
|
entry->DeleteChildren();
|
||||||
entry->SetImplicit(false);
|
entry->SetImplicit(false);
|
||||||
|
entry->SetFD(fd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// nope -- create it
|
// nope -- create it
|
||||||
entry = Entry::Create(name, nameLength, isImplicit);
|
entry = Entry::Create(name, nameLength, fd, isImplicit);
|
||||||
parent->AddChild(entry);
|
parent->AddChild(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,14 +676,22 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// open the node
|
// open the node
|
||||||
int fd = openat(dirFD, fileName,
|
int fd;
|
||||||
O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
|
FileDescriptorCloser fdCloser;
|
||||||
if (fd < 0) {
|
|
||||||
fListener->PrintError("Failed to open entry \"%s\": %s\n", fileName,
|
if (entry != NULL && entry->FD() >= 0) {
|
||||||
strerror(errno));
|
// a file descriptor is already given -- use that
|
||||||
throw status_t(errno);
|
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
|
// stat the node
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|||||||
Reference in New Issue
Block a user