/** * Simple data fetcher. * @param url path or url of data to fetch. * @return data fetched, or NULL on error. Must be freed with g_free. */ static char * lastfm_get(const char *url, GMutex *mutex, GCond *cond) { struct input_stream *input_stream; GError *error = NULL; char buffer[4096]; size_t length = 0, nbytes; input_stream = input_stream_open(url, mutex, cond, &error); if (input_stream == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return NULL; } g_mutex_lock(mutex); input_stream_wait_ready(input_stream); do { nbytes = input_stream_read(input_stream, buffer + length, sizeof(buffer) - length, &error); if (nbytes == 0) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } if (input_stream_eof(input_stream)) break; /* I/O error */ g_mutex_unlock(mutex); input_stream_close(input_stream); return NULL; } length += nbytes; } while (length < sizeof(buffer)); g_mutex_unlock(mutex); input_stream_close(input_stream); return g_strndup(buffer, length); }
/** * Opens the input stream with input_stream_open(), and waits until * the stream gets ready. If a decoder STOP command is received * during that, it cancels the operation (but does not close the * stream). * * Unlock the decoder before calling this function. * * @return an input_stream on success or if #DECODE_COMMAND_STOP is * received, NULL on error */ static struct input_stream * decoder_input_stream_open(struct decoder_control *dc, const char *uri) { GError *error = NULL; struct input_stream *is; is = input_stream_open(uri, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return NULL; } /* wait for the input stream to become ready; its metadata will be available then */ while (!is->ready && decoder_lock_get_command(dc) != DECODE_COMMAND_STOP) { int ret; ret = input_stream_buffer(is, &error); if (ret < 0) { input_stream_close(is); g_warning("%s", error->message); g_error_free(error); return NULL; } } return is; }
enum playlist_result playlist_open_into_queue(const char *uri, unsigned start_index, unsigned end_index, struct playlist *dest, struct player_control *pc, bool secure) { GMutex *mutex = g_mutex_new(); GCond *cond = g_cond_new(); struct input_stream *is; struct playlist_provider *playlist = playlist_open_any(uri, mutex, cond, &is); if (playlist == NULL) { g_cond_free(cond); g_mutex_free(mutex); return PLAYLIST_RESULT_NO_SUCH_LIST; } enum playlist_result result = playlist_load_into_queue(uri, playlist, start_index, end_index, dest, pc, secure); playlist_plugin_close(playlist); if (is != NULL) input_stream_close(is); g_cond_free(cond); g_mutex_free(mutex); return result; }
static struct playlist_provider * playlist_open_remote(const char *uri, GMutex *mutex, GCond *cond, struct input_stream **is_r) { assert(uri_has_scheme(uri)); struct playlist_provider *playlist = playlist_list_open_uri(uri, mutex, cond); if (playlist != NULL) { *is_r = NULL; return playlist; } GError *error = NULL; struct input_stream *is = input_stream_open(uri, mutex, cond, &error); if (is == NULL) { if (error != NULL) { g_warning("Failed to open %s: %s", uri, error->message); g_error_free(error); } return NULL; } playlist = playlist_list_open_stream(is, uri); if (playlist == NULL) { input_stream_close(is); return NULL; } *is_r = is; return playlist; }
int main(int argc, char **argv) { GError *error = NULL; struct input_stream *is; int ret; if (argc != 2) { g_printerr("Usage: run_input URI\n"); return 1; } /* initialize GLib */ g_thread_init(NULL); g_log_set_default_handler(my_log_func, NULL); /* initialize MPD */ tag_pool_init(); config_global_init(); #ifdef ENABLE_ARCHIVE archive_plugin_init_all(); #endif if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); return 2; } /* open the stream and dump it */ is = input_stream_open(argv[1], &error); if (is != NULL) { ret = dump_input_stream(is); input_stream_close(is); } else { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } else g_printerr("input_stream_open() failed\n"); ret = 2; } /* deinitialize everything */ input_stream_global_finish(); #ifdef ENABLE_ARCHIVE archive_plugin_deinit_all(); #endif config_global_finish(); tag_pool_deinit(); return ret; }
static void lastfm_close(struct playlist_provider *_playlist) { struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist; playlist_plugin_close(playlist->xspf); input_stream_close(playlist->is); g_free(playlist); }
void zonefile_close(zone_file* in_file) { zassert(in_file != NULL); /* The filter closes the filtered */ input_stream_close(&in_file->bis); }
static void buffer_input_stream_close(input_stream* stream) { buffer_input_stream_data* data = (buffer_input_stream_data*)stream->data; input_stream_close(&data->filtered); free(data); input_stream_set_void(stream); }
static void zdb_zone_axfr_input_stream_close(input_stream* is) { zdb_zone_axfr_input_stream_data* data = (zdb_zone_axfr_input_stream_data*)is->data; input_stream_close(&data->filtered); free(data); input_stream_set_void(is); }
struct playlist_provider * playlist_list_open_path(const char *path_fs) { GError *error = NULL; const char *suffix; struct input_stream *is; struct playlist_provider *playlist; assert(path_fs != NULL); suffix = uri_get_suffix(path_fs); if (suffix == NULL || !playlist_suffix_supported(suffix)) return NULL; is = input_stream_open(path_fs, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return NULL; } while (!is->ready) { int ret = input_stream_buffer(is, &error); if (ret < 0) { input_stream_close(is); g_warning("%s", error->message); g_error_free(error); return NULL; } } playlist = playlist_list_open_stream_suffix(is, suffix); if (playlist == NULL) input_stream_close(is); return playlist; }
static void bz2_close(struct archive_file *file) { struct bz2_archive_file *context = (struct bz2_archive_file *) file; if (!refcount_dec(&context->ref)) return; g_free(context->name); input_stream_close(context->istream); g_free(context); }
static enum playlist_result playlist_open_remote_into_queue(const char *uri, struct playlist *dest) { GError *error = NULL; struct playlist_provider *playlist; struct input_stream *is = NULL; enum playlist_result result; assert(uri_has_scheme(uri)); playlist = playlist_list_open_uri(uri); if (playlist == NULL) { is = input_stream_open(uri, &error); if (is == NULL) { if (error != NULL) { g_warning("Failed to open %s: %s", uri, error->message); g_error_free(error); } return PLAYLIST_RESULT_NO_SUCH_LIST; } playlist = playlist_list_open_stream(is, uri); if (playlist == NULL) { input_stream_close(is); return PLAYLIST_RESULT_NO_SUCH_LIST; } } result = playlist_load_into_queue(uri, playlist, dest); playlist_plugin_close(playlist); if (is != NULL) input_stream_close(is); return result; }
/** * Try decoding a file. */ static bool decoder_run_file(struct decoder *decoder, const char *path_fs) { struct decoder_control *dc = decoder->dc; const char *suffix = uri_get_suffix(path_fs); const struct decoder_plugin *plugin = NULL; if (suffix == NULL) return false; decoder_unlock(dc); decoder_load_replay_gain(decoder, path_fs); while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) { if (plugin->file_decode != NULL) { decoder_lock(dc); if (decoder_file_decode(plugin, decoder, path_fs)) return true; decoder_unlock(dc); } else if (plugin->stream_decode != NULL) { struct input_stream *input_stream; bool success; input_stream = decoder_input_stream_open(dc, path_fs); if (input_stream == NULL) continue; decoder_lock(dc); success = decoder_stream_decode(plugin, decoder, input_stream); decoder_unlock(dc); input_stream_close(input_stream); if (success) { decoder_lock(dc); return true; } } } decoder_lock(dc); return false; }
static bool wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc, struct wavpack_input *wpi) { char *utf8url; char *wvc_url = NULL; bool ret; char first_byte; size_t nbytes; /* * As we use dc->utf8url, this function will be bad for * single files. utf8url is not absolute file path :/ */ utf8url = decoder_get_uri(decoder); if (utf8url == NULL) { return false; } wvc_url = g_strconcat(utf8url, "c", NULL); g_free(utf8url); ret = input_stream_open(is_wvc, wvc_url); g_free(wvc_url); if (!ret) { return false; } /* * And we try to buffer in order to get know * about a possible 404 error. */ nbytes = decoder_read( decoder, is_wvc, &first_byte, sizeof(first_byte) ); if (nbytes == 0) { input_stream_close(is_wvc); return false; } /* push it back */ wavpack_input_init(wpi, decoder, is_wvc); wpi->last_byte = first_byte; return true; }
/* this is primarily used for getting total time for tags */ static int mp3_total_file_time(const char *file) { struct input_stream input_stream; struct mp3_data data; int ret; if (!input_stream_open(&input_stream, file)) return -1; mp3_data_init(&data, NULL, &input_stream); if (!mp3_decode_first_frame(&data, NULL, NULL)) ret = -1; else ret = data.total_time + 0.5; mp3_data_finish(&data); input_stream_close(&input_stream); return ret; }
enum playlist_result playlist_open_into_queue(const char *uri, struct playlist *dest, struct player_control *pc, bool secure) { struct input_stream *is; struct playlist_provider *playlist = playlist_open_any(uri, &is); if (playlist == NULL) return PLAYLIST_RESULT_NO_SUCH_LIST; enum playlist_result result = playlist_load_into_queue(uri, playlist, dest, pc, secure); playlist_plugin_close(playlist); if (is != NULL) input_stream_close(is); return result; }
static struct input_stream * wavpack_open_wvc(struct decoder *decoder, const char *uri, struct wavpack_input *wpi) { struct input_stream *is_wvc; char *wvc_url = NULL; char first_byte; size_t nbytes; /* * As we use dc->utf8url, this function will be bad for * single files. utf8url is not absolute file path :/ */ if (uri == NULL) return false; wvc_url = g_strconcat(uri, "c", NULL); is_wvc = input_stream_open(wvc_url, NULL); g_free(wvc_url); if (is_wvc == NULL) return NULL; /* * And we try to buffer in order to get know * about a possible 404 error. */ nbytes = decoder_read( decoder, is_wvc, &first_byte, sizeof(first_byte) ); if (nbytes == 0) { input_stream_close(is_wvc); return NULL; } /* push it back */ wavpack_input_init(wpi, decoder, is_wvc); wpi->last_byte = first_byte; return is_wvc; }
/* * Decodes a stream. */ static void wavpack_streamdecode(struct decoder * decoder, struct input_stream *is) { char error[ERRORLEN]; WavpackContext *wpc; struct input_stream *is_wvc; int open_flags = OPEN_NORMALIZE; struct wavpack_input isp, isp_wvc; bool can_seek = is->seekable; is_wvc = wavpack_open_wvc(decoder, is->uri, &isp_wvc); if (is_wvc != NULL) { open_flags |= OPEN_WVC; can_seek &= is_wvc->seekable; } if (!can_seek) { open_flags |= OPEN_STREAMING; } wavpack_input_init(&isp, decoder, is); wpc = WavpackOpenFileInputEx( &mpd_is_reader, &isp, open_flags & OPEN_WVC ? &isp_wvc : NULL, error, open_flags, 23 ); if (wpc == NULL) { g_warning("failed to open WavPack stream: %s\n", error); return; } wavpack_decode(decoder, wpc, can_seek); WavpackCloseFile(wpc); if (open_flags & OPEN_WVC) { input_stream_close(is_wvc); } }
/** * Try decoding a stream. */ static bool decoder_run_stream(struct decoder *decoder, const char *uri) { struct decoder_control *dc = decoder->dc; struct input_stream *input_stream; bool success; decoder_unlock(dc); input_stream = decoder_input_stream_open(dc, uri); if (input_stream == NULL) { decoder_lock(dc); return false; } decoder_lock(dc); GSList *tried = NULL; success = dc->command == DECODE_COMMAND_STOP || /* first we try mime types: */ decoder_run_stream_mime_type(decoder, input_stream, &tried) || /* if that fails, try suffix matching the URL: */ decoder_run_stream_suffix(decoder, input_stream, uri, &tried) || /* fallback to mp3: this is needed for bastard streams that don't have a suffix or set the mimeType */ (tried == NULL && decoder_run_stream_fallback(decoder, input_stream)); g_slist_free(tried); decoder_unlock(dc); input_stream_close(input_stream); decoder_lock(dc); return success; }
static void xfr_input_stream_close(input_stream *is) { xfr_input_stream_data *data = (xfr_input_stream_data*)is->data; if(data->need_cleanup_tsig) { log_err("TSIG has not been cleared"); data->need_cleanup_tsig = FALSE; } output_stream_close(&data->pipe_stream_output); input_stream_close(&data->pipe_stream_input); free(data->first_soa_record); #ifdef DEBUG memset(data, 0xfe, sizeof(xfr_input_stream_data)); #endif ZFREE(data, xfr_input_stream_data); // used to be leaked ? input_stream_set_void(is); }
int main(int argc, char **argv) { GError *error = NULL; const char *decoder_name; struct decoder decoder; if (argc != 3) { g_printerr("Usage: run_decoder DECODER URI >OUT\n"); return 1; } decoder_name = argv[1]; decoder.uri = argv[2]; g_log_set_default_handler(my_log_func, NULL); tag_pool_init(); if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); return 2; } decoder_plugin_init_all(); decoder.plugin = decoder_plugin_from_name(decoder_name); if (decoder.plugin == NULL) { g_printerr("No such decoder: %s\n", decoder_name); return 1; } decoder.initialized = false; if (decoder.plugin->file_decode != NULL) { decoder_plugin_file_decode(decoder.plugin, &decoder, decoder.uri); } else if (decoder.plugin->stream_decode != NULL) { struct input_stream *is = input_stream_open(decoder.uri, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } else g_printerr("input_stream_open() failed\n"); return 1; } decoder_plugin_stream_decode(decoder.plugin, &decoder, is); input_stream_close(is); } else { g_printerr("Decoder plugin is not usable\n"); return 1; } decoder_plugin_deinit_all(); input_stream_global_finish(); if (!decoder.initialized) { g_printerr("Decoding failed\n"); return 1; } tag_pool_deinit(); return 0; }
bool song_file_update(struct song *song) { const char *suffix; char *path_fs; const struct decoder_plugin *plugin; struct stat st; struct input_stream *is = NULL; assert(song_is_file(song)); /* check if there's a suffix and a plugin */ suffix = uri_get_suffix(song->uri); if (suffix == NULL) return false; plugin = decoder_plugin_from_suffix(suffix, NULL); if (plugin == NULL) return false; path_fs = map_song_fs(song); if (path_fs == NULL) return false; if (song->tag != NULL) { tag_free(song->tag); song->tag = NULL; } if (stat(path_fs, &st) < 0 || !S_ISREG(st.st_mode)) { g_free(path_fs); return false; } song->mtime = st.st_mtime; GMutex *mutex = NULL; GCond *cond; #if !GCC_CHECK_VERSION(4, 2) /* work around "may be used uninitialized in this function" false positive */ cond = NULL; #endif do { /* load file tag */ song->tag = tag_new(); if (decoder_plugin_scan_file(plugin, path_fs, &full_tag_handler, song->tag)) break; tag_free(song->tag); song->tag = NULL; /* fall back to stream tag */ if (plugin->scan_stream != NULL) { /* open the input_stream (if not already open) */ if (is == NULL) { mutex = g_mutex_new(); cond = g_cond_new(); is = input_stream_open(path_fs, mutex, cond, NULL); } /* now try the stream_tag() method */ if (is != NULL) { song->tag = tag_new(); if (decoder_plugin_scan_stream(plugin, is, &full_tag_handler, song->tag)) break; tag_free(song->tag); song->tag = NULL; input_stream_lock_seek(is, 0, SEEK_SET, NULL); } } plugin = decoder_plugin_from_suffix(suffix, plugin); } while (plugin != NULL); if (is != NULL) input_stream_close(is); if (mutex != NULL) { g_cond_free(cond); g_mutex_free(mutex); } if (song->tag != NULL && tag_is_empty(song->tag)) tag_scan_fallback(path_fs, &full_tag_handler, song->tag); g_free(path_fs); return song->tag != NULL; }
int main(int argc, char **argv) { GError *error = NULL; const char *decoder_name, *path; const struct decoder_plugin *plugin; struct tag *tag; bool empty; #ifdef HAVE_LOCALE_H /* initialize locale */ setlocale(LC_CTYPE,""); #endif if (argc != 3) { g_printerr("Usage: read_tags DECODER FILE\n"); return 1; } decoder_name = argv[1]; path = argv[2]; tag_pool_init(); if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); return 2; } decoder_plugin_init_all(); plugin = decoder_plugin_from_name(decoder_name); if (plugin == NULL) { g_printerr("No such decoder: %s\n", decoder_name); return 1; } tag = decoder_plugin_tag_dup(plugin, path); if (tag == NULL && plugin->stream_tag != NULL) { struct input_stream *is = input_stream_open(path, &error); if (is == NULL) { g_printerr("Failed to open %s: %s\n", path, error->message); g_error_free(error); return 1; } tag = decoder_plugin_stream_tag(plugin, is); input_stream_close(is); } decoder_plugin_deinit_all(); input_stream_global_finish(); if (tag == NULL) { g_printerr("Failed to read tags\n"); return 1; } print_tag(tag); empty = tag_is_empty(tag); tag_free(tag); if (empty) { tag = tag_ape_load(path); if (tag == NULL) tag = tag_id3_load(path); if (tag != NULL) { print_tag(tag); tag_free(tag); } } tag_pool_deinit(); return 0; }
static ya_result journal_ix_get_ixfr_stream_at_serial(journal *jh, u32 serial_from, input_stream *out_input_stream, dns_resource_record *last_soa_rr) { journal_ix *jix = (journal_ix*)jh; ya_result return_value = SUCCESS; journal_ix_readlock(jix); /* * check that serial_from in in the journal range * set the file descriptor to the position * create a stream that'll stop at the current end of the stream */ if(serial_lt(serial_from, jix->first_serial) || serial_ge(serial_from, jix->last_serial) || ((jix->first_serial == 0) && (jix->last_serial == 0))) { /* out of known range */ journal_ix_readunlock(jix); if(serial_from == jix->last_serial) { return SUCCESS; } else { return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } } /* * On success, dup() returns a new file descriptor that has the following in common with the original: * * _ Same open file (or pipe) * _ Same file pointer (both file descriptors share one file pointer) <= THIS is a problem * _ Same access mode (read, write, or read/write) * * So this is wrong: * * cloned_fd = dup(jix->fd); */ int cloned_fd; while((cloned_fd = open_ex(jix->journal_name, O_RDONLY)) < 0) { int err = errno; if(err == EINTR) { continue; } return_value = MAKE_ERRNO_ERROR(err); #ifdef DEBUG log_debug("journal: ix: unable to clone the file descriptor: %r", return_value); #endif journal_ix_readunlock(jix); return return_value; } /* * given that I use a clone of the fd and * given that only appends are done in the file and * given that the limit of the file has already been processed (should be at this point) * * THEN * * there is no point keeping the lock for reading (on unix systems) */ struct stat journal_stat; s64 last_page_offset = jix->last_page_offset; if(fstat(cloned_fd, &journal_stat) < 0) { return_value = ERRNO_ERROR; log_err("journal: ix: unable to get journal file status", return_value); close_ex(cloned_fd); return return_value; } s64 file_size = journal_stat.st_size; #if DEBUG_JOURNAL log_debug("journal: ix: the last page starts at position %lld", last_page_offset); #endif journal_ix_readunlock(jix); jix = NULL; input_stream fis; fd_input_stream_attach(&fis, cloned_fd); if(last_soa_rr != NULL) { /* seek and store the last SOA print*/ last_soa_rr->tctr.qtype = 0; // clear type if(lseek(cloned_fd, last_page_offset, SEEK_SET) >= 0) { /* deleted SOA */ if((return_value = dns_resource_record_read(last_soa_rr, &fis)) > 0 ) // Not FAIL nor EOF { if(last_soa_rr->tctr.qtype == TYPE_SOA) { /* DEL records */ last_soa_rr->tctr.qtype = 0; // clear type /* scan until added SOA found */ while((return_value = dns_resource_record_read(last_soa_rr, &fis)) > 0 ) // Not FAIL nor EOF { if(last_soa_rr->tctr.qtype == TYPE_SOA) { break; } } } } // if the SOA has not been found, it's an error (EOF has been reached is covered by this) if(ISOK(return_value)) { if(last_soa_rr->tctr.qtype != TYPE_SOA) { return_value = ZDB_JOURNAL_SOA_RECORD_EXPECTED; } } } else { return_value = ERRNO_ERROR; } if(FAIL(return_value)) { input_stream_close(&fis); return return_value; } } /* * this format has no indexing so we scan for a page that STARTS with a DELETE of the SOA with serial = serial_from */ if(lseek(cloned_fd, 0, SEEK_SET) != 0) /* the resulting offset MUST be zero */ { return_value = ERRNO_ERROR; if(ISOK(return_value)) { return_value = ERROR; } input_stream_close(&fis); return return_value; } input_stream bis; dns_resource_record rr; dns_resource_record_init(&rr); buffer_input_stream_init(&fis, &bis, 512); s64 offset = 0; /* skip until the right serial is found */ u32 soa_count = 0; #ifdef DEBUG_JOURNAL u32 rr_count = 0; #endif for(;;) { if( (return_value = dns_resource_record_read(&rr, &bis)) <= 0 ) // FAIL or nothing to { return_value = ZDB_JOURNAL_ERROR_READING_JOURNAL; /* is the journal file broken ? */ break; } #ifdef DEBUG_JOURNAL rr_count++; #endif u32 record_size = return_value; if(rr.tctr.qtype == TYPE_SOA) { // ((0+1)&1) != 0 => Y N Y N if((++soa_count & 1) != 0) // 1 2 3 4 { u8 *p = rr.rdata; if(FAIL(return_value = dnsname_len(p))) { break; } p += return_value; if(FAIL(return_value = dnsname_len(p))) { break; } p += return_value; u32 serial = ntohl(GET_U32_AT(*p)); if(serial_ge(serial, serial_from)) { if(serial == serial_from) { /* setup the serial to be from 'offset' up to the current length of the stream */ return_value = SUCCESS; } else { /* the serial does not exist in the range */ return_value = ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } break; } } } offset += record_size; } #if DEBUG_JOURNAL log_debug("journal: ix: serial %08x (%d) is at offset %lld. %d records parsed", serial_from, serial_from, offset, rr_count); #endif dns_resource_record_clear(&rr); /* * detach the file descriptor from the file stream in the buffer stream * I do it like this because the streams are not needed anymore but the * file descriptor still is (if no error occurred) */ fd_input_stream_detach(buffer_input_stream_get_filtered(&bis)); input_stream_close(&bis); if(ISOK(return_value)) { // offset is the start of the page we are looking for if(lseek(cloned_fd, offset, SEEK_SET) >= 0) { fd_input_stream_attach(&fis, cloned_fd); limited_input_stream_init(&fis, out_input_stream, file_size - offset); } else { return_value = ERRNO_ERROR; close_ex(cloned_fd); } } else { close_ex(cloned_fd); } return return_value; }
ya_result zdb_icmtl_replay(zdb_zone *zone) { ya_result return_value; u32 serial; zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); return_value = zdb_zone_getserial(zone, &serial); // zone is locked if(FAIL(return_value)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading serial for zone: %r", zone->origin, return_value); return return_value; } input_stream is; #if ICMTL_DUMP_JOURNAL_RECORDS log_debug("journal: zdb_icmtl_replay(%{dnsname})", zone->origin); logger_flush(); #endif u32 first_serial; u32 last_serial; if(FAIL(return_value = zdb_zone_journal_get_serial_range(zone, &first_serial, &last_serial))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); if(return_value == ZDB_ERROR_ICMTL_NOTFOUND) { return_value = SUCCESS; } else { log_err("journal: %{dnsname}: error opening journal for zone: %r", zone->origin, return_value); } return return_value; } log_debug("journal: %{dnsname}: zone serial is %i, journal covers serials from %i to %i", zone->origin, serial, first_serial, last_serial); if(last_serial == serial) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_debug("journal: %{dnsname}: nothing to read from the journal", zone->origin); return 0; } if(serial_lt(serial, first_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: first serial from the journal is after the zone", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(serial_gt(serial, last_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: last serial from the journal is before the zone", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(FAIL(return_value = zdb_zone_journal_get_ixfr_stream_at_serial(zone, serial, &is, NULL))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading journal from serial %d: %r",zone->origin, serial, return_value); return return_value; } log_info("journal: %{dnsname}: replaying from serial %u",zone->origin, serial); buffer_input_stream_init(&is, &is, ZDB_ICMTL_REPLAY_BUFFER_SIZE); u16 shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; u32 current_serial = serial; /* * Read all records from [ SOA ... SOA ... [ SOA in memory */ output_stream baos; input_stream bais; dns_resource_record rr; int baos_rr_count = 0; int baos_soa_count = 0; bool was_nsec3 = zdb_zone_is_nsec3(zone); bytearray_output_stream_init_ex(&baos, NULL, ZDB_ICMTL_REPLAY_BUFFER_SIZE, BYTEARRAY_DYNAMIC); dns_resource_record_init(&rr); // 0: gather, 1: commit, 2: commit & stop for(int replay_state = ZDB_ICMTL_REPLAY_GATHER; replay_state != ZDB_ICMTL_REPLAY_COMMIT_AND_STOP;) { // ensure it's not supposed to shutdown (every few iterations) if(--shutdown_test_countdown <= 0) { if(dnscore_shuttingdown()) { return_value = STOPPED_BY_APPLICATION_SHUTDOWN; break; } shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; } // read the next record if((return_value = dns_resource_record_read(&rr, &is)) <= 0) { if(ISOK(return_value)) { log_info("journal: %{dnsname}: reached the end of the journal file", zone->origin); replay_state = ZDB_ICMTL_REPLAY_COMMIT_AND_STOP; } else { log_err("journal: broken journal: %r", return_value); logger_flush(); // broken journal (flush is slow, but this is bad, so : keep it) replay_state = ZDB_ICMTL_REPLAY_STOP; } } else // first record must be an SOA (or it's wrong) if(baos_rr_count == 0) // first record ? { if(rr.tctr.qtype != TYPE_SOA) // must be SOA { // expected an SOA return_value = ERROR; break; } ++baos_soa_count; // 0 -> 1 // this is not mandatory but clearer to read } else // the page ends with an SOA or end of stream if(rr.tctr.qtype == TYPE_SOA) { if(baos_soa_count == 2) { // this record is the start of the next stream, keep it for the next iteration replay_state = ZDB_ICMTL_REPLAY_COMMIT; } ++baos_soa_count; } ++baos_rr_count; if((replay_state & ZDB_ICMTL_REPLAY_COMMIT) != 0) { log_info("journal: %{dnsname}: committing changes", zone->origin); u64 ts_start = timeus(); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); bytearray_input_stream_init_const(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); return_value = zdb_icmtl_replay_commit(zone, &bais, ¤t_serial); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); input_stream_close(&bais); u64 ts_stop = timeus(); if(ts_stop < ts_start) // time change { ts_stop = ts_start; } u64 ts_delta = ts_stop - ts_start; if(ISOK(return_value)) { if(ts_delta < 1000) { log_info("journal: %{dnsname}: committed changes (%lluus)", zone->origin, ts_delta); } else if(ts_delta < 1000000) { double ts_delta_s = ts_delta; ts_delta_s /= 1000.0; log_info("journal: %{dnsname}: committed changes (%5.2fms)", zone->origin, ts_delta_s); } else { double ts_delta_s = ts_delta; ts_delta_s /= 1000000.0; log_info("journal: %{dnsname}: committed changes (%5.2fs)", zone->origin, ts_delta_s); } } else { log_err("journal: %{dnsname}: failed to committed changes", zone->origin); break; } // the current page has been processed if(replay_state == ZDB_ICMTL_REPLAY_COMMIT_AND_STOP) { // no more page to read break; } // reset the state for the next page // note: the next written record will be the last read SOA baos_rr_count = 1; baos_soa_count = 1; replay_state = ZDB_ICMTL_REPLAY_GATHER; bytearray_output_stream_reset(&baos); } // end if replay_state is ZDB_ICMTL_REPLAY_COMMIT (mask) dns_resource_record_write(&rr, &baos); } input_stream_close(&is); output_stream_close(&baos); dns_resource_record_clear(&rr); // cleanup destroyed nsec3 chains if(ISOK(return_value)) { bool is_nsec3 = zdb_zone_is_nsec3(zone); if(is_nsec3 && !was_nsec3) { // the chain has just been created, but is probably missing internal links log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: updating links", zone->origin); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); nsec3_zone_update_chain0_links(zone); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: links updated", zone->origin); } if(FAIL(return_value = zdb_zone_getserial(zone, &serial))) // zone is locked { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading confirmation serial for zone: %r",zone->origin, return_value); return return_value; } if(serial != last_serial) { log_warn("journal: %{dnsname}: expected serial to be %i but it is %i instead",zone->origin, last_serial, serial); } #if 0 // ICMTL_DUMP_JOURNAL_RECORDS if(is_nsec) { nsec_logdump_tree(zone); logger_flush(); } #endif } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_info("journal: %{dnsname}: done", zone->origin); return return_value; }
static struct playlist_provider * lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond) { struct lastfm_playlist *playlist; GError *error = NULL; char *p, *q, *response, *session; /* handshake */ p = g_strconcat("http://ws.audioscrobbler.com/radio/handshake.php?" "version=1.1.1&platform=linux&" "username="******"&" "passwordmd5=", lastfm_config.md5, "&" "debug=0&partner=", NULL); response = lastfm_get(p, mutex, cond); g_free(p); if (response == NULL) return NULL; /* extract session id from response */ session = lastfm_find(response, "session"); g_free(response); if (session == NULL) { g_warning("last.fm handshake failed"); return NULL; } q = g_uri_escape_string(session, NULL, false); g_free(session); session = q; g_debug("session='%s'", session); /* "adjust" last.fm radio */ if (strlen(uri) > 9) { char *escaped_uri; escaped_uri = g_uri_escape_string(uri, NULL, false); p = g_strconcat("http://ws.audioscrobbler.com/radio/adjust.php?" "session=", session, "&url=", escaped_uri, "&debug=0", NULL); g_free(escaped_uri); response = lastfm_get(p, mutex, cond); g_free(response); g_free(p); if (response == NULL) { g_free(session); return NULL; } } /* create the playlist object */ playlist = g_new(struct lastfm_playlist, 1); playlist_provider_init(&playlist->base, &lastfm_playlist_plugin); /* open the last.fm playlist */ p = g_strconcat("http://ws.audioscrobbler.com/radio/xspf.php?" "sk=", session, "&discovery=0&desktop=1.5.1.31879", NULL); g_free(session); playlist->is = input_stream_open(p, mutex, cond, &error); g_free(p); if (playlist->is == NULL) { if (error != NULL) { g_warning("Failed to load XSPF playlist: %s", error->message); g_error_free(error); } else g_warning("Failed to load XSPF playlist"); g_free(playlist); return NULL; } g_mutex_lock(mutex); input_stream_wait_ready(playlist->is); /* last.fm does not send a MIME type, we have to fake it here :-( */ g_free(playlist->is->mime); playlist->is->mime = g_strdup("application/xspf+xml"); g_mutex_unlock(mutex); /* parse the XSPF playlist */ playlist->xspf = playlist_list_open_stream(playlist->is, NULL); if (playlist->xspf == NULL) { input_stream_close(playlist->is); g_free(playlist); g_warning("Failed to parse XSPF playlist"); return NULL; } return &playlist->base; }
void input_close(struct input_desc *s) { input_stream_close(s->s); free(s); }
bool song_file_update(struct song *song) { const char *suffix; char *path_fs; const struct decoder_plugin *plugin; struct stat st; struct input_stream *is = NULL; assert(song_is_file(song)); /* check if there's a suffix and a plugin */ suffix = uri_get_suffix(song->uri); if (suffix == NULL) return false; plugin = decoder_plugin_from_suffix(suffix, NULL); if (plugin == NULL) return false; path_fs = map_song_fs(song); if (path_fs == NULL) return false; if (song->tag != NULL) { tag_free(song->tag); song->tag = NULL; } if (stat(path_fs, &st) < 0 || !S_ISREG(st.st_mode)) { g_free(path_fs); return false; } song->mtime = st.st_mtime; do { /* load file tag */ song->tag = decoder_plugin_tag_dup(plugin, path_fs); if (song->tag != NULL) break; /* fall back to stream tag */ if (plugin->stream_tag != NULL) { /* open the input_stream (if not already open) */ if (is == NULL) is = input_stream_open(path_fs, NULL); /* now try the stream_tag() method */ if (is != NULL) { song->tag = decoder_plugin_stream_tag(plugin, is); if (song->tag != NULL) break; input_stream_seek(is, 0, SEEK_SET, NULL); } } plugin = decoder_plugin_from_suffix(suffix, plugin); } while (plugin != NULL); if (is != NULL) input_stream_close(is); if (song->tag != NULL && tag_is_empty(song->tag)) song->tag = tag_fallback(path_fs, song->tag); g_free(path_fs); return song->tag != NULL; }
int main(int argc, char **argv) { const char *uri; struct input_stream *is = NULL; bool success; GError *error = NULL; struct playlist_provider *playlist; struct song *song; if (argc != 3) { g_printerr("Usage: dump_playlist CONFIG URI\n"); return 1; } uri = argv[2]; /* initialize GLib */ g_thread_init(NULL); g_log_set_default_handler(my_log_func, NULL); /* initialize MPD */ config_global_init(); success = config_read_file(argv[1], &error); if (!success) { g_printerr("%s\n", error->message); g_error_free(error); return 1; } io_thread_init(); if (!io_thread_start(&error)) { g_warning("%s", error->message); g_error_free(error); return EXIT_FAILURE; } if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); return 2; } playlist_list_global_init(); decoder_plugin_init_all(); /* open the playlist */ GMutex *mutex = g_mutex_new(); GCond *cond = g_cond_new(); playlist = playlist_list_open_uri(uri, mutex, cond); if (playlist == NULL) { /* open the stream and wait until it becomes ready */ is = input_stream_open(uri, mutex, cond, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } else g_printerr("input_stream_open() failed\n"); return 2; } input_stream_lock_wait_ready(is); /* open the playlist */ playlist = playlist_list_open_stream(is, uri); if (playlist == NULL) { input_stream_close(is); g_printerr("Failed to open playlist\n"); return 2; } } /* dump the playlist */ while ((song = playlist_plugin_read(playlist)) != NULL) { g_print("%s\n", song->uri); if (song->end_ms > 0) g_print("range: %u:%02u..%u:%02u\n", song->start_ms / 60000, (song->start_ms / 1000) % 60, song->end_ms / 60000, (song->end_ms / 1000) % 60); else if (song->start_ms > 0) g_print("range: %u:%02u..\n", song->start_ms / 60000, (song->start_ms / 1000) % 60); if (song->tag != NULL) tag_save(stdout, song->tag); song_free(song); } /* deinitialize everything */ playlist_plugin_close(playlist); if (is != NULL) input_stream_close(is); g_cond_free(cond); g_mutex_free(mutex); decoder_plugin_deinit_all(); playlist_list_global_finish(); input_stream_global_finish(); io_thread_deinit(); config_global_finish(); return 0; }
/** * Read JSON data and parse it using the given YAJL parser. * @param url URL of the JSON data. * @param hand YAJL parser handle. * @return -1 on error, 0 on success. */ static int soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* cond) { struct input_stream *input_stream; GError *error = NULL; char buffer[4096]; unsigned char *ubuffer = (unsigned char *)buffer; size_t nbytes; input_stream = input_stream_open(url, mutex, cond, &error); if (input_stream == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return -1; } g_mutex_lock(mutex); input_stream_wait_ready(input_stream); yajl_status stat; int done = 0; while (!done) { nbytes = input_stream_read(input_stream, buffer, sizeof(buffer), &error); if (nbytes == 0) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } if (input_stream_eof(input_stream)) { done = true; } else { g_mutex_unlock(mutex); input_stream_close(input_stream); return -1; } } if (done) stat = yajl_parse_complete(hand); else stat = yajl_parse(hand, ubuffer, nbytes); if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) { unsigned char *str = yajl_get_error(hand, 1, ubuffer, nbytes); g_warning("%s", str); yajl_free_error(hand, str); break; } } g_mutex_unlock(mutex); input_stream_close(input_stream); return 0; }