Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirecting to /dev/null fails with noclobber #2191

Open
Janfel opened this issue Dec 10, 2024 · 3 comments
Open

Redirecting to /dev/null fails with noclobber #2191

Janfel opened this issue Dec 10, 2024 · 3 comments

Comments

@Janfel
Copy link

Janfel commented Dec 10, 2024

Hi, I’ve noticed that OSH raises an error when redirecting to /dev/null while noclobber is set.

$ set -C
$ >/dev/null
  >/dev/null
  ^
[ interactive ]:2: Can't open '/dev/null': File exists (noclobber)
[ interactive ]:2: I/O error applying redirect: File exists

It seems that OSH applies noclobber to non-regular files as well as regular files. Compare POSIX (emphasis mine):

Output redirection using the '>' format shall fail if the noclobber option is set (see the description of set -C) and the file named by the expansion of word exists and is a regular file. Otherwise, redirection using the '>' or ">|" formats shall cause the file whose name results from the expansion of word to be created and opened for output on the designated file descriptor, or standard output if none is specified. If the file does not exist, it shall be created; otherwise, it shall be truncated to be an empty file after being opened.
POSIX 2018, Section 2.7.2 Redirecting Output

@andychu
Copy link
Contributor

andychu commented Dec 10, 2024

Thanks for noticing this! And for finding the documentation

If you have any time or interest, a patch would be very welcome -- I usually use grep to find the tests and the code

$ grep noclobber */*.py
core/process.py:                # noclobber flag is OR'd with other flags when allowed
core/process.py:                noclobber_mode = O_EXCL if self.exec_opts.noclobber() else 0
core/process.py:                    # NOTE: This is different than >| because it respects noclobber, but
core/process.py:                    mode = O_CREAT | O_WRONLY | O_TRUNC | noclobber_mode
core/process.py:                    mode = O_CREAT | O_WRONLY | O_APPEND | noclobber_mode
core/process.py:                    if e.errno == EEXIST and self.exec_opts.noclobber():
core/process.py:                        extra = ' (noclobber)'
frontend/option_def.py:    ('C', 'noclobber'),
frontend/option_def.py:    # set -o noclobber, etc.
osh/word_eval.py:    if exec_opts.noclobber():

and

andy@hoover:~/git/oilshell/oil$ grep noclobber spec/*

spec/redirect.test.sh:set -o noclobber
spec/sh-options.test.sh:#### noclobber off
spec/sh-options.test.sh:set +o noclobber
spec/sh-options.test.sh:#### noclobber on
spec/sh-options.test.sh:#### noclobber on <>

https://github.com/oils-for-unix/oils/wiki/Contributing

https://github.com/oils-for-unix/oils/wiki/Where-Contributors-Have-Problems

I'm pretty sure @momiji helped us with this a few months ago

@Janfel
Copy link
Author

Janfel commented Dec 10, 2024

I’ve looked into it and this seems to be a more complex topic than I thought, if you want to do it right that is. See the discussion in the comments of https://unix.stackexchange.com/questions/720024/is-dev-null-treated-differently-from-other-files-when-the-noclobber-option.

@andychu
Copy link
Contributor

andychu commented Dec 12, 2024

OK, thank you for looking into it, and thanks for the report!

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

No branches or pull requests

2 participants