+ struct file_info *file;
+ int state;
+ char *prefix = udata;
+
+ if(!fname || !*fname) {
+ ass_errno = ENOENT;
+ return 0;
+ }
+
+ if(!(file = malloc(sizeof *file))) {
+ ass_errno = ENOMEM;
+ return 0;
+ }
+ if(!(file->cache_fname = cache_filename(fname, udata))) {
+ free(file);
+ ass_errno = ENOMEM;
+ return 0;
+ }
+ printf("assman: mod_url cache file: %s\n", file->cache_fname);
+ if(!(file->cache_file = fopen(file->cache_fname, "wb"))) {
+ fprintf(stderr, "assman: mod_url: failed to open cache file (%s) for writing: %s\n",
+ file->cache_fname, strerror(errno));
+ ass_errno = errno;
+ free(file->cache_fname);
+ free(file);
+ return 0;
+ }
+
+ if(!(file->url = malloc(strlen(prefix) + strlen(fname) + 2))) {
+ perror("assman: mod_url: failed to allocate url buffer");
+ ass_errno = errno;
+ fclose(file->cache_file);
+ remove(file->cache_fname);
+ free(file->cache_fname);
+ free(file);
+ return 0;
+ }
+ if(prefix && *prefix) {
+ sprintf(file->url, "%s/%s", prefix, fname);
+ } else {
+ strcpy(file->url, fname);
+ }
+
+ file->state = DL_UNKNOWN;
+ pthread_mutex_init(&file->state_mutex, 0);
+ pthread_cond_init(&file->state_cond, 0);
+
+ ass_tpool_enqueue(tpool, file, download, 0);
+
+ /* wait until the file changes state */
+ pthread_mutex_lock(&file->state_mutex);
+ while(file->state == DL_UNKNOWN) {
+ pthread_cond_wait(&file->state_cond, &file->state_mutex);
+ }
+ state = file->state;
+ pthread_mutex_unlock(&file->state_mutex);
+
+ if(state == DL_ERROR) {
+ /* the worker stopped, so we can safely cleanup and return error */
+ fclose(file->cache_file);
+ remove(file->cache_fname);
+ free(file->cache_fname);
+ pthread_cond_destroy(&file->state_cond);
+ pthread_mutex_destroy(&file->state_mutex);
+ free(file);
+ ass_errno = ENOENT; /* TODO: differentiate between 403 and 404 */
+ return 0;
+ }
+ return file;
+}
+
+static void wait_done(struct file_info *file)
+{
+ pthread_mutex_lock(&file->state_mutex);
+ while(file->state != DL_DONE && file->state != DL_ERROR) {
+ pthread_cond_wait(&file->state_cond, &file->state_mutex);
+ }
+ pthread_mutex_unlock(&file->state_mutex);