From e6466c9a347a96e75691e19e1373a5c9fc907e5f Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 30 Jun 2011 00:04:54 +0200 Subject: [PATCH] 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. --- src/bin/package/command_extract.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/bin/package/command_extract.cpp b/src/bin/package/command_extract.cpp index 7c8b19c517..d3269c883f 100644 --- a/src/bin/package/command_extract.cpp +++ b/src/bin/package/command_extract.cpp @@ -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);