Possible bug in .read when a directory is specified?
(1) By L Carl (lcarlp) on 2020-07-16 17:50:47 [link]
I have a file named v3_port.sql with some SQL statements in it, and also a directory named v3_port. Maybe not the best idea, but that’s what I had. I entered the command: .read v3_port I meant to say v3_port.sql, but I left off the extension due to a habit formed when I was working with Oracle. Strangely, it appeared to do nothing at all when I specified the directory. There were no error messages and as far as I can tell it did not try to read any of the files in that directory. Is this expected behavior? I would have preferred an error message, “Hey! Wake up! That’s a directory!”. But, maybe there’s a good reason why it doesn’t do that.
(2) By Stephan Beal (stephan) on 2020-07-16 17:58:15 in reply to 1 [link]
> Strangely, it appeared to do nothing at all when I specified the directory. On Unix systems, at least, directories can be fopen()ed just like files, and they contain binary content. It sounds like perhaps yours started with a NUL byte which ended the "sql" the shell thought it was reading. That's *actually* correct behavior, but the shell could arguably check whether it's a directory before opening it. (The same thing bit me in another piece of software a few years ago.)
(3) By anonymous on 2020-07-17 13:42:08 in reply to 2 [link]
> On Unix systems, at least, directories can be fopen()ed just like files, and they contain binary content. Not sure what does POSIX specify about this, but trying to `fread()` (but not `fopen()`!) a directory on GNU/Linux results in an error: ```c #include <errno.h> #include <stdio.h> #include <string.h> char buf[256]; int main() { int e; size_t i; FILE * f = fopen(".", "r"); printf("%p\n", f); if (!f) return -1; i = fread(buf, 1, sizeof buf, f); e = errno; printf("%llu %d %s\n", (unsigned long long)i, e, strerror(e)); fclose(f); return 0; } ``` ``` 0x55b11dfd7010 0 21 Is a directory ```
(4) By Warren Young (wyoung) on 2020-07-17 17:19:56 in reply to 3
Those are the C library interfaces. Try the POSIX ones, without the leading “f”. I assume the Unix VFS uses the latter.
(5.2) By Stephan Beal (stephan) on 2020-07-17 17:48:20 edited from 5.1 in reply to 4 [link]
> Those are the C library interfaces. Try the POSIX ones, without the leading “f”. I assume the Unix VFS uses the latter. `open()` and `read()` do the same on my system (Mint Linux 20): ```c #include <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main() { int e; size_t i; char buf[256]; int fd = open(".", O_RDONLY); printf("%d\n", fd); if (!fd<0) return -1; i = (ssize_t) read(fd, buf, sizeof(buf)); e = errno; printf("%llu %d %s\n", (unsigned long long)i, e, strerror(e)); close(fd); return 0; } ``` Output: ``` 3 18446744073709551615 21 Is a directory ``` Whether or not that's a standard behaviour, i don't know. It was a good 5 or 6 years ago that i had a piece of software simply open/fopen and read/fread a directory handle - perhaps that was specific to those C libs. No man pages i've found make any mention of it being an error to open/fopen a directory. [IEEE fopen() lists only one error case][ieee] which sounds relevant: [ieee]: https://pubs.opengroup.org/onlinepubs/9699919799/ ``` [EISDIR] [CX] [Option Start] The named file is a directory and mode requires write access. ``` strongly implying that opening a directory *is* acceptable in read-only mode. Edit: in any case, the opening is succeeding, both with open() and fopen(), but the reading, both with read() and fread(), on my current system. [This StackOverflow answer](https://stackoverflow.com/a/24981747) says that the ability to read() a directory entry existed historically but was eventually removed. Edit: IBM's z/OS docs [say that fread() returns 0 when used to read a directory][zos], which differs from how Linux does it. Insofar as i can determine, this capability lives in the realm of implementation-defined behaviour. [zos]: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxbd00/fread.htm /shrugs shoulders
(8) By Rowan Worth (sqweek) on 2020-07-20 05:35:39 in reply to 2 [link]
Historically I recall observing the same thing, that you could even `cat` a directory and get garbage printed to your terminal. However I think it was widely regarded as a misfeature and there's generally been a move towards the `read` syscall itself returning EISDIR as noted elsewhere in the thread. I've just tested linux (3.10.0-693.5.2.el7) and OpenBSD (6.4) and they both display this behaviour. OSX (Darwin kernel 19.5.0) reports "Operation not supported" trying to cat a directory but I'm not sure how to check the syscalls here.
(6) By luuk on 2020-07-18 07:52:55 in reply to 1 [link]
On both tests there is a directory 'test' and a file 'test.sql'. Windows: ``` D:\TEMP>sqlite3 test.db SQLite version 3.32.3 2020-06-18 14:00:33 Enter ".help" for usage hints. sqlite> .read test Error: cannot open "test" sqlite> .q ``` Linux (WSL): ``` /mnt/d/TEMP$ sqlite3 test.db SQLite version 3.31.1 2020-01-27 19:55:54 Enter ".help" for usage hints. sqlite> .read test sqlite> .q ``` It could be the difference in versions, but it's different.
(7) By anonymous on 2020-07-19 14:18:48 in reply to 6 [link]
IMHO reading a directory as SQL doesn't make sense, even if it were technically possible. It would be good style to warn the user about this with an error message. W. Oertl