2003-07-01 20:37:09 +00:00
|
|
|
// The contents of this file are subject to the BOINC Public License
|
2002-04-30 22:22:54 +00:00
|
|
|
// Version 1.0 (the "License"); you may not use this file except in
|
|
|
|
// compliance with the License. You may obtain a copy of the License at
|
2003-07-01 20:37:09 +00:00
|
|
|
// http://boinc.berkeley.edu/license_1.0.txt
|
2003-07-03 00:48:43 +00:00
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
// Software distributed under the License is distributed on an "AS IS"
|
|
|
|
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
|
|
// License for the specific language governing rights and limitations
|
2003-07-03 00:48:43 +00:00
|
|
|
// under the License.
|
|
|
|
//
|
|
|
|
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
// The Initial Developer of the Original Code is the SETI@home project.
|
|
|
|
// Portions created by the SETI@home project are Copyright (C) 2002
|
2003-07-03 00:48:43 +00:00
|
|
|
// University of California at Berkeley. All Rights Reserved.
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
// Contributor(s):
|
|
|
|
//
|
|
|
|
|
|
|
|
// If you change anything, make sure you also change:
|
2004-07-14 20:55:26 +00:00
|
|
|
// client_types.C (to write and parse it)
|
2002-04-30 22:22:54 +00:00
|
|
|
// client_state.C (to cross-link objects)
|
|
|
|
//
|
|
|
|
|
2002-06-21 06:52:47 +00:00
|
|
|
#ifndef _CLIENT_TYPES_
|
|
|
|
#define _CLIENT_TYPES_
|
2002-08-22 20:23:24 +00:00
|
|
|
|
2003-10-16 19:03:49 +00:00
|
|
|
#include "cpp.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2004-03-04 11:41:43 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <stdio.h>
|
2003-07-03 05:01:29 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
2004-04-18 18:40:13 +00:00
|
|
|
#include "md5_file.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "hostinfo.h"
|
2004-06-12 04:45:36 +00:00
|
|
|
#include "miofile.h"
|
2003-06-11 18:38:08 +00:00
|
|
|
#include "result_state.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2003-02-11 00:52:44 +00:00
|
|
|
#define MAX_BLOB_LEN 4096
|
2004-08-05 21:42:26 +00:00
|
|
|
#define P_LOW 1
|
|
|
|
#define P_MEDIUM 3
|
|
|
|
#define P_HIGH 5
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2002-06-10 06:14:18 +00:00
|
|
|
struct STRING256 {
|
|
|
|
char text[256];
|
|
|
|
};
|
|
|
|
|
2003-11-02 22:51:49 +00:00
|
|
|
// If the status is neither of these two,
|
|
|
|
// it will be an error code defined in error_numbers.h,
|
2004-03-25 22:24:33 +00:00
|
|
|
// indicating an unrecoverable error in the upload or download of the file,
|
|
|
|
// or that the file was too big and was deleted
|
2003-11-02 22:51:49 +00:00
|
|
|
//
|
|
|
|
#define FILE_NOT_PRESENT 0
|
|
|
|
#define FILE_PRESENT 1
|
|
|
|
|
|
|
|
class FILE_INFO {
|
|
|
|
public:
|
|
|
|
char name[256];
|
|
|
|
char md5_cksum[33];
|
|
|
|
double max_nbytes;
|
|
|
|
double nbytes;
|
|
|
|
double upload_offset;
|
|
|
|
bool generated_locally; // file is produced by app
|
|
|
|
int status;
|
|
|
|
bool executable; // change file protections to make executable
|
|
|
|
bool uploaded; // file has been uploaded
|
|
|
|
bool upload_when_present;
|
|
|
|
bool sticky; // don't delete unless instructed to do so
|
2004-09-10 00:41:48 +00:00
|
|
|
bool report_on_rpc; // include this in each scheduler request
|
2003-11-02 22:51:49 +00:00
|
|
|
bool signature_required; // true iff associated with app version
|
|
|
|
bool is_user_file;
|
2004-07-14 20:55:26 +00:00
|
|
|
class PERS_FILE_XFER* pers_file_xfer; // nonzero if in the process of being up/downloaded
|
2004-07-13 23:51:09 +00:00
|
|
|
struct RESULT* result; // for upload files (to authenticate)
|
2004-07-14 20:55:26 +00:00
|
|
|
class PROJECT* project;
|
2003-11-02 22:51:49 +00:00
|
|
|
int ref_cnt;
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<STRING256> urls;
|
2003-11-02 22:51:49 +00:00
|
|
|
int start_url;
|
|
|
|
int current_url;
|
|
|
|
char signed_xml[MAX_BLOB_LEN];
|
2004-08-11 09:42:29 +00:00
|
|
|
// if the file_info is signed (for uploadable files)
|
|
|
|
// this is the text that is signed
|
2004-10-11 01:44:02 +00:00
|
|
|
// Otherwise it is the FILE_INFO's XML descriptor
|
|
|
|
// (without enclosing <file_info> tags)
|
2003-11-02 22:51:49 +00:00
|
|
|
char xml_signature[MAX_BLOB_LEN];
|
2004-08-11 09:42:29 +00:00
|
|
|
// ... and this is the signature
|
2003-11-02 22:51:49 +00:00
|
|
|
char file_signature[MAX_BLOB_LEN];
|
2004-08-11 09:42:29 +00:00
|
|
|
// if the file itself is signed (for executable files)
|
|
|
|
// this is the signature
|
2004-08-13 11:21:12 +00:00
|
|
|
#if 0
|
2004-08-05 21:42:26 +00:00
|
|
|
int priority;
|
2004-10-25 20:16:30 +00:00
|
|
|
double time_last_used; // time of last use of FILE_INFO, update during parsing, writing, or application usage
|
|
|
|
double exp_date;
|
2004-08-13 11:21:12 +00:00
|
|
|
#endif
|
2004-06-30 18:17:21 +00:00
|
|
|
std::string error_msg; // if permanent error occurs during file xfer,
|
2003-11-02 22:51:49 +00:00
|
|
|
// it's recorded here
|
|
|
|
|
|
|
|
FILE_INFO();
|
|
|
|
~FILE_INFO();
|
2004-09-02 16:23:21 +00:00
|
|
|
void reset();
|
2003-11-02 22:51:49 +00:00
|
|
|
int set_permissions();
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse(MIOFILE&, bool from_server);
|
|
|
|
int write(MIOFILE&, bool to_server);
|
2004-07-13 23:51:09 +00:00
|
|
|
int write_gui(MIOFILE&);
|
2003-11-02 22:51:49 +00:00
|
|
|
int delete_file(); // attempt to delete the underlying file
|
2004-07-06 17:37:58 +00:00
|
|
|
char* get_init_url(bool);
|
2004-07-06 18:31:56 +00:00
|
|
|
char* get_next_url(bool);
|
|
|
|
char* get_current_url(bool);
|
|
|
|
bool is_correct_url_type(bool, STRING256);
|
2004-10-07 19:18:37 +00:00
|
|
|
bool had_failure(int& failnum, char* buf=0);
|
2004-03-24 23:33:46 +00:00
|
|
|
bool verify_existing_file();
|
2004-07-06 18:31:56 +00:00
|
|
|
int merge_info(FILE_INFO&);
|
2004-09-02 16:23:21 +00:00
|
|
|
int verify_downloaded_file();
|
2004-08-05 21:42:26 +00:00
|
|
|
int update_time(); // updates time last used to the current time
|
2003-11-02 22:51:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Describes a connection between a file and a workunit, result, or application.
|
|
|
|
// In the first two cases,
|
|
|
|
// the app will either use open() or fopen() to access the file
|
|
|
|
// (in which case "open_name" is the name it will use)
|
|
|
|
// or the app will be connected by the given fd (in which case fd is nonzero)
|
|
|
|
//
|
|
|
|
struct FILE_REF {
|
|
|
|
char file_name[256];
|
|
|
|
char open_name[256];
|
|
|
|
int fd;
|
|
|
|
bool main_program;
|
|
|
|
FILE_INFO* file_info;
|
2004-07-06 18:31:56 +00:00
|
|
|
bool copy_file; // if true, core client will copy the file instead of linking
|
2003-11-02 22:51:49 +00:00
|
|
|
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse(MIOFILE&);
|
|
|
|
int write(MIOFILE&);
|
2003-11-02 22:51:49 +00:00
|
|
|
};
|
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
class PROJECT {
|
|
|
|
public:
|
2003-02-28 23:14:18 +00:00
|
|
|
// the following items come from the account file
|
2002-06-21 06:52:47 +00:00
|
|
|
// They are a function only of the user and the project
|
|
|
|
//
|
2002-07-15 23:37:55 +00:00
|
|
|
char master_url[256]; // url of site that contains scheduler tags
|
|
|
|
// for this project
|
2002-04-30 22:22:54 +00:00
|
|
|
char authenticator[256]; // user's authenticator on this project
|
2004-09-22 22:28:25 +00:00
|
|
|
#if 0
|
2004-09-27 19:44:40 +00:00
|
|
|
// deletion policy, least recently used
|
|
|
|
bool deletion_policy_priority; // deletion policy, priority of files
|
|
|
|
bool deletion_policy_expire; // deletion policy, delete expired files first
|
2004-08-05 21:42:26 +00:00
|
|
|
double share_size; // size allocated by the resource share
|
|
|
|
// used for enforcement of boundaries but isn't one itself
|
|
|
|
double size; // the total size of all the files in all subfolder
|
|
|
|
// of the project
|
2004-09-22 22:28:25 +00:00
|
|
|
#endif
|
2004-06-30 18:17:21 +00:00
|
|
|
std::string project_prefs;
|
2003-11-28 19:19:11 +00:00
|
|
|
// without the enclosing <project_preferences> tags.
|
|
|
|
// May include <venue> elements
|
|
|
|
// This field is used only briefly: between handling a
|
|
|
|
// scheduler RPC reply and writing the account file
|
2004-06-30 18:17:21 +00:00
|
|
|
std::string project_specific_prefs;
|
2003-11-28 19:19:11 +00:00
|
|
|
// without enclosing <project_specific> tags
|
|
|
|
// Does not include <venue> elements
|
2004-09-27 19:44:40 +00:00
|
|
|
std::string gui_urls;
|
|
|
|
// GUI URLs, with enclosing <gui_urls> tags
|
2003-11-28 19:19:11 +00:00
|
|
|
double resource_share;
|
|
|
|
// project's resource share relative to other projects.
|
2004-10-01 08:15:58 +00:00
|
|
|
char host_venue[256];
|
2002-06-21 06:52:47 +00:00
|
|
|
|
|
|
|
// the following items come from client_state.xml
|
|
|
|
// They may depend on the host as well as user and project
|
2003-05-13 18:55:07 +00:00
|
|
|
// NOTE: if you add anything, add it to copy_state_fields() also!!!
|
2002-06-21 06:52:47 +00:00
|
|
|
//
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<STRING256> scheduler_urls; // where to find scheduling servers
|
2002-06-21 06:52:47 +00:00
|
|
|
char project_name[256]; // descriptive. not unique
|
|
|
|
char user_name[256];
|
2003-02-24 21:25:16 +00:00
|
|
|
char team_name[256];
|
2004-04-18 18:40:13 +00:00
|
|
|
char email_hash[MD5_LEN];
|
|
|
|
char cross_project_id[MD5_LEN];
|
2004-12-01 20:56:20 +00:00
|
|
|
double user_total_credit; // as reported by server
|
|
|
|
double user_expavg_credit; // as reported by server
|
|
|
|
double user_create_time; // as reported by server
|
2002-04-30 22:22:54 +00:00
|
|
|
int rpc_seqno;
|
|
|
|
int hostid;
|
2002-10-22 21:44:16 +00:00
|
|
|
double host_total_credit; // as reported by server
|
|
|
|
double host_expavg_credit; // as reported by server
|
2004-12-01 20:56:20 +00:00
|
|
|
double host_create_time; // as reported by server
|
2004-04-07 07:21:35 +00:00
|
|
|
double exp_avg_cpu; // exponentially weighted CPU time
|
|
|
|
double exp_avg_mod_time; // last time average was changed
|
2002-07-15 05:34:32 +00:00
|
|
|
int nrpc_failures; // # of consecutive times we've failed to
|
|
|
|
// contact all scheduling servers
|
2003-02-28 23:14:18 +00:00
|
|
|
int master_fetch_failures;
|
2004-10-25 20:16:30 +00:00
|
|
|
double min_rpc_time; // earliest time to contact any server
|
2003-07-03 00:48:43 +00:00
|
|
|
// of this project (or zero)
|
2004-10-25 20:16:30 +00:00
|
|
|
double min_report_min_rpc_time; // when to next report on min_rpc_time
|
2003-07-03 00:48:43 +00:00
|
|
|
// (or zero)
|
2002-07-15 05:34:32 +00:00
|
|
|
bool master_url_fetch_pending;
|
|
|
|
// need to fetch and parse the master URL
|
2003-05-13 18:55:07 +00:00
|
|
|
bool sched_rpc_pending; // contact scheduling server for preferences
|
|
|
|
bool tentative; // master URL and account ID not confirmed
|
2004-07-06 18:31:56 +00:00
|
|
|
bool anonymous_platform; // app_versions.xml file found in project dir;
|
|
|
|
// use those apps rather then getting from server
|
2004-09-23 22:27:41 +00:00
|
|
|
bool non_cpu_intensive;
|
|
|
|
bool send_file_list;
|
|
|
|
// send the list of permanent files associated/with the project
|
|
|
|
// in the next scheduler reply
|
2004-09-26 04:16:52 +00:00
|
|
|
bool suspended_via_gui;
|
2004-12-30 03:03:26 +00:00
|
|
|
bool dont_request_more_work;
|
|
|
|
// set the project to only return work and not request more
|
|
|
|
// for a clean exit to a project, or if a user wants to
|
|
|
|
// pause doing work for the project
|
2003-02-28 23:14:18 +00:00
|
|
|
char code_sign_key[MAX_BLOB_LEN];
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<FILE_REF> user_files;
|
2003-11-02 22:51:49 +00:00
|
|
|
int parse_preferences_for_user_files();
|
2004-06-30 01:10:22 +00:00
|
|
|
|
|
|
|
// the following fields used by CPU scheduler
|
|
|
|
double debt; // how much CPU time we owe this project (secs)
|
2004-08-21 23:11:19 +00:00
|
|
|
|
2003-02-28 23:14:18 +00:00
|
|
|
// the following items are transient; not saved in state file
|
2004-06-30 01:10:22 +00:00
|
|
|
double anticipated_debt; // expected debt by the end of the preemption period
|
|
|
|
double work_done_this_period; // how much CPU time has been devoted to this
|
|
|
|
// project in the current period (secs)
|
2004-07-13 23:51:09 +00:00
|
|
|
struct RESULT *next_runnable_result; // the next result to run for this project
|
2004-07-06 18:31:56 +00:00
|
|
|
|
|
|
|
// the following used by work-fetch algorithm
|
2004-06-30 01:10:22 +00:00
|
|
|
double work_request; // how much work a project needs (secs)
|
2004-08-21 23:11:19 +00:00
|
|
|
|
2004-09-27 19:44:40 +00:00
|
|
|
#if 0
|
|
|
|
// used in disk-space management (temp)
|
2004-08-21 23:11:19 +00:00
|
|
|
bool checked;
|
2004-09-27 19:44:40 +00:00
|
|
|
#endif
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2002-06-21 06:52:47 +00:00
|
|
|
PROJECT();
|
|
|
|
~PROJECT();
|
2003-06-23 22:05:14 +00:00
|
|
|
void init();
|
2002-06-21 06:52:47 +00:00
|
|
|
void copy_state_fields(PROJECT&);
|
2003-05-08 23:28:01 +00:00
|
|
|
char *get_project_name();
|
2003-05-13 18:55:07 +00:00
|
|
|
int write_account_file();
|
2002-09-26 05:57:10 +00:00
|
|
|
int parse_account(FILE*);
|
2003-11-02 22:51:49 +00:00
|
|
|
int parse_account_file();
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse_state(MIOFILE&);
|
2004-07-19 19:40:06 +00:00
|
|
|
int write_state(MIOFILE&, bool gui_rpc=false);
|
2004-09-27 19:44:40 +00:00
|
|
|
#if 0
|
2004-08-05 21:42:26 +00:00
|
|
|
bool associate_file(FILE_INFO*);
|
2004-09-27 19:44:40 +00:00
|
|
|
#endif
|
2003-07-03 00:48:43 +00:00
|
|
|
|
|
|
|
// set min_rpc_time and have_reported_min_rpc_time
|
2004-10-25 20:16:30 +00:00
|
|
|
void set_min_rpc_time(double future_time);
|
2003-07-03 00:48:43 +00:00
|
|
|
// returns true if min_rpc_time > now; may print a message
|
2004-10-25 20:16:30 +00:00
|
|
|
bool waiting_until_min_rpc_time(double now);
|
2002-04-30 22:22:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct APP {
|
|
|
|
char name[256];
|
|
|
|
PROJECT* project;
|
|
|
|
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse(MIOFILE&);
|
|
|
|
int write(MIOFILE&);
|
2002-04-30 22:22:54 +00:00
|
|
|
};
|
|
|
|
|
2002-05-17 22:33:57 +00:00
|
|
|
struct APP_VERSION {
|
|
|
|
char app_name[256];
|
|
|
|
int version_num;
|
|
|
|
APP* app;
|
|
|
|
PROJECT* project;
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<FILE_REF> app_files;
|
2003-03-02 19:24:09 +00:00
|
|
|
int ref_cnt;
|
2002-05-17 22:33:57 +00:00
|
|
|
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse(MIOFILE&);
|
|
|
|
int write(MIOFILE&);
|
2004-10-07 19:18:37 +00:00
|
|
|
bool had_download_failure(int& failnum);
|
2004-09-02 16:23:21 +00:00
|
|
|
void get_file_errors(std::string&);
|
|
|
|
void clear_errors();
|
2002-05-17 22:33:57 +00:00
|
|
|
};
|
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
struct WORKUNIT {
|
|
|
|
char name[256];
|
|
|
|
char app_name[256];
|
|
|
|
int version_num;
|
|
|
|
// This isn't sent from the server.
|
2002-07-29 00:39:45 +00:00
|
|
|
// Instead, the client picks the latest app version
|
2004-12-26 02:55:31 +00:00
|
|
|
std::string command_line;
|
|
|
|
//char env_vars[256]; // environment vars in URL format
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<FILE_REF> input_files;
|
2002-04-30 22:22:54 +00:00
|
|
|
PROJECT* project;
|
|
|
|
APP* app;
|
|
|
|
APP_VERSION* avp;
|
|
|
|
int ref_cnt;
|
2003-09-04 00:41:51 +00:00
|
|
|
double rsc_fpops_est;
|
|
|
|
double rsc_fpops_bound;
|
|
|
|
double rsc_memory_bound;
|
|
|
|
double rsc_disk_bound;
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse(MIOFILE&);
|
|
|
|
int write(MIOFILE&);
|
2004-10-07 19:18:37 +00:00
|
|
|
bool had_download_failure(int& failnum);
|
2004-06-30 18:17:21 +00:00
|
|
|
void get_file_errors(std::string&);
|
2002-04-30 22:22:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct RESULT {
|
|
|
|
char name[256];
|
|
|
|
char wu_name[256];
|
2004-12-01 20:56:20 +00:00
|
|
|
double report_deadline;
|
2004-06-30 18:17:21 +00:00
|
|
|
std::vector<FILE_REF> output_files;
|
2003-09-23 23:19:41 +00:00
|
|
|
bool ready_to_report;
|
|
|
|
// we're ready to report this result to the server;
|
|
|
|
// either computation is done and all the files have been uploaded
|
|
|
|
// or there was an error
|
|
|
|
bool got_server_ack;
|
|
|
|
// we're received the ack for this result from the server
|
2002-08-05 00:29:34 +00:00
|
|
|
double final_cpu_time;
|
2004-10-07 19:18:37 +00:00
|
|
|
int state; // state of this result: see lib/result_state.h
|
2002-08-12 21:54:19 +00:00
|
|
|
int exit_status; // return value from the application
|
2004-06-30 18:17:21 +00:00
|
|
|
std::string stderr_out;
|
2003-12-30 23:14:34 +00:00
|
|
|
// the concatenation of:
|
|
|
|
//
|
|
|
|
// - if report_result_error() is called for this result:
|
|
|
|
// <message>x</message>
|
|
|
|
// <exit_status>x</exit_status>
|
|
|
|
// <signal>x</signal>
|
|
|
|
// - if called in FILES_DOWNLOADED state:
|
|
|
|
// <couldnt_start>x</couldnt_start>
|
|
|
|
// - if called in NEW state:
|
|
|
|
// <download_error>x</download_error> for each failed download
|
|
|
|
// - if called in COMPUTE_DONE state:
|
|
|
|
// <upload_error>x</upload_error> for each failed upload
|
|
|
|
//
|
|
|
|
// - <stderr_txt>X</stderr_txt>, where X is the app's stderr output
|
2003-07-03 00:48:43 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
APP* app;
|
|
|
|
WORKUNIT* wup;
|
2003-09-23 23:19:41 +00:00
|
|
|
// this may be NULL after result is finished
|
2002-04-30 22:22:54 +00:00
|
|
|
PROJECT* project;
|
|
|
|
|
2004-06-30 01:10:22 +00:00
|
|
|
bool already_selected;
|
|
|
|
// used to keep cpu scheduler from scheduling a result twice
|
2004-09-04 19:33:54 +00:00
|
|
|
// transient; used only within schedule_cpus()
|
2002-07-05 05:33:40 +00:00
|
|
|
void clear();
|
2004-06-12 04:45:36 +00:00
|
|
|
int parse_server(MIOFILE&);
|
|
|
|
int parse_state(MIOFILE&);
|
2002-07-05 05:33:40 +00:00
|
|
|
int parse_ack(FILE*);
|
2004-06-12 04:45:36 +00:00
|
|
|
int write(MIOFILE&, bool to_server);
|
2004-07-13 23:51:09 +00:00
|
|
|
int write_gui(MIOFILE&);
|
2002-04-30 22:22:54 +00:00
|
|
|
bool is_upload_done(); // files uploaded?
|
2004-06-30 18:17:21 +00:00
|
|
|
void get_app_version_string(std::string&);
|
2004-08-05 21:42:26 +00:00
|
|
|
void reset_files();
|
2004-10-20 21:11:29 +00:00
|
|
|
double estimated_cpu_time();
|
|
|
|
double estimated_cpu_time_remaining();
|
2002-04-30 22:22:54 +00:00
|
|
|
};
|
|
|
|
|
2002-08-07 22:52:10 +00:00
|
|
|
int verify_downloaded_file(char* pathname, FILE_INFO& file_info);
|
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
#endif
|