diff options
author | Max Kellermann <max@duempel.org> | 2009-11-14 23:53:04 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-12-15 23:12:11 +0100 |
commit | 228b03edf8513aa1cdaf4e4647279cc580245555 (patch) | |
tree | 7f5b03a9727fb8c371885469296eb7f49f6fa68b /src/input | |
parent | d000d31355c824a076324b647a3f056aab9ddabe (diff) | |
download | mpd-228b03edf8513aa1cdaf4e4647279cc580245555.tar.gz mpd-228b03edf8513aa1cdaf4e4647279cc580245555.tar.xz mpd-228b03edf8513aa1cdaf4e4647279cc580245555.zip |
input_stream: return errors with GError
Diffstat (limited to '')
-rw-r--r-- | src/input/archive_input_plugin.c | 9 | ||||
-rw-r--r-- | src/input/curl_input_plugin.c | 97 | ||||
-rw-r--r-- | src/input/file_input_plugin.c | 38 | ||||
-rw-r--r-- | src/input/mms_input_plugin.c | 24 | ||||
-rw-r--r-- | src/input_plugin.h | 11 | ||||
-rw-r--r-- | src/input_stream.c | 37 | ||||
-rw-r--r-- | src/input_stream.h | 15 |
7 files changed, 149 insertions, 82 deletions
diff --git a/src/input/archive_input_plugin.c b/src/input/archive_input_plugin.c index 18fa735c2..ad077828a 100644 --- a/src/input/archive_input_plugin.c +++ b/src/input/archive_input_plugin.c @@ -34,7 +34,8 @@ * plugin and gzip fetches file from disk */ static bool -input_archive_open(struct input_stream *is, const char *pathname) +input_archive_open(struct input_stream *is, const char *pathname, + GError **error_r) { const struct archive_plugin *arplug; struct archive_file *file; @@ -63,15 +64,15 @@ input_archive_open(struct input_stream *is, const char *pathname) file = arplug->open(archive); //setup fileops - opened = arplug->open_stream(file, is, filename); + opened = arplug->open_stream(file, is, filename, error_r); + g_free(pname); if (!opened) { - g_warning("open inarchive file %s failed\n\n",filename); arplug->close(file); } else { is->ready = true; } - g_free(pname); + return opened; } diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c index 69b19c371..c6e5a30af 100644 --- a/src/input/curl_input_plugin.c +++ b/src/input/curl_input_plugin.c @@ -103,6 +103,12 @@ static struct curl_slist *http_200_aliases; static const char *proxy, *proxy_user, *proxy_password; static unsigned proxy_port; +static inline GQuark +curl_quark(void) +{ + return g_quark_from_static_string("curl"); +} + static bool input_curl_init(const struct config_param *param, G_GNUC_UNUSED GError **error_r) @@ -216,7 +222,7 @@ input_curl_tag(struct input_stream *is) } static bool -input_curl_multi_info_read(struct input_stream *is) +input_curl_multi_info_read(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMsg *msg; @@ -229,8 +235,9 @@ input_curl_multi_info_read(struct input_stream *is) is->ready = true; if (msg->data.result != CURLE_OK) { - g_warning("curl failed: %s\n", c->error); - is->error = -1; + g_set_error(error_r, curl_quark(), + msg->data.result, + "curl failed: %s", c->error); return false; } } @@ -246,7 +253,7 @@ input_curl_multi_info_read(struct input_stream *is) * available */ static int -input_curl_select(struct input_curl *c) +input_curl_select(struct input_curl *c, GError **error_r) { fd_set rfds, wfds, efds; int max_fd, ret; @@ -265,8 +272,9 @@ input_curl_select(struct input_curl *c) mcode = curl_multi_fdset(c->multi, &rfds, &wfds, &efds, &max_fd); if (mcode != CURLM_OK) { - g_warning("curl_multi_fdset() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_fdset() failed: %s", + curl_multi_strerror(mcode)); return -1; } @@ -274,13 +282,15 @@ input_curl_select(struct input_curl *c) ret = select(max_fd + 1, &rfds, &wfds, &efds, &timeout); if (ret < 0) - g_warning("select() failed: %s\n", strerror(errno)); + g_set_error(error_r, g_quark_from_static_string("errno"), + errno, + "select() failed: %s\n", g_strerror(errno)); return ret; } static bool -fill_buffer(struct input_stream *is) +fill_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode = CURLM_CALL_MULTI_PERFORM; @@ -292,7 +302,7 @@ fill_buffer(struct input_stream *is) if (mcode != CURLM_CALL_MULTI_PERFORM) { /* if we're still here, there is no input yet - wait for input */ - int ret = input_curl_select(c); + int ret = input_curl_select(c, error_r); if (ret <= 0) /* no data yet or error */ return false; @@ -300,14 +310,15 @@ fill_buffer(struct input_stream *is) mcode = curl_multi_perform(c->multi, &running_handles); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return false; } - bret = input_curl_multi_info_read(is); + bret = input_curl_multi_info_read(is, error_r); if (!bret) return false; } @@ -411,7 +422,8 @@ copy_icy_tag(struct input_curl *c) } static size_t -input_curl_read(struct input_stream *is, void *ptr, size_t size) +input_curl_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { struct input_curl *c = is->data; bool success; @@ -443,7 +455,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) do { /* fill the buffer */ - success = fill_buffer(is); + success = fill_buffer(is, error_r); if (!success) return 0; @@ -518,7 +530,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is) } static int -input_curl_buffer(struct input_stream *is) +input_curl_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode; @@ -531,7 +543,8 @@ input_curl_buffer(struct input_stream *is) /* not ready yet means the caller is waiting in a busy loop; relax that by calling select() on the socket */ - input_curl_select(c); + if (input_curl_select(c, error_r) < 0) + return -1; do { mcode = curl_multi_perform(c->multi, &running_handles); @@ -539,14 +552,15 @@ input_curl_buffer(struct input_stream *is) g_queue_is_empty(c->buffers)); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return -1; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) return -1; @@ -672,7 +686,7 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) } static bool -input_curl_easy_init(struct input_stream *is) +input_curl_easy_init(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLcode code; @@ -682,13 +696,18 @@ input_curl_easy_init(struct input_stream *is) c->easy = curl_easy_init(); if (c->easy == NULL) { - g_warning("curl_easy_init() failed\n"); + g_set_error(error_r, curl_quark(), 0, + "curl_easy_init() failed"); return false; } mcode = curl_multi_add_handle(c->multi, c->easy); - if (mcode != CURLM_OK) + if (mcode != CURLM_OK) { + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_add_handle() failed: %s", + curl_multi_strerror(mcode)); return false; + } curl_easy_setopt(c->easy, CURLOPT_USERAGENT, "Music Player Daemon " VERSION); @@ -718,8 +737,12 @@ input_curl_easy_init(struct input_stream *is) } code = curl_easy_setopt(c->easy, CURLOPT_URL, c->url); - if (code != CURLE_OK) + if (code != CURLE_OK) { + g_set_error(error_r, curl_quark(), code, + "curl_easy_setopt() failed: %s", + curl_easy_strerror(code)); return false; + } c->request_headers = NULL; c->request_headers = curl_slist_append(c->request_headers, @@ -730,7 +753,7 @@ input_curl_easy_init(struct input_stream *is) } static bool -input_curl_send_request(struct input_curl *c) +input_curl_send_request(struct input_curl *c, GError **error_r) { CURLMcode mcode; int running_handles; @@ -740,8 +763,9 @@ input_curl_send_request(struct input_curl *c) } while (mcode == CURLM_CALL_MULTI_PERFORM); if (mcode != CURLM_OK) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); return false; } @@ -815,7 +839,8 @@ input_curl_rewind(struct input_stream *is) } static bool -input_curl_seek(struct input_stream *is, goffset offset, int whence) +input_curl_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r) { struct input_curl *c = is->data; bool ret; @@ -907,7 +932,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence) return true; } - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) return false; @@ -918,15 +943,15 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence) curl_easy_setopt(c->easy, CURLOPT_RANGE, c->range); } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) return false; - return input_curl_multi_info_read(is); + return input_curl_multi_info_read(is, error_r); } static bool -input_curl_open(struct input_stream *is, const char *url) +input_curl_open(struct input_stream *is, const char *url, GError **error_r) { struct input_curl *c; bool ret; @@ -944,8 +969,8 @@ input_curl_open(struct input_stream *is, const char *url) c->multi = curl_multi_init(); if (c->multi == NULL) { - g_warning("curl_multi_init() failed\n"); - + g_set_error(error_r, curl_quark(), 0, + "curl_multi_init() failed"); input_curl_free(is); return false; } @@ -953,19 +978,19 @@ input_curl_open(struct input_stream *is, const char *url) icy_clear(&c->icy_metadata); c->tag = NULL; - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) { input_curl_free(is); return false; diff --git a/src/input/file_input_plugin.c b/src/input/file_input_plugin.c index 73dcf4c0f..e8ad87f45 100644 --- a/src/input/file_input_plugin.c +++ b/src/input/file_input_plugin.c @@ -32,8 +32,15 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "input_file" +static inline GQuark +file_quark(void) +{ + return g_quark_from_static_string("file"); +} + static bool -input_file_open(struct input_stream *is, const char *filename) +input_file_open(struct input_stream *is, const char *filename, + GError **error_r) { int fd, ret; struct stat st; @@ -43,9 +50,10 @@ input_file_open(struct input_stream *is, const char *filename) fd = open_cloexec(filename, O_RDONLY, 0); if (fd < 0) { - is->error = errno; - g_debug("Failed to open \"%s\": %s", - filename, g_strerror(errno)); + if (errno != ENOENT && errno != ENOTDIR) + g_set_error(error_r, file_quark(), errno, + "Failed to open \"%s\": %s", + filename, g_strerror(errno)); return false; } @@ -53,14 +61,16 @@ input_file_open(struct input_stream *is, const char *filename) ret = fstat(fd, &st); if (ret < 0) { - is->error = errno; + g_set_error(error_r, file_quark(), errno, + "Failed to stat \"%s\": %s", + filename, g_strerror(errno)); close(fd); return false; } if (!S_ISREG(st.st_mode)) { - g_debug("Not a regular file: %s", filename); - is->error = EINVAL; + g_set_error(error_r, file_quark(), 0, + "Not a regular file: %s", filename); close(fd); return false; } @@ -79,13 +89,15 @@ input_file_open(struct input_stream *is, const char *filename) } static bool -input_file_seek(struct input_stream *is, goffset offset, int whence) +input_file_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r) { int fd = GPOINTER_TO_INT(is->data); offset = (goffset)lseek(fd, (off_t)offset, whence); if (offset < 0) { - is->error = errno; + g_set_error(error_r, file_quark(), errno, + "Failed to seek: %s", g_strerror(errno)); return false; } @@ -94,16 +106,16 @@ input_file_seek(struct input_stream *is, goffset offset, int whence) } static size_t -input_file_read(struct input_stream *is, void *ptr, size_t size) +input_file_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { int fd = GPOINTER_TO_INT(is->data); ssize_t nbytes; nbytes = read(fd, ptr, size); if (nbytes < 0) { - is->error = errno; - g_debug("input_file_read: error reading: %s\n", - strerror(is->error)); + g_set_error(error_r, file_quark(), errno, + "Failed to read: %s", g_strerror(errno)); return 0; } diff --git a/src/input/mms_input_plugin.c b/src/input/mms_input_plugin.c index eb2665afb..b38fb43df 100644 --- a/src/input/mms_input_plugin.c +++ b/src/input/mms_input_plugin.c @@ -36,8 +36,14 @@ struct input_mms { bool eof; }; +static inline GQuark +mms_quark(void) +{ + return g_quark_from_static_string("mms"); +} + static bool -input_mms_open(struct input_stream *is, const char *url) +input_mms_open(struct input_stream *is, const char *url, GError **error_r) { struct input_mms *m; @@ -50,7 +56,7 @@ input_mms_open(struct input_stream *is, const char *url) m = g_new(struct input_mms, 1); m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024); if (m->mms == NULL) { - g_warning("mmsx_connect() failed"); + g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed"); return false; } @@ -65,7 +71,8 @@ input_mms_open(struct input_stream *is, const char *url) } static size_t -input_mms_read(struct input_stream *is, void *ptr, size_t size) +input_mms_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { struct input_mms *m = is->data; int ret; @@ -73,8 +80,9 @@ input_mms_read(struct input_stream *is, void *ptr, size_t size) ret = mmsx_read(NULL, m->mms, ptr, size); if (ret <= 0) { if (ret < 0) { - is->error = errno; - g_warning("mmsx_read() failed: %s", g_strerror(errno)); + g_set_error(error_r, mms_quark(), errno, + "mmsx_read() failed: %s", + g_strerror(errno)); } m->eof = true; @@ -104,14 +112,16 @@ input_mms_eof(struct input_stream *is) } static int -input_mms_buffer(G_GNUC_UNUSED struct input_stream *is) +input_mms_buffer(G_GNUC_UNUSED struct input_stream *is, + G_GNUC_UNUSED GError **error_r) { return 0; } static bool input_mms_seek(G_GNUC_UNUSED struct input_stream *is, - G_GNUC_UNUSED goffset offset, G_GNUC_UNUSED int whence) + G_GNUC_UNUSED goffset offset, G_GNUC_UNUSED int whence, + G_GNUC_UNUSED GError **error_r) { return false; } diff --git a/src/input_plugin.h b/src/input_plugin.h index b0ba37959..d7dbfa853 100644 --- a/src/input_plugin.h +++ b/src/input_plugin.h @@ -48,14 +48,17 @@ struct input_plugin { */ void (*finish)(void); - bool (*open)(struct input_stream *is, const char *url); + bool (*open)(struct input_stream *is, const char *url, + GError **error_r); void (*close)(struct input_stream *is); struct tag *(*tag)(struct input_stream *is); - int (*buffer)(struct input_stream *is); - size_t (*read)(struct input_stream *is, void *ptr, size_t size); + int (*buffer)(struct input_stream *is, GError **error_r); + size_t (*read)(struct input_stream *is, void *ptr, size_t size, + GError **error_r); bool (*eof)(struct input_stream *is); - bool (*seek)(struct input_stream *is, goffset offset, int whence); + bool (*seek)(struct input_stream *is, goffset offset, int whence, + GError **error_r); }; #endif diff --git a/src/input_stream.c b/src/input_stream.c index 54ea1c995..27cf4abda 100644 --- a/src/input_stream.c +++ b/src/input_stream.c @@ -25,20 +25,32 @@ #include <glib.h> #include <assert.h> +static inline GQuark +input_quark(void) +{ + return g_quark_from_static_string("input"); +} + bool -input_stream_open(struct input_stream *is, const char *url) +input_stream_open(struct input_stream *is, const char *url, GError **error_r) { + GError *error = NULL; + + assert(error_r == NULL || *error_r == NULL); + is->seekable = false; is->ready = false; is->offset = 0; is->size = -1; - is->error = 0; is->mime = NULL; for (unsigned i = 0; input_plugins[i] != NULL; ++i) { const struct input_plugin *plugin = input_plugins[i]; - if (input_plugins_enabled[i] && plugin->open(is, url)) { + if (!input_plugins_enabled[i]) + continue; + + if (plugin->open(is, url, &error)) { assert(is->plugin != NULL); assert(is->plugin->close != NULL); assert(is->plugin->read != NULL); @@ -46,19 +58,24 @@ input_stream_open(struct input_stream *is, const char *url) assert(!is->seekable || is->plugin->seek != NULL); return true; + } else if (error != NULL) { + g_propagate_error(error_r, error); + return false; } } + g_set_error(error_r, input_quark(), 0, "Unrecognized URI"); return false; } bool -input_stream_seek(struct input_stream *is, goffset offset, int whence) +input_stream_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r) { if (is->plugin->seek == NULL) return false; - return is->plugin->seek(is, offset, whence); + return is->plugin->seek(is, offset, whence, error_r); } struct tag * @@ -72,12 +89,13 @@ input_stream_tag(struct input_stream *is) } size_t -input_stream_read(struct input_stream *is, void *ptr, size_t size) +input_stream_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { assert(ptr != NULL); assert(size > 0); - return is->plugin->read(is, ptr, size); + return is->plugin->read(is, ptr, size, error_r); } void input_stream_close(struct input_stream *is) @@ -92,10 +110,11 @@ bool input_stream_eof(struct input_stream *is) return is->plugin->eof(is); } -int input_stream_buffer(struct input_stream *is) +int +input_stream_buffer(struct input_stream *is, GError **error_r) { if (is->plugin->buffer == NULL) return 0; - return is->plugin->buffer(is); + return is->plugin->buffer(is, error_r); } diff --git a/src/input_stream.h b/src/input_stream.h index 63327c137..7d61b9d86 100644 --- a/src/input_stream.h +++ b/src/input_stream.h @@ -55,11 +55,6 @@ struct input_stream { bool seekable; /** - * an optional errno error code, set to non-zero after an error occured - */ - int error; - - /** * the size of the resource, or -1 if unknown */ goffset size; @@ -83,7 +78,7 @@ struct input_stream { * @return true on success */ bool -input_stream_open(struct input_stream *is, const char *url); +input_stream_open(struct input_stream *is, const char *url, GError **error_r); /** * Closes the input stream and free resources. This does not free the @@ -102,7 +97,8 @@ input_stream_close(struct input_stream *is); * @param whence the base of the seek, one of SEEK_SET, SEEK_CUR, SEEK_END */ bool -input_stream_seek(struct input_stream *is, goffset offset, int whence); +input_stream_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r); /** * Returns true if the stream has reached end-of-file. @@ -126,7 +122,7 @@ input_stream_tag(struct input_stream *is); * The semantics of this function are not well-defined, and it will * eventually be removed. */ -int input_stream_buffer(struct input_stream *is); +int input_stream_buffer(struct input_stream *is, GError **error_r); /** * Reads data from the stream into the caller-supplied buffer. @@ -138,6 +134,7 @@ int input_stream_buffer(struct input_stream *is); * @return the number of bytes read */ size_t -input_stream_read(struct input_stream *is, void *ptr, size_t size); +input_stream_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r); #endif |