From: Rob Warnock on
Teemu Likonen <tlikonen(a)iki.fi> wrote:
+---------------
| I'm wondering what would be the best way to detect the cause of some
| file errors. I mean opening a file may fail because the file doesn't
| exist or user has no access to the file (for example). I'm looking for
| ideas to detect the difference. The condition type doesn't tell much:
|
| (handler-case
| (with-open-file (s "/etc/shadow")) ;No permissions to read
| (t (c) (princ-to-string (type-of c))))
| => "SIMPLE-FILE-ERROR"
+---------------

Taking the TYPE-OF a condition throws away a lot of information.
In CMUCL, at least, you get much more information by simply PRINCing
the condition object *itself* rather than just its type. The PRINT-OBJECT
method for conditions knows quite a bit about picking them apart, e.g.:

cmu> (handler-case
(with-open-file (s "/etc/shadow")) ; No such file on FreeBSD
(t (c) c))

#<KERNEL:SIMPLE-FILE-ERROR {48AF44ED}>
cmu> (type-of *)

KERNEL:SIMPLE-FILE-ERROR
cmu> (princ-to-string **)

"
File-error in function LISP::FD-OPEN:
Error opening #P\"/etc/shadow\", No such file or directory."
cmu> (describe ***)

#<KERNEL:SIMPLE-FILE-ERROR {48B2266D}> is a structure of type SIMPLE-FILE-ERROR.
FUNCTION-NAME: LISP::FD-OPEN.
ACTUAL-INITARGS: (:PATHNAME #P"/etc/shadow" :FORMAT-CONTROL
"Error opening ~S, ~A." :FORMAT-ARGUMENTS ...).
ASSIGNED-SLOTS: (CONDITIONS::FORMAT-ARGUMENTS
(#P"/etc/shadow" "No such file or directory")
CONDITIONS::FORMAT-CONTROL "Error opening ~S, ~A.").
cmu>

Similarly:

cmu> (handler-case
(with-open-file (s "/etc/master.passwd")) ; No permission
(t (c) c))

#<KERNEL:SIMPLE-FILE-ERROR {48B3626D}>
cmu> (type-of *)

KERNEL:SIMPLE-FILE-ERROR
cmu> (princ-to-string **)

"
File-error in function LISP::FD-OPEN:
Error opening #P\"/etc/master.passwd\", Permission denied."
cmu>


-Rob

-----
Rob Warnock <rpw3(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

From: Teemu Likonen on
* 2010-07-01 20:45 (-0500), Rob Warnock wrote:

> Taking the TYPE-OF a condition throws away a lot of information.

It this case it throws away some information but I don't think Common
Lisp's standard conditions contain a "lot of information", as you put
it. In this case it doesn't have the information I want.

> In CMUCL, at least, you get much more information by simply PRINCing
> the condition object *itself* rather than just its type. The
> PRINT-OBJECT method for conditions knows quite a bit about picking
> them apart, e.g.:

I already mentioned PRINT-OBJECT in my original message (with SBCL
examples) and rejected the idea of using condition object's PRINC
output. I was looking for a more stable source of information for my
program's internal use. The PRINCed output is meant for humans.

Anyway, SBCL's SB-POSIX:ACCESS function gives nice and as exact as
possible (I think) information about file access. SB-POSIX:SYSCALL-ERROR
condition has a clearly defined ERRNO slot. Obviously that's because of
the POSIX standard.
From: Alessio Stalla on
On Jul 1, 4:38 pm, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:
> Unfortunately, conditions are somewhat underspecified in Common Lisp.
> To the point they're almost useless, for automatic processing or
> recovery.  

FWIW, in Java also there's a single exception type to signal all
"could not open file" situations, and it's even misnamed
(java.io.FileNotFoundException). A richer set of conditions - file
does not exist, permission denied, others? - would be nice to have,
but you can't go too deep in detail without creating lots of OS-
specific conditions.

Regards,
Alessio
From: Teemu Likonen on
* 2010-07-02 02:22 (-0700), Alessio Stalla wrote:

> A richer set of conditions - file does not exist, permission denied,
> others? - would be nice to have [...]

Below are the ones that POSIX access() offers. I think EACCES and ENOENT
are the most important for usual programs but for some file utilities
many others may be useful or necessary.


ERRORS
The access() function shall fail if:

EACCES Permission bits of the file mode do not permit the requested
access, or search permission is denied on a component of the
path prefix.

ELOOP A loop exists in symbolic links encountered during resolution
of the path argument.

ENAMETOOLONG
The length of the path argument exceeds {PATH_MAX} or a path-
name component is longer than {NAME_MAX}.

ENOENT A component of path does not name an existing file or path is
an empty string.

ENOTDIR
A component of the path prefix is not a directory.

EROFS Write access is requested for a file on a read-only file sys-
tem.

The access() function may fail if:

EINVAL The value of the amode argument is invalid.

ELOOP More than {SYMLOOP_MAX} symbolic links were encountered during
resolution of the path argument.

ENAMETOOLONG
As a result of encountering a symbolic link in resolution of
the path argument, the length of the substituted pathname
string exceeded {PATH_MAX}.

ETXTBSY
Write access is requested for a pure procedure (shared text)
file that is being executed.
From: Pascal J. Bourguignon on
Alessio Stalla <alessiostalla(a)gmail.com> writes:

> On Jul 1, 4:38�pm, p...(a)informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Unfortunately, conditions are somewhat underspecified in Common Lisp.
>> To the point they're almost useless, for automatic processing or
>> recovery. �
>
> FWIW, in Java also there's a single exception type to signal all
> "could not open file" situations, and it's even misnamed
> (java.io.FileNotFoundException). A richer set of conditions - file
> does not exist, permission denied, others? - would be nice to have,
> but you can't go too deep in detail without creating lots of OS-
> specific conditions.

Not at all. I spoke of a exceptional situation _ontology_. This is
something that can and should be made as general as possible.

The problem here, that you're pointing out by saying "OS-Specific" is
that programmers usually signal conditions that are actually the state
of the program when the exceptional situation is encountered.
Basically, they do (ERROR (cons source-file line-number)).

They should actually identify the ontological situation and signal
that.


At least if you want to have any chance of dealing intelligently with
the condition.

--
__Pascal Bourguignon__ http://www.informatimago.com/