Sent: Wednesday, March 21, 2018 at 10:28 AM From: monty monty2@programmer.net To: vm-dev@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...
I would like to hear more ideas.
Sent: Wednesday, March 21, 2018 at 7:08 AM From: "Alistair Grant" akgrant0710@gmail.com To: "Squeak Virtual Machine Development Discussion" vm-dev@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@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