# D_DISK - Specifications for POSIX-like DISK I/O library

### Copyright (C) 1998, Gregg Jennings

#### UPDATE: 26-Feb-1999

There is a major flaw in my implementation: the count argument for d_read and d_write indicate the number of sectors rather than the Unix-like way of number of bytes. This means that I screwed up and Unix-like code will not be able to be ported via D_DISK to DOS/Windows. I will be fixing this.

#### Last Code Update: 29-Nov-1998

D_DISK is a specifcation and implementation of a set of standard-like functions and data types for low-level disk drive reading and writing based on the POSIX 1003.1 file I/O functions.

Please note that for an OS that allows disks to be read and written to by the standard C functions open(), read(), write(), etc., the D_DISK library is probably NOT going to add anything new. However, for OSs such as DOS and Windows, this library should be quite nice.

The implementation is compatible with DOS and WIN32, supporting the Watcom, Microsoft and DJGPP compilers. For other compilers and operating systems help by others will be needed. (The WIN32 version is only for Windows 95 and it may have problems. Under Windows NT drives can already be accessed by file handles.)

I am in the process of converting D_DISK to use my DISKLIB library. If DISKLIB is defined on the command line (see the makefiles) it will be used. DISKLIB is more up to date than the disk library files in D_DISK and also has a more complete implementation for Windows. The test applications here (see NOTES.TXT) have only been proven for the DOS versions. The DJGPP version has also not been tested yet. I will be updating D_DISK for Windows and DJGPP some day.

### The code archives

Version 0.6b, 29-Dec-1998 [more info]

29-Dec-1998: Fixed a few bugs introduced in the last "update".

30-Nov-1998: Code has been cleaned up and makefiles updated. Now compiles and runs with Microsoft and Watcom for DOS and Windows 98.

### Function Summary

`int d_open(const char *path, int oflags)`

Opens a disk for access. The disk is designated by a root `path` name including the drive number (i.e. `"C:\\"`). `oflags` will include `O_RDONLY`, `O_RDWR` and `O_BINARY`. Returns a disk handle or -1 if error.

`O_BINARY` refers not to the data read (it's always raw), but to the initial disk (sector) position. For non-binary access position zero is the BOOT sector; for binary access position zero is the PARTITION sector for HD drives.

`int d_close(int dh)`

Closes a disk handle previously open by `d_open()`. Returns zero, or -1 if error.

`int d_read(int dh, void *buf, int nsectors)`

Reads sectors (not bytes) from a disk handle. Sectors are read starting at the current disk position and the disk postion incremented accordingly. Returns the number of sectors read or -1 if error. If an end of disk condition occurs the return may be less than the number requested.

`int d_write(int dh, const void *buf, int nsectors)`

Writes sectors (not bytes) to a disk handle. Sectors are written starting at the current disk position and the disk postion incremented accordingly. Returns the number of sectors written or -1 if error. If an end of disk condition occurs the return will be less than the number requested.

`long int d_lseek(int dh, long int offset, int whence)`

Sets the current disk position. offset is used as an absolute sector position. Only `SEEK_SET` and `SEEK_CUR` will be recognized for values of whence. Returns the new disk position or -1 if error.

`long int d_tell(int dh)`

Returns the current disk position or -1 if error. A value of zero indicates the start of a disk.

`int d_stat(const char *path, struct stat *buf)`

Obtains information about a disk referenced by `path` (i.e. `"C:\\"`) and places it in `buf`. Returns zero, or -1 if error.

`int d_hstat(int dh, struct stat *buf)`

Obtains information about a disk referenced by an opened disk handle `dh` and places it in `buf`. Returns zero, or -1 if error.

`void d_perror(const char *msg)`

Prints a string desribing the last error, if any.

### Defined Types

This structure most likely will be changed quite a bit as needed. It currently is formed around the FAT file format.

`struct d_stat {`
`char d_fsid[]; /* file system id */`
`char d_dev[]; /* disk ID */`
`long d_ino; /* disk serial number */`
`long d_mode; /* mode of access to disk */`
`long d_atime; /* time of last access */`
`long d_mtime; /* time of last data modification */`
`long d_ctime; /* time of last status change */`
`long d_size; /* total size in bytes */`
`long d_bsize; /* sector size in bytes */`
`long d_bnum; /* number of sectors */`
`long d_bres; /* number of reserved sectors */`
`long d_bhid; /* number of hidden sectors */`
`long d_usize; /* allocation unit (cluster) size in sectors */`
`long d_units; /* number of allocation units */`
`long d_ufree; /* number of free allocation units */`
`long d_ftable; /* number of allocation tables */`
`long d_ftsize; /* allocation table size in sectors */`
`long d_ndir; /* root dir entries */`
`long d_ptracks; /* physical number of tracks */`
`long d_pheads; /* physical number of heads */`
`long d_psecs; /* physical number of sectors per track */`
`};`

### Global Data

`int d_errno`

### Error Values

These are not complete, but should give you enough information.

`D_EHANDLE, /* invalid disk handle */`
`D_EINVAL, /* invalid argument */`
`D_EUNIT, /* unknown unit */`
`D_ENREADY, /* drive not ready */`
`D_ECRC, /* data error (CRC) */`
`D_EREQ, /* bad driver request structure length */`
`D_ESEEK, /* seek error */`
`D_ETYPE, /* unknown media type */`
`D_ESECNO, /* sector not found */`
`D_EWRITE, /* write fault */`
`D_EREAD, /* read fault */`
`D_EGENF, /* general failure */`
`D_EINVCH, /* invalid media change */`
`D_EINVCMD, /* invalid command */`
`D_EINVMED, /* invalid media */`
`D_EADDR, /* address mark not found */`
`D_ESEEKF, /* seek failure */`
`D_ECONTRL, /* controller failure */`
`D_EWPROT, /* disk write protected */`
`D_ERESET, /* reset failure */`
`D_EDMA, /* DMA error/overrun */`
`D_EBAD, /* bad sector/track detected */`

### Notes

I do not have any documnents describing the POSIX library; I have used only the standard C library references (like those that come with any modern ANSI compiler) for my specifications. I have also NOT based my code on, nor derived my code from, anybody else's. Certainly, over the years, I have "retained in memory" all my experiences of reading other people's code, but any similarities, outside the specifications drawn up here in this document, to any other program or library is coincidence (or just because that is the way code must be written to interface with the operating systems that I code for).

However, I will thank the following people and organizations: Ward Christensen for his work on CP/M which started me on this road; Brian W. Kernighan & Dennis M. Ritchie for "The C Programming Language" which taught me C; The C User's Group and Victor Volkman who inspired me to give away much of my source code; P. J. Plauger for his many articles about C from which I have gained clarity; D. J. Delorie for his DJGPP compiler.

And NO THANKS go to the many slick-magazine-columists-whose-picture-appears-in-print, who, over the years, have given out vague, opinionated and false programming information which caused me no so much grief when I was trying to figure out PC programming.

There are no copy restrictions on the D_DISK Library.