[Vm-dev] [PATCH] added FilePlugin error code lookup function

monty monty2 at programmer.net
Wed Mar 21 14:28:05 UTC 2018


The SQ_FILE_*_ERROR codes can be mapped directly to an expanded file exception hierarchy, so an appropriate exception class can be thrown (and caught) on failure. #primitiveFailForOSError: can be used for this. Or it can be used with the raw errno/GetLastError() codes, and a sqFileErrorCodeFromSystemErrorCode()-based primitive can be used after to map it.

We need some way in-image to portably, correctly distinguish certain failure modes (like a file not existing) from others. (Code in the current Squeak image just guesses.) The exact values of the errno.h E* defines are technically unspecified, and the perror()/strerror_r() messages are locale-specific: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_03

I would like to hear more ideas.

> Sent: Wednesday, March 21, 2018 at 7:08 AM
> From: "Alistair Grant" <akgrant0710 at gmail.com>
> To: "Squeak Virtual Machine Development Discussion" <vm-dev at lists.squeakfoundation.org>
> Subject: Re: [Vm-dev] [PATCH] added FilePlugin error code lookup function
>
>  
> Hi Monty,
> 
> The VM has a primitive failure that allows the OS error to be
> returned: #primitiveFailForOSError:
> 
> Why not simply return the OS error and allow the image to deal with it?
> 
> Cheers,
> Alistair
> 
> 
> 
> On 21 March 2018 at 07:52, monty <monty2 at programmer.net> wrote:
> >
> > ---
> >  platforms/Cross/plugins/FilePlugin/FilePlugin.h    | 17 ++++++
> >  .../plugins/FilePlugin/sqFilePluginBasicPrims.c    | 56 ++++++++++++++++++
> >  .../win32/plugins/FilePlugin/sqWin32FilePrims.c    | 69 ++++++++++++++++++++++
> >  3 files changed, 142 insertions(+)
> >
> > diff --git a/platforms/Cross/plugins/FilePlugin/FilePlugin.h b/platforms/Cross/plugins/FilePlugin/FilePlugin.h
> > index 13e7b7ce9..5d61733a0 100644
> > --- a/platforms/Cross/plugins/FilePlugin/FilePlugin.h
> > +++ b/platforms/Cross/plugins/FilePlugin/FilePlugin.h
> > @@ -44,6 +44,21 @@ typedef struct {
> >  #endif
> >  } SQFile;
> >
> > +enum {
> > +       SQ_FILE_ERROR,
> > +       SQ_FILE_PERMISSION_ERROR,
> > +       SQ_FILE_ALREADY_EXISTS_ERROR,
> > +       SQ_FILE_DOES_NOT_EXIST_ERROR,
> > +       SQ_FILE_RESOURCE_LIMIT_ERROR,
> > +       SQ_FILE_INVALID_OPERATION_ERROR,
> > +       SQ_FILE_IO_ERROR,
> > +       SQ_FILE_BAD_HANDLE_ERROR,
> > +       SQ_FILE_IS_DIRECTORY_ERROR,
> > +       SQ_FILE_IS_NOT_DIRECTORY_ERROR,
> > +       SQ_FILE_INVALID_NAME_ERROR,
> > +       SQ_FILE_IN_PROGRESS_ERROR
> > +};
> > +
> >  /* file i/o */
> >
> >  sqInt   sqFileAtEnd(SQFile *f);
> > @@ -67,6 +82,8 @@ sqInt   sqFileSync(SQFile *f);
> >  sqInt   sqFileTruncate(SQFile *f,squeakFileOffsetType offset);
> >  sqInt   sqFileThisSession(void);
> >  sqInt   sqFileStdioHandlesInto(SQFile files[3]);
> > +sqInt   sqFileErrorCodeFromSystemErrorCode(sqInt errorCode);
> > +
> >
> >  /* directories */
> >
> > diff --git a/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c b/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c
> > index 48117181f..803ad5b8a 100755
> > --- a/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c
> > +++ b/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c
> > @@ -754,4 +754,60 @@ sqInt
> >  sqFileThisSession() {
> >         return thisSession;
> >  }
> > +
> > +sqInt
> > +sqFileErrorCodeFromSystemErrorCode(sqInt errorCode)
> > +{
> > +       /* A switch statement is avoided, since some error codes, like EAGAIN/EWOULDBLOCK, can
> > +          overlap, and EINTR is not propagated as SQ_FILE_IN_PROGRESS_ERROR, since it should be
> > +          handled internally where possible and because only certain operations can be safely
> > +          reattempted after failing with EINTR
> > +       */
> > +       if (errorCode == EACCES
> > +               || errorCode == EPERM
> > +               || errorCode == EROFS)
> > +               return SQ_FILE_PERMISSION_ERROR;
> > +       else if (errorCode == EEXIST)
> > +               return SQ_FILE_ALREADY_EXISTS_ERROR;
> > +       else if (errorCode == ENOENT
> > +               || errorCode == ENODEV
> > +               || errorCode == ENXIO)
> > +               return SQ_FILE_DOES_NOT_EXIST_ERROR;
> > +       else if (errorCode == EDQUOT
> > +               || errorCode == EFBIG
> > +               || errorCode == EMFILE
> > +               || errorCode == EMLINK
> > +               || errorCode == ENFILE
> > +               || errorCode == ENOLCK
> > +               || errorCode == ENOLINK
> > +               || errorCode == ENOMEM
> > +               || errorCode == ENOSPC)
> > +               return SQ_FILE_RESOURCE_LIMIT_ERROR;
> > +       else if (errorCode == EINVAL
> > +               || errorCode == ENOTTY
> > +               || errorCode == ENOSYS
> > +               || errorCode == ENOTEMPTY
> > +               || errorCode == EFAULT
> > +               || errorCode == ESPIPE
> > +               || errorCode == EXDEV)
> > +               return SQ_FILE_INVALID_OPERATION_ERROR;
> > +       else if (errorCode == EIO)
> > +               return SQ_FILE_IO_ERROR;
> > +       else if (errorCode == EBADF)
> > +               return SQ_FILE_BAD_HANDLE_ERROR;
> > +       else if (errorCode == EISDIR)
> > +               return SQ_FILE_IS_DIRECTORY_ERROR;
> > +       else if (errorCode == ENOTDIR)
> > +               return SQ_FILE_IS_NOT_DIRECTORY_ERROR;
> > +       else if (errorCode == ENAMETOOLONG
> > +               || errorCode == ELOOP)
> > +               return SQ_FILE_INVALID_NAME_ERROR;
> > +       else if (errorCode == EAGAIN
> > +               || errorCode == EWOULDBLOCK
> > +               || errorCode == EINPROGRESS)
> > +               return SQ_FILE_IN_PROGRESS_ERROR;
> > +       else
> > +               return SQ_FILE_ERROR;
> > +}
> > +
> >  #endif /* NO_STD_FILE_SUPPORT */
> > diff --git a/platforms/win32/plugins/FilePlugin/sqWin32FilePrims.c b/platforms/win32/plugins/FilePlugin/sqWin32FilePrims.c
> > index 39ae4ec15..1e7d80782 100644
> > --- a/platforms/win32/plugins/FilePlugin/sqWin32FilePrims.c
> > +++ b/platforms/win32/plugins/FilePlugin/sqWin32FilePrims.c
> > @@ -528,4 +528,73 @@ squeakFileOffsetType sqImageFileSize(sqImageFile h)
> >    return ofs.offset;
> >  }
> >
> > +sqInt
> > +sqFileErrorCodeFromSystemErrorCode(sqInt errorCode)
> > +{
> > +       /* Newer constants are avoided for backwards compatibility */
> > +       if (errorCode == ERROR_ACCESS_DENIED
> > +               || errorCode == ERROR_FILE_READ_ONLY
> > +               || errorCode == ERROR_WRITE_PROTECT
> > +               || errorCode == 313) /* ERROR_NOT_ALLOWED_ON_SYSTEM_FILE */
> > +               return SQ_FILE_PERMISSION_ERROR;
> > +       else if (errorCode == ERROR_FILE_EXISTS
> > +               || errorCode == ERROR_ALREADY_EXISTS)
> > +               return SQ_FILE_ALREADY_EXISTS_ERROR;
> > +       else if (errorCode == ERROR_FILE_NOT_FOUND
> > +               || errorCode == ERROR_PATH_NOT_FOUND
> > +               || errorCode == ERROR_DEV_NOT_EXIST)
> > +               return SQ_FILE_DOES_NOT_EXIST_ERROR;
> > +       else if (errorCode == ERROR_NO_MORE_FILES
> > +               || errorCode == ERROR_TOO_MANY_OPEN_FILES
> > +               || errorCode == ERROR_DISK_FULL
> > +               || errorCode == ERROR_HANDLE_DISK_FULL
> > +               || errorCode == ERROR_DISK_TOO_FRAGMENTED
> > +               || errorCode == ERROR_NO_MORE_SEARCH_HANDLES
> > +               || errorCode == ERROR_NOT_ENOUGH_QUOTA
> > +               || errorCode == 223 /* ERROR_FILE_TOO_LARGE */
> > +               || errorCode == 314 /* ERROR_DISK_RESOURCES_EXHAUSTED */
> > +               || errorCode == 322 /* ERROR_DEVICE_NO_RESOURCES */
> > +               || errorCode == 331) /* ERROR_TOO_MANY_DESCRIPTORS */
> > +               return SQ_FILE_RESOURCE_LIMIT_ERROR;
> > +       else if (errorCode == ERROR_WRITE_FAULT
> > +               || errorCode == ERROR_READ_FAULT
> > +               || errorCode == ERROR_OPERATION_ABORTED
> > +               || errorCode == ERROR_CANNOT_MAKE
> > +               || errorCode == ERROR_IO_DEVICE)
> > +               return SQ_FILE_IO_ERROR;
> > +       else if (errorCode == ERROR_INVALID_FUNCTION
> > +               || errorCode == ERROR_BAD_ARGUMENTS
> > +               || errorCode == ERROR_INVALID_PARAMETER
> > +               || errorCode == ERROR_NOT_SUPPORTED
> > +               || errorCode == ERROR_NEGATIVE_SEEK
> > +               || errorCode == ERROR_SEEK_ON_DEVICE
> > +               || errorCode == ERROR_CURRENT_DIRECTORY
> > +               || errorCode == ERROR_DIR_NOT_EMPTY)
> > +               return SQ_FILE_INVALID_OPERATION_ERROR;
> > +       else if (errorCode == ERROR_INVALID_HANDLE
> > +               || errorCode == ERROR_INVALID_TARGET_HANDLE
> > +               || errorCode == ERROR_DIRECT_ACCESS_HANDLE
> > +               || errorCode == ERROR_OPEN_FAILED
> > +               || errorCode == ERROR_DELETE_PENDING
> > +               || errorCode == 321) /* ERROR_DEVICE_UNREACHABLE */
> > +               return SQ_FILE_BAD_HANDLE_ERROR;
> > +       else if (errorCode == 336) /* ERROR_DIRECTORY_NOT_SUPPORTED */
> > +               return SQ_FILE_IS_DIRECTORY_ERROR;
> > +       else if (errorCode == 334 /* ERROR_RESIDENT_FILE_NOT_SUPPORTED */
> > +               || errorCode == 335) /* ERROR_COMPRESSED_FILE_NOT_SUPPORTED */
> > +               return SQ_FILE_IS_NOT_DIRECTORY_ERROR;
> > +       else if (errorCode == ERROR_INVALID_NAME
> > +               || errorCode == ERROR_DIRECTORY
> > +               || errorCode == ERROR_BAD_PATHNAME
> > +               || errorCode == ERROR_FILENAME_EXCED_RANGE
> > +               || errorCode == 305 /* ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME */
> > +               || errorCode == 330) /* ERROR_BAD_DEVICE_PATH */
> > +               return SQ_FILE_INVALID_NAME_ERROR;
> > +       else if (errorCode == ERROR_IO_PENDING
> > +               || errorCode == ERROR_IO_INCOMPLETE)
> > +               return SQ_FILE_IN_PROGRESS_ERROR;
> > +       else
> > +               return SQ_FILE_ERROR;
> > +}
> > +
> >  #endif /* WIN32_FILE_SUPPORT */
> > --
> > 2.11.0
> >
> 


More information about the Vm-dev mailing list