In a bout of hubris I produced the following (also linked from the ALU
CLiki) proposal for an operating system interface. Several issues are
still unsolved, but I like to think of this as a good start.
A reference implementation is also in the works (on SBCL).
Flames welcome,
-- Nikodemus
FI-HUT-TSIIVOLA-OSI
AN OPERATING SYSTEM INTERFACE PROPOSAL
for Common Lisp
status: unfinished (2003-05-02)
Copyright (c) 2003 Nikodemus Siivola
Permission is hereby granted, free of charge, to any person obtaining
a copy of this document (the "Document"), to deal in the Document
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Document, and to permit persons to whom the Document is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Document.
Notes
* Should the be a MAKE-DIRECTORY? It is covered by
ENSURE-DIRECTORIES-EXIST. Only reasons to include it would be a
more guessable name, and possibility to allow creation of only a
single directory (as opposed to tree).
* Currently we are throwing a lot of FILE-ERROR's around. It might
make sense to define a couple of other conditions as well...
* DEFAULT-DIRECTORY and (SETF DEFAULT-DIRECTORY) could be excluded with
the same rationale as MAKE-DIRECTORY, since this functionality
should be available via *DEFAULT-PATHNAME-DEFAULTS*. However:
- this is less verbose
- we can do some sanity checking on assignment
- we can ensure that lisp and os have the same ideas about the
default directory -- we can even deal with cwd / pwd schitzophrenia
* What about permission violations? In some cases we should provide
a :force key to ignore them (eq. read-only files owned by user),
in others we should signal errors.
* The various file attributes for supported platforms need to be
defined.
* The supported platforms need to be though about -- current spec is
a tad POSIX centric... What is supported? What about things that
are *needed* on some platforms, but do not exist on others? Should
there be OSI-WINDOWS style extensions, or should the bits not
supported on some platforms just signal NOT-SUPPORTED?
* Should there be support for directory tree traversal (ala find)? What
about copying files / trees?
package OPERATING-SYSTEM-INTERFACE
Nicknames: OSI
Exports: ENVIRONMENT-VARIABLE, (SETF ENVIRONMENT-VARIABLE),
PROBE-DIRECTORY, DIRECTORY-LIST, DELETE-DIRECTORY,
DEFAULT-DIRECTORY, (SETF DEFAULT-DIRECTORY), MAKE-LINK,
PROBE-LINK, FOLLOW-LINK, OPEN-TEMPORARY-FILE,
WITH-TEMPORARY-FILE, FILE-ATTRIBUTE-LIST, FILE-ATTRIBUTE,
(SETF FILE-ATTRIBUTE), RUN-PROGRAM,
PROGRAM, PROGRAM-PID, PROGRAM-INPUT, PROGRAM-OUTPUT,
PROGRAM-ERROR, FIND-PROGRAM
function ENVIRONMENT-VARIABLE name => string
Return the string stored in the environment variable NAME. Return
NIL if the environment variable is not defined.
function (SETF ENVIRONMENT-VARIABLE) name value => string
Assign VALUE to the environment variable NAME. VALUE is coerced to
string before assignment with (format nil "~A" value) or equivalent.
function OSI:PROBE-DIRECTORY pathspec => truename
Return the truename of PATHSPEC if it designates an
existing directory, NIL otherwise. A FILE-ERROR is
signaled if PATHSPEC is wild.
function OSI:DIRECTORY-LIST pathspec => list
Return the list of directory entries in the directory
designated by PATHSPEC. This list contains all the
immediate children of the directory: both files and
subdirectories. A FILE-ERROR is signaled if PATHSPEC does
not designate an existing directory or if the PATHSPEC is
wild.
function OSI:DELETE-DIRECTORY pathspec &key delete-tree
Delete the directory designated by PATHSPEC. If the directory is not
empty a FILE-ERROR error is signaled unless and DELETE-TREE is true,
in which case the entire directory tree is deleted. FILE-ERROR is
likewise signaled if PATHSPEC is wild or does not designate an
existing directory.
function OSI:DEFAULT-DIRECTORY => truename
Set *default-pathname-defaults* to the truename of operating systems
idea of current working directory and return the same.
function OSI:(SETF DEFAULT-DIRECTORY pathspec) => truename
Set *default-pathname-defaults* to the truename of pathspec, and set
the operating systems current working directory and the environment
variable PWD to the same.
Signals an error if PATHSPEC does not designate an existing
directory, or if PATHSPEC is wild.
function OSI:MAKE-LINK target name &key force => truename
Create a symbolic link designated by NAME to file or directory
specified by TARGET. Return truename of TARGET or NIL if file or
directory designated by TARGET didn't exist.
Signals a FILE-ERROR if the a link designated by NAME exists
already, unless FORCE is non-NIL, in which case the existing
link is updated.
Signals a FILE-ERROR if a non-link designated by NAME exists already.
function OSI:PROBE-LINK pathspec => truename
Return the truename of the symbolic link designated by PATHSPEC, or
NIL if the PATHSPEC does not designate a symbolic link. A FILE-ERROR
is signaled if PATHSPEC is wild.
function OSI:FOLLOW-LINK pathspec => pathname
Return the pathname pointed to by the symbolic link designated by
PATHSPEC. Signals a FILE-ERROR if PATHSPEC is wild or does not
designate a symbolic link.
function OSI:OPEN-TEMPORARY-FILE => two-way-stream
Return a two-way stream connected to a temporary file that is
automatically deleted when the stream is closed.
function OSI:WITH-TEMPORARY-FILE variable form*
Execute FORM's with VARIABLE bound to stream opened with
OPEN-TEMPORATY-FILE. The stream is guaranteed to be closed when
FORM's return.
function OSI:FILE-ATTRIBUTE-LIST pathspec => list
Return a list of attribute names associated with the file designated
by PATHSPEC. The list of names and their meanings is platform
dependant.
function OSI:FILE-ATTRIBUTE pathspec name => object
Return file attribute NAME of the file designated by
PATHSPEC. Signals FILE-ERROR if the designated file does not have
the attribute NAME, or if the file does not exist.
function OSI:(SETF FILE-ATTRIBUTE) pathspec name object => object
Set the file attribute NAME of the file designated by PATHSPEC to
OBJECT. Signals FILE-ERROR if the designated file does not have the
attribute NAME, or the attribute NAME is not settable, or if the
file does not exist.
function RUN-PROGRAM pathspec args &key environment wait input output
error status-hook
Creates a new process running the program found in the file
designated by PATHSPEC. ARGS are a list of strings passed as
command-line arguments to the the program. For no arguments, use
NIL.
Return NIL or a PROGRAM structure.
The &KEY arguments have the following meanings:
:ENVIRONMENT
A list of SIMPLE-STRINGs describing the environment
of the new process (on POSIX as in "man environ"). The default
is to copy the environment of the current process.
:WAIT
If non-NIL (default), wait until the created process finishes. If
NIL, return the PROGRAM structure and continue Lisp execution.
:INPUT
A stream-specifier.
:OUTPUT
A stream-specifier.
:ERROR
A stream-specifier or :OUTPUT, in which case all error output
is routed to the same place as normal output.
In this context a stream-specifier can be either T, NIL, a stream,
:STREAM, or :PTY. If T, the corresponding stream for the current
process is inherited. If NIL, /dev/null (or equivalent on non-POSIX
systems) is used. If a stream, all the input is read from that
stream and send to the subprocess. If :STREAM or :PTY, the
corresponding PROGRAM slot is filled in with a stream connected to
the process. If :PTY the stream is a pseudo-terminal
stream. Defaults to NIL.
:INPUT corresponds to *standard-input* and PROGRAM-INPUT
:OUTPUT corresponds to *standard-output* and PROGRAM-OUTPUT
:ERROR corresponds to *error-output* and PROGRAM-ERROR
structure PROGRAM
Slot accessors: PROGRAM-PID, PROGRAM-INPUT, PROGRAM-OUTPUT,
PROGRAM-ERROR
function FIND-PROGRAM name [path] => truename
Return truename of first executable file called NAME found in any of
the directories in PATH (searched in order). PATH defaults to the
environment variable PATH. If no program is found, NIL is returned.
Nikodemus Siivola <········@kekkonen.cs.hut.fi> writes:
> In a bout of hubris I produced the following (also linked from the ALU
> CLiki) proposal for an operating system interface. Several issues are
> still unsolved, but I like to think of this as a good start.
>
> [...]
I see you introduce symbolic links into the file system calculus yet
you don't define what "truename" is. I can see two possible
definitions of it:
1. Resolve symbolic links until you gain a pathname of which none of
its components name a symbolic link.
2. Just merge in enough from *default-pathname-defaults* and possible
OS defaults until you reach a pathname whose mapping to a file
system only depend on the file system itself. Vague, I know.
In face of symbolics links option 2 no longer yields a canonical name
in all cases. [Minor point: In face of hard links there is no
canonical name]. This would suggest option 1.
While option 2 it yields an IMHO more expected behavior when TRUENAME
is applied to say a stream.
So we might want both behaviors.
Further:
> function OSI:FOLLOW-LINK pathspec => pathname
>
> Return the pathname pointed to by the symbolic link designated by
> PATHSPEC. Signals a FILE-ERROR if PATHSPEC is wild or does not
> designate a symbolic link.
Suppose I do [unix pathname syntax assumed]:
(ensure-directories-exists #p"/foodir/")
(osi:make-link #p"/foodir/" #p"/zoodir/")
How am I now supposed to follow the created link?
(osi:follow-link #p"/zoodir") ;A file, eh?
or
(osi:follow-link #p"/zoodir/") ;A dir, hmm?
Further what do the following yield?
(osi:probe-directory #p"/noodir")
(osi:probe-directory #p"/zoodir")
(osi:probe-directory #p"/zoodir/")
(osi:probe-directory #p"/foodir")
(osi:probe-directory #p"/foodir/")
(osi:probe-directory #p"/foodir/bar.text")
Why is OSI:DIRECTORY-LIST needed, when we have CL:DIRECTORY?
Just a few nitpicking questions,
--
Gilbert Baumann
;; Will hack for food.
Gilbert Baumann <····@rz.uni-karlsruhe.de> wrote:
> I see you introduce symbolic links into the file system calculus yet
> you don't define what "truename" is. I can see two possible
> definitions of it:
For now I've been using it in the same sense as the ANSI spec:
"
Even where multiple names are possible, most file systems have a
convention for generating a canonical filename in such situations. Such a
canonical filename (or the pathname representing such a filename) is
called a truename.
"
> 1. Resolve symbolic links until you gain a pathname of which none of
> its components name a symbolic link.
This is it, except if the filesystem has more severe ideas about what a
canonical name is.
> 2. Just merge in enough from *default-pathname-defaults* and possible
> OS defaults until you reach a pathname whose mapping to a file
> system only depend on the file system itself. Vague, I know.
> In face of symbolics links option 2 no longer yields a canonical name
> in all cases. [Minor point: In face of hard links there is no
> canonical name]. This would suggest option 1.
> While option 2 it yields an IMHO more expected behavior when TRUENAME
> is applied to say a stream.
I don't follow. Why is no 2. better when applied to a stream?
OTOH I do understand the need for relative & non-canonical names as well,
but I generally tend to feel that relative names are more important.
Which is another sticky point with symbolic links: there should be a
mechanism to make links either absolute or relative. The current version
doesn't say enything about that (though the current implementation makes
all symlinks absolute).
> So we might want both behaviors.
Might be. Then should this behaviour be extended over other,
similar functions which currently return truenames? Should OSI contain
such extended versions of CL functions like PROBE-FILE and RENAME-FILE?
>> function OSI:FOLLOW-LINK pathspec => pathname
>>
>> Return the pathname pointed to by the symbolic link designated by
>> PATHSPEC. Signals a FILE-ERROR if PATHSPEC is wild or does not
>> designate a symbolic link.
> Suppose I do [unix pathname syntax assumed]:
> (ensure-directories-exists #p"/foodir/")
> (osi:make-link #p"/foodir/" #p"/zoodir/")
> How am I now supposed to follow the created link?
Hmm. I'd say that you have shot yourself in the foot by relying the
vagaries of PARSE-NAMESTRING. You should have used MAKE-PATHNAME and
avoid the ambiguiety, or you should not have used the trailing slash in
either.
A bit of a null answer, really -- I admit. However, I think that this is
an issue of pathname ambiguiety and PARSE-NAMESTRING ambiguiety, not
FOLLOW-LINK ambiguiety.
Am I missing something here?
A related question: should there be OSI:PARSE-PATHNAME, or something like
that with simpler syntax, plus the associated reader macro? This could
then have an explicitly defined behaviour on supported platforms.
> Why is OSI:DIRECTORY-LIST needed, when we have CL:DIRECTORY?
Because of the way CL:DIRECTORY is defined. From HyperSpec:
"
directory pathspec &key => pathnames
Arguments and Values:
pathspec---a pathname designator, which may contain wild components.
pathnames---a list of physical pathnames.
Description:
Determines which, if any, files that are present in the file system have
names matching pathspec, and returns a fresh list of pathnames
corresponding to the truenames of those files.
"
The way I read it, to say in an portable way "all the files and
directories that are direct children of /tmp" would go something like
this:
(let ((d (make-pathname :directory (:absolute "tmp" :wild))
(f (make-pathname :directory (:absolute "tmp") :name :wild)))
(union (directory f) (directory d)))
And given the way *default-pathname-defaults* works, even that is not
really enough... DIRECTORY is more general, but harder to control across
implementations, IMHO.
Cheers,
-- Nikodemus
In article <··············@midnight.cs.hut.fi>,
Nikodemus Siivola <········@kekkonen.cs.hut.fi> wrote:
> Which is another sticky point with symbolic links: there should be a
> mechanism to make links either absolute or relative. The current version
> doesn't say enything about that (though the current implementation makes
> all symlinks absolute).
If I could put in my two cents:
Coming from a perspective of doing a lot of Unix-system-building
and weird-c-toolchain-building, I believe the defaults for symlinks
should always be the shortest possible relative path. It is the
default that makes the most sense when confronted by chrooting and
remounting directory structure in different places.
For example, I need to link /mnt/system-build/bin/busybox to:
(among others)
/mnt/system-build/usr/bin/du
/mnt/system-build/usr/sbin/chroot
/mnt/system-build/bin/ls
/mnt/system-build/sbin/halt
/mnt/system-build will wind up on / on the running system.
Linking from /mnt/system-build/bin/busybox will break the eventual
running system. Linking from /bin/busybox will make it not work
on the build system. So the proper links should be:
/mnt/system-build/usr/sbin/chroot -> ../../bin/busybox
/mnt/system-build/usr/bin/du -> ../../bin/busybox
/mnt/system-build/sbin/halt -> ../bin/busybox
/mnt/system-build/bin/ls -> busybox
That being said, there are some times when an absolute symlink is
the right thing. So an absolute option is also important. I just
think that relative is the more generally useful case.
Sorry, I know this is deep Unix ugliness for a Lisp group, but if
proper link behavior is important you need to get a little deep
into the muck. :)
-bcd
Brian Downing <···········@lavos.net> wrote:
> and weird-c-toolchain-building, I believe the defaults for symlinks
> should always be the shortest possible relative path. It is the
How's about this?
absolute target pathspec, relative t => shortest relative link
relative target pathspec, relative t => given relative link
I am inclined to make absolute the default, though.
Cheers,
-- Nikodemus
Nikodemus Siivola wrote:
>
> Brian Downing <···········@lavos.net> wrote:
>
> > and weird-c-toolchain-building, I believe the defaults for symlinks
> > should always be the shortest possible relative path. It is the
>
> How's about this?
>
> absolute target pathspec, relative t => shortest relative link
> relative target pathspec, relative t => given relative link
>
> I am inclined to make absolute the default, though.
Any particular reason? I've just done a quick count,
and of the 957 symlinks on this PC only 89 are absolute,
so from my point of view you'd be optimising for the
less common case.
Ian Wild <···@cfmu.eurocontrol.be> wrote:
> Any particular reason? I've just done a quick count,
> and of the 957 symlinks on this PC only 89 are absolute,
> so from my point of view you'd be optimising for the
Ok. Taken under advice. Another consideration is the abstraction across
OS's. My hunch (and reason) was that absolute links are more common
outside POSIX, but I am not sure -- yet. Need to think and research.
One possibility would be to supply both absolute and relative as keyword
arguments and use an OS based default.
Which leads to another question: what OS's should be supported? What about
the OS's of tomorrow? I have some ideas, but...
Cheers,
-- Nikodemus
Another aspect to consider is not just whether absolute or relative is
more common, but which of the two is more commonly manipulated in
software. Which should be the default seems to me a more slippery
question. Not that this is all that critical to get just right...
Sunil
Nikodemus Siivola wrote:
> Ian Wild <···@cfmu.eurocontrol.be> wrote:
>
>
>>Any particular reason? I've just done a quick count,
>>and of the 957 symlinks on this PC only 89 are absolute,
>>so from my point of view you'd be optimising for the
>
>
> Ok. Taken under advice. Another consideration is the abstraction across
> OS's. My hunch (and reason) was that absolute links are more common
> outside POSIX, but I am not sure -- yet. Need to think and research.
>
> One possibility would be to supply both absolute and relative as keyword
> arguments and use an OS based default.
>
> Which leads to another question: what OS's should be supported? What about
> the OS's of tomorrow? I have some ideas, but...
>
> Cheers,
>
> -- Nikodemus
In article <··············@midnight.cs.hut.fi>,
Nikodemus Siivola <········@kekkonen.cs.hut.fi> wrote:
> How's about this?
>
> absolute target pathspec, relative t => shortest relative link
> relative target pathspec, relative t => given relative link
That seems right to me.
-bcd
--
*** Brian Downing <bdowning at lavos dot net>
Nikodemus Siivola <········@kekkonen.cs.hut.fi> writes:
> Gilbert Baumann <····@rz.uni-karlsruhe.de> wrote:
> >> function OSI:FOLLOW-LINK pathspec => pathname
> >>
> >> Return the pathname pointed to by the symbolic link designated by
> >> PATHSPEC. Signals a FILE-ERROR if PATHSPEC is wild or does not
> >> designate a symbolic link.
>
> > Suppose I do [unix pathname syntax assumed]:
>
> > (ensure-directories-exists #p"/foodir/")
> > (osi:make-link #p"/foodir/" #p"/zoodir/")
>
> > How am I now supposed to follow the created link?
>
> Hmm. I'd say that you have shot yourself in the foot by relying the
> vagaries of PARSE-NAMESTRING. You should have used MAKE-PATHNAME and
> avoid the ambiguiety, or you should not have used the trailing slash in
> either.
Right. So once again ..
(ensure-directories-exists
(make-pathname :directory '(:absolute "foodir")
:host *your-host*))
(osi:make-link
(make-pathname :directory '(:absolute "foodir")
:host *your-host*)
(make-pathname :directory '(:absolute "zoodir")
:host *your-host*))
Then what do
(osi:follow-link
(make-pathname :directory '(:absolute)
:name "zoodir"
:host *your-host*))
or
(osi:follow-link
(make-pathname :directory '(:absolute "zoodir")
:host *your-host*))
yield?
> A bit of a null answer, really -- I admit. However, I think that this is
> an issue of pathname ambiguiety and PARSE-NAMESTRING ambiguiety, not
> FOLLOW-LINK ambiguiety.
>
> Am I missing something here?
I think the ambiguiety is not so much on PARSE-NAMESTRING (although it
is implementation defined) but on whether you allow to refer to
entities which are not files but directories or symbolic links to
directories by slapping the directory path to the directory it
contains in front of a PATHNAME-NAME naming it.
> A related question: should there be OSI:PARSE-PATHNAME, or something like
> that with simpler syntax, plus the associated reader macro? This could
> then have an explicitly defined behaviour on supported platforms.
I would be happy if there were a specified syntax to map a string to
the various pathname components irregardless of the underlying OS. So
that for instance [I invent here a perhaps non-existing syntax for
less confusion with Unixisms]:
"{foo}:quux:bar:*:boo.text.18"
could map to (make-pathname :device "foo"
:directory (:absolute "quux" "bar" :wild)
:name "boo"
:type "text"
:version 18)
> > Why is OSI:DIRECTORY-LIST needed, when we have CL:DIRECTORY?
>
> Because of the way CL:DIRECTORY is defined. From HyperSpec:
>
> "
> [...]
> "
>
> The way I read it, to say in an portable way "all the files and
> directories that are direct children of /tmp" would go something like
> this:
>
> (let ((d (make-pathname :directory (:absolute "tmp" :wild))
> (f (make-pathname :directory (:absolute "tmp") :name :wild)))
> (union (directory f) (directory d)))
>
> And given the way *default-pathname-defaults* works, even that is not
> really enough... DIRECTORY is more general, but harder to control across
> implementations, IMHO.
IMHO confusion about DIRECTORY arises because implementations disagree
if a directory is an enity in itself; that is whether (make-pathname
:name "foo") can possibly name a directory or not. [I am repeating
myself here].
But then all in all I like your proprosal as it is in the spirit of
Common Lisp; read: it does not feel alien to me.
--
Gilbert Baumann
;; Will hack for food.
Gilbert Baumann <····@rz.uni-karlsruhe.de> wrote:
> (ensure-directories-exists
> (make-pathname :directory '(:absolute "foodir")
> :host *your-host*))
> (osi:make-link
> (make-pathname :directory '(:absolute "foodir")
> :host *your-host*)
> (make-pathname :directory '(:absolute "zoodir")
> :host *your-host*))
> Then what do
> (osi:follow-link
> (make-pathname :directory '(:absolute)
> :name "zoodir"
> :host *your-host*))
> or
> (osi:follow-link
> (make-pathname :directory '(:absolute "zoodir")
> :host *your-host*))
> yield?
Ah! Now I see your meaning... Hairy.
> I think the ambiguiety is not so much on PARSE-NAMESTRING (although it
> is implementation defined) but on whether you allow to refer to
> entities which are not files but directories or symbolic links to
> directories by slapping the directory path to the directory it
> contains in front of a PATHNAME-NAME naming it.
I see too alternatives.
1. Since POSIX (and Windows, I believe) does not differentiate between
files and directories in it's pathname syntax #p"/zoodir" can be
either. We must allow those meanings to stand for each other since the
state of the underlying filesystem can change after the pathname
has been constructed.
2. A file is a file, and a directory is a directory. Pathnames of CL make
this distinction even if the underlying system does not. A symbolic
link to directory must be referred to as a directory, and a symbolic
link to a file must be referred to as a file. If the underlying state
changes, so must the CL pathname.
I believe that the number 1 is the easier one to live with, and SBCL seems
to agree:
* (defvar p #p"/tmp/foo")
* (describe p)
#P"/tmp/foo" is an instance of class #<STRUCTURE-CLASS PATHNAME>.
The following slots have :INSTANCE allocation:
HOST #<SB-IMPL::UNIX-HOST {5069989}>
DEVICE NIL
DIRECTORY (:ABSOLUTE "tmp")
NAME "foo"
TYPE NIL
VERSION :NEWEST
* (describe (truename p))
#P"/tmp/foo/" is an instance of class #<STRUCTURE-CLASS PATHNAME>.
The following slots have :INSTANCE allocation:
HOST #<SB-IMPL::UNIX-HOST {5069989}>
DEVICE NIL
DIRECTORY (:ABSOLUTE "tmp" "foo")
NAME NIL
TYPE NIL
VERSION NIL
OTOH, reading the spec I get the impression that this is implementation
dependant. Urgh. I suppose the "correct" thing would be to keep the
corresponding osi-symlink behaviour implementation dependant as well.
Then again, this may be one case of implementation dependancy that I am
not willing to live with. Would it be too fascist to say that an
implementation supporting the OSI-package *must* behave in a certain way?
> I would be happy if there were a specified syntax to map a string to
> the various pathname components irregardless of the underlying OS. So
> that for instance [I invent here a perhaps non-existing syntax for
> less confusion with Unixisms]:
I like this! The syntax needs to be thought about, but the idea is very
nice.
> IMHO confusion about DIRECTORY arises because implementations disagree
> if a directory is an enity in itself; that is whether (make-pathname
> :name "foo") can possibly name a directory or not. [I am repeating
> myself here].
Partly, at least. But I think there is more than that.
The sentence: "files that are present in the file system have names
matching pathspec" is the problem. Whether files in this context are
directories or not is implementation defined, and so is the meaning of
"matching pathspec".
DIRECTORY-LIST is explicit about returning directories as well, and avoids
the matching pathspec trap by disallowing wild pathnames. The ambiguiety
whether (make-pathname :name "bar") is something DIRECTORY-LIST suffers
from as well.
Cheers,
-- Nikodemus
Updated version is available at:
http://www.niksula.cs.hut.fi/~tsiivola/files/fi-hut-tsiivola-osi.txt
Comments here, on ALU CLiki, or in private mail welcome.
revision history:
2003-05-04 - Specified file attributes on POSIX. Added PWD handling
to DEFAULT-DIRECTORY. Added details of relative path
handling to MAKE-LINK. Specified behaviour when setting
attributes of symbolic links. Added TRUENAME1. Added
FOLLOW-LINK clarification. Miscellaneous notes.
2003-05-02 - First public version
Cheers,
-- Nikodemus