commit 6b16e82553d01de6b3876846bc3d4b4ffa01d0a8 Author: Egeyar Bagcioglu Date: Mon Oct 26 00:04:58 2020 +0100 ios: Improve error handling of ios_open. 2020-10-26 Egeyar Bagcioglu * libpoke/ios-dev-file.h: Include errno.h. (ios_dev_file_handler_normalize): Pass a new argument to be filled with the new_handler. Convert the return value to int to return IOD error types. In case of no errors, return IOD_OK. (ios_dev_file_open): Pass a new argument to be filled with the newly opened device. Convert the return value into an int to return IOD error types. In case of no errors, return IOD_OK. * libpoke/ios-dev-mem.h (ios_dev_mem_handler_normalize): Like ios_dev_file_handler_normalize. (ios_dev_mem_open): Like ios_dev_file_open. * libpoke/ios-dev-nbd.h (ios_dev_nbd_handler_normalize): Like ios_dev_file_handler_normalize. (ios_dev_nbd_open): Like ios_dev_file_open. * libpoke/ios-dev-stream.h (ios_dev_stream_handler_normalize): Like ios_dev_file_handler_normalize. (ios_dev_stream_open): Like ios_dev_file_open. * libpoke/ios-dev.h (handler_normalize): Pass a new argument to be filled with the new_handler. Convert the return value to int. (open): Pass a new argument to be filled with the newly opened device. Convert the return value into an int to return IOD error types. In case of no errors, return IOD_OK. * libpoke/ios.c (ios_open): Set IO id after making sure open won't fail. Handle errors returned by handler_normalize and open. Prevent opening an already-open IO space. * libpoke/ios.h: Introduce IOS_EOPEN. * libpoke/pvm.jitter (open): Raise a PVM_E_IO for all possible error values of ios_open. diff --git a/ChangeLog b/ChangeLog index 95da9548..6e2427ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2020-10-26 Egeyar Bagcioglu + + * libpoke/ios-dev-file.h: Include errno.h. + (ios_dev_file_handler_normalize): Pass a new argument to be filled + with the new_handler. Convert the return value to int to return IOD + error types. In case of no errors, return IOD_OK. + (ios_dev_file_open): Pass a new argument to be filled with the newly + opened device. Convert the return value into an int to return IOD + error types. In case of no errors, return IOD_OK. + * libpoke/ios-dev-mem.h (ios_dev_mem_handler_normalize): Like + ios_dev_file_handler_normalize. + (ios_dev_mem_open): Like ios_dev_file_open. + * libpoke/ios-dev-nbd.h (ios_dev_nbd_handler_normalize): Like + ios_dev_file_handler_normalize. + (ios_dev_nbd_open): Like ios_dev_file_open. + * libpoke/ios-dev-stream.h (ios_dev_stream_handler_normalize): Like + ios_dev_file_handler_normalize. + (ios_dev_stream_open): Like ios_dev_file_open. + * libpoke/ios-dev.h (handler_normalize): Pass a new argument to be + filled with the new_handler. Convert the return value to int. + (open): Pass a new argument to be filled with the newly opened device. + Convert the return value into an int to return IOD error types. In + case of no errors, return IOD_OK. + * libpoke/ios.c (ios_open): Set IO id after making sure open won't + fail. Handle errors returned by handler_normalize and open. Prevent + opening an already-open IO space. + * libpoke/ios.h: Introduce IOS_EOPEN. + * libpoke/pvm.jitter (open): Raise a PVM_E_IO for all possible error + values of ios_open. + 2020-10-25 Egeyar Bagcioglu * libpoke/ios-dev.h: Add IOD_OK, IOD_EIOFF, IOD_EFLAGS and IOD_ENOMEM. diff --git a/libpoke/ios-dev-file.c b/libpoke/ios-dev-file.c index 5c70264f..1945dae3 100644 --- a/libpoke/ios-dev-file.c +++ b/libpoke/ios-dev-file.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "ios.h" #include "ios-dev.h" @@ -45,18 +46,20 @@ ios_dev_file_get_if_name () { return "FILE"; } -static char * -ios_dev_file_handler_normalize (const char *handler, uint64_t flags) +static int +ios_dev_file_handler_normalize (const char *handler, uint64_t flags, char **newhandler) { - char *newhandler; - IOS_FILE_HANDLER_NORMALIZE (handler, newhandler); + IOS_FILE_HANDLER_NORMALIZE (handler, *newhandler); - /* TODO handle the case where newhandler is NULL. */ - return newhandler; + /* Every handler is accepted as a file handler. */ + if (*newhandler == NULL) + return IOD_ENOMEM; + else + return IOD_OK; } -static void * -ios_dev_file_open (const char *handler, uint64_t flags, int *error) +static int +ios_dev_file_open (const char *handler, uint64_t flags, void **dev) { struct ios_dev_file *fio = NULL; FILE *f; @@ -75,12 +78,7 @@ ios_dev_file_open (const char *handler, uint64_t flags, int *error) else if (flags_mode == (IOS_F_WRITE | IOS_F_CREATE | IOS_F_TRUNCATE)) mode = "w+b"; else - { - /* Invalid mode. */ - if (error != NULL) - *error = IOD_EINVAL; - return NULL; - } + return IOD_EFLAGS; f = fopen (handler, mode); } @@ -111,22 +109,23 @@ ios_dev_file_open (const char *handler, uint64_t flags, int *error) fio->file = f; fio->flags = flags; - return fio; + *dev = fio; + return IOD_OK; err: - if (fio) - { - free (fio->filename); - free (fio); - } + free (fio->filename); + free (fio); if (f) fclose (f); - if (error != NULL) - *error = IOD_ERROR; - - return NULL; + if (errno == ENOMEM) + return IOD_ENOMEM; + else if (errno == EINVAL) + return IOD_EINVAL; + /* Should never happen. */ + else + return IOD_ERROR; } static int diff --git a/libpoke/ios-dev-mem.c b/libpoke/ios-dev-mem.c index 948430f1..15e32435 100644 --- a/libpoke/ios-dev-mem.c +++ b/libpoke/ios-dev-mem.c @@ -40,33 +40,38 @@ ios_dev_mem_get_if_name () { return "MEMORY"; } -static char * -ios_dev_mem_handler_normalize (const char *handler, uint64_t flags) +static int +ios_dev_mem_handler_normalize (const char *handler, uint64_t flags, char **newhandler) { if (handler[0] == '*' && handler[strlen (handler) - 1] == '*') - return strdup (handler); - return NULL; + { + *newhandler = strdup (handler); + if (*newhandler == NULL) + return IOD_ENOMEM; + } + return IOD_OK; } -static void * -ios_dev_mem_open (const char *handler, uint64_t flags, int *error) +static int +ios_dev_mem_open (const char *handler, uint64_t flags, void **dev) { struct ios_dev_mem *mio = malloc (sizeof (struct ios_dev_mem)); if (!mio) - return NULL; + return IOD_ENOMEM; mio->pointer = calloc (MEM_STEP, 1); if (!mio->pointer) { free (mio); - return NULL; + return IOD_ENOMEM; } mio->size = MEM_STEP; mio->flags = flags; - return mio; + *dev = mio; + return IOD_OK; } static int diff --git a/libpoke/ios-dev-nbd.c b/libpoke/ios-dev-nbd.c index cf3d5a5c..02e99104 100644 --- a/libpoke/ios-dev-nbd.c +++ b/libpoke/ios-dev-nbd.c @@ -49,17 +49,21 @@ ios_dev_nbd_get_if_name () { return "NBD"; } -static char * -ios_dev_nbd_handler_normalize (const char *handler, uint64_t flags) +static int +ios_dev_nbd_handler_normalize (const char *handler, uint64_t flags, char **newhandler) { if (startswith (handler, "nbd://") || startswith (handler, "nbd+unix://")) - return strdup (handler); - return NULL; + { + *newhandler = strdup (handler); + if (*newhandler == NULL) + return IOD_ENOMEM; + } + return IOD_OK; } -static void * -ios_dev_nbd_open (const char *handler, uint64_t flags, int *error) +static int +ios_dev_nbd_open (const char *handler, uint64_t flags, void **dev) { struct ios_dev_nbd *nio = NULL; struct nbd_handle *nbd = NULL; @@ -70,7 +74,7 @@ ios_dev_nbd_open (const char *handler, uint64_t flags, int *error) /* We don't permit truncation. */ if (flags_mode & IOS_F_TRUNCATE) { - err = IOD_EINVAL; + err = IOD_EFLAGS; goto err; } @@ -100,32 +104,33 @@ ios_dev_nbd_open (const char *handler, uint64_t flags, int *error) nio = malloc (sizeof *nio); if (!nio) - goto err; + { + err = IOD_ENOMEM; + goto err; + } nio->uri = strdup (handler); if (!nio->uri) - goto err; + { + err = IOD_ENOMEM; + goto err; + } nio->nbd = nbd; nio->size = size; nio->flags = flags; - return nio; + *dev = nio; + return IOD_OK; err: /* Worth logging nbd_get_error ()? */ - if (error) - *error = err; - - if (nio) - { - free (nio->uri); - free (nio); - } + free (nio->uri); + free (nio); nbd_close (nbd); - return NULL; + return err; } static int diff --git a/libpoke/ios-dev-stream.c b/libpoke/ios-dev-stream.c index 93f3b048..09b23785 100644 --- a/libpoke/ios-dev-stream.c +++ b/libpoke/ios-dev-stream.c @@ -52,30 +52,40 @@ ios_dev_stream_get_dev_if_name () { return "STREAM"; } -static char * -ios_dev_stream_handler_normalize (const char *handler, uint64_t flags) +static int +ios_dev_stream_handler_normalize (const char *handler, uint64_t flags, char **newhandler) { /* TODO handle the case where strdup fails. */ if (STREQ (handler, IOS_STDIN_HANDLER) || STREQ (handler, IOS_STDOUT_HANDLER) || STREQ (handler, IOS_STDERR_HANDLER)) - return strdup (handler); - else - return NULL; + { + *newhandler = strdup (handler); + if (*newhandler == NULL) + return IOD_ENOMEM; + } + return IOD_OK; } -static void * -ios_dev_stream_open (const char *handler, uint64_t flags, int *error) +static int +ios_dev_stream_open (const char *handler, uint64_t flags, void **dev) { struct ios_dev_stream *sio; + int error = IOD_ERROR; sio = malloc (sizeof (struct ios_dev_stream)); if (!sio) - goto error; + { + error = IOD_ENOMEM; + goto error; + } sio->handler = strdup (handler); if (!sio->handler) - goto error; + { + error = IOD_ENOMEM; + goto error; + } if (STREQ (handler, IOS_STDIN_HANDLER)) { @@ -83,7 +93,10 @@ ios_dev_stream_open (const char *handler, uint64_t flags, int *error) sio->flags = IOS_F_READ; sio->buffer = ios_buffer_init (); if (!sio->buffer) - goto error; + { + error = IOD_ENOMEM; + goto error; + } } else if (STREQ (handler, IOS_STDOUT_HANDLER)) { @@ -100,16 +113,14 @@ ios_dev_stream_open (const char *handler, uint64_t flags, int *error) else goto error; - return sio; + *dev = sio; + return IOD_OK; error: - if (sio) - { - free (sio->handler); - free (sio); - } - *error = IOD_ERROR; - return NULL; + free (sio->handler); + free (sio); + + return error; } static int diff --git a/libpoke/ios-dev.h b/libpoke/ios-dev.h index 2a7cc1b5..2d670f21 100644 --- a/libpoke/ios-dev.h +++ b/libpoke/ios-dev.h @@ -53,18 +53,18 @@ struct ios_dev_if char *(*get_if_name) (); /* Determine whether the provided HANDLER is recognized as a valid - device spec by this backend, and if so, return its normalized - form (caller will free). If not, return NULL. */ + device spec by this backend, and if so, copy its normalized + form into newhandler (caller will free). In case of error, + return the error code. If not, return IOD_OK. */ - char *(*handler_normalize) (const char *handler, uint64_t flags); + int (*handler_normalize) (const char *handler, uint64_t flags, char **newhandler); - /* Open a device using the provided HANDLER. Return the opened - device, or NULL if there was an error. In case of invalid flags, - store IOD_EINVAL in ERROR. Note that this function assumes that + /* Open a device using the provided HANDLER. Fill DEV with the opened + device, or return the error code. Note that this function assumes that HANDLER is recognized as a handler by the backend, i.e. HANDLER_P returns 1 if HANDLER is passed to it. */ - void *(*open) (const char *handler, uint64_t flags, int *error); + int (*open) (const char *handler, uint64_t flags, void **dev); /* Close the given device. Return 0 if there was an error during diff --git a/libpoke/ios.c b/libpoke/ios.c index b77acf20..8f49c091 100644 --- a/libpoke/ios.c +++ b/libpoke/ios.c @@ -121,14 +121,15 @@ ios_open (const char *handler, uint64_t flags, int set_cur) { struct ios *io; struct ios_dev_if **dev_if = NULL; - int error = IOD_ERROR, ret; + int iod_error = IOD_OK, error = IOS_ERROR; /* Allocate and initialize the new IO space. */ io = malloc (sizeof (struct ios)); if (!io) return IOS_ENOMEM; - io->id = ios_next_id++; + io->handler = NULL; + io->dev = NULL; io->next = NULL; io->bias = 0; @@ -136,7 +137,9 @@ ios_open (const char *handler, uint64_t flags, int set_cur) handler. */ for (dev_if = ios_dev_ifs; *dev_if; ++dev_if) { - io->handler = (*dev_if)->handler_normalize (handler, flags); + iod_error = (*dev_if)->handler_normalize (handler, flags, &io->handler); + if (iod_error) + goto error; if (io->handler) break; } @@ -146,11 +149,22 @@ ios_open (const char *handler, uint64_t flags, int set_cur) io->dev_if = *dev_if; + /* Do not re-open an already-open IO space. */ + for (ios i = io_list; i; i = i->next) + if (STREQ (i->handler, io->handler)) + { + error = IOS_EOPEN; + goto error; + } + /* Open the device using the interface found above. */ - io->dev = io->dev_if->open (handler, flags, &error); - if (io->dev == NULL) + iod_error = io->dev_if->open (handler, flags, &io->dev); + if (iod_error || io->dev == NULL) goto error; + /* Increment the id counter after all possible errors are avoided. */ + io->id = ios_next_id++; + /* Add the newly created space to the list, and update the current space. */ io->next = io_list; @@ -162,16 +176,15 @@ ios_open (const char *handler, uint64_t flags, int set_cur) return io->id; error: - if (io) + if (io) { free (io->handler); - free (io); + free (io); + } - if (error == IOD_EINVAL) - ret = IOS_EFLAGS; - else - ret = IOS_ERROR; + if (iod_error) + error = IOD_ERROR_TO_IOS_ERROR (iod_error); - return ret; + return error; } void diff --git a/libpoke/ios.h b/libpoke/ios.h index f58c082e..3ffd5bfc 100644 --- a/libpoke/ios.h +++ b/libpoke/ios.h @@ -100,6 +100,8 @@ typedef int64_t ios_off; #define IOS_EINVAL -6 /* Invalid argument. */ +#define IOS_EOPEN -7 /* IO space is already open. */ + #define IOD_ERROR_TO_IOS_ERROR(error_no) (error_no) /* **************** IOS flags ****************************** diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter index 3a052c20..3293c3f9 100644 --- a/libpoke/pvm.jitter +++ b/libpoke/pvm.jitter @@ -812,7 +812,7 @@ instruction open () if (ret == IOS_EFLAGS) PVM_RAISE_DFL (PVM_E_IOFLAGS); - else if (ret == IOS_ERROR) + else if (ret < IOS_OK) PVM_RAISE_DFL (PVM_E_IO); JITTER_DROP_STACK ();