bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why does "mapfile -d delim" (delim != '\n') use unbuffered read?


From: Robert Elz
Subject: Re: Why does "mapfile -d delim" (delim != '\n') use unbuffered read?
Date: Wed, 05 May 2021 03:05:07 +0700

    Date:        Tue, 4 May 2021 09:28:04 -0400
    From:        Chet Ramey <chet.ramey@case.edu>
    Message-ID:  <c8b1b097-d430-e840-017d-52a1a6a393d0@case.edu>

  | The issue with the BSDs and terminal devices is that the current code
  | only checks for -1/ESPIPE, but they return a different value for errno
  | (EINVAL? I forget.)

On traditional unix, since forever, lseek() on a terminal is simply a no-op.
(The seek() sys call that preceded it, on 6th edition and earlier was the 
same.) No error, no effect -- or no useful effect, the "file offset" might
get set, so you can't even:
        pos = lseek(0,somewhere,0);
        if (lseek(0, pos, 0) != somewhere)
                /* unseekable */
as that would probably (seem to) succeed, but terminals don't use it.

jinx$ cat /tmp/t.c
main()
{
   if (lseek(0, 0L, 0) < 0)
        perror("lseek");
   exit(0);
}
jinx$ # ignore the gcc warnings when compiling this nonsense...
jinx$ /tmp/t
jinx$ 

(stdin was the terminal)

jinx$ /tmp/t < /etc/motd
jinx$ cat /etc/motd | /tmp/t
lseek: Illegal seek
jinx$ 

If you want to add this optimisation, just fstat(0, &...) and check
for it being a regular file.   If it is, then check if lseek will work
(pipes tend to masquerade as files in some systems when examined this way).

Otherwise fall back to byte at a time reads.  (The \n delimiter special case
just optimises for terminal input, where one line max is all you get, but
that doesn't help if you want to end the read on some other delimiter).

You could optimise block devices (and yes, even the block device interface
to a tape drive, seek works there - I once ran the root filesystem from
a 9 track (reel to reel) tape (read only of course) - slow, but it worked.
But why would anyone care?  What would be the use case for sh's "read" from
a block device?  Just leave that slow for anyone weird enough to try it.
But block devices are for housing filesystems, which requires the ability
to seek, so by definition, any block device must support seek.

kre





reply via email to

[Prev in Thread] Current Thread [Next in Thread]