예제 #1
0
static void fs_sis_file_close(struct fs_file *_file)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;

	if (file->hash_input != NULL)
		i_stream_unref(&file->hash_input);
	fs_file_close(file->hash_file);
	fs_file_close(file->super);
}
예제 #2
0
static void fs_compress_file_close(struct fs_file *_file)
{
	struct compress_fs_file *file = (struct compress_fs_file *)_file;

	if (file->input != NULL)
		i_stream_unref(&file->input);
	if (file->super_read != NULL)
		fs_file_close(file->super_read);
	if (_file->parent != NULL)
		fs_file_close(_file->parent);
}
예제 #3
0
bool code_write(code_t *code, const char *filename, const char *lnofile) {
    prog_header_t  code_header;
    fs_file_t     *fp = NULL;

    code_create_header(code, &code_header, filename, lnofile);

    if (lnofile) {
        uint32_t version = 1;

        fp = fs_file_open(lnofile, "wb");
        if (!fp)
            return false;

        util_endianswap(&version,         1,                          sizeof(version));
        util_endianswap(code->linenums,   vec_size(code->linenums),   sizeof(code->linenums[0]));
        util_endianswap(code->columnnums, vec_size(code->columnnums), sizeof(code->columnnums[0]));

        if (fs_file_write("LNOF",                          4,                                      1,                          fp) != 1 ||
            fs_file_write(&version,                        sizeof(version),                        1,                          fp) != 1 ||
            fs_file_write(&code_header.defs.length,        sizeof(code_header.defs.length),        1,                          fp) != 1 ||
            fs_file_write(&code_header.globals.length,     sizeof(code_header.globals.length),     1,                          fp) != 1 ||
            fs_file_write(&code_header.fields.length,      sizeof(code_header.fields.length),      1,                          fp) != 1 ||
            fs_file_write(&code_header.statements.length,  sizeof(code_header.statements.length),  1,                          fp) != 1 ||
            fs_file_write(code->linenums,                  sizeof(code->linenums[0]),              vec_size(code->linenums),   fp) != vec_size(code->linenums) ||
            fs_file_write(code->columnnums,                sizeof(code->columnnums[0]),            vec_size(code->columnnums), fp) != vec_size(code->columnnums))
        {
            con_err("failed to write lno file\n");
        }

        fs_file_close(fp);
        fp = NULL;
    }

    fp = fs_file_open(filename, "wb");
    if (!fp)
        return false;

    if (1                          != fs_file_write(&code_header,     sizeof(prog_header_t)           , 1                         , fp) ||
        vec_size(code->statements) != fs_file_write(code->statements, sizeof(prog_section_statement_t), vec_size(code->statements), fp) ||
        vec_size(code->defs)       != fs_file_write(code->defs,       sizeof(prog_section_def_t)      , vec_size(code->defs)      , fp) ||
        vec_size(code->fields)     != fs_file_write(code->fields,     sizeof(prog_section_field_t)    , vec_size(code->fields)    , fp) ||
        vec_size(code->functions)  != fs_file_write(code->functions,  sizeof(prog_section_function_t) , vec_size(code->functions) , fp) ||
        vec_size(code->globals)    != fs_file_write(code->globals,    sizeof(int32_t)                 , vec_size(code->globals)   , fp) ||
        vec_size(code->chars)      != fs_file_write(code->chars,      1                               , vec_size(code->chars)     , fp))
    {
        fs_file_close(fp);
        return false;
    }

    fs_file_close(fp);
    code_stats(filename, lnofile, code, &code_header);
    return true;
}
예제 #4
0
    static int task_pclose(fs_file_t **files) {
        popen_t *open = ((popen_t*)files);

        fs_file_close(files[1]);
        fs_file_close(files[2]);

        remove(open->name_err);
        remove(open->name_out);

        mem_d(open);

        return EXIT_SUCCESS;
    }
예제 #5
0
파일: pak.c 프로젝트: matthiaskrgr/gmqcc
/*
 * Extraction abilities.  These work as you expect them to.
 */
static bool pak_extract_one(pak_file_t *pak, const char *file, const char *outdir) {
    pak_directory_t *dir   = NULL;
    unsigned char   *dat   = NULL;
    char            *local = NULL;
    FILE            *out   = NULL;

    if (!pak_exists(pak, file, &dir)) {
        return false;
    }

    if (!(dat = (unsigned char *)mem_a(dir->len)))
        goto err;

    /*
     * Generate the directory structure / tree that will be required
     * to store the extracted file.
     */
    pak_tree_build(file);

    /* TODO portable path seperators */
    util_asprintf(&local, "%s/%s", outdir, file);

    /*
     * Now create the file, if this operation fails.  Then abort
     * It shouldn't fail though.
     */
    if (!(out = fs_file_open(local, "wb")))
        goto err;

    /* free memory for directory string */
    mem_d(local);

    /* read */
    if (fs_file_seek (pak->handle, dir->pos, SEEK_SET) != 0)
        goto err;

    fs_file_read (dat, 1, dir->len, pak->handle);
    fs_file_write(dat, 1, dir->len, out);
    fs_file_close(out);

    mem_d(dat);
    return true;

err:
    if (dat) mem_d(dat);
    if (out) fs_file_close(out);
    return false;
}
예제 #6
0
파일: opts.c 프로젝트: fmutant/scriptorium
/*
 * Actual loading subsystem, this finds the ini or cfg file, and properly
 * loads it and executes it to set compiler options.
 */
void opts_ini_init(const char *file) {
    /*
     * Possible matches are:
     *  gmqcc.ini
     *  gmqcc.cfg
     */
    char       *error = NULL;
    char       *parse_file = NULL;
    size_t     line;
    fs_file_t  *ini;

    if (!file) {
        /* try ini */
        if (!(ini = fs_file_open((file = "gmqcc.ini"), "r")))
            /* try cfg */
            if (!(ini = fs_file_open((file = "gmqcc.cfg"), "r")))
                return;
    } else if (!(ini = fs_file_open(file, "r")))
        return;

    con_out("found ini file `%s`\n", file);

    parse_file = util_strdup(file);
    if ((line = opts_ini_parse(ini, &opts_ini_load, &error, &parse_file)) != 0) {
        /* there was a parse error with the ini file */
        con_printmsg(LVL_ERROR, parse_file, line, 0 /*TODO: column for ini error*/, "error", error);
        vec_free(error);
    }
    mem_d(parse_file);

    fs_file_close(ini);
}
예제 #7
0
static void fs_sis_queue_file_close(struct fs_file *_file)
{
	struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;

	if (file->super != NULL)
		fs_file_close(file->super);
}
예제 #8
0
파일: pak.c 프로젝트: matthiaskrgr/gmqcc
static bool pak_close(pak_file_t *pak) {
    size_t itr;
    long   tell;

    if (!pak)
        return false;

    /*
     * In insert mode we need to patch the header, and write
     * our directory entries at the end of the file.
     */
    if (pak->insert) {
        if ((tell = fs_file_tell(pak->handle)) != 0)
            goto err;

        pak->header.dirlen = vec_size(pak->directories) * 64;
        pak->header.diroff = tell;

        /* patch header */
        if (fs_file_seek (pak->handle, 0, SEEK_SET) != 0)
            goto err;

        fs_file_write(&(pak->header), sizeof(pak_header_t), 1, pak->handle);

        /* write directories */
        if (fs_file_seek (pak->handle, pak->header.diroff, SEEK_SET) != 0)
            goto err;

        for (itr = 0; itr < vec_size(pak->directories); itr++) {
            fs_file_write(&(pak->directories[itr]), sizeof(pak_directory_t), 1, pak->handle);
        }
    }

    vec_free     (pak->directories);
    fs_file_close(pak->handle);
    mem_d        (pak);

    return true;

err:
    vec_free     (pak->directories);
    fs_file_close(pak->handle);
    mem_d        (pak);

    return false;
}
예제 #9
0
파일: pak.c 프로젝트: CurrentResident/gmqcc
static pak_file_t *pak_open_read(const char *file) {
    pak_file_t *pak;
    size_t      itr;

    if (!(pak = (pak_file_t*)mem_a(sizeof(pak_file_t))))
        return NULL;

    if (!(pak->handle = fs_file_open(file, "rb"))) {
        mem_d(pak);
        return NULL;
    }

    pak->directories = NULL;
    pak->insert      = false; /* read doesn't allow insert */

    memset         (&pak->header, 0, sizeof(pak_header_t));
    fs_file_read   (&pak->header,    sizeof(pak_header_t), 1, pak->handle);

    util_endianswap(&pak->header.magic,  1, sizeof(pak->header.magic));
    util_endianswap(&pak->header.diroff, 1, sizeof(pak->header.diroff));
    util_endianswap(&pak->header.dirlen, 1, sizeof(pak->header.dirlen));

    /*
     * Every PAK file has "PACK" stored as FOURCC data in the
     * header.  If this data cannot compare (as checked here), it's
     * probably not a PAK file.
     */
    if (pak->header.magic != PAK_FOURCC) {
        fs_file_close(pak->handle);
        mem_d        (pak);
        return NULL;
    }

    /*
     * Time to read in the directory handles and prepare the directories
     * vector.  We're going to be reading some the file inwards soon.
     */
    fs_file_seek(pak->handle, pak->header.diroff, FS_FILE_SEEK_SET);

    /*
     * Read in all directories from the PAK file. These are considered
     * to be the "file entries".
     */
    for (itr = 0; itr < pak->header.dirlen / 64; itr++) {
        pak_directory_t dir;
        fs_file_read   (&dir,    sizeof(pak_directory_t), 1, pak->handle);

        /* Don't translate name - it's just an array of bytes. */
        util_endianswap(&dir.pos, 1, sizeof(dir.pos));
        util_endianswap(&dir.len, 1, sizeof(dir.len));

        vec_push(pak->directories, dir);
    }
    return pak;
}
예제 #10
0
static void task_destroy(void) {
    /*
     * Free all the data in the task list and finally the list itself
     * then proceed to cleanup anything else outside the program like
     * temporary files.
     */
    size_t i;
    for (i = 0; i < vec_size(task_tasks); i++) {
        /*
         * Close any open handles to files or processes here.  It's mighty
         * annoying to have to do all this cleanup work.
         */
        if (task_tasks[i].stdoutlog)  fs_file_close (task_tasks[i].stdoutlog);
        if (task_tasks[i].stderrlog)  fs_file_close (task_tasks[i].stderrlog);

        /*
         * Only remove the log files if the test actually compiled otherwise
         * forget about it (or if it didn't compile, and the procedure type
         * was set to -fail (meaning it shouldn't compile) .. stil remove)
         */
        if (task_tasks[i].compiled || !strcmp(task_tasks[i].tmpl->proceduretype, "-fail")) {
            if (remove(task_tasks[i].stdoutlogfile))
                con_err("error removing stdout log file: %s\n", task_tasks[i].stdoutlogfile);
            if (remove(task_tasks[i].stderrlogfile))
                con_err("error removing stderr log file: %s\n", task_tasks[i].stderrlogfile);

            (void)!remove(task_tasks[i].tmpl->tempfilename);
        }

        /* free util_strdup data for log files */
        mem_d(task_tasks[i].stdoutlogfile);
        mem_d(task_tasks[i].stderrlogfile);

        task_template_destroy(task_tasks[i].tmpl);
    }
    vec_free(task_tasks);
}
예제 #11
0
/*
 * This executes the QCVM task for a specificly compiled progs.dat
 * using the template passed into it for call-flags and user defined
 * messages IF the procedure type is -execute, otherwise it matches
 * the preprocessor output.
 */
static bool task_trymatch(size_t i, char ***line) {
    bool             success = true;
    bool             process = true;
    int              retval  = EXIT_SUCCESS;
    fs_file_t       *execute;
    char             buffer[4096];
    task_template_t *tmpl = task_tasks[i].tmpl;

    memset  (buffer,0,sizeof(buffer));

    if (!strcmp(tmpl->proceduretype, "-execute")) {
        /*
         * Drop the execution flags for the QCVM if none where
         * actually specified.
         */
        if (!strcmp(tmpl->executeflags, "$null")) {
            util_snprintf(buffer,  sizeof(buffer), "%s %s",
                task_bins[TASK_EXECUTE],
                tmpl->tempfilename
            );
        } else {
            util_snprintf(buffer,  sizeof(buffer), "%s %s %s",
                task_bins[TASK_EXECUTE],
                tmpl->executeflags,
                tmpl->tempfilename
            );
        }

        execute = (fs_file_t*)popen(buffer, "r");
        if (!execute)
            return false;
    } else if (!strcmp(tmpl->proceduretype, "-pp")) {
        /*
         * we're preprocessing, which means we need to read int
         * the produced file and do some really weird shit.
         */
        if (!(execute = fs_file_open(tmpl->tempfilename, "r")))
            return false;

        process = false;
    } else {
        /*
         * we're testing diagnostic output, which means it will be
         * in runhandles[2] (stderr) since that is where the compiler
         * puts it's errors.
         */
        if (!(execute = fs_file_open(task_tasks[i].stderrlogfile, "r")))
            return false;

        process = false;
    }

    /*
     * Now lets read the lines and compare them to the matches we expect
     * and handle accordingly.
     */
    {
        char  *data    = NULL;
        size_t size    = 0;
        size_t compare = 0;

        while (fs_file_getline(&data, &size, execute) != FS_FILE_EOF) {
            if (!strcmp(data, "No main function found\n")) {
                con_err("test failure: `%s` (No main function found) [%s]\n",
                    tmpl->description,
                    tmpl->rulesfile
                );
                if (!process)
                    fs_file_close(execute);
                else
                    pclose((FILE*)execute);
                return false;
            }

            /*
             * Trim newlines from data since they will just break our
             * ability to properly validate matches.
             */
            if  (strrchr(data, '\n'))
                *strrchr(data, '\n') = '\0';

            /*
             * We remove the file/directory and stuff from the error
             * match messages when testing diagnostics.
             */
            if(!strcmp(tmpl->proceduretype, "-diagnostic")) {
                if (strstr(data, "there have been errors, bailing out"))
                    continue; /* ignore it */
                if (strstr(data, ": error: ")) {
                    char *claim = util_strdup(data + (strstr(data, ": error: ") - data) + 9);
                    mem_d(data);
                    data = claim;
                }
            }

            /*
             * We need to ignore null lines for when -pp is used (preprocessor), since
             * the preprocessor is likely to create empty newlines in certain macro
             * instantations, otherwise it's in the wrong nature to ignore empty newlines.
             */
            if (!strcmp(tmpl->proceduretype, "-pp") && !*data)
                continue;

            if (vec_size(tmpl->comparematch) > compare) {
                if (strcmp(data, tmpl->comparematch[compare++])) {
                    success = false;
                }
            } else {
                success = false;
            }

            /*
             * Copy to output vector for diagnostics if execution match
             * fails.
             */
            vec_push(*line, data);

            /* reset */
            data = NULL;
            size = 0;
        }

        if (compare != vec_size(tmpl->comparematch))
            success = false;

        mem_d(data);
        data = NULL;
    }

    if (process)
        retval = pclose((FILE*)execute);
    else
        fs_file_close(execute);

    return success && retval == EXIT_SUCCESS;
}
예제 #12
0
static task_template_t *task_template_compile(const char *file, const char *dir, size_t *pad) {
    /* a page should be enough */
    char             fullfile[4096];
    size_t           filepadd = 0;
    fs_file_t       *tempfile = NULL;
    task_template_t *tmpl     = NULL;

    util_snprintf(fullfile,    sizeof(fullfile), "%s/%s", dir, file);

    tempfile = fs_file_open(fullfile, "r");
    tmpl     = (task_template_t*)mem_a(sizeof(task_template_t));
    task_template_nullify(tmpl);

    /*
     * Create some padding for the printing to align the
     * printing of the rules file to the console.
     */
    if ((filepadd = strlen(fullfile)) > pad[1])
        pad[1] = filepadd;

    tmpl->rulesfile = util_strdup(fullfile);

    /*
     * Esnure the file even exists for the task, this is pretty useless
     * to even do.
     */
    if (!tempfile) {
        con_err("template file: %s does not exist or invalid permissions\n",
            file
        );
        goto failure;
    }

    if (!task_template_parse(file, tmpl, tempfile, pad)) {
        con_err("template parse error: error during parsing\n");
        goto failure;
    }

    /*
     * Regardless procedure type, the following tags must exist:
     *  D
     *  T
     *  C
     *  I
     */
    if (!tmpl->description) {
        con_err("template compile error: %s missing `D:` tag\n", file);
        goto failure;
    }
    if (!tmpl->proceduretype) {
        con_err("template compile error: %s missing `T:` tag\n", file);
        goto failure;
    }
    if (!tmpl->compileflags) {
        con_err("template compile error: %s missing `C:` tag\n", file);
        goto failure;
    }
    if (!tmpl->sourcefile) {
        con_err("template compile error: %s missing `I:` tag\n", file);
        goto failure;
    }

    /*
     * Now lets compile the template, compilation is really just
     * the process of validating the input.
     */
    if (!strcmp(tmpl->proceduretype, "-compile")) {
        if (tmpl->executeflags)
            con_err("template compile warning: %s erroneous tag `E:` when only compiling\n", file);
        if (tmpl->comparematch)
            con_err("template compile warning: %s erroneous tag `M:` when only compiling\n", file);
        goto success;
    } else if (!strcmp(tmpl->proceduretype, "-execute")) {
        if (!tmpl->executeflags) {
            /* default to $null */
            tmpl->executeflags = util_strdup("$null");
        }
        if (!tmpl->comparematch) {
            con_err("template compile error: %s missing `M:` tag (use `$null` for exclude)\n", file);
            goto failure;
        }
    } else if (!strcmp(tmpl->proceduretype, "-fail")) {
        if (tmpl->executeflags)
            con_err("template compile warning: %s erroneous tag `E:` when only failing\n", file);
        if (tmpl->comparematch)
            con_err("template compile warning: %s erroneous tag `M:` when only failing\n", file);
    } else if (!strcmp(tmpl->proceduretype, "-diagnostic")) {
        if (tmpl->executeflags)
            con_err("template compile warning: %s erroneous tag `E:` when only diagnostic\n", file);
        if (!tmpl->comparematch) {
            con_err("template compile error: %s missing `M:` tag (use `$null` for exclude)\n", file);
            goto failure;
        }
    } else if (!strcmp(tmpl->proceduretype, "-pp")) {
        if (tmpl->executeflags)
            con_err("template compile warning: %s erroneous tag `E:` when only preprocessing\n", file);
        if (!tmpl->comparematch) {
            con_err("template compile error: %s missing `M:` tag (use `$null` for exclude)\n", file);
            goto failure;
        }
    } else {
        con_err("template compile error: %s invalid procedure type: %s\n", file, tmpl->proceduretype);
        goto failure;
    }

success:
    fs_file_close(tempfile);
    return tmpl;

failure:
    /*
     * The file might not exist and we jump here when that doesn't happen
     * so the check to see if it's not null here is required.
     */
    if (tempfile)
        fs_file_close(tempfile);
    mem_d (tmpl);

    return NULL;
}
예제 #13
0
파일: opts.c 프로젝트: fmutant/scriptorium
static char *opts_ini_load(const char *section, const char *name, const char *value, char **parse_file) {
    char *error = NULL;
    bool  found = false;

    /*
     * undef all of these because they may still be defined like in my
     * case they where.
     */
    #undef GMQCC_TYPE_FLAGS
    #undef GMQCC_TYPE_OPTIMIZATIONS
    #undef GMQCC_TYPE_WARNS

    /* deal with includes */
    if (!strcmp(section, "includes")) {
        static const char *include_error_beg = "failed to open file `";
        static const char *include_error_end = "' for inclusion";
        fs_file_t *file = fs_file_open(value, "r");
        found = true;
        if (!file) {
            vec_append(error, strlen(include_error_beg), include_error_beg);
            vec_append(error, strlen(value), value);
            vec_append(error, strlen(include_error_end), include_error_end);
        } else {
            if (opts_ini_parse(file, &opts_ini_load, &error, parse_file) != 0)
                found = false;
            /* Change the file name */
            mem_d(*parse_file);
            *parse_file = util_strdup(value);
            fs_file_close(file);
        }
    }

    /* flags */
    #define GMQCC_TYPE_FLAGS
    #define GMQCC_DEFINE_FLAG(X)                                       \
    if (!strcmp(section, "flags") && !strcmp(name, #X)) {              \
        opts_set(opts.flags, X, opts_ini_bool(value));                 \
        found = true;                                                  \
    }
    #include "opts.def"

    /* warnings */
    #define GMQCC_TYPE_WARNS
    #define GMQCC_DEFINE_FLAG(X)                                       \
    if (!strcmp(section, "warnings") && !strcmp(name, #X)) {           \
        opts_set(opts.warn, WARN_##X, opts_ini_bool(value));           \
        found = true;                                                  \
    }
    #include "opts.def"

    /* Werror-individuals */
    #define GMQCC_TYPE_WARNS
    #define GMQCC_DEFINE_FLAG(X)                                       \
    if (!strcmp(section, "errors") && !strcmp(name, #X)) {             \
        opts_set(opts.werror, WARN_##X, opts_ini_bool(value));         \
        found = true;                                                  \
    }
    #include "opts.def"

    /* optimizations */
    #define GMQCC_TYPE_OPTIMIZATIONS
    #define GMQCC_DEFINE_FLAG(X,Y)                                     \
    if (!strcmp(section, "optimizations") && !strcmp(name, #X)) {      \
        opts_set(opts.optimization, OPTIM_##X, opts_ini_bool(value));  \
        found = true;                                                  \
    }
    #include "opts.def"

    /* nothing was found ever! */
    if (!found) {
        if (strcmp(section, "includes") &&
            strcmp(section, "flags")    &&
            strcmp(section, "warnings") &&
            strcmp(section, "optimizations"))
        {
            static const char *invalid_section = "invalid_section `";
            vec_append(error, strlen(invalid_section), invalid_section);
            vec_append(error, strlen(section), section);
            vec_push(error, '`');
        } else if (strcmp(section, "includes")) {
            static const char *invalid_variable = "invalid_variable `";
            static const char *in_section = "` in section: `";
            vec_append(error, strlen(invalid_variable), invalid_variable);
            vec_append(error, strlen(name), name);
            vec_append(error, strlen(in_section), in_section);
            vec_append(error, strlen(section), section);
            vec_push(error, '`');
        } else {
            static const char *expected_something = "expected something";
            vec_append(error, strlen(expected_something), expected_something);
        }
    }
    vec_push(error, '\0');
    return error;
}
예제 #14
0
파일: fs-wrapper.c 프로젝트: rowhit/core-1
void fs_wrapper_file_close(struct fs_file *file)
{
	fs_file_close(file->parent);
}
예제 #15
0
파일: pak.c 프로젝트: matthiaskrgr/gmqcc
/*
 * Insertion functions (the opposite of extraction).  Yes for generating
 * PAKs.
 */
static bool pak_insert_one(pak_file_t *pak, const char *file) {
    pak_directory_t dir;
    unsigned char  *dat;
    long            len;
    FILE           *fp;

    /*
     * We don't allow insertion on files that already exist within the
     * pak file.  Weird shit can happen if we allow that ;). We also
     * don't allow insertion if the pak isn't opened in write mode.
     */
    if (!pak || !file || !pak->insert || pak_exists(pak, file, NULL))
        return false;

    if (!(fp = fs_file_open(file, "rb")))
        return false;

    /*
     * Calculate the total file length, since it will be wrote to
     * the directory entry, and the actual contents of the file
     * to the PAK file itself.
     */
    if (fs_file_seek(fp, 0, SEEK_END) != 0 || ((len = fs_file_tell(fp)) < 0))
        goto err;
    if (fs_file_seek(fp, 0, SEEK_SET) != 0)
        goto err;

    dir.len = len;
    dir.pos = fs_file_tell(pak->handle);

    /*
     * We're limited to 56 bytes for a file name string, that INCLUDES
     * the directory and '/' seperators.
     */
    if (strlen(file) >= 56)
        goto err;

    util_strncpy(dir.name, file, strlen(file));

    /*
     * Allocate some memory for loading in the data that will be
     * redirected into the PAK file.
     */
    if (!(dat = (unsigned char *)mem_a(dir.len)))
        goto err;

    fs_file_read (dat, dir.len, 1, fp);
    fs_file_close(fp);
    fs_file_write(dat, dir.len, 1, pak->handle);

    /*
     * Now add the directory to the directories vector, so pak_close
     * can actually write it.
     */
    vec_push(pak->directories, dir);

    return true;

err:
    fs_file_close(fp);
    return false;
}
예제 #16
0
void con_close() {
    if (!GMQCC_IS_DEFINE(console.handle_err))
        fs_file_close(console.handle_err);
    if (!GMQCC_IS_DEFINE(console.handle_out))
        fs_file_close(console.handle_out);
}