DOS
From Amiga Development Wiki
Contents
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; }