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

monty monty2 at programmer.net
Wed Mar 21 14:36:03 UTC 2018



> Sent: Wednesday, March 21, 2018 at 10:28 AM
> From: monty <monty2 at programmer.net>
> To: vm-dev at lists.squeakfoundation.org
> Subject: Re: [Vm-dev] [PATCH] added FilePlugin error code lookup function
>
>  
> 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.

With this second approach, the raw error code could be saved in an inst var of the mapped exception before throwing it, which the user could look up if needed. But it has more overhead.

> 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