package extract: Delay setting node permissions

In HandleEntry() create the file/directory with sufficient permissions
for the user and set the archived permissions in HandleEntryDone(). This
makes sure child attributes and entries can be created.
This commit is contained in:
Ingo Weinhold 2011-06-30 00:04:54 +02:00
parent 1bcc0f6e4a
commit 1ef35574eb
1 changed files with 22 additions and 3 deletions

View File

@ -116,7 +116,10 @@ struct PackageContentExtractHandler : BPackageContentHandler {
if (S_ISREG(entry->Mode())) {
// create the file
fd = openat(parentFD, entry->Name(), O_RDWR | O_CREAT | O_EXCL,
entry->Mode() & ALLPERMS);
S_IRUSR | S_IWUSR);
// Note: We use read+write user permissions now -- so write
// operations (e.g. attributes) won't fail, but set them to the
// desired ones in HandleEntryDone().
if (fd < 0) {
fprintf(stderr, "Error: Failed to create file \"%s\": %s\n",
entry->Name(), strerror(errno));
@ -148,8 +151,10 @@ struct PackageContentExtractHandler : BPackageContentHandler {
} else if (S_ISDIR(entry->Mode())) {
// create the directory, if necessary
if (!entryExists
&& mkdirat(parentFD, entry->Name(), entry->Mode() & ALLPERMS)
!= 0) {
&& mkdirat(parentFD, entry->Name(), S_IRWXU) != 0) {
// Note: We use read+write+exec user permissions now -- so write
// operations (e.g. attributes) won't fail, but set them to the
// desired ones in HandleEntryDone().
fprintf(stderr, "Error: Failed to create directory \"%s\": "
"%s\n", entry->Name(), strerror(errno));
return errno;
@ -216,6 +221,20 @@ struct PackageContentExtractHandler : BPackageContentHandler {
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
// set the node permissions for non-symlinks
if (!S_ISLNK(entry->Mode())) {
// get parent FD
int parentFD = AT_FDCWD;
if (entry->Parent() != NULL)
parentFD = ((Token*)entry->Parent()->UserToken())->fd;
if (fchmodat(parentFD, entry->Name(), entry->Mode() & ALLPERMS,
/*AT_SYMLINK_NOFOLLOW*/0) != 0) {
fprintf(stderr, "Warning: Failed to set permissions of file "
"\"%s\": %s\n", entry->Name(), strerror(errno));
}
}
if (Token* token = (Token*)entry->UserToken()) {
delete token;
entry->SetUserToken(NULL);