DOS

From Amiga Development Wiki
Jump to: navigation, search

Files and directories

Open a file

BPTR filehandle = Open(CONST_STRPTR filename, ULONG mode);

Where mode is one of the following:

Mode Description
MODE_OLDFILE Open an existing file for reading or writing. If the file does not exist then Open() will fail and return NULL.
MODE_NEWFILE Create new file for writing. An existing file is deleted and an exclusive file handle is returned.
MODE_READWRITE Open a file for reading or writing.
BPTR fh = Open("RAM:test", MODE_READWRITE);

Close a file

Close(BPTR filehandle);

Seek

Mode Description
OFFSET_BEGINNING Relative to the beginning of the file.
OFFSET_CURRENT Relative to current position in the file.
OFFSET_END Relative to the end of the file.
LONG old_position = Seek(BPTR filehandle, LONG position, ULONG seekmode);
QUAD old_position = Seek64(BPTR filehandle, QUAD position, ULONG seekmode);

Writing and reading

There are two sets of functions to read and write files: unbuffered and buffered. Buffered I/O is efficient for small reads and writes.

Unbuffered read/write:

ULONG bytes_read = Read(BPTR filehandle, APTR buffer, ULONG bufferlength);
ULONG bytes_written = Write(BPTR filehandle, CONST_APTR buffer, ULONG bufferlength);

Buffered read/write:

ULONG blocks_read = FRead(BPTR filehandle, APTR buffer, ULONG blocklength, ULONG numblocks);
ULONG blocks_written = FWrite(BPTR filehandle, CONST_APTR buffer, ULONG blocklength, ULONG numblocks);
</source>
 
You must use FFlush() when switching from buffered I/O to unbuffered I/O or vice versa:
<source lang="c">
FFlush(BPTR filehandle);

Example

#include <string.h>
 
#include <proto/dos.h>
 
int main()
{
   BPTR fh = Open("RAM:test", MODE_READWRITE);
 
   if (fh)
   {
      TEXT buf[200];
      stccpy(buf, "This is a test.\n", sizeof(buf));
 
      Write(fh, buf, strlen(buf));
      Seek(fh, 0, OFFSET_BEGINNING);
      Read(fh, buf, sizeof(buf));
 
      Close(fh);
   }
 
   return 0;
}

Scanning directories

Mode Description
ED_NAME Fill name only.
ED_TYPE Fill name and type.
ED_SIZE Fill name, type and size in bytes (32-bit).
ED_PROTECTION Fill name, type, size in bytes (32-bit) and protection flags.
ED_DATE Fill name, type, size in bytes (32-bit), protection flags and date.
ED_COMMENT Fill name, type, size in bytes (32-bit), protection flags, date and comment.
ED_OWNER Fill name, type, size in bytes (32-bit), protection flags, date, comment and owner IDs.
ED_SIZE64 Fill name, type, size in bytes (32-bit), protection flags, date, comment, owner IDs and size in bytes (64-bit).

Some filesystems may not support ED_SIZE64 and return an error when it is used. Check return code and fallback to other ExAll() mode.

#include <dos/dosextens.h>
#include <dos/exall.h>
#include <proto/dos.h>
 
#define EXALL_BUFSIZE 8192
 
int main()
{
   int retval = RETURN_FAIL;
   struct ExAllData *buffer = AllocMem(EXALL_BUFSIZE, MEMF_ANY);
 
   if (buffer)
   {
      BPTR lock = Lock("SYS:", ACCESS_READ);
 
      if (lock)
      {
         struct ExAllControl *eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
 
         if (eac)
         {
            ULONG type = ED_SIZE64;
            BOOL keep_scanning;
 
            eac->eac_LastKey = 0;
 
            do
            {
               keep_scanning = ExAll(lock, buffer, EXALL_BUFSIZE, type, eac);
 
               if (!keep_scanning)
               {
                  LONG err = IoErr();
 
                  switch (err)
                  {
                     case ERROR_NO_MORE_ENTRIES:
                        break;
 
                     case ERROR_BAD_NUMBER:
                        if (type == ED_SIZE64)
                        {
                           type = ED_OWNER;
                           keep_scanning = TRUE;
                           break;
                        }
                        /* fall through */
                      default:
                         PrintFault(err, "Directory scanning failed:\n");
                         break;
                  }
                  else
                  {
                     struct ExAllData *ead = buffer;
 
                     if (eac->eac_Entries == 0)
                        continue;
 
                     do
                     {
                        Printf("%s\n", ead->ed_Name);
                        ead = ead->ed_Next;
                     }
                     while (ead);
                  }
               }
            }
            while();
 
            ExAllEnd(lock, buffer, EXALL_BUFSIZE, type, eac);
            FreeDosObject(DOS_EXALLCONTROL, eac);
         }
 
         UnLock(lock);
      }
   }
 
   return retval;
}

Notifications

With StartNotify() and EndNotify() you can start and stop getting notifications when files have changed. You can ask dos.library to notify you with a signal or a message. Please note that not all file systems support notifications.

#include <exec/execbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
 
int main()
{
   struct NotifyRequest req;
   struct MsgPort *port;
 
   memset(&req, 0, sizeof(req));
   port = CreateMsgPort();
 
   if (port)
   {
      req.nr_Name = "S:User-Startup";
      req.nr_Flags = NRF_SEND_MESSAGE | NRF_WAIT_REPLY;
      req.nr_stuff.nr_Signal.nr_Port = port;
 
      if (StartNotify(&req))
      {
         ULONG notifymask = 1 << port->mp_SigBit;
 
         while (TRUE)
         {
            ULONG sigs = Wait(notifymask | SIGBREAKF_CTRL_C);
 
            if (sigs & SIGBREAKF_CTRL_C)
               break;
 
            if (sigs & notifymask)
            {
               struct NotifyMessage *msg = GetMsg(port);
 
               if (msg)
               {
                  PutStr("File changed!");
                  ReplyMsg(msg);
               }
            }
         }
 
         EndNotify(&req);
      }
 
      DeleteMsgPort(port);
   }
 
   return 0;
}