[PATCH] added FilePlugin error code lookup function

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] added FilePlugin error code lookup function

monty-3
 
---
 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

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

alistairgrant
 
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 <[hidden email]> 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
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

monty-3
 
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" <[hidden email]>
> To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
> 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 <[hidden email]> 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
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

monty-3
 


> Sent: Wednesday, March 21, 2018 at 10:28 AM
> From: monty <[hidden email]>
> To: [hidden email]
> 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" <[hidden email]>
> > To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
> > 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 <[hidden email]> 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
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

Ben Coman
In reply to this post by monty-3
 


On 21 March 2018 at 22:28, monty <[hidden email]> wrote:
>
>
> 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.
>
> The exact values of the errno.h E* defines are technically unspecified,

By "unspecified" do you just mean that they are different between platforms.
What about embedding  errno.h  in the compiled VM and let the Image side browse and parse it, so the error mapping/condensing can be done Image-side?
I'm not sure of the difficulty to do this since I haven't done it before,
but maybe something like...  https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char


> 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.)

This should(?) portably provide the exact C label for a numeric error.  
The Image-side might need per-platform mapping/condensing, but still may be nicer to do it there.

cheers -ben

 

>
> 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" <[hidden email]>
> > To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
> > 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 <[hidden email]> wrote:
> > >
> > >
> > > +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
> > > +};
> > > 
> > > +
> > > +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

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

Eliot Miranda-2
 
Hi Ben, Hi Alistair, Hi Monty,

    I have thought for a long time that the way to go this is to generate a C program and compile it either to a shared object or, as Mariano and others suggested and implemented, have its output be the values needed.  See the Pharo dev thread "Can OSProcess functionality be implemented using FFI instead of plugin?".  The key idea is to maintain a per-host-type pool of constants, comprising error codes, ioctls, typedefs, etc, whatever one needs, and have the C be generated from the pool.  The C source is needed only at development time.  I think Mariano settled on STON as the C output format.  Anyway, I'm not reiterating here.  I will say that coming up with a different solution per plugin is a waste of effort when one can find up with a general scheme that will serve many needs and b extensible with very little effort.  The key idea is that one gets the system to generate a C program that is compiled and run on each host type and that compiled form or its output therefore faithfully reflects the values of error codes, types etc of the host.

_,,,^..^,,,_ (phone)

On Mar 21, 2018, at 6:04 PM, Ben Coman <[hidden email]> wrote:



On 21 March 2018 at 22:28, monty <[hidden email]> wrote:
>
>
> 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.
>
> The exact values of the errno.h E* defines are technically unspecified,

By "unspecified" do you just mean that they are different between platforms.
What about embedding  errno.h  in the compiled VM and let the Image side browse and parse it, so the error mapping/condensing can be done Image-side?
I'm not sure of the difficulty to do this since I haven't done it before,
but maybe something like...  https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char


> 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.)

This should(?) portably provide the exact C label for a numeric error.  
The Image-side might need per-platform mapping/condensing, but still may be nicer to do it there.

cheers -ben

 

>
> 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" <[hidden email]>
> > To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
> > 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 <[hidden email]> wrote:
> > >
> > >
> > > +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
> > > +};
> > > 
> > > +
> > > +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

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

alistairgrant
 
On 22 March 2018 at 03:07, Eliot Miranda <[hidden email]> wrote:
>
> Hi Ben, Hi Alistair, Hi Monty,
>
>     I have thought for a long time that the way to go this is to generate a C program and compile it either to a shared object or, as Mariano and others suggested and implemented, have its output be the values needed.  See the Pharo dev thread "Can OSProcess functionality be implemented using FFI instead of plugin?".  The key idea is to maintain a per-host-type pool of constants, comprising error codes, ioctls, typedefs, etc, whatever one needs, and have the C be generated from the pool.  The C source is needed only at development time.  I think Mariano settled on STON as the C output format.  Anyway, I'm not reiterating here.  I will say that coming up with a different solution per plugin is a waste of effort when one can find up with a general scheme that will serve many needs and b extensible with very little effort.  The key idea is that one gets the system to generate a C program that is compiled and run on each host type and that compiled form or its output therefore faithfully reflects the values of error codes, types etc of the host.

This sounds like a good idea.  Eliot, I assume the email you're referring to is:

http://forum.world.st/Can-OSProcess-functionality-be-implemented-using-FFI-instead-of-plugin-tt4610297.html#a4873116

From what I can see, Mariano didn't make the code available (please
correct me if I'm wrong).

Thanks,
Alistair



> On Mar 21, 2018, at 6:04 PM, Ben Coman <[hidden email]> wrote:
>
>
>
> On 21 March 2018 at 22:28, monty <[hidden email]> wrote:
>>
>>
>> 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.
>>
>> The exact values of the errno.h E* defines are technically unspecified,
>
> By "unspecified" do you just mean that they are different between platforms.
> What about embedding  errno.h  in the compiled VM and let the Image side browse and parse it, so the error mapping/condensing can be done Image-side?
> I'm not sure of the difficulty to do this since I haven't done it before,
> but maybe something like...  https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char
>
>
>> 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.)
>
> This should(?) portably provide the exact C label for a numeric error.
> The Image-side might need per-platform mapping/condensing, but still may be nicer to do it there.
>
> cheers -ben
>
>
>>
>> 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" <[hidden email]>
>> > To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
>> > 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 <[hidden email]> wrote:
>> > >
>> > >
>> > > +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
>> > > +};
>> > >
>> > > +
>> > > +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
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

monty-3
In reply to this post by Eliot Miranda-2
 
Echoing Alistair, no SharedPool in my generated VMMaker image seems to do what you describe. If you want, I can do the implementation. (In the FFI-Pools package.)
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

Eliot Miranda-2
 
Hi Monty,

On Fri, Mar 23, 2018 at 10:12 PM, monty <[hidden email]> wrote:

Echoing Alistair, no SharedPool in my generated VMMaker image seems to do what you describe.

That's right.  I did a prototype for VisualWorks when I worked at Cincom.  I don't think they would object to me giving you the code but if you can do with out it would be better, and since the code isn't that difficult it might be better to start afresh.  But if you read the thread you'll see that Mariano Martines Peck did something in Pharo based on our conversations and that might be a better starting point.
 
If you want, I can do the implementation. (In the FFI-Pools package.)

That would be great.  Remember the major requirements:

Deployment:
The output of the C program should be a concise parseable, human-editable document (in STON?) whose name identifies the platform.  Let's call it PlatformConstants-XXX.ext (where ext reflects the syntax chosen).
Various PlatformConstants-XXX.ext files can live either in a folder in the virtual machine or a folder parallel to the image
Various PlatformConstants-XXX.ext files and the pool definition that generated them should live somewhere on squeak.org so people can download them without needing a C development environment to get access to new constants, etc.
The PlatformConstants-XXX.ext file is only parsed on start-up if the image comes up on a different platform.  Parsing happens before any FFI/socket call
An alternative would be "conditional bindings", where the various platform-specific values for a particular constant could be in additional inst vars of a suitable binding type, which could allow for a default value for concision, for example
Global variableSubclass: #PlatformConstant
instanceVariableNames: 'default'
classVariableNames: ''
poolDictionaries: ''
category: 'FFI-Core'
and then the alternatives different from the default would be held in indexed inst vars as pairs of platform moniker, value

Development:
Generating a new PlatformConstants-XXX.ext file should be entirely automatic, but would assume the platform's standard compiler would be available


_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

monty-3
 
Check your inbox.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] added FilePlugin error code lookup function

monty-3
In reply to this post by Eliot Miranda-2
 
I'm attaching my latest FFIExternalSharedPool packages for review by anyone. (I have no repo to put them in.)
 
___
montyos.wordpress.com
 
 

Sent: Saturday, March 24, 2018 at 9:47 AM
From: "Eliot Miranda" <[hidden email]>
To: "Squeak Virtual Machine Development Discussion" <[hidden email]>
Subject: Re: [Vm-dev] [PATCH] added FilePlugin error code lookup function

FFI-Pools-monty.12.mcz (37K) Download Attachment
FFI-PoolsTests-monty.5.mcz (9K) Download Attachment