From: Houder <houder@xs4all.nl>
To: cygwin@cygwin.com
Subject: Re: /dev/fd/N not synonymous with file descriptor N; it is on Linux
Date: Tue, 22 Jan 2019 08:57:00 -0000 [thread overview]
Message-ID: <1c60402837d6510667357257b5e96e88@xs4all.nl> (raw)
In-Reply-To: <d6431739e2801a80d73e7cb68b4fcc19@smtp-cloud8.xs4all.net>
[-- Attachment #1: Type: text/plain, Size: 1212 bytes --]
On 2019-01-22 09:50, Houder wrote:
> On Sun, 6 Jan 2019 21:19:50, Corinna Vinschen wrote:
>>
>> On Dec 16 17:31, Houder wrote:
>> > 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 should work in the latest developer snapshot uploaded to
>> https://cygwin.com/snapshots/ Please give it a try.
>>
>> Thanks,
>> Corinna
>
> Nice!
>
> This solves: <program> -i /dev/fd/N N<<EOF (i.e. Steven Penny's
> problem)
>
> Howver ...
> (and I sure that I am not telling you anything new)
>
> it still not the same as Linux ...
>
> So, for the record only:
and as another example, this STC succeeds on Linux ..., but fails on
Cygwin.
64-@@ ./stca /dev/fd/0 <<EOF
> bla
> EOF
fd1 = 0
argv[1] = /dev/fd/0
fd2 = 3
id = writefd2, errno = 13, errstr = Permission denied
64-@@
=====
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: stca.c --]
[-- Type: text/x-c; name=stca.c, Size: 6104 bytes --]
// gcc -Wall -o stca stca.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> // strerror()
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h> // lstat()
#include <time.h>
/*
A file that has been deleted, but is still "held open" by an entry in the open file table
(i.e. the file is referred by an open file descriptor), can be opened again read-write in
Linux, but not in Cygwin ...
*/
// NOTE: my text uses "fd 2" for a file descriptor that equals 2; and fd2 for variable fd2
static int
errExit(const char *str)
{
printf("id = %s, errno = %d, errstr = %s\n", str, errno, strerror(errno));
fflush(stdout);
exit(EXIT_FAILURE);
}
static void
Usage(const char *const arg)
{
fprintf(stderr, "Usage: %s /dev/fd/N\n", arg);
exit(EXIT_FAILURE);
}
#if 0
#define DISPLAYSTATINFO
static void displayStatInfo(const struct stat *sb);
#endif
// invoke as follows: ./stca /dev/fd/0 <<EOF
int
main(int argc, char *argv[])
{
if (argc < 2) {
Usage(argv[0]);
exit(EXIT_SUCCESS);
}
// @@ ./stca /dev/fd/8 8<<EOF 0<&- # fd 8 is connected to tmpfile (bash!)
// using an argument, the stc can be told to read from fd 8 (fd 0 can be closed)
// @@ ./stca /dev/fd/5 8<<EOF 5<&8- 0<&- # ... here fd 0 and fd 8 are closed
// kludge
if (strlen(argv[1]) < 9) Usage(argv[0]);
if (strncmp(argv[1], "/dev/fd/", 8) != 0) Usage(argv[0]);
if ( (strlen(argv[1]) > 9) ||
( (argv[1][8] - 0x30 < 0) || (argv[1][8] - 0x30 > 9) ) ) {
fprintf(stderr, "N must be a single digit, please!\n");
Usage(argv[0]);
}
// end kludge
int fd1;
fd1 = argv[1][8] - 0x30;
printf("fd1 = %d\n", fd1);
// using bash, /dev/fd/N refers to a file which been unlink'ed
printf("argv[1] = %s\n", argv[1]);
errno = 0;
int fd2;
#if 0
if ( (fd2 = open(argv[1], O_RDONLY)) == -1) errExit("openfd2"); // what 'cat' does
#else
#define WRITE
if ( (fd2 = open(argv[1], O_RDWR)) == -1) errExit("openfd2");
//if ( (fd2 = open(argv[1], O_RDWR | O_APPEND)) == -1) errExit("openfd2");
#endif
printf("fd2 = %d\n", fd2);
#if defined(DISPLAYSTATINFO)
struct stat sb;
if (fstat(fd2, &sb) == -1) errExit("fstatfd2");
displayStatInfo(&sb);
#endif
/* if file has been opened read-write, write() will succeed in Linux,
but fail in Cygwin
*/
#if defined(WRITE)
if (write(fd2, "Hello, world!\n", 14) == -1) errExit("writefd2");
#endif
// how about an lseek() first? (write() modifies the file offset)
if (lseek(fd2, 0, SEEK_SET) == -1) errExit("lseekfd2");
char buf[80] = { 0 }; // another kludge
if (read(fd2, buf, sizeof(buf) ) == -1) errExit("readfd2");
printf("buf = \\\n%s", buf);
if (close(fd2) == -1) printf("closefd2 failed\n");
}
#if defined(DISPLAYSTATINFO)
#if 1
static void
displayStatInfo(const struct stat *sb)
{
printf("Link count: %ld\n", (long)sb->st_nlink);
}
#else
static char *filePermStr(mode_t perm, int flags);
static void
displayStatInfo(const struct stat *sb)
{
printf("File type: ");
// deprecated by S_ISREG(m) and c.s. ...? /usr/include/linux/stat.h
switch (sb->st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long)sb->st_ino);
#if 0
printf("Mode: %lo (octal)\n", (unsigned long)sb->st_mode);
#else
printf("Mode: %lo (octal), ls(1)-style: %s\n",
(unsigned long)sb->st_mode, filePermStr(sb->st_mode, 0));
#endif
printf("Link count: %ld\n", (long)sb->st_nlink);
printf("Ownership: UID=%ld GID=%ld\n", (long)sb->st_uid, (long)sb->st_gid);
printf("Preferred I/O block size: %ld bytes\n", (long)sb->st_blksize);
printf("File size: %lld bytes\n", (long long)sb->st_size);
printf("Blocks allocated: %lld\n", (long long)sb->st_blocks);
printf("Last status change: %s", ctime(&sb->st_ctime));
printf("Last file access: %s", ctime(&sb->st_atime));
printf("Last file modification: %s", ctime(&sb->st_mtime));
}
/* Return ls(1)-style string for file permissions mask */
/* Include set-user-ID, set-group-ID, and sticky bit information in
returned string */
#define FP_SPECIAL 1
#define STR_SIZE sizeof("rwxrwxrwx")
static char *
filePermStr(mode_t perm, int flags)
{
static char str[STR_SIZE];
/* If FP_SPECIAL was specified, we emulate the trickery of ls(1) in
returning set-user-ID, set-group-ID, and sticky bit information in
the user/group/other execute fields. This is made more complex by
the fact that the case of the character displayed for this bits
depends on whether the corresponding execute bit is on or off. */
snprintf(str, STR_SIZE, "%c%c%c%c%c%c%c%c%c",
(perm & S_IRUSR) ? 'r' : '-', (perm & S_IWUSR) ? 'w' : '-',
(perm & S_IXUSR) ?
(((perm & S_ISUID) && (flags & FP_SPECIAL)) ? 's' : 'x') :
(((perm & S_ISUID) && (flags & FP_SPECIAL)) ? 'S' : '-'),
(perm & S_IRGRP) ? 'r' : '-', (perm & S_IWGRP) ? 'w' : '-',
(perm & S_IXGRP) ?
(((perm & S_ISGID) && (flags & FP_SPECIAL)) ? 's' : 'x') :
(((perm & S_ISGID) && (flags & FP_SPECIAL)) ? 'S' : '-'),
(perm & S_IROTH) ? 'r' : '-', (perm & S_IWOTH) ? 'w' : '-',
(perm & S_IXOTH) ?
(((perm & S_ISVTX) && (flags & FP_SPECIAL)) ? 't' : 'x') :
(((perm & S_ISVTX) && (flags & FP_SPECIAL)) ? 'T' : '-'));
return str;
}
#endif
#endif
//=====
[-- 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 prev parent reply other threads:[~2019-01-22 8:57 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-16 16:31 Houder
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 [this message]
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=1c60402837d6510667357257b5e96e88@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).