/* Load config from file */ static int load_from_file(const char * confname) { vfs68_t * is = 0; char s[256], * word; int err; option68_t * opt; strcpy(s, "sc68://config/"); strcat(s, confname); is = uri68_vfs(s, 1, 0); err = vfs68_open(is); if (err) goto error; for(;;) { char * name; int i, len, c = 0; len = vfs68_gets(is, s, sizeof(s)); if (len == -1) { err = -1; break; } if (len == 0) { break; } i = 0; /* Skip space */ while (i < len && (c=s[i++], isspace(c))) ; if (!is_symbol_char(c)) { continue; } /* Get symbol name. */ name = s+i-1; while (i < len && is_symbol_char(c = s[i++])) if (c == '_') s[i-1] = c = '-'; s[i-1] = 0; /* TRACE68(config68_cat,"conf68: load get key name='%s\n", name); */ /* Skip space */ while (i < len && isspace(c)) c=s[i++]; /* Must have '=' */ if (c != '=') { continue; } c=s[i++]; /* Skip space */ while (i < len && isspace(c)) c=s[i++]; word = s + i - 1; while (i < len && (c = s[i++]) && c != '\n'); s[i-1] = 0; opt = option68_get(name, opt68_ALWAYS); if (!opt) { TRACE68(config68_cat, "conf68: unknown config key '%s'='%s'\n", name, word); continue; } if (!opt->save) { TRACE68(config68_cat, "conf68: config key '%s'='%s' not for save\n", name, word); } TRACE68(config68_cat, "conf68: set name='%s'='%s'\n", name, word); option68_set(opt, word, opt68_PRIO, opt68_CFG); } error: vfs68_destroy(is); TRACE68(config68_cat, "conf68: loaded => [%s]\n",strok68(err)); return err; }
istream68_t * url68_stream_create(const char * url, int mode) { char protocol[16]; char tmp[512]; const int max = sizeof(tmp)-1; istream68_t * isf = 0; int has_protocol; /* in fact protocol:// length */ has_protocol = parse_protocol(protocol, sizeof(protocol), url); if (has_protocol) { if (!strcmp68(protocol, "PASS")) { /* This is special pass thru protocol. It allows to send any other protocol:// or whatever to the default file handler. On some OS with some libC it may be useful. */ url += has_protocol; /* Skip protocol:// part */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "RSC68")) { isf = rsc68_create_url(url, mode, 0); } else if (!strcmp68(protocol, "SC68")) { /* sc68://author/hw/title/track:loop */ url += has_protocol; /* Skip protocol:// part */ strncpy(tmp, "rsc68://music/",max); strncpy(tmp+14, url, max-14); tmp[max] = 0; msg68(-1,"url is now [%s]\n",tmp); isf = rsc68_create_url(tmp, mode, 0); } else if (!strcmp68(protocol, "FILE") || !strcmp68(protocol, "LOCAL")) { url += has_protocol; /* Skip protocol:// part */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "NULL")) { isf = istream68_null_create(url); } else if (!strcmp68(protocol, "AUDIO")) { url += 5+3; isf = istream68_ao_create(url,mode); } else if (!strcmp68(protocol, "STDIN")) { if (mode != 1) return 0; /* stdin is READ_ONLY */ isf = istream68_fd_create("stdin://",0,1); url = "/dev/stdin"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "STDOUT")) { if (mode != 2) return 0; /* stdout is WRITE_ONLY */ isf = istream68_fd_create("stdout://",1,2); url = "/dev/stdout"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "STDERR")) { if (mode != 2) return 0; /* stderr is WRITE_ONLY */ isf = istream68_fd_create("stderr://",2,2); url = "/dev/stderr"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else { /* Try cURL for all unknown protocol */ isf = istream68_curl_create(url,mode); } } /* Fallback open only if no protocol (or explicitly allowed) */ if (!has_protocol) { if (!isf) { /* Default open as FILE */ isf = istream68_file_create(url,mode); } if (!isf) { /* Fallback to file descriptor */ isf = istream68_fd_create(url,-1,mode); } } msg68_debug("url68: create url='%s' %c%c => [%s,'%s']\n", strnevernull68(url), (mode&1) ? 'R' : '.', (mode&2) ? 'W' : '.', strok68(!isf), istream68_filename(isf)); return isf; }
static vfs68_t * default_open(rsc68_t type, const char *name, int mode, rsc68_info_t * info) { vfs68_t * is = 0; int err = -1; const char *subdir = 0, *ext = 0; char tmp[1024], * apath = 0; char tmpname[512]; int alen = 0; char_cv_t cv_path=0, cv_extra=0; struct { const char * path, * sdir, * ext; int curl; } pathes[4]; int ipath, npath = 0; const char * share_path = default_share_path(); const char * rmusic_path = default_rmusic_path(); /* default to invalid type. */ if (info) { info->type = rsc68_last; } if ( (int) type < 0 || (int)type >= rsc68_last) { return 0; } memset(pathes,0,sizeof(pathes)); if (type == rsc68_music && lmusic_path) { /* local music path is prior to user share */ pathes[npath].path = lmusic_path; pathes[npath].sdir = "/"; ++npath; } /* Build default pathes list */ if (user_path) { pathes[npath++].path = user_path; } switch (mode &= 3) { case 1: case 2: break; default: assert(!"invalid mode"); return 0; } if (mode == 1 && share_path) { pathes[npath++].path = share_path; } subdir = rsc68_table[type].path; ext = rsc68_table[type].ext; /* Set a default name for config file if none is given. */ if (type == rsc68_config && (!name || !name[0])) { name = "sc68"; } TRACE68(rsc68_cat,"rsc68: open %c 'sc68://%s/%s%s'\n", (mode==1)?'R':'W',rsc68_table[type].name, name, ext?ext:""); /* Any specific stuff. */ switch (type) { case rsc68_replay: #if defined (USE_REPLAY68) && 0 /* Method using vfs to inflate data. Notice that unfortunatly * we can't use a proper Z stream because the replay loader needs * to know the length and vfs68_z::length() method does not * have this information before it has inflated the all data. This * is a limitation that could probably be dealt with, at least * with gziped stream as the information is available at the end * of the stream. Also in this particular case the inflate size is * available via the replay68_get() function. */ if (mode == 1) { const void * cdata; int csize, dsize; vfs68_t * is_in; TRACE68(rsc68_cat,"rsc68: trying built-in replay -- %s\n", name); if (!replay68_get(name, &cdata, &csize, &dsize)) { TRACE68(rsc68_cat,"rsc68: found built-in replay -- %s %d %d\n", name, csize, dsize); is_in = vfs68_z_create( vfs68_mem_create(cdata, csize, mode), mode|VFS68_SLAVE, vfs68_z_default_option); if (is_in) { is = vfs68_mem_create(0, dsize, 3); if (!vfs68_open(is_in) && !vfs68_open(is)) { int n; while (n = vfs68_read(is_in, tmpname, sizeof(tmpname)), n > 0) if (vfs68_write(is, tmpname, n) != n) { n = -1; break; } err = -!!n; } vfs68_destroy(is_in); vfs68_seek_to(is,0); } } } #elif defined (USE_REPLAY68) /* Method using gzip68_buffer() is probably faster (less memory * copy) than the previous Z stream one. It still need to allocate * a temporary buffer to store deflated data whereas a proper * vfs could have deflated on the fly into the 68k memory * buffer. See previous method comment on that matter. */ if (mode == 1) { const void * cdata; void * ddata; int csize, dsize; TRACE68(rsc68_cat,"rsc68: trying built-in replay -- %s\n", name); if (!replay68_get(name, &cdata, &csize, &dsize)) { TRACE68(rsc68_cat,"rsc68: found built-in replay -- %s %d %d\n", name, csize, dsize); ddata = malloc(dsize); if (ddata) { int inflate = gzip68_buffer(ddata, dsize, cdata, csize); if (inflate != dsize) { msg68_error("rsc68: inflated size of built-in replay differs" " -- %s %d %d\n",name, inflate, dsize); err = -1; } else { is = vfs68_mem_create(ddata, dsize, mode|VFS68_SLAVE); if ( (err = -!is) != 0) { free(ddata); } } } } } #endif cv_extra = cv_lower; /* $$$ transform replay name to lower case. */ break; case rsc68_music: if (mode == 1 && rmusic_path) { pathes[npath].path = rmusic_path; pathes[npath].sdir = "/"; pathes[npath].curl = 1; ++npath; } name = convert_music_path(tmpname, sizeof(tmpname), name, info); break; default: break; } for (ipath=0; !is && name && ipath < npath; ++ipath) { const char *cpath, * cdir, * cext; char *p, *pe, *path; int len, l; cpath = pathes[ipath].path; cdir = pathes[ipath].sdir ? pathes[ipath].sdir : subdir; cext = pathes[ipath].ext ? pathes[ipath].ext : ext; len = 1 + strlen(cpath) + strlen(cdir) + strlen(name) + (cext ? strlen(cext) : 0); if (len <= alen) { path = apath; } else if (len <= sizeof(tmp)) { path = tmp; } else { free(apath); apath = malloc(len); alen = apath ? len : 0; path = apath; } if (!path) { continue; } p = path; pe = path + len; cv_path = pathes[ipath].curl ? cv_path_remote : cv_path_local; /* Build path. */ l = copy_path(p, pe-p, cpath, cv_path, 0 , 0); p += l; l = copy_path(p, pe-p, cdir, cv_path, 0, 0); p += l; l = copy_path(p, pe-p, name, cv_path, cv_extra, 0); p += l; if (cext) { l = copy_path(p, pe-p, cext, 0, 0 ,0); p += l; } is = uri68_vfs(path, mode, 0); err = vfs68_open(is); TRACE68(rsc68_cat, "rsc68: try [%s]\n", strok68(err)); if (!err) break; vfs68_destroy(is); is = 0; } if (apath != tmp) free(apath); if (err) { vfs68_destroy(is); is = 0; } if (is && info) info->type = type; TRACE68(rsc68_cat, "rsc68: open '%s' -- *%s*\n", vfs68_filename(is), strok68(!is)); return is; }