Subject: [clisp-list] with-open-file limitation on linux

From: Peter Wood <[email-masked]>
Date: Sun Feb 24 07:57:01 2002

Hi

This may be of interest to Clispers on Linux.  Certain functions of
the linux kernel can be controlled by echoing a '1' or '0' or '-1' to
various files in the /proc filesystem. (Common knowledge)

It turns out that Common Lisp's built in #'open and the with-open-file
macro are useless for writing to these files.  The kernel expects to
have the number echoed thus:

$ echo -1 > /proc/sys/fs/bin_fmt/status 

(for example)

and the shell redirection operator '>' results in the the file being
truncated to zero length.  CL doesn't seem to allow for this behaviour
in #'open keywords.  I tried :supersede :overwrite and :append and
they all resulted in Unix error EINVAL (invalid argument) and a
rubbished terminal.

I ended up using (linux:fopen "path" "w") since the "w" mode
automatically results in truncation to zero length,  and it worked
fine.

Regards,
Peter

---

From: [email-masked] (Don Cohen)
Date: Sun Feb 24 08:34:02 2002

> $ echo -1 > /proc/sys/fs/bin_fmt/status 
Well, I don't seem to have this file, so it's possible that it's a
problem with this particular file.
Since every proc file has its own program for read/write it seems
possible (even likely) that different files will act in different
ways. 

 > they all resulted in Unix error EINVAL (invalid argument) and a

I don't see this problem (see below) unless I try to write as
non-root.

[1]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout") (read f))
299
[2]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout" :direction :output) (princ "1100" f))
"1100"
[3]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout") (read f))
1100
[4]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout" :direction :output) (princ "300" f))
"300"
[5]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout") (read f))
3000

 ;; oops ...

[6]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout" :direction :output ) (format f "300~%"))
NIL
[7]> (with-open-file (f "/proc/sys/net/ipv4/route/gc_timeout") (read f))
300
[8]> 

and at this point in another shell
cat /proc/sys/net/ipv4/route/gc_timeout
300

---

From: Peter Wood <[email-masked]>
Date: Sun Feb 24 09:58:03 2002

>  > the linux kernel can be controlled by echoing a '1' or '0' or '-1' to
                                                      ^^^^^^^^^^^^^^^^^

>  > macro are useless for writing to these files.  The kernel expects to
                                   ^^^^^^^^^^^^^^^
> possible (even likely) that different files will act in different

You won't have it unless you enabled the binfmt_misc option when you
built the kernel.  You are right about different files acting
differently.  I have been writing to (for example)
/proc/sys/fs/binfmt_misc/register from lisp every time my machine
boots for several months.  The problem I described only applies to the
files in binfmt_misc, which can be controlled by a -1, 0 or 1.  I did
mention that.

> I don't see this problem (see below) unless I try to write as

You don't see _this_ problem even if you do try to write as non-root,
you see _another_ problem. :-)

You don't see it because you aren't doing the same thing as I was.  I
believe it only applies to files which the kernel expects to be
truncated to zero length (as happens when you use the redirection
operator '>'.  (info bash)) Echoing a -1 to
/proc/sys/fs/binfmt_misc/status does not leave status with a '-1' in
it, it _removes_ status and any files have been registered through
/proc/sys/fs/binfmt_misc/register.

> cat /proc/sys/net/ipv4/route/gc_timeout

I know with-open-file works on some files in the system, because I've
been using lisp to write to them for some time.  But it does not work
with the files in /proc/sys/fs/binfmt_misc/ _except_ the file called
register which doesn't get truncated.  Try wiping out gc_timeout in
your example above with:

echo > /proc/.../gc_timeout

And you'll find it still contains the value 300.  Normally, that would
leave an empty file.  

I do think the problem I described is due to the kernel needing the
file to be truncated to zero length before they get written to.  That
is what happens when fopen() gets called on the file with a MODE of
"w", and using linux:fopen allows me to write to it from lisp.

Regards,
Peter