Skip to content

Commit

Permalink
building: fix executable-bit preservation for collected shell scripts
Browse files Browse the repository at this point in the history
Add special handling for data files with executable bit set (such
as shell scripts).

In `COLLECT` and `BUNDLE`, we now set mode `0755` if typecode
matches the one for binary type OR if the source file has an
executable bit set.

In `PKG`, we manually force the PKG typecode for DATA entries to
`b` ("binary") if source file has an executable bit set.
  • Loading branch information
rokm committed Sep 22, 2023
1 parent 59ea410 commit 227b648
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
17 changes: 13 additions & 4 deletions PyInstaller/building/api.py
Expand Up @@ -306,7 +306,13 @@ def assemble(self):
if self.exclude_binaries:
self.dependencies.append((dest_name, src_name, typecode))
else:
archive_toc.append((dest_name, src_name, self.cdict.get(typecode, False), self.xformdict[typecode]))
if typecode == 'DATA' and os.access(src_name, os.X_OK):
# DATA with executable bit set (e.g., shell script); turn into binary so that executable bit is
# restored on the extracted file.
carchive_typecode = 'b'
else:
carchive_typecode = self.xformdict[typecode]
archive_toc.append((dest_name, src_name, self.cdict.get(typecode, False), carchive_typecode))
elif typecode == 'OPTION':
archive_toc.append((dest_name, '', False, 'o'))
elif typecode in ('PYSOURCE', 'PYMODULE'):
Expand Down Expand Up @@ -1142,10 +1148,13 @@ def assemble(self):
)
# Use `shutil.copyfile` to copy file with default permissions. We do not attempt to preserve original
# permissions nor metadata, as they might be too restrictive and cause issues either during subsequent
# re-build attempts or when trying to move the application bundle. For binaries, we manually set the
# executable bits after copying the file.
# re-build attempts or when trying to move the application bundle. For binaries (and data files with
# executable bit set), we manually set the executable bits after copying the file.
shutil.copyfile(src_name, dest_path)
if typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE'):
if (
typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE')
or (typecode == 'DATA' and os.access(src_name, os.X_OK))
):
os.chmod(dest_path, 0o755)
logger.info("Building COLLECT %s completed successfully.", self.tocbasename)

Expand Down
9 changes: 6 additions & 3 deletions PyInstaller/building/osx.py
Expand Up @@ -646,10 +646,13 @@ def assemble(self):
)
# Use `shutil.copyfile` to copy file with default permissions. We do not attempt to preserve original
# permissions nor metadata, as they might be too restrictive and cause issues either during subsequent
# re-build attempts or when trying to move the application bundle. For binaries, we manually set the
# executable bits after copying the file.
# re-build attempts or when trying to move the application bundle. For binaries (and data files with
# executable bit set), we manually set the executable bits after copying the file.
shutil.copyfile(src_name, dest_path)
if typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE'):
if (
typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE')
or (typecode == 'DATA' and os.access(src_name, os.X_OK))
):
os.chmod(dest_path, 0o755)

# Sign the bundle
Expand Down
7 changes: 4 additions & 3 deletions news/7950.bootloader.rst
@@ -1,5 +1,6 @@
(Linux, macOS) When extracting files from ``onefile`` archive, the
executable bit is now set only on binaries (files whose TOC type code
was either ``BINARY``, ``EXECUTABLE``, or ``EXTENSION``). Therefore,
binaries are now extracted with permissions bits set to ``0700``, while
all other files have permissions bits set to ``0600``.
was either ``BINARY``, ``EXECUTABLE``, or ``EXTENSION``) or data files
that originally had the executable bit set. Therefore, binaries are now
extracted with permissions bits set to ``0700``, while all other files
have permissions bits set to ``0600``.

0 comments on commit 227b648

Please sign in to comment.