// Class for converting between UNIX and RISC OS file information


// File primitives.  The lowest set of operations.  Performs direct
// file manipulation.
class FileHandle
{
 private:
  int fd; // File descriptor (UNIX file handle); -1 if unallocated
  uint32_t offset; // Current file offset
  char *real_object_name; // UNIX-fs object file name (includes filetype)
  bool readonly; // Set TRUE if this is opened readonly

 public:
  bool eof; // EOF-error-on-next-read flag
  bool written_to; // Set true if a write operation has occurred
  uint32_t filetype; // RISC OS filetype
  uint32_t object_length; // File length
  int object_type;
  uint32_t attributes; // File attributes (RISC OS format)

  uint32_t load_address;
  uint32_t exec_address;

  char *object_path; // Path to object
  char *object_name; // Object file name as RISC OS would see it
  int object_name_len;
  char *canon_name; // UNIX-style canonicalised name

  time_t unixtime; // UNIX version of time.
  unsigned char rotime[8]; // RISC OS 5-byte time.

  bool FixFilename (const char *path, const char *fname);
  mode_t UNIXAttributes (void);
  int SetType (uint32_t new_filetype);
  int SetAttributes (void);
  int Info (void);
  int Open (int reason);
  int Read (void *buffer, int bytes);
  int Write (const void *buffer, int bytes);
  int Close (void);
  int Seek (uint32_t offset);
  uint32_t Offset (void)
    { return offset; }
  int SetExtent (uint32_t new_length);
  int Extent (void) { return object_length; }
  int Flush (void) { return fsync (fd); }

  // Upon instantiating this class, one of these two functions should
  // be called to initialise the data structures.
  void SetFile (const char *path, const char *fname);
  void SetFile (const char *fname);

  FileHandle ()
    {
      real_object_name = NULL;
      object_path = NULL;
      object_name = NULL;
      canon_name = NULL;
      object_name_len = 0;
    }
  ~FileHandle ()
    {
      if (real_object_name) free (real_object_name);
      if (object_path) free (object_path);
      if (object_name) free (object_name);
      if (canon_name) free (canon_name);
    }
};

class FileSwitch
{
 private:
  FileHandle *fh[255];

 public:
  int Open (const char *fname, int reason, int &handle);
  int Close (int handle);
  int Read (int handle, char *buffer, int bytes);
  int Write (int handle, const char *buffer, int bytes);
  int Seek (int handle, uint32_t offset);
  int Flush (int handle);
  bool ValidFile (int fd);
  FileHandle *operator[] (int handle)
    {
      if (handle <= 0 || handle >= 255)
	return NULL;
      return fh[handle];
    }
  FileSwitch ();
  ~FileSwitch ();
};

// Class for dealing with directories
class OSDir
{
 public:
  char *name; // Directory name
  vector<FileHandle *> entries; // List of directory entries

  OSDir (const char *dirname);
  ~OSDir ();
  int Count () { return entries.size (); }
  FileHandle *GetEntry (int offset) { return entries[offset]; }
};
