Skip to content

GH-81881: Raise SpecialFileError for sockets and devices in shutil.copyfile#142693

Open
savannahostrowski wants to merge 10 commits into
python:mainfrom
savannahostrowski:special-file-shutil
Open

GH-81881: Raise SpecialFileError for sockets and devices in shutil.copyfile#142693
savannahostrowski wants to merge 10 commits into
python:mainfrom
savannahostrowski:special-file-shutil

Conversation

@savannahostrowski

@savannahostrowski savannahostrowski commented Dec 14, 2025

Copy link
Copy Markdown
Member

The original issue just mentions sockets, but while documenting this I found it very confusing and inconsistent that device files didn't get the same treatment, so I figured I'd fix them all in one go.


📚 Documentation preview 📚: https://cpython-previews--142693.org.readthedocs.build/

@github-actions

github-actions Bot commented May 3, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label May 3, 2026
@orsenthil

Copy link
Copy Markdown
Member

@savannahostrowski , are you interested in pursuing this. Overall this looks good to me.

@read-the-docs-community

read-the-docs-community Bot commented Jun 27, 2026

Copy link
Copy Markdown

@savannahostrowski

Copy link
Copy Markdown
Member Author

@orsenthil Yes, but was waiting for someone else to review it!

@orsenthil

Copy link
Copy Markdown
Member

Test failures in test_logging seems unrelated. It should be re-run.

  1. Raising for Socket devices is correct. The code raises OSError right now. So raising a specific sub-exception, SpecialFileError is correct.

  2. Block devices raise OSError too. So, good here.

For Character Device. This is a legitimate program at the moment and it will stop functioning after this change.

import shutil

shutil.copyfile('noisy_error_log.log', '/dev/null')
shutil.copyfile('/dev/null', 'empty_file.txt')

However, this is not pythonic and correct way piping to character device /dev/null is using subprocess.DEVNULL which uses os.devnull

Empty file is created using open and close call. Or pathlib.Path.touch

It only "works" because '/dev/null' happens to return EOF immediately It's incidental, not designed. Similarly, using /dev/random would be boundless call and an exploit.

So, it okay to raise against the Character Device too.

I did a github search of using shutil with /dev/null and I couldn't find any.

@orsenthil orsenthil left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@orsenthil

Copy link
Copy Markdown
Member

but was waiting for someone else to review it!

Reviewed and approved. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting merge stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants