size_t decode_dict(const char *b,size_t len,const char *keylist)
{
  size_t rl,dl,nl;
  const char *pkey;
  dl = 0;
  if(2 > len || *b != 'd') return 0;

  dl++; len--;
  for(;len && *(b + dl) != 'e';){
    rl = buf_str(b + dl,len,&pkey,&nl);

    if( !rl || KEYNAME_SIZ < nl) return 0;
    dl += rl;
    len -= rl;

    if(keylist && compare_key(pkey,nl,keylist) == 0){
      pkey = next_key(keylist);
      if(! *pkey ) return dl;
      rl = decode_dict(b + dl,len, pkey);
      if( !rl ) return 0;
      return dl + rl;
    }

    rl = decode_rev(b + dl,len,(const char*) 0);
    if( !rl ) return 0;

    dl += rl;len -= rl;
  }
  if( !len || keylist) return 0;
  return dl + 1;	/* add the last char 'e' */
}
size_t decode_rev(const char *b,size_t len,const char *keylist)
{
  if( !b ) return 0;
  switch( *b ){
  case 'i': return decode_int(b,len);
  case 'd': return decode_dict(b,len,keylist);
  case 'l': return decode_list(b,len,keylist);
  default: return decode_str(b,len);
  }
}
예제 #3
0
파일: butil.c 프로젝트: ddenchev/bit-md
/* Determine the type and pass processing to the next apropriate function
  * Accepts: buffer, pointer to msg, char of type return, pointer to memory registrar
  * Returns: a pointer to the decoded msg
*/
void *decode_next(struct Buffer *buf, char **bi, char *type) {
    
    if (*bi < buf->cnt + (buf->size - 2)) {
        switch (**bi) {
            case 'd':
                *type = 'd';
                return decode_dict(buf, bi);
                break;
            case 'l':
                *type = 'l';
                return decode_list(buf, bi);
                break;
            case 'i':
                *type = 'i';
                return decode_int(buf, bi);
                break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                *type = 's';
                return decode_str(buf, bi);
                break;
            default:
                fprintf(stderr, "error: decode_next could not determine type encoding %c\n", **bi);
                exit(1);
        }
    } else {
        return NULL;
        //fprintf(stderr, "error: decode_next - unexcpected end of buffer\n");
        //exit(1);
    }
}
예제 #4
0
int btTracker::_UpdatePeerList(char *buf, size_t bufsiz)
{

	char tmphost[MAXHOSTNAMELEN + 1] = {'\0'};
	char warnmsg[1024] = {'\0'};
	char failreason[1024] = {'\0'};

	const char *ps = NULL;
	size_t i, pos, tmpport;
	size_t cnt = 0;

	struct sockaddr_in addr = {0, 0,
		{0},
		{0}};
	memset((void *) &addr, 0, sizeof(addr));

	if (decode_query(buf, bufsiz, "failure reason", &ps, &i, (int64_t *) 0, QUERY_STR)) {

		if (i < 1024) {
			memcpy(failreason, ps, i);
			failreason[i] = '\0';
		} else {
			memcpy(failreason, ps, 1000);
			failreason[1000] = '\0';
			strcat(failreason, "...");
		}
		CONSOLE.Warning(1, "TRACKER FAILURE REASON: %s", failreason);
		return -1;
	}
	if (decode_query
		(buf, bufsiz, "warning message", &ps, &i, (int64_t *) 0,
		QUERY_STR)) {

		if (i < 1024) {
			memcpy(warnmsg, ps, i);
			warnmsg[i] = '\0';
		} else {
			memcpy(warnmsg, ps, 1000);
			warnmsg[1000] = '\0';
			strcat(warnmsg, "...");
		}
		CONSOLE.Warning(2, "TRACKER WARNING: %s", warnmsg);
	}

	m_peers_count = m_seeds_count = 0;

	if (decode_query
		(buf, bufsiz, "tracker id", &ps, &i, (int64_t *) 0, QUERY_STR)) {
		if (i <= PEER_ID_LEN) {
			memcpy(m_trackerid, ps, i);
			m_trackerid[i] = '\0';
		} else {
			memcpy(m_trackerid, ps, PEER_ID_LEN);
			m_trackerid[PEER_ID_LEN] = '\0';
		}
	}

	if (!decode_query(buf, bufsiz, "interval", (const char **) 0, &i,
		(int64_t *) 0, QUERY_INT))
		return -1;

	if (m_interval != (time_t) i)
		m_interval = (time_t) i;
	if (m_default_interval != (time_t) i)
		m_default_interval = (time_t) i;

	if (decode_query(buf, bufsiz, "complete", (const char **) 0, &i, (int64_t *) 0, QUERY_INT))
		m_seeds_count = i;
	if (decode_query(buf, bufsiz, "incomplete", (const char **) 0, &i, (int64_t *) 0, QUERY_INT))
		m_peers_count = m_seeds_count + i;
	else {
		if (arg_verbose && 0 == m_seeds_count)
			CONSOLE.Debug("Tracker did not supply peers count.");
		m_peers_count = m_seeds_count;
	}

	pos = decode_query(buf, bufsiz, "peers", (const char **) 0, (size_t *) 0, (int64_t *) 0, QUERY_POS);

	if (!pos) {
		return -1;
	}

	if (4 > bufsiz - pos) {
		return -1;
	} // peers list ̫С

	buf += (pos + 1);
	bufsiz -= (pos + 1);

	ps = buf - 1;
	if (*ps != 'l') { // binary peers section if not 'l'
		addr.sin_family = AF_INET;
		i = 0;

		while (*ps != ':')
			i = i * 10 + (*ps++ -'0');

		i /= 6;
		ps++;
		while (i-- > 0) {

			memcpy(&addr.sin_addr, ps, sizeof(struct in_addr));
			memcpy(&addr.sin_port, ps + sizeof(struct in_addr), sizeof(unsigned short));

			if (!Self.IpEquiv(addr)) {
				cnt++;
				IPQUEUE.Add(&addr);
			}
			ps += 6;
		}
	} else
		for (; bufsiz && *buf != 'e'; buf += pos, bufsiz -= pos) {
			pos = decode_dict(buf, bufsiz, (char *) 0);
			if (!pos)
				break;
			if (!decode_query
				(buf, pos, "ip", &ps, &i, (int64_t *) 0, QUERY_STR)
				|| MAXHOSTNAMELEN < i)
				continue;
			memcpy(tmphost, ps, i);
			tmphost[i] = '\0';

			if (!decode_query
				(buf, pos, "port", (const char **) 0, &tmpport,
				(int64_t *) 0, QUERY_INT))
				continue;

			if (!decode_query
				(buf, pos, "peer id", &ps, &i, (int64_t *) 0,
				QUERY_STR) && i != 20)
				continue;

			if (_IPsin(tmphost, tmpport, &addr) < 0) {
				CONSOLE.Warning(3, "warn, detected invalid ip address %s.", tmphost);
				continue;
			}

			if (!Self.IpEquiv(addr)) {
				cnt++;
				IPQUEUE.Add(&addr);
			}
		}

	if (0 == m_peers_count) {
		m_peers_count = cnt + 1; // include myself
		m_f_boguspeercnt = 1;
	} else
		m_f_boguspeercnt = 0;
	if (arg_verbose)
		CONSOLE.Debug("new peers=%d; next check in %d sec",
		(int) cnt, (int) m_interval);
	return 0;
}
예제 #5
0
int btContent::InitialFromMI(const char *metainfo_fname,const char *saveas)
{
#define ERR_RETURN()	{if(b) delete []b; return -1;}
  unsigned char *ptr = m_shake_buffer;
  char *b;
  const char *s;
  size_t flen, q, r;

  b = _file2mem(metainfo_fname,&flen);
  if ( !b ) return -1;

  // announce
  if( !meta_str("announce",&s,&r) ) ERR_RETURN();
  if( r > MAXPATHLEN ) ERR_RETURN();
  m_announce = new char [r + 1];
  memcpy(m_announce, s, r);
  m_announce[r] = '\0';
  
  // infohash
  if( !(r = meta_pos("info")) ) ERR_RETURN();
  if( !(q = decode_dict(b + r, flen - r, (char *) 0)) ) ERR_RETURN();
  Sha1(b + r, q, m_shake_buffer + 28);

  if( meta_int("creation date",&r)) m_create_date = (time_t) r;
 
  // hash table
  if( !meta_str("info|pieces",&s,&m_hashtable_length) ||
      m_hashtable_length % 20 != 0) ERR_RETURN();

  m_hash_table = new unsigned char[m_hashtable_length];

#ifndef WINDOWS
  if( !m_hash_table ) ERR_RETURN();
#endif
  memcpy(m_hash_table, s, m_hashtable_length);

  if(!meta_int("info|piece length",&m_piece_length)) ERR_RETURN();
  m_npieces = m_hashtable_length / 20;

  if( m_piece_length > cfg_max_slice_size * cfg_req_queue_length ){
    fprintf(stderr,"error, piece length too long[%u]. please recomplie CTorrent with a larger cfg_max_slice_size in <btconfig.h>.\n", m_piece_length);
    ERR_RETURN();
  }

  if( m_piece_length < cfg_req_slice_size )
    cfg_req_slice_size = m_piece_length;
  else{
    for( ;(m_piece_length / cfg_req_slice_size) >= cfg_req_queue_length; ){
      cfg_req_slice_size *= 2;
      if( cfg_req_slice_size > cfg_max_slice_size ) ERR_RETURN();
    }
  }
  
  if( m_btfiles.BuildFromMI(b, flen, saveas) < 0) ERR_RETURN();

  delete []b;
  PrintOut();
  
  if( arg_flg_exam_only ) return 0;

  if( ( r = m_btfiles.CreateFiles() ) < 0) ERR_RETURN();

  global_piece_buffer = new char[m_piece_length];
#ifndef WINDOWS
  if( !global_piece_buffer ) ERR_RETURN();
#endif

  pBF = new BitField(m_npieces);
#ifndef WINDOWS
  if( !pBF ) ERR_RETURN();
#endif

  m_left_bytes = m_btfiles.GetTotalLength() / m_piece_length;
  if( m_btfiles.GetTotalLength() % m_piece_length ) m_left_bytes++;
  if( m_left_bytes != m_npieces ) ERR_RETURN();
  
  m_left_bytes = m_btfiles.GetTotalLength();

  if( arg_bitfield_file ){

    if( !arg_flg_check_only ){
      if( pBF->SetReferFile(arg_bitfield_file) >= 0){
	size_t idx;
	r = 0;
	for( idx = 0; idx < m_npieces; idx++ )
	  if( pBF->IsSet(idx) ) m_left_bytes -= GetPieceLength(idx);
      }
      else{
	fprintf(stderr,"warn, couldn't set bit field refer file %s.\n",arg_bitfield_file);
      }
    }
    
    if( r ) CheckExist();
    
  }else if( arg_flg_force_seed_mode ){
    pBF->SetAll();
    m_left_bytes = 0;
  }else if( r ){
    CheckExist();
  }
  
  printf("Already/Total: %u/%u\n",pBF->Count(),m_npieces);
  
  if( arg_flg_check_only ){
    if( arg_bitfield_file ) pBF->WriteToFile(arg_bitfield_file);
    exit(1);
  }
  
  CacheConfigure();

  *ptr = (unsigned char) 19; ptr++; // protocol string length
  memcpy(ptr,"BitTorrent protocol",19); ptr += 19; //  protocol string
  memset(ptr,0,8);		// reserved set zero.

  {				// peer id
    int i;
    ptr = m_shake_buffer + 48;
    for( i = 0; i < 20; i++,ptr++) *ptr = (unsigned char)(rand() & 0xFF);
  }

  return 0;
}
예제 #6
0
int btFiles::BuildFromMI(const char *metabuf, const size_t metabuf_len, const char *saveas)
{
  char path[MAXPATHLEN];
  const char *s, *p;
  size_t r,q,n;
  int64_t t;
  int f_warned = 0;

  if( !decode_query(metabuf, metabuf_len, "info|name", &s, &q, (int64_t*)0,
      QUERY_STR) || MAXPATHLEN <= q )
    return -1;

  memcpy(path, s, q);
  path[q] = '\0';

  r = decode_query(metabuf, metabuf_len, "info|files", (const char**)0, &q,
                   (int64_t*)0, QUERY_POS);

  if( r ){
    BTFILE *pbf_last = (BTFILE*) 0; 
    BTFILE *pbf = (BTFILE*) 0;
    size_t dl;
    if( decode_query(metabuf,metabuf_len,"info|length",
                    (const char**) 0,(size_t*) 0,(int64_t*) 0,QUERY_LONG) )
      return -1;

    if( saveas ){
      m_directory = new char[strlen(saveas) + 1];
#ifndef WINDOWS
      if(!m_directory) return -1;
#endif
      strcpy(m_directory,saveas);
    }else{
      int f_conv;
      char *tmpfn = new char[strlen(path)*2+5];
#ifndef WINDOWS
      if( !tmpfn ) return -1;
#endif
      if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){
        if( arg_flg_convert_filenames ){
          m_directory = new char[strlen(tmpfn) + 1];
#ifndef WINDOWS
          if( !m_directory ){
            delete []tmpfn;
            return -1;
          }
#endif
          strcpy(m_directory,tmpfn);
        }else{
          CONSOLE.Warning(3,
            "Dir name contains non-printable characters; use -T to convert.");
          f_warned = 1;
        }
      }
      delete []tmpfn;
      if( !f_conv || !arg_flg_convert_filenames ){
        m_directory = new char[strlen(path) + 1];
#ifndef WINDOWS
        if( !m_directory ) return -1;
#endif
        strcpy(m_directory,path);
      }
    }

    /* now r saved the pos of files list. q saved list length */
    p = metabuf + r + 1; 
    q--;
    for(; q && 'e' != *p; p += dl, q -= dl){
      if(!(dl = decode_dict(p, q, (const char*) 0)) ) return -1;
      if( !decode_query(p, dl, "length", (const char**) 0,
                       (size_t*) 0,&t,QUERY_LONG) ) return -1;
      pbf = _new_bfnode();
#ifndef WINDOWS
      if( !pbf ) return -1;
#endif
      pbf->bf_length = t;
      m_total_files_length += t;
      r = decode_query(p, dl, "path", (const char **)0, &n, (int64_t*)0,
                       QUERY_POS);
      if( !r ) return -1;
      if(!decode_list2path(p + r, n, path)) return -1;

      int f_conv;
      char *tmpfn = new char[strlen(path)*2+5];
#ifndef WINDOWS
      if( !tmpfn ) return -1;
#endif
      if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){
        if( arg_flg_convert_filenames ){
          pbf->bf_filename = new char[strlen(tmpfn) + 1];
#ifndef WINDOWS
          if( !pbf->bf_filename ){
            delete []tmpfn;
            return -1;
          }
#endif
          strcpy(pbf->bf_filename, tmpfn);
        }else if(!f_warned){
          CONSOLE.Warning(3,
            "Filename contains non-printable characters; use -T to convert.");
          f_warned = 1;
        }
      }
      delete []tmpfn;
      if( !f_conv || !arg_flg_convert_filenames ){
        pbf->bf_filename = new char[strlen(path) + 1];
#ifndef WINDOWS
        if( !pbf->bf_filename ) return -1;
#endif
        strcpy(pbf->bf_filename, path);
      }
      if(pbf_last) pbf_last->bf_next = pbf; else m_btfhead = pbf;
      pbf_last = pbf;
    }
  }else{
    if( !decode_query(metabuf,metabuf_len,"info|length",
                     (const char**) 0,(size_t*) 0,&t,QUERY_LONG) )
      return -1;
    m_btfhead = _new_bfnode();
#ifndef WINDOWS
    if( !m_btfhead) return -1;
#endif
    m_btfhead->bf_length = m_total_files_length = t;
    if( saveas ){
      m_btfhead->bf_filename = new char[strlen(saveas) + 1];
#ifndef WINDOWS
      if(!m_btfhead->bf_filename ) return -1;
#endif
      strcpy(m_btfhead->bf_filename, saveas);
    }else if( arg_flg_convert_filenames ){
      char *tmpfn = new char[strlen(path)*2+5];
#ifndef WINDOWS
      if( !tmpfn ) return -1;
#endif
      ConvertFilename(tmpfn, path, strlen(path)*2+5);
      m_btfhead->bf_filename = new char[strlen(tmpfn) + 1];
#ifndef WINDOWS
      if( !m_btfhead->bf_filename ){
        delete []tmpfn;
        return -1;
      }
#endif
      strcpy(m_btfhead->bf_filename, tmpfn);
      delete []tmpfn;
    }else{
      m_btfhead->bf_filename = new char[strlen(path) + 1];
#ifndef WINDOWS
      if(!m_btfhead->bf_filename ) return -1;
#endif
      strcpy(m_btfhead->bf_filename, path);
    }
  }
  return 0;
}
예제 #7
0
dt_result_t btTracker::ParseResponse(const char *buf, size_t bufsiz)
{
  char tmphost[MAXHOSTNAMELEN];
  const char *ps;
  size_t i, pos, tmpport;
  int64_t bint;
  dt_count_t cnt = 0;

  struct sockaddr_in addr;

  if( decode_query(buf, bufsiz, "failure reason", &ps, &i, (int64_t *)0,
                   DT_QUERY_STR) ){
    char failreason[1024];
    if( i < 1024 ){
      memcpy(failreason, ps, i);
      failreason[i] = '\0';
    }else{
      memcpy(failreason, ps, 1000);
      failreason[1000] = '\0';
      strcat(failreason, "...");
    }
    CONSOLE.Warning(1, "TRACKER FAILURE from %s:  %s", m_spec->url, failreason);
    return DT_FAILURE;
  }
  if( decode_query(buf, bufsiz, "warning message", &ps, &i, (int64_t *)0,
                   DT_QUERY_STR) ){
    char warnmsg[1024];
    if( i < 1024 ){
      memcpy(warnmsg, ps, i);
      warnmsg[i] = '\0';
    }else{
      memcpy(warnmsg, ps, 1000);
      warnmsg[1000] = '\0';
      strcat(warnmsg, "...");
    }
    CONSOLE.Warning(2, "TRACKER WARNING from %s:  %s", m_spec->url, warnmsg);
  }

  m_peers_count = m_seeds_count = 0;

  if( decode_query(buf, bufsiz, "tracker id", &ps, &i, (int64_t *)0,
                   DT_QUERY_STR) ){
    if( i <= PEER_ID_LEN ){
      memcpy(m_trackerid, ps, i);
      m_trackerid[i] = '\0';
    }else{
      memcpy(m_trackerid, ps, PEER_ID_LEN);
      m_trackerid[PEER_ID_LEN] = '\0';
    }
  }

  if( decode_query(buf, bufsiz, "interval", (const char **)0, NULL, &bint,
                   DT_QUERY_INT) ){
    m_interval = m_default_interval = (time_t)bint;
  }else{
    CONSOLE.Debug("Tracker at %s did not specify interval.", m_spec->url);
    m_interval = m_default_interval;
  }

  if( decode_query(buf, bufsiz, "complete", (const char **)0, NULL, &bint,
                   DT_QUERY_INT) ){
    m_seeds_count = bint;
  }
  if( decode_query(buf, bufsiz, "incomplete", (const char **)0, NULL, &bint,
                   DT_QUERY_INT) ){
    m_peers_count = m_seeds_count + bint;
  }else{
    if( *cfg_verbose && 0==m_seeds_count )
      CONSOLE.Debug("Tracker at %s did not supply peers count.", m_spec->url);
    m_peers_count = m_seeds_count;
  }

  pos = decode_query(buf, bufsiz, "peers", (const char **)0, (size_t *)0,
                     (int64_t *)0, DT_QUERY_POS);
  if( !pos ){
    CONSOLE.Debug("Tracker at %s did not supply peers.", m_spec->url);
    return DT_FAILURE;
  }
  if( 4 > bufsiz - pos ){
    CONSOLE.Debug("Tracker at %s supplied an invalid peers list.", m_spec->url);
    return DT_FAILURE;
  }

  buf += (pos + 1);
  bufsiz -= (pos + 1);

  ps = buf-1;
  if( *ps != 'l' ){  // binary peers section if not 'l'
    addr.sin_family = AF_INET;
    i = 0;
    while( *ps != ':' ) i = i * 10 + (*ps++ - '0');
    i /= 6;
    ps++;
    while( i-- > 0 ){
      memcpy(&addr.sin_addr, ps, sizeof(struct in_addr));
      memcpy(&addr.sin_port, ps+sizeof(struct in_addr), sizeof(unsigned short));
      if( !Self.IpEquiv(addr) ){
        cnt++;
        IPQUEUE.Add(&addr);
      }
      ps += 6;
    }
  }else for( ; bufsiz && *buf != 'e'; buf += pos, bufsiz -= pos ){
    pos = decode_dict(buf, bufsiz, (char *)0);
    if( !pos ) break;
    if( !decode_query(buf, pos, "ip", &ps, &i, (int64_t *)0, DT_QUERY_STR) ||
        MAXHOSTNAMELEN < i ){
      continue;
    }
    memcpy(tmphost, ps, i);
    tmphost[i] = '\0';

    if( !decode_query(buf, pos, "port", (const char **)0, NULL, &bint,
                      DT_QUERY_INT) ){
      continue;
    }
    tmpport = bint;

    if( !decode_query(buf, pos, "peer id", &ps, &i, (int64_t *)0,
                      DT_QUERY_STR) && i != 20 ){
      continue;
    }

    if( _IPsin(tmphost, tmpport, &addr) < 0 ){
      CONSOLE.Warning(3, "warn, detected invalid ip address %s.", tmphost);
      continue;
    }

    if( !Self.IpEquiv(addr) ){
      cnt++;
      IPQUEUE.Add(&addr);
    }
  }

  if( 0==m_peers_count ){
    m_peers_count = cnt + 1;  // include myself
    m_f_boguspeercnt = 1;
  }else m_f_boguspeercnt = 0;
  if(*cfg_verbose) CONSOLE.Debug("new peers=%d; next check in %d sec [%s]",
    (int)cnt, (int)m_interval, m_spec->url);
  return DT_SUCCESS;
}
예제 #8
0
파일: btfiles.cpp 프로젝트: OPSF/uClinux
int btFiles::BuildFromMI(const char *metabuf, const size_t metabuf_len, const char *saveas)
{
  char path[MAXPATHLEN];
  const char *s, *p;
  size_t r,q,n;
  if( !decode_query(metabuf, metabuf_len, "info|name",&s,&q,QUERY_STR) ||
      MAXPATHLEN <= q) return -1;

  memcpy(path, s, q);
  path[q] = '\0';

  r = decode_query(metabuf,metabuf_len,"info|files",(const char**) 0, &q,QUERY_POS);

  if( r ){
    BTFILE *pbf_last = (BTFILE*) 0; 
    BTFILE *pbf = (BTFILE*) 0;
    size_t dl;
    if( decode_query(metabuf,metabuf_len,"info|length",
		     (const char**) 0,(size_t*) 0,QUERY_INT) )
      return -1;

    if( saveas ){
      m_directory = new char[strlen(saveas) + 1];
#ifndef WINDOWS
      if(!m_directory) return -1;
#endif
      strcpy(m_directory,saveas);
    }else{
      m_directory = new char[strlen(path) + 1];
#ifndef WINDOWS
      if( !m_directory) return -1;
#endif
      strcpy(m_directory,path);
    }

    /* now r saved the pos of files list. q saved list length */
    p = metabuf + r + 1; 
    q--;
    for(; q && 'e' != *p; p += dl, q -= dl){
      if(!(dl = decode_dict(p, q, (const char*) 0)) ) return -1;
      if( !decode_query(p, dl, "length", (const char**) 0,
			&r,QUERY_INT) ) return -1;
      pbf = _new_bfnode();
#ifndef WINDOWS
      if( !pbf ) return -1;
#endif
      pbf->bf_length = r;
      m_total_files_length += r;
      r = decode_query(p, dl, "path", (const char **) 0, &n,QUERY_POS);
      if( !r ) return -1;
      if(!decode_list2path(p + r, n, path)) return -1;
      pbf->bf_filename = new char[strlen(path) + 1];
#ifndef WINDOWS
      if( !pbf->bf_filename ) return -1;
#endif
      strcpy(pbf->bf_filename, path);
      if(pbf_last) pbf_last->bf_next = pbf; else m_btfhead = pbf;
      pbf_last = pbf;
    }
  }else{
    if( !decode_query(metabuf,metabuf_len,"info|length",
		      (const char**) 0,(size_t*) &q,QUERY_INT) )
      return -1;
    m_btfhead = _new_bfnode();
#ifndef WINDOWS
    if( !m_btfhead) return -1;
#endif
    m_btfhead->bf_length = m_total_files_length = q;
    if( saveas ){
      m_btfhead->bf_filename = new char[strlen(saveas) + 1];
#ifndef WINDOWS
      if(!m_btfhead->bf_filename ) return -1;
#endif
      strcpy(m_btfhead->bf_filename, saveas);
    }else{
      m_btfhead->bf_filename = new char[strlen(path) + 1];
#ifndef WINDOWS
      if(!m_btfhead->bf_filename ) return -1;
#endif
      strcpy(m_btfhead->bf_filename, path);
    }
  }
  return 0;
}