Re: File type nomenclature in 170 Lassi Kortela 31 Jul 2020 11:44 UTC

Point 3, identifying a file's type. We do it with these predicates:

(file-info-directory? file-info)  POSIX S_ISDIR()
(file-info-fifo? file-info)       POSIX S_ISFIFO()
(file-info-symlink? file-info)    POSIX S_ISLNK()
(file-info-regular? file-info)    POSIX S_ISREG()

If these are kept, we should add `file-info-socket?` and

I would replace these with a single procedure: (file-info:type
file-info). It would return a symbol that is one of:

- file (regular files only)
- pipe (named pipes and anonymous pipes, which Unix says are same)
- socket (local-domain, internet, etc. sockets, all are one to Unix)
- device (block and character devices, are the same on some kernels)
- directory (speaks for itself; also Windows drives are dirs)

The equivalent WinAPI ones from

- FILE_ATTRIBUTE_REPARSE_POINT (one of the weird symlink emulations)
- other ones are regular files

Ruby's `ftype` method classifies files like I suggest above
(<>): one of “file”,
“directory”, “characterSpecial”, “blockSpecial”, “fifo”, “link”,
“socket”, or “unknown”.

Really the character-special vs block-special distinction is pretty moot
at this point. FreeBSD hasn't had block devices in years. Windows only
has "devices". And people who care about block vs character devices can
always go fishing in the raw bitfield from `file-info:mode`.

The word "special" (as opposed to "device") is also confusing and I
think we shouldn't promulgate it.

Here's a demo program that shows Unix thinks named pipes (FIFOs) and
anon pipes are the same in this respect as well:

#include <sys/types.h>

#include <sys/socket.h>
#include <sys/stat.h>

#include <arpa/inet.h>
#include <netinet/in.h>

#include <stdio.h>
#include <unistd.h>

#define NAMED "our-named-pipe"

static struct stat st;

static int classify(const char *which, int stat_retval) {
   int is_pipe;

   if (stat_retval == -1)
     return -1;
   is_pipe = (st.st_mode & S_IFMT) == S_IFIFO;
   printf("%s %s\n", which, is_pipe ? "is a pipe" : "Ceci n'est pas une
   return 0;

int main(void) {
   int fds[2];

   if (pipe(fds) == -1)
     return 1;
   if (classify("anon pipe reader", fstat(fds[0], &st)) == -1)
     return 1;
   if (classify("anon pipe writer", fstat(fds[1], &st)) == -1)
     return 1;
   if (mkfifo(NAMED, 0600) == -1)
     return 1;
   if (classify("named pipe", stat(NAMED, &st)) == -1)
     return 1;
   return 0;

Here's a comparison of named pipes on Unix and Windows: