Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening a device file using erlang

Is there any way to open a terminal device file in erlang ?

I am on Solaris and I am trying the following::

Erlang (BEAM) emulator version 5.6 [source] [64-bit] [async-threads:0] [kernel-poll:false]

/xlcabpuser1/xlc/abp/arunmu/Dolphin/ebin
Eshell V5.6  (abort with ^G)
1> file:open("/dev/pts/2",[write]).
{error,eisdir}
2> file:open("/dev/null",[write]).
{ok,}
3>

As can be seen above the erlang file driver has no problem in opening a null fle but does not open a terminal device file!!

Unable to come to a conclusion as the file driver is able to open a null file.

Is there any other way to open terminal device files ?

Thanks

like image 834
Arunmu Avatar asked Dec 23 '10 09:12

Arunmu


1 Answers

Update: I was able to work around the limitation described below using a port. For example, here is a sample program that prints "hello world" to /dev/stdout:

-module(test).
-export([main/1]).

main(X) ->
    P = open_port({spawn, "/bin/cat >/dev/stdout"}, [out]),
    P ! {self(), {command, "hello world"}}.

This is a bit inconvenient because a port doesn't act like a regular file, but at least it's one way to get the job done.


In efile_openfile() (in erts/emulator/drivers/unix/unix_efile.c) there is the following code:

    if (stat(name, &statbuf) >= 0 && !ISREG(statbuf)) {
#if !defined(VXWORKS) && !defined(OSE)
        /*
         * For UNIX only, here is some ugly code to allow
         * /dev/null to be opened as a file.
         *
         * Assumption: The i-node number for /dev/null cannot be zero.
         */
        static ino_t dev_null_ino = 0;

        if (dev_null_ino == 0) {
            struct stat nullstatbuf;

            if (stat("/dev/null", &nullstatbuf) >= 0) {
                dev_null_ino = nullstatbuf.st_ino;
            }
        }
        if (!(dev_null_ino && statbuf.st_ino == dev_null_ino)) {
#endif
            errno = EISDIR;
            return check_error(-1, errInfo);
#if !defined(VXWORKS) && !defined(OSE)
        }
#endif
    }

This code (confusingly) returns the EISDIR error if the file is not a regular file (which is the ISREG(statbuf) check), unless the file specifically is /dev/null. The file(3) documentation states:

     eisdir :
       The named file is not a regular file. It  may  be  a  directory,  a
       fifo, or a device.

so it's actually documented to do that. I'm not sure why that restriction exists, though—perhaps it's got something to do with performance because device drivers might block for more time than an ordinary file generally will.

like image 127
Greg Hewgill Avatar answered Sep 23 '22 15:09

Greg Hewgill