/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-98 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              E-mail: ig@datarescue.com, ig@estar.msk.su
 *
 *
 */

#ifndef _DISKIO_HPP
#define _DISKIO_HPP
#pragma pack(push, 1)

//
//      This file contains file I/O functions for IDA.
//      You should not use standard C file I/O functions in modules.
//      Use functions from this header, pro.h and fpro.h instead.
//
//      Also this file declares a call_system() function.
//

#include <stdio.h>
#include <help.h>
#include <llong.hpp>

//-------------------------------------------------------------------------
//      F I L E   N A M E   M A N I P U L A T I O N
//-------------------------------------------------------------------------

// Set file name extension if none exist
// This function appends extension to a file name.
// It won't change file name if extension already exists
//      file - file name to modify
//      ext  - extension with or without '.'
// returns: 'file'

idaman char *ida_export FileExt(char *file,const char *ext);    // Set EXT if no ext


// Set file name extension unconditionally
//      outbuf  - buffer to hold answer. if NULL, 'file' is modified
//      file    - file name
//      ext     - new extension
// returns: pointer to new file name

idaman char *ida_export SetFileExt(char *outbuf,char *file,const char *ext); // Always set ext


// Get pointer to extension of file name
//      file - file name
// returns: pointer to file name or NULL if extension doesn't exist

idaman char *ida_export hasExt(const char *file);             // has Extension ?


//-------------------------------------------------------------------------
//      S E A R C H   F O R   F I L E S
//-------------------------------------------------------------------------


// Get IDA directory

idaman const char *ida_export idadir(void);


// Seach for IDA system file
// This function searches for a file in
//  1. ida directory
//  2. current directory
//  3. in the PATH
//      filename - name of file to search
// returns: NULL-not found, otherwise - pointer to full file name in
// a static storage

idaman char *ida_export getsysfile(const char *filename);         // Search for IDA system file


// enumerate files in the specified directory
// while func() returns 0
//      path    - directory to enumerate files in
//      fname   - mask of file names to enumerate
//      func    - callback function called for each file
//                      file - full file name (with path)
//                      ud   - user data
//                if 'func' returns non-zero value, the enumeration
//                is stopped and full path of the current file
//                is returned to the caller.
//      ud      - user data. this pointer will be passed to
//                the callback function
// return name of file (ptr to static) or NULL if callback never returned
// non-zero value

idaman char *ida_export enumerate_files(const char *path,
                             const char *fname,
                             int (idaapi*func)(const char *file,void *ud),
                             void *ud);


// enumerate IDA system files
//      fname   - mask of file names to enumerate
//      func    - callback function called for each file
//                      file - full file name (with path)
//                      ud   - user data
//                if 'func' returns non-zero value, the enumeration
//                is stopped and full path of the current file
//                is returned to the caller.
//      ud      - user data. this pointer will be passed to
//                the callback function
// return name of file (ptr to static) or NULL if callback never returned
// non-zero value

idaman char *ida_export enumerate_system_files(const char *fname,
                             int (idaapi*func)(const char *file,void *ud),
                             void *ud);


//-------------------------------------------------------------------------
//      O P E N / R E A D / W R I T E / C L O S E   F I L E S
//-------------------------------------------------------------------------

//      There are two sets of "open file" functions.
//      The first set tries to open a file and returns: success or failure
//      The second set is "open or die": if the file cannot be opened
//      then the function will display an error message and exit.


// Open a new file for write in text mode, deny write
// If a file exists, it will be removed.
// returns: NULL-failure

idaman FILE *ida_export fopenWT(const char *file);


// Open a new file for write in binary mode, deny read/write
// If a file exists, it will be removed.
// returns: NULL-failure

idaman FILE *ida_export fopenWB(const char *file);


// Open a file for read in text mode, deny write
// returns: NULL-failure

idaman FILE *ida_export fopenRT(const char *file);


// Open a file for read in binary mode, deny write
// returns: NULL-failure

idaman FILE *ida_export fopenRB(const char *file);


// Open a file for read/write in binary mode, deny write
// returns: NULL-failure

idaman FILE *ida_export fopenM(const char *file);


// Open a file for append in text mode, deny none
// returns: NULL-failure

idaman FILE *ida_export fopenA(const char *file);


// Open a file for read in binary mode or die, deny write
// If a file cannot be opened, this function displays a message and exits.

idaman FILE *ida_export openR(const char *file);


// Open a file for read in text mode or die, deny write
// If a file cannot be opened, this function displays a message and exits.

idaman FILE *ida_export openRT(const char *file);


// Open a file for read/write in binary mode or die, deny read/write
// If a file cannot be opened, this function displays a message and exits.

idaman FILE *ida_export openM(const char *file);


// Open a new file for write in binary mode or die, deny read/write
// If a file exists, it will be removed.
// If a file cannot be opened, this function displays a message and exits.

idaman FILE *ida_export ecreate(const char *file);


// Open a new file for write in text mode or die, deny read/write
// If a file exists, it will be removed.
// If a file cannot be opened, this function displays a message and exits.

idaman FILE *ida_export ecreateT(const char *file);


// Close a file or die.
// If a file cannot be closed, this function displays a message and exits.

idaman void ida_export eclose(FILE *fp);


// Read from file or die.
//      fp   - pointer to file
//      buf  - buffer to read in
//      size - number of bytes to read
// If a read error occurs, this function displays a message and exits.

idaman void ida_export eread(FILE *fp,void *buf,unsigned size);


// Write to file or die.
//      fp   - pointer to file
//      buf  - buffer to write
//      size - number of bytes to write
// If a write error occurs, this function displays a message and exits.

idaman void ida_export ewrite(FILE *fp,const void *buf,unsigned size);


// Position in the file or die.
//      fp   - pointer to file
//      pos  - absolute position in the file
// If an error occurs, this function displays a message and exits.

idaman void ida_export eseek(FILE *fp,long pos);


//-------------------------------------------------------------------------
//      F I L E   S I Z E   /   D I S K   S P A C E
//-------------------------------------------------------------------------

// Get length of file in bytes
//      fp   - pointer to file

idaman ulong ida_export efilelength(FILE *fp);


// Change size of file or die.
//      fp   - pointer to file
//      size - new size of file
// If the file is expanded, it is expanded with zero bytes.
// If an error occurs, this function displays a message and exits.

idaman void ida_export echsize(FILE *fp,ulong size);


// Get free disk space in bytes
//      path - name of any directory on the disk to get information about

idaman ulonglong ida_export getdspace(const char *path);


//-------------------------------------------------------------------------
//      I / O  P O R T  D E F I N I T I O N S  F I L E
//-------------------------------------------------------------------------
struct ioport_bit_t
{
  char *name;           // name of the bit (attention: may be NULL!)
  char *cmt;            // comment
};

typedef ioport_bit_t ioport_bits_t[16];

struct ioport_t
{
  int address;          // address of the port
  char *name;           // name of the port
  char *cmt;            // comment
  ioport_bits_t *bits;  // bit names
  void *userdata;       // arbitrary data. initialized by NULL.
};

// read i/o port definitions from a config file
//      _numports - place to put the number of ports
//      file      - config file name
//      default_device - contains device name to load. If default_device[0] == 0
//                  then the default device is determined by .default directive
//                  in the config file
//                  sizeof(default_device) should be at least MAXSTR.
//      callback  - callback to call when the input line can't be parsed normally
//                    line - input line to parse
//                  returns error message. if NULL, then the line is parsed ok.
// returns: array of ioports
// The format of the input file:
// ; each device definition begins with a line like this:
// ;
// ;       .devicename
// ;
// ;  after it go the port definitions in this format:
// ;
// ;       portname        address
// ;
// ;  the bit definitions (optional) are represented like this:
// ;
// ;       portname.bitname  bitnumber
// ;
// ; lines beginning with a space are ignored.
// ; comment lines should be started with ';' character.
// ;
// ; the default device is specified at the start of the file
// ;
// ;       .default device_name
// ;
// ; all lines non conforming to the format are passed to the callback function
// It is allowed to have a symbol mapped to several addresses
// but all addresses must be unique

idaman ioport_t *ida_export read_ioports(int *_numports,
                       const char *file,
                       char *default_device,
                       const char *idaapi callback(const ioport_t *ports, int numports, const char *line)=NULL);

// Allow the user to choose the ioport device
//      file      - config file name
//      device    - in: contains default device name. If default_device[0] == 0
//                  then the default device is determined by .default directive
//                  in the config file
//                  out: the selected device name
//                  sizeof(device) should be at least MAXSTR.
//      parse_params - if present (non NULL), then defines a callback which
//                  will be called for all lines not starting with a dot (.)
//                  This callback may parse these lines are prepare simple
//                  processor parameter string. This string will be displayed
//                  along with the device name.
// returns: true  - the user selected a device, its name is in 'device'
//          false - the selection was cancelled. if device=="NONE" upon return,
//                  then no devices were found in the configuration file

idaman bool ida_export choose_ioport_device(const char *file,
                              char *device,
                              const char *idaapi parse_params(const char *line,
                                                          char *buf,
                                                          int bufsize)=NULL);


// Find ioport in the array of ioports
idaman const ioport_t *ida_export find_ioport(const ioport_t *ports, int numports, int address);


// Find ioport bit in the array of ioports
idaman const ioport_bit_t *ida_export find_ioport_bit(const ioport_t *ports, int numports, int address, int bit);


// Free ioports array. The 'userdata' field is not examined!
idaman void ida_export free_ioports(ioport_t *ports, int numports);


//-------------------------------------------------------------------------
//      S Y S T E M  S P E C I F I C  C A L L S
//-------------------------------------------------------------------------

// Execute a operating system command
// This function suspends the interface (Tvision), runs the command
// and redraw the screen.
//      command - command to execute. If NULL, a shell is activated
// Returns: the error code returned by system() call.

idaman int ida_export call_system(const char *command);


// Work with priorities

ulong get_thread_priority(void);        // 0 - something wrong (can't happen
                                        // under OS/2)
idaman int   ida_export set_thread_priority(ushort pclass,long delta);


//-------------------------------------------------------------------------
//      K E R N E L   O N L Y   F U N C T I O N S
//-------------------------------------------------------------------------

// The following definitions are for the kernel only:

idaman void ida_export checkdspace(unsigned long space); // if there is less than
                                                // 'space' on the current disk
                                                // warns the user
int     lowdiskgo(unsigned long space);         // if there is less than
                                                // 'space' on the current disk
                                                // asks user to confirm
                                                // returns 1 - continue


extern char **ida_argv;
extern char *exename;


#pragma pack(pop)
#endif // _DISKIO_HPP
