public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Johannes Schindelin <johannes.schindelin@gmx.de>
To: cygwin-patches@cygwin.com
Subject: [PATCH 1/2] Implicitly support the /dev/fd symlink and friends
Date: Mon, 21 Feb 2022 14:36:37 +0100 (CET)	[thread overview]
Message-ID: <3a2c29ef16c74f83237d5e55119e8b1e2f069f36.1645450518.git.johannes.schindelin@gmx.de> (raw)
In-Reply-To: <cover.1645450518.git.johannes.schindelin@gmx.de>

Bash has a very convenient feature that is called process substitution
(e.g. `diff -u <(seq 0 10) <(seq 1 11)`). To make this work, Bash
requires the `/dev/fd` symlink to exist, and Cygwin therefore creates
this symlink (together with the `stdin`, `stdout` and `stderr` ones)
upon start-up.

This strategy is incompatible with the idea of providing a subset of
Cygwin in a `.zip` file (because there is no standard way to represent
symlinks in `.zip` files, and besides, older Windows versions would
potentially lack support for them anyway).

That type of `.zip` file is what Git for Windows wants to use, though,
bundling a minimal subset for third-party applications in MinGit (see
https://github.com/git-for-windows/git/wiki/MinGit for details).

Let's side-step this problem completely by creating those symlinks
implicitly, similar to the way `/dev/` is populated with special
devices.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 winsup/cygwin/Makefile.am        |  1 +
 winsup/cygwin/devices.h          |  3 +-
 winsup/cygwin/devices.in         |  4 +++
 winsup/cygwin/dtable.cc          |  3 ++
 winsup/cygwin/fhandler.h         | 28 +++++++++++++++++
 winsup/cygwin/fhandler_dev_fd.cc | 53 ++++++++++++++++++++++++++++++++
 6 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 winsup/cygwin/fhandler_dev_fd.cc

diff --git a/winsup/cygwin/Makefile.am b/winsup/cygwin/Makefile.am
index 2b8e87fcd0..c8936354b8 100644
--- a/winsup/cygwin/Makefile.am
+++ b/winsup/cygwin/Makefile.am
@@ -230,6 +230,7 @@ DLL_FILES= \
 	fhandler_console.cc \
 	fhandler_cygdrive.cc \
 	fhandler_dev.cc \
+	fhandler_dev_fd.cc \
 	fhandler_disk_file.cc \
 	fhandler_dsp.cc \
 	fhandler_fifo.cc \
diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h
index 4310f435fe..fbbde6ab9c 100644
--- a/winsup/cygwin/devices.h
+++ b/winsup/cygwin/devices.h
@@ -70,6 +70,7 @@ enum fh_devices
   FH_NETDRIVE= FHDEV (DEV_VIRTFS_MAJOR, 194),
   FH_DEV     = FHDEV (DEV_VIRTFS_MAJOR, 193),
   FH_CYGDRIVE= FHDEV (DEV_VIRTFS_MAJOR, 192),
+  FH_DEV_FD  = FHDEV (DEV_VIRTFS_MAJOR, 191),

   FH_SIGNALFD= FHDEV (DEV_VIRTFS_MAJOR, 13),
   FH_TIMERFD = FHDEV (DEV_VIRTFS_MAJOR, 14),
@@ -436,7 +437,7 @@ extern const _device dev_fs_storage;
 #define isprocsys_dev(devn) (devn == FH_PROCSYS)

 #define isvirtual_dev(devn) \
-  (isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE)
+  (isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE || devn == FH_DEV_FD)

 #define iscons_dev(n) \
   ((device::major ((dev_t) (n)) == DEV_CONS_MAJOR) \
diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in
index f33510eb7e..7506dfe9cb 100644
--- a/winsup/cygwin/devices.in
+++ b/winsup/cygwin/devices.in
@@ -175,6 +175,10 @@ const _device dev_error_storage =
 "/dev/fd%(0-15)d", BRACK(FHDEV(DEV_FLOPPY_MAJOR, {$1})), "\\Device\\Floppy{$1}", exists_ntdev, S_IFBLK
 "/dev/scd%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
 "/dev/sr%(0-15)d", BRACK(FHDEV(DEV_CDROM_MAJOR, {$1})), "\\Device\\CdRom{$1}", exists_ntdev, S_IFBLK
+"/dev/fd", BRACK(FH_DEV_FD), "/proc/self/fd", exists, S_IFLNK
+"/dev/stdin", BRACK(FH_DEV_FD), "/proc/self/fd/0", exists, S_IFLNK
+"/dev/stdout", BRACK(FH_DEV_FD), "/proc/self/fd/1", exists, S_IFLNK
+"/dev/stderr", BRACK(FH_DEV_FD), "/proc/self/fd/2", exists, S_IFLNK
 %other	{return	NULL;}
 %%
 #undef BRACK
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index ce5f6411b3..28d7697259 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -579,6 +579,9 @@ fh_alloc (path_conv& pc)
 	case FH_DEV:
 	  fh = cnew (fhandler_dev);
 	  break;
+	case FH_DEV_FD:
+	  fh = cnew (fhandler_dev_fd);
+	  break;
 	case FH_CYGDRIVE:
 	  fh = cnew (fhandler_cygdrive);
 	  break;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index f764eccd33..6c1b2a8025 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -3009,6 +3009,33 @@ class fhandler_procnet: public fhandler_proc
   }
 };

+class fhandler_dev_fd: public fhandler_virtual
+{
+ public:
+  fhandler_dev_fd ();
+  virtual_ftype_t exists();
+
+  int __reg2 fstat (struct stat *buf);
+  bool fill_filebuf ();
+
+  fhandler_dev_fd (void *) {}
+
+  virtual void copy_from (fhandler_base *x)
+  {
+    pc.free_strings ();
+    *this = *reinterpret_cast<fhandler_dev_fd *> (x);
+    _copy_from_reset_helper ();
+  }
+
+  virtual fhandler_dev_fd *clone (cygheap_types malloc_type = HEAP_FHANDLER)
+  {
+    void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_dev_fd));
+    fhandler_dev_fd *fh = new (ptr) fhandler_dev_fd (ptr);
+    fh->copy_from (this);
+    return fh;
+  }
+};
+
 class fhandler_signalfd : public fhandler_base
 {
   sigset_t sigset;
@@ -3208,6 +3235,7 @@ typedef union
   char __dev_raw[sizeof (fhandler_dev_raw)];
   char __dev_tape[sizeof (fhandler_dev_tape)];
   char __dev_zero[sizeof (fhandler_dev_zero)];
+  char __dev_fd[sizeof (fhandler_dev_fd)];
   char __disk_file[sizeof (fhandler_disk_file)];
   char __fifo[sizeof (fhandler_fifo)];
   char __netdrive[sizeof (fhandler_netdrive)];
diff --git a/winsup/cygwin/fhandler_dev_fd.cc b/winsup/cygwin/fhandler_dev_fd.cc
new file mode 100644
index 0000000000..6462838317
--- /dev/null
+++ b/winsup/cygwin/fhandler_dev_fd.cc
@@ -0,0 +1,53 @@
+/* fhandler_process_fd.cc: fhandler for the /dev/{fd,std{in,out,err}} symlinks
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include "path.h"
+#include "fhandler.h"
+
+fhandler_dev_fd::fhandler_dev_fd ():
+  fhandler_virtual ()
+{
+}
+
+virtual_ftype_t
+fhandler_dev_fd::exists ()
+{
+  return virt_symlink;
+}
+
+int __reg2
+fhandler_dev_fd::fstat (struct stat *buf)
+{
+  const char *path = get_name ();
+  debug_printf ("fstat (%s)", path);
+
+  fhandler_base::fstat (buf);
+
+  buf->st_mode = S_IFLNK | STD_RBITS | S_IWUSR | S_IWGRP | S_IWOTH | STD_XBITS;
+  buf->st_ino = get_ino ();
+
+  return 0;
+}
+
+bool
+fhandler_dev_fd::fill_filebuf ()
+{
+  const char *path = get_name ();
+  debug_printf ("fill_filebuf (%s)", path);
+
+  const char *native = get_native_name ();
+  if (!native)
+    {
+      return false;
+    }
+
+  free(filebuf);
+  filebuf = cstrdup (native);
+  return true;
+}
--
2.35.1



  reply	other threads:[~2022-02-21 13:36 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-21 13:36 [PATCH 0/2] Provide virtual /dev/fd and /dev/{stdin,stdout,stderr} symlinks Johannes Schindelin
2022-02-21 13:36 ` Johannes Schindelin [this message]
2022-02-21 13:36 ` [PATCH 2/2] Regenerate devices.cc Johannes Schindelin
2022-02-22 12:34 ` [PATCH 0/2] Provide virtual /dev/fd and /dev/{stdin,stdout,stderr} symlinks Corinna Vinschen
2022-02-25 15:46   ` [PATCH 0/2] Provide virtual /dev/fd and /dev/{stdin, stdout, stderr} symlinks Johannes Schindelin
2022-02-28  9:24     ` Corinna Vinschen
2022-02-28  9:57       ` Corinna Vinschen
2023-03-28  8:34         ` Johannes Schindelin
2022-02-25 18:35 ` [PATCH 0/2] Provide virtual /dev/fd and /dev/{stdin,stdout,stderr} symlinks Brian Inglis
2023-03-28  8:36   ` Johannes Schindelin

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=3a2c29ef16c74f83237d5e55119e8b1e2f069f36.1645450518.git.johannes.schindelin@gmx.de \
    --to=johannes.schindelin@gmx.de \
    --cc=cygwin-patches@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).