Ejemplo n.º 1
0
/* <string> .libfile <string> false */
int                             /* exported for zsysvm.c */
zlibfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    int code;
    byte cname[DEFAULT_BUFFER_SIZE];
    uint clen;
    gs_parsed_file_name_t pname;
    stream *s;
    gx_io_device *iodev_dflt;

    check_ostack(2);
    code = parse_file_name(op, &pname, i_ctx_p->LockFilePermissions, imemory);
    if (code < 0)
        return code;
    iodev_dflt = iodev_default(imemory);
    if (pname.iodev == NULL)
        pname.iodev = iodev_dflt;
    if (pname.iodev != iodev_dflt) { /* Non-OS devices don't have search paths (yet). */
        code = zopen_file(i_ctx_p, &pname, "r", &s, imemory);
        if (code >= 0) {
            code = ssetfilename(s, op->value.const_bytes, r_size(op));
            if (code < 0) {
                sclose(s);
                return_error(e_VMerror);
            }
        }
        if (code < 0) {
            push(1);
            make_false(op);
            return 0;
        }
        make_stream_file(op, s, "r");
    } else {
        ref fref;

        code = lib_file_open(i_ctx_p->lib_path, imemory, i_ctx_p, pname.fname, pname.len,
                             (char *)cname, sizeof(cname), &clen, &fref);
        if (code >= 0) {
            s = fptr(&fref);
            code = ssetfilename(s, cname, clen);
            if (code < 0) {
                sclose(s);
                return_error(e_VMerror);
            }
        }
        if (code < 0) {
            if (code == e_VMerror || code == e_invalidfileaccess)
                return code;
            push(1);
            make_false(op);
            return 0;
        }
        ref_assign(op, &fref);
    }
    push(1);
    make_true(op);
    return 0;
}
/* Parse a real (non-device) file name and convert to a C string. */
int
parse_real_file_name(const ref *op, parsed_file_name *pfn, client_name_t cname)
{   int code = parse_file_name(op, pfn);
    if ( code < 0 )
        return code;
    if ( pfn->len == 0 )
        return_error(e_invalidfileaccess); /* device only */
    return terminate_file_name(pfn, cname);
}
Ejemplo n.º 3
0
static int
zfilenameforall(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    file_enum *pfen;
    gx_io_device *iodev = NULL;
    gs_parsed_file_name_t pname;
    int code = 0;

    check_write_type(*op, t_string);
    check_proc(op[-1]);
    check_read_type(op[-2], t_string);
    /* Push a mark, the iodev, devicenamelen, the scratch string, the enumerator, */
    /* and the procedure, and invoke the continuation. */
    check_estack(7);
    /* Get the iodevice */
    code = parse_file_name(op - 2, &pname, i_ctx_p->LockFilePermissions);
    if (code < 0)
	return code;
    iodev = (pname.iodev == NULL) ? iodev_default : pname.iodev;

    /* Check for several conditions that just cause us to return success */
    if (pname.len == 0 || iodev->procs.enumerate_files == iodev_no_enumerate_files) {
        pop(3);
        return 0;	/* no pattern, or device not found -- just return */
    }
    pfen = iodev->procs.enumerate_files(iodev, (const char *)pname.fname,
    		pname.len, imemory);
    if (pfen == 0)
	return_error(e_VMerror);
    push_mark_estack(es_for, file_cleanup);
    ++esp;
    make_istruct(esp, 0, iodev);
    ++esp;
    make_int(esp, r_size(op-2) - pname.len);
    *++esp = *op;
    ++esp;
    make_istruct(esp, 0, pfen);
    *++esp = op[-1];
    pop(3);
    code = file_continue(i_ctx_p);
    return (code == o_pop_estack ? o_push_estack : code);
}
Ejemplo n.º 4
0
Bool
add_KDE_colorscheme( const char *new_cs_file ) 
{
	Bool success = False; 
#define KDE_CSRC_PATH  		"$KDEHOME/share/apps/kdisplay/color-schemes/"
	
	if( new_cs_file ) 
	{	
		int i = 1;
		char *dst_path ;
		char *dst_full_fname ; 
		char *fname  = NULL ; 

		parse_file_name(new_cs_file, NULL, &fname );
		dst_path = copy_replace_envvar( KDE_CSRC_PATH );
		
		while( dst_path[i] != '\0' ) 
		{	
			if( dst_path[i] == '/' ) 
			{
				char t = dst_path[i];
				dst_path[i] = '\0' ; 
				if (CheckDir (dst_path) != 0)
					mkdir (dst_path, 0755);
				dst_path[i] = t ;
			}
			++i;
		}			   

		dst_full_fname = safemalloc( i+strlen(fname)+1 );
		sprintf( dst_full_fname, "%s%s", dst_path, fname );
		success = (CopyFile( new_cs_file, dst_full_fname )==0);

		free( dst_full_fname );
		free( dst_path );
		free( fname );
	}

	return success;
}
Ejemplo n.º 5
0
/* <string> status false */
static int
zstatus(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;

    switch (r_type(op)) {
	case t_file:
	    {
		stream *s;

		make_bool(op, (file_is_valid(s, op) ? 1 : 0));
	    }
	    return 0;
	case t_string:
	    {
		gs_parsed_file_name_t pname;
		struct stat fstat;
		int code = parse_file_name(op, &pname, i_ctx_p->LockFilePermissions);

		if (code < 0)
		    return code;
		code = gs_terminate_file_name(&pname, imemory, "status");
		if (code < 0)
		    return code;
		code = (*pname.iodev->procs.file_status)(pname.iodev,
						       pname.fname, &fstat);
		switch (code) {
		    case 0:
			check_ostack(4);
			/*
			 * Check to make sure that the file size fits into
			 * a PostScript integer.  (On some systems, long is
			 * 32 bits, but file sizes are 64 bits.)
			 */
			push(4);
			make_int(op - 4, stat_blocks(&fstat));
			make_int(op - 3, fstat.st_size);
			/*
			 * We can't check the value simply by using ==,
			 * because signed/unsigned == does the wrong thing.
			 * Instead, since integer assignment only keeps the
			 * bottom bits, we convert the values to double
			 * and then test for equality.  This handles all
			 * cases of signed/unsigned or width mismatch.
			 */
			if ((double)op[-4].value.intval !=
			      (double)stat_blocks(&fstat) ||
			    (double)op[-3].value.intval !=
			      (double)fstat.st_size
			    )
			    return_error(e_limitcheck);
			make_int(op - 2, fstat.st_mtime);
			make_int(op - 1, fstat.st_ctime);
			make_bool(op, 1);
			break;
		    case e_undefinedfilename:
			make_bool(op, 0);
			code = 0;
		}
		gs_free_file_name(&pname, "status");
		return code;
	    }
	default:
	    return_op_typecheck(op);
    }
}
Ejemplo n.º 6
0
/* <name_string> <access_string> file <file> */
int				/* exported for zsysvm.c */
zfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    char file_access[4];
    gs_parsed_file_name_t pname;
    int code = parse_file_access_string(op, file_access);
    stream *s;

    if (code < 0)
	return code;
    code = parse_file_name(op - 1, &pname, i_ctx_p->LockFilePermissions);
    if (code < 0)
	return code;
	/*
	 * HACK: temporarily patch the current context pointer into the
	 * state pointer for stdio-related devices.  See ziodev.c for
	 * more information.
	 */
    if (pname.iodev && pname.iodev->dtype == iodev_dtype_stdio) {
	bool statement = (strcmp(pname.iodev->dname, "%statementedit%") == 0);
	bool lineedit = (strcmp(pname.iodev->dname, "%lineedit%") == 0);
	if (pname.fname)
	    return_error(e_invalidfileaccess);
	if (statement || lineedit) {
	    /* These need special code to support callouts */
	    gx_io_device *indev = gs_findiodevice((const byte *)"%stdin", 6);
	    stream *ins;
	    if (strcmp(file_access, "r"))
		return_error(e_invalidfileaccess);
	    indev->state = i_ctx_p;
	    code = (indev->procs.open_device)(indev, file_access, &ins, imemory);
	    indev->state = 0;
	    if (code < 0)
		return code;
	    check_ostack(2);
	    push(2);
	    make_stream_file(op - 3, ins, file_access);
	    make_bool(op-2, statement);
	    make_int(op-1, 0);
	    make_string(op, icurrent_space, 0, NULL);
	    return zfilelineedit(i_ctx_p);
	}
	pname.iodev->state = i_ctx_p;
	code = (*pname.iodev->procs.open_device)(pname.iodev,
						 file_access, &s, imemory);
	pname.iodev->state = NULL;
    } else {
	if (pname.iodev == NULL)
	    pname.iodev = iodev_default;
	code = zopen_file(i_ctx_p, &pname, file_access, &s, imemory);
    }
    if (code < 0)
	return code;
    code = ssetfilename(s, op[-1].value.const_bytes, r_size(op - 1));
    if (code < 0) {
	sclose(s);
	return_error(e_VMerror);
    }
    make_stream_file(op - 1, s, file_access);
    pop(1);
    return code;
}
Ejemplo n.º 7
0
int
main (int argc, char **argv)
{
  program_name = argv[0];

  /* Set locale according to user's wishes.  */
  setlocale (LC_ALL, "");

  /* Tell program which translations to use and where to find.  */
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  for (;;)
    {
      int optc = getopt_long (argc, argv, "i:x:l:m:d:p:",
			      long_options, (int *) 0);
      if (optc < 0)
	break;
      switch (optc)
	{
	case 0:
	  break;

	case 'i':
	  include_languages (optarg);
	  break;

	case 'x':
	  exclude_languages (optarg);
	  break;

	case 'l':
	  language_save_arg (optarg);
	  break;

	case 'm':
	  lang_map_file_name = optarg;
	  break;

	case 'd':
	  set_default_language (optarg);
	  break;

	case 'p':
	  if (cw_dlink == 0)
	    cw_dlink = init_walker (&idh);
	  prune_file_names (optarg, cw_dlink);
	  break;

	default:
	  usage ();
	}
    }

  if (show_version)
    {
      printf ("%s - %s\n", program_name, PACKAGE_VERSION);
      exit (0);
    }

  if (show_help)
    help_me ();

  argc -= optind;
  argv += optind;
  if (argc == 0)
    {
      static char dot[] = ".";
      static char *dotp = dot;
      argc = 1;
      argv = &dotp;
    }

  language_getopt ();
  if (cw_dlink == 0)
    cw_dlink = init_walker (&idh);
  parse_language_map (lang_map_file_name);

  while (argc--)
    {
      struct file_link *flink = parse_file_name (*argv++, cw_dlink);
      if (flink)
	walk_flink (flink, 0);
    }
  mark_member_file_links (&idh);
  obstack_init (&tokens_obstack);
  scan_files (&idh);

  return 0;
}
Ejemplo n.º 8
0
uint8 FSDrive::open_file(int channel, const uint8 *name, int name_len)
{
	char plain_name[NAMEBUF_LENGTH];
	int plain_name_len;
	int mode = FMODE_READ;
	int type = FTYPE_PRG;
	int rec_len = 0;
	parse_file_name(name, name_len, (uint8 *)plain_name, plain_name_len, mode, type, rec_len, true);

	// Channel 0 is READ, channel 1 is WRITE
	if (channel == 0 || channel == 1) {
		mode = channel ? FMODE_WRITE : FMODE_READ;
		if (type == FTYPE_DEL)
			type = FTYPE_PRG;
	}

	bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);

	// Expand wildcards (only allowed on reading)
	if (strchr(plain_name, '*') || strchr(plain_name, '?')) {
		if (writing) {
			set_error(ERR_SYNTAX33);
			return ST_OK;
		} else
			find_first_file(plain_name);
	}

	// Relative files are not supported
	if (type == FTYPE_REL) {
		set_error(ERR_UNIMPLEMENTED);
		return ST_OK;
	}

	// Select fopen() mode according to file mode
	const char *mode_str = "rb";
	switch (mode) {
		case FMODE_WRITE:
			mode_str = "wb";
			break;
		case FMODE_APPEND:
			mode_str = "ab";
			break;
	}

	// Open file
#ifndef __riscos__
	if (chdir(dir_path))
		set_error(ERR_NOTREADY);
	else if ((file[channel] = fopen(plain_name, mode_str)) != NULL) {
		if (mode == FMODE_READ || mode == FMODE_M)	// Read and buffer first byte
			read_char[channel] = fgetc(file[channel]);
	} else
		set_error(ERR_FILENOTFOUND);
#ifdef SPMP
	libgame_chdir_game();
#else
	chdir(AppDirPath);
#endif
#else
	{
	  char fullname[NAMEBUF_LENGTH];

  	  // On RISC OS make a full filename
	  sprintf(fullname,"%s.%s",dir_path,plain_name);
	  if ((file[channel] = fopen(fullname, mode)) != NULL)
	  {
	    if (mode == FMODE_READ || mode == FMODE_M)
	    {
	      read_char[channel] = fgetc(file[channel]);
	    }
	  }
	  else
	  {
	    set_error(ERR_FILENOTFOUND);
	  }
	}
#endif

	return ST_OK;
}
Ejemplo n.º 9
0
int
spawn_child( const char *cmd, int singleton_id, int screen, const char *orig_display, Window w, int context, Bool do_fork, Bool pass_args, ... )
{
    int pid = 0;

    if( cmd == NULL )
        return 0;
	if( as_init_singletons )
	{
		register int i ;
		for( i = 0; i < MAX_SINGLETONS_NUM ; i++ )
			as_singletons[i] = 0 ;
		signal (SIGCHLD, as_sigchild_handler);
		as_init_singletons = False ;
	}

	if( singleton_id >= 0 )
	{
		if( singleton_id >= MAX_SINGLETONS_NUM )
			singleton_id = MAX_SINGLETONS_NUM-1;
		if( as_singletons[singleton_id] > 0 )
			check_singleton_child( singleton_id, True );
	}

    if( do_fork )
        pid = fork();

    if( pid != 0 )
	{
		/* there is a possibility of the race condition here
		 * but it really is not worse the trouble to try and avoid it.
		 */
    	if( singleton_id >= 0 )
			as_singletons[singleton_id] = pid ;
  	    return pid;
	}else
    {/* we get here only in child process. We now need to spawn new proggy here: */
        int len;
        char *display = mystrdup(XDisplayString (dpy));
		char **envp ; 
        register char *ptr ;

        char *cmdl;
        char *arg, *screen_str = NULL, *w_str = NULL, *context_str = NULL ;
		int env_s = 0;
		char **envvars = AS_environ ; 
		int font_path_slot = -1, image_path_slot = -1 ;

        va_list ap;
		LOCAL_DEBUG_OUT( "dpy = %p, DisplayString = \"%s\"", dpy, display );
		LOCAL_DEBUG_OUT( "pid(%d), entered child process to spawn ...", pid );

#if HAVE_DECL_ENVIRON
		if( envvars == NULL ) 
		{
			envvars = environ ;
		}	 
#else
/* how the hell could we get environment otherwise ? */
#endif
		if( envvars ) 
		{
			int font_path_len = strlen(ASFONT_PATH_ENVVAR);
			int image_path_len = strlen(ASIMAGE_PATH_ENVVAR);
			for( env_s = 0  ; envvars[env_s] != NULL ; ++env_s )
			{
				if( font_path_slot < 0 && strlen(envvars[env_s]) > font_path_len ) 
					if(strncmp(envvars[env_s], ASFONT_PATH_ENVVAR, font_path_len)==0)
						font_path_slot = env_s ; 
				if( image_path_slot < 0 && strlen(envvars[env_s]) > image_path_len) 
					if(strncmp(envvars[env_s], ASIMAGE_PATH_ENVVAR, image_path_len)==0)
						image_path_slot = env_s ;
			}	
		}
		if( font_path_slot < 0 ) 
			++env_s ;
		if( image_path_slot  < 0 ) 
			++env_s ;
		envp = safecalloc( env_s+2, sizeof(char*));

		/* environment variabless to pass to child process */
		if( envvars ) 
			for( env_s = 0  ; envvars[env_s] != NULL ; ++env_s )
				envp[env_s] = envvars[env_s] ;	
        
		envp[env_s] = safemalloc(8+strlen(orig_display?orig_display:display)+1);
		sprintf( envp[env_s], "DISPLAY=%s", orig_display?orig_display:display );
		++env_s ;
		if( Environment ) 
		{
			if( Environment->pixmap_path != NULL ) 
			{	
				int slot_no = image_path_slot ; 
				if( slot_no < 0 ) 
					slot_no = env_s++ ; 
					
				envp[slot_no] = safemalloc(strlen( ASIMAGE_PATH_ENVVAR ) + 1 + strlen(Environment->pixmap_path)+1) ;
				sprintf( envp[slot_no], "%s=%s", ASIMAGE_PATH_ENVVAR, Environment->pixmap_path );
			}
			if( Environment->font_path ) 
			{	
				int slot_no = font_path_slot ; 
				if( slot_no < 0 ) 
					slot_no = env_s++ ; 
				envp[slot_no] = safemalloc(strlen( ASFONT_PATH_ENVVAR ) + 1 + strlen(Environment->font_path)+1) ;
				sprintf( envp[slot_no], "%s=%s", ASFONT_PATH_ENVVAR, Environment->font_path );
			}
		}	 
			
        len = strlen((char*)cmd);
        if( pass_args )
        {
            register int i = 0 ;

            while( display[i] ) ++i;

            while( i > 0 && isdigit(display[--i]) );
            if( display[i] == '.' )
                display[i+1] = '\0' ;
/*
            This bit of code seems to break AS restarting
            on Fedora 8. causing DISPLAY=":0.0" to
            become DISPLAY=":0.".  -- Jeremy
*/
            if( screen >= 0 )
                screen_str = string_from_int( screen );
            if( w != None )
                w_str = string_from_int( w );
            if( context != C_NO_CONTEXT )
                context_str = string_from_int( context );

            len += 1+2+1+strlen( orig_display?orig_display:display );
            if( screen_str )
                len += strlen(screen_str);
            len += 3 ;                         /* for "-s " */
            if ( get_flags( as_app_args.flags, ASS_Debugging) )
                len += 8 ;
            if ( get_flags( as_app_args.flags, ASS_Restarting) )
                len += 3 ;
            if ( as_app_args.override_config )
                len += 4+strlen(as_app_args.override_config);
            if ( as_app_args.override_home )
                len += 4+strlen(as_app_args.override_home);
            if ( as_app_args.override_share )
                len += 4+strlen(as_app_args.override_share);

			if ( as_app_args.locale )
                len += 4+strlen(as_app_args.locale);

            if( as_app_args.verbosity_level != OUTPUT_DEFAULT_THRESHOLD )
                len += 4+32 ;
#ifdef DEBUG_TRACE_X
            if( as_app_args.trace_calls )
                len += 13+strlen( as_app_args.trace_calls );
#endif
            if( w_str )
                len += 1+8+1+strlen(w_str);
            if( context_str )
                len += 1+9+1+strlen(context_str);
        }
        /* now we want to append arbitrary number of arguments to the end of command line : */
        va_start( ap, pass_args );
        while( (arg = va_arg(ap,char*)) != NULL )
            len += 1+strlen(arg);
        va_end(ap);

        len+=4;

        ptr = cmdl = safemalloc( len );
        strcpy( cmdl, (char*)cmd );
        while(*ptr) ptr++;
        if( pass_args )
        {
			if (orig_display)
    	        ptr += sprintf( ptr, " -d %s -s", orig_display );
			else
	            ptr += sprintf( ptr, " -d %s%s -s", display, screen_str?screen_str:"" );
            if ( get_flags( as_app_args.flags, ASS_Debugging) )
            {
                strcpy( ptr, " --debug");
                ptr+=8 ;
            }
            if ( get_flags( as_app_args.flags, ASS_Restarting) )
            {
                strcpy( ptr, " -r");
                ptr += 3 ;
            }
            if ( as_app_args.override_config )
                ptr += sprintf( ptr, " -f %s", as_app_args.override_config );
            if ( as_app_args.override_home )
                ptr += sprintf( ptr, " -p %s", as_app_args.override_home );
            if ( as_app_args.override_share )
                ptr += sprintf( ptr, " -g %s", as_app_args.override_share );
            if( as_app_args.verbosity_level != OUTPUT_DEFAULT_THRESHOLD )
                ptr += sprintf( ptr, " -V %d", as_app_args.verbosity_level );
LOCAL_DEBUG_OUT( "len = %d, cmdl = \"%s\" strlen = %d, locale = \"%s\", ptr-cmdl = %d", len, cmdl, (int)strlen(cmdl), as_app_args.locale, (int)(ptr-cmdl) );
			if( as_app_args.locale && as_app_args.locale[0] && !isspace(as_app_args.locale[0]))
                ptr += sprintf( ptr, " -L %s", as_app_args.locale );
			
#ifdef DEBUG_TRACE_X
            if( as_app_args.trace_calls )
                ptr += sprintf( ptr, " --trace-func %s", as_app_args.trace_calls );
#endif
            if( w_str )
                ptr += sprintf( ptr, " --window %s", w_str );
            if( context_str )
                ptr += sprintf( ptr, " --context %s", context_str );
        }
        
		va_start( ap, pass_args );
        while( (arg = va_arg(ap,char*)) != NULL )
        {
            *(ptr++) = ' ';
            strcpy( ptr, arg );
            while(*ptr) ptr++;
LOCAL_DEBUG_OUT( "len = %d, cmdl = \"%s\" strlen = %d", len, cmdl, (int)strlen(cmdl) );
        
		}
        va_end(ap);
        if( do_fork )
        {
            int i = ptr-cmdl;
            while( --i >= 0 ) if( !isspace(cmdl[i]) ) break;
            do_fork = ( i < 0 || cmdl[i] != '&' );
        }
		strcpy (ptr, do_fork?" &\n":"\n");

LOCAL_DEBUG_OUT( "len = %d, cmdl = \"%s\" strlen = %d", len, cmdl, (int)strlen(cmdl) );
#if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
		{
			FILE *fff = fopen ("/tmp/afterstep.exec.log", "a");
			if( fff ) 
			{
				fprintf( fff, "%s:%ld: [%s]", MyName, time(NULL), cmdl );
				fclose(fff);
			}
		}	
#endif			   
     
        LOCAL_DEBUG_OUT("execle(\"%s\")", cmdl );
        /* fprintf( stderr, "len=%d: execl(\"%s\")", len, cmdl ); */

        /* CYGWIN does not handle close-on-exec gracefully - whave to do it ourselves : */
        if( CloseOnExec )
            CloseOnExec();

		{
			const char     *shell;
			char *argv0 ;

	    	if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
				shell = mystrdup("/bin/sh");

			parse_file_name(shell, NULL, &argv0);
	    	/* argv0 = basename(shell); */

        	execle (shell, argv0 , "-c", cmdl, (char *)0, envp);
		}

        if( screen >= 0 )
            show_error( "failed to start %s on the screen %d", cmd, screen );
        else
            show_error( "failed to start %s", cmd );
        show_system_error( " complete command line: \"%s\"\n", cmdl );
        exit(128);
    }
}
Ejemplo n.º 10
0
uint8 ArchDrive::open_file(int channel, const uint8 *name, int name_len)
{
	uint8 plain_name[NAMEBUF_LENGTH];
	int plain_name_len;
	int mode = FMODE_READ;
	int type = FTYPE_DEL;
	int rec_len = 0;
	parse_file_name(name, name_len, plain_name, plain_name_len, mode, type, rec_len);

	// Channel 0 is READ, channel 1 is WRITE
	if (channel == 0 || channel == 1) {
		mode = channel ? FMODE_WRITE : FMODE_READ;
		if (type == FTYPE_DEL)
			type = FTYPE_PRG;
	}

	bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);

	// Wildcards are only allowed on reading
	if (writing && (strchr((const char *)plain_name, '*') || strchr((const char *)plain_name, '?'))) {
		set_error(ERR_SYNTAX33);
		return ST_OK;
	}

	// Allow only read accesses
	if (writing) {
		set_error(ERR_WRITEPROTECT);
		return ST_OK;
	}

	// Relative files are not supported
	if (type == FTYPE_REL) {
		set_error(ERR_UNIMPLEMENTED);
		return ST_OK;
	}

	// Find file
	int num;
	if (find_first_file(plain_name, plain_name_len, num)) {

		// Open temporary file
		if ((file[channel] = tmpfile()) != NULL) {

			// Write load address (.t64 only)
			if (archive_type == TYPE_T64) {
				fwrite(&file_info[num].sa_lo, 1, 1, file[channel]);
				fwrite(&file_info[num].sa_hi, 1, 1, file[channel]);
			}

			// Copy file contents from archive file to temp file
			uint8 *buf = new uint8[file_info[num].size];
			fseek(the_file, file_info[num].offset, SEEK_SET);
			fread(buf, file_info[num].size, 1, the_file);
			fwrite(buf, file_info[num].size, 1, file[channel]);
			rewind(file[channel]);
			delete[] buf;

			if (mode == FMODE_READ)	// Read and buffer first byte
				read_char[channel] = getc(file[channel]);
		}
	} else
		set_error(ERR_FILENOTFOUND);

	return ST_OK;
}