Beispiel #1
0
/* 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;

}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}