[Ms-nfs41-client-devel] Fwd: Implementing mkfifo, mknod support with NFS_SPECFILE_FIFO and NFS_SPECFILE_SOCK?

Corinna Vinschen corinna-cygwin@cygwin.com
Tue Feb 4 11:08:07 GMT 2025


On Jan 31 14:23, Roland Mainz via Cygwin wrote:
> On Thu, Jan 30, 2025 at 2:34 PM Cedric Blancher
> <cedric.blancher@gmail.com> wrote:
> [snip]
> > Does the ms-nfs41-client support NFS_SPECFILE_FIFO and NFS_SPECFILE_SOCK?
>> No, but if Cygwin implements this for the Microsoft NFSv3 client then
> I'll add support for ms-nfs41-client and ms-nfs42-client ASAP.
>> But I really would prefer if Cygwin would NOT use |NFS_SPECFILE_LNK|
> (all other |NFS_SPECFILE_*| would be OK), because it seems to be
> limited to |2050| bytes, while ms-nfs41-client/ms-nfs42-client doesn't
> have such a limit (currently supported are 4096 byte long paths, which
> sites like CERN&&Pasteur really use (measured by the bug reports about
> "... paths with 3280 bytes etc don't work...") ...).
>> Question for Corinna:
> Why did Cygwin never use
> |NFS_SPECFILE_FIFO|/|NFS_SPECFILE_SOCK|/|NFS_SPECFILE_CHR| from
> https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ff4df658-7f27-476a-8025-4074c0121eec
> ?

Because I didn't know about it until I read your mail.
The NFS code in Cygwin is basically from 2008. Back in those days, I
learned how to access NFS using EAs from a nice developer at Microsoft,
who worked on SFU at the time. There was never any communication about
an additional reparse point type, and I'm pretty sure it wasn't officially
documented at the time either.
However, testing is better than talking, so I quickly hacked up an STC:
$ cat > mk-dev-nfs.c <<EOF
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
typedef struct {
 DWORD ReparseTag;
 WORD ReparseDataLength;
 WORD Reserved;
 struct {
	BYTE DataBuffer[1];
 } GenericReparseBuffer;
 struct {
	ULONGLONG	Type;
	union {
	 struct {
	 ULONG	Major;
	 ULONG	Minor;
	 } Device;
	 WCHAR		LnkBuffer[1];
	};
 } NfsReparseBuffer;
} MY_REPARSE_DATA_BUFFER, *MY_PREPARSE_DATA_BUFFER;
#define NFS_SPECFILE_LNK	0x00000000014B4E4CL
#define NFS_SPECFILE_CHR	0x0000000000524843L
#define NFS_SPECFILE_BLK	0x00000000004B4C42L
#define NFS_SPECFILE_FIFO	0x000000004F464946L
#define	NFS_SPECFILE_SOCK	0x000000004B434F53L
int
main (int argc, char **argv)
{
 HANDLE fh;
 char buf[65536];
 DWORD size_ret;
 MY_PREPARSE_DATA_BUFFER rp;
 if (argc < 3)
 {
 fprintf (stderr, "usage: %s <name> b|c|f|s [major] [minor]\n", argv[0]);
 return 1;
 }
 fh = CreateFile (argv[1],
 GENERIC_WRITE,
 0,
 NULL,
 CREATE_ALWAYS,
 FILE_FLAG_BACKUP_SEMANTICS
 | FILE_FLAG_OPEN_REPARSE_POINT,
 NULL);
 if (fh == INVALID_HANDLE_VALUE)
 {
 fprintf (stderr, "CreateFile: %d\n", GetLastError ());
 return 1;
 }
 rp = (MY_PREPARSE_DATA_BUFFER) buf;
 rp->ReparseTag = IO_REPARSE_TAG_NFS;
 rp->ReparseDataLength = sizeof (ULONGLONG);
 switch (argv[2][0])
 {
 case 'b':
 case 'c':
 if (argc != 5)
 {
	 fprintf (stderr, "usage: %s <name> b|c|f|s [major] [minor]\n",
		 argv[0]);
	 return 1;
	}
 rp->ReparseDataLength += 2 * sizeof (ULONG);
 rp->NfsReparseBuffer.Type = argv[2][0] == 'b' ?
				 NFS_SPECFILE_BLK
				 : NFS_SPECFILE_CHR;
 rp->NfsReparseBuffer.Device.Major = strtoul (argv[3], NULL, 0);
 rp->NfsReparseBuffer.Device.Minor = strtoul (argv[4], NULL, 0);
 break;
 case 'f':
 rp->NfsReparseBuffer.Type = NFS_SPECFILE_FIFO;
 break;
 case 's':
 rp->NfsReparseBuffer.Type = NFS_SPECFILE_SOCK;
 break;
 }
 rp->ReparseDataLength = sizeof (ULONGLONG) + 2 * sizeof (ULONG);
 rp->NfsReparseBuffer.Type = NFS_SPECFILE_BLK;
 if (! DeviceIoControl (fh, FSCTL_SET_REPARSE_POINT,
 (LPVOID) buf,
 REPARSE_GUID_DATA_BUFFER_HEADER_SIZE
 + rp->ReparseDataLength,
 NULL, 0, &size_ret, NULL))
 {
 fprintf (stderr, "DeviceIoControl: %d\n", GetLastError ());
 CloseHandle (fh);
 DeleteFile (argv[1]);
 return 1;
 }
 CloseHandle (fh);
 return 0;
}
EOF
$ gcc -g ../src/mk-dev-nfs.c -o mk-dev-nfs
$ pwd
/home/corinna/tests/x86_64
$ mount | grep tests
//calimero.vinschen.de/cygwin/tests on /home/corinna/tests type nfs (binary,user,bind)
So we're in an NFS-mounted directory, let's try to create a FIFO:
$ ./mk-dev-nfs
usage: ./mk-dev-nfs <name> b|c|f|s [major] [minor]
$ ./mk-dev-nfs fifo f
DeviceIoControl: 50
$ ll fifo
ls: cannot access 'fifo': No such file or directory
$ ./mk-dev-nfs sock s
DeviceIoControl: 50
$ ./mk-dev-nfs blk b 0 0
DeviceIoControl: 50
$ ./mk-dev-nfs chr c 0 0
DeviceIoControl: 50
So... if you tell me what I'm doing wrong, I'm all ears.
Corinna


More information about the Cygwin mailing list

AltStyle によって変換されたページ (->オリジナル) /