From: Houder <houder@xs4all.nl>
To: cygwin@cygwin.com
Subject: /dev/fd/N not synonymous with file descriptor N; it is on Linux
Date: Sun, 16 Dec 2018 16:31:00 -0000 [thread overview]
Message-ID: <0f030e809f063f5a5e64ff7a7a0c3227@xs4all.nl> (raw)
[-- Attachment #1: Type: text/plain, Size: 956 bytes --]
L.S.,
/dev/fd/N not synonymous with file descriptor N; it is on Linux
64-@@ cat /dev/fd/0 <<\EOF
> Hi
> EOF
cat: /dev/fd/0: No such file or directory
fails on Cygwin; not on Linux.
Also see:
https://cygwin.com/ml/cygwin/2018-12/msg00028.html
( Bash heredoc on FD 3 )
Based on the output of strace on Linux, I composed an STC, that
duplicates
the steps taken by bash (and cat).
This STC succeeds on Linux, but fails on Cygwin.
What does the STC do:
- it creates a (temporary) file in the same way that bash does
- the file is written to, the file descriptor is closed and the file
unlinked
- however, before the file is unlinked, it is opened a second time,
like bash
would do
Next
- the file /dev/fd/N is opened, where N is the file descriptor that has
been
left open; this is what the "cat command" would do.
The "cat command" on Linux succeeds; it fails on Cygwin.
Regards,
Henri
STC attached (hopefully)
=====
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: stc.c --]
[-- Type: text/x-c; name=stc.c, Size: 3256 bytes --]
// gcc -Wall -o stc stc.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> // strerror()
#include <errno.h>
#include <fcntl.h>
/*
LPI, 5.11 The /dev/fd Directory (Linux Programming Interface, Michael Kerrisk)
"For each process, the kernel provides the special virtual directory /dev/fd.
This directory contains filenames of the form /dev/fd/n, where n is a number
corresponding to one of the open file descriptors for the process."
"... Opening one of the files in the /dev/fd directory is equivalent to duplicating
the corresponding file descriptor. ..."
"... The files in the /dev/fd directory are rarely used within programs. Their most
common use is in the shell. Many user-level commands take filename arguments, and
sometimes we would like to put them in a pipeline and have one of the arguments be
standard input or output instead. ..."
*/
void
errExit(const char *str)
{
printf("id = %s, errno = %d, errstr = %s\n", str, errno, strerror(errno));
fflush(stdout);
exit(EXIT_FAILURE);
}
int
main()
{
int fd1, fd2, fd3;
errno = 0;
// create a tmpfile in the same way that bash would do ...
fd1 = open("/tmp/stc.txt", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
if (fd1 == -1)
errExit("openfd1");
errno = 0;
if (write(fd1, "Hello, world!\n", 14) == -1) errExit("writefd1");
errno = 0;
// also open this tmpfile for reading like bash would do ...
fd2 = open("/tmp/stc.txt", O_RDONLY);
if (fd2 == -1)
errExit("openfd2");
errno = 0;
// close fd 1 like bash would do ...
if (close(fd1) == -1) errExit("closefd1");
errno = 0;
// delete the tmpfile like bash would do ...
if (unlink("/tmp/stc.txt") == -1) errExit("unlink");
// kludge: compose a string (using fd2) representing "the device file"
// in /dev/fd (a symlnk to /proc/self/fd) for the file descriptor fd 2
// that is still open ...
char devfile[12] = "/dev/fd/"; devfile[8] = fd2 + 0x30; devfile[9] = '\0';
printf("devfile = %s\n", devfile);
errno = 0;
// open this device file; it succeeds on Linux, but fails on Cygwin ...
fd3 = open(devfile, O_RDONLY);
const char *id = "openfd3";
if (fd3 == -1) {
#if 0
errExit(id);
#else
printf("%s: Cannot open!, id = %s, errno = %d, errmsg = %s\n", devfile,
id, errno, strerror(errno));
char buf[16] = { 0 };
// however the file to which the symlnk refers, is still present ...
// Q: does Cygwin attempt to read the /tmp directory? (an attempt that
// will fail, because the file has been unlinked)
// it appears that a readlink of a file in /dev/fd must be diverted to
// the open file descriptor of the process ...
errno = 0;
if (read(fd2, buf, sizeof(buf) ) == -1) errExit("readfd2");
printf("buf = %s", buf);
if (close(fd2) == -1) printf("closefd2 failed\n");
exit(EXIT_FAILURE);
#endif
}
char buf[16] = { 0 };
errno = 0;
if (read(fd3, buf, sizeof(buf) ) == -1) errExit("readfd3");
printf("buf = %s", buf);
if (close(fd3) == -1) printf("closefd3 failed\n");
if (close(fd2) == -1) printf("closefd2 failed\n");
}
//=====
[-- Attachment #3: Type: text/plain, Size: 219 bytes --]
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
next reply other threads:[~2018-12-16 16:31 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-16 16:31 Houder [this message]
2018-12-16 20:28 ` Corinna Vinschen
2018-12-16 20:31 ` Corinna Vinschen
2018-12-16 21:36 ` Wayne Davison
2018-12-16 21:55 ` Corinna Vinschen
2018-12-17 4:30 ` Houder
2018-12-17 9:25 ` Corinna Vinschen
2018-12-17 11:26 ` Corinna Vinschen
2019-01-02 13:56 ` Houder
2018-12-17 3:41 ` Houder
2019-01-06 20:19 ` Corinna Vinschen
2019-01-22 8:50 ` Houder
2019-01-22 8:57 ` Houder
2019-01-22 9:06 ` Corinna Vinschen
2019-01-22 9:25 ` Houder
2019-01-22 9:42 ` Corinna Vinschen
2019-01-22 10:20 ` Houder
2019-01-22 10:39 ` Corinna Vinschen
2019-01-27 18:39 ` Houder
2019-01-27 21:57 ` Corinna Vinschen
2019-01-27 22:12 ` Corinna Vinschen
2019-01-28 14:15 ` Houder
2019-01-28 16:51 ` Corinna Vinschen
2019-01-22 9:02 ` Corinna Vinschen
2019-01-22 9:07 ` Corinna Vinschen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0f030e809f063f5a5e64ff7a7a0c3227@xs4all.nl \
--to=houder@xs4all.nl \
--cc=cygwin@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).