home *** CD-ROM | disk | FTP | other *** search
- /* MS-DOS Direct Disk I/O
- *
- * MS-DOS Direct Disk I/O - Copyright (c) 1989 Data Logic Limited.
- *
- * dio_read and dio_write based on original code copyrighted (c) 1989
- * Harold G. Walters.
- *
- * The rest of the code has been written from scatch to support multiple disk
- * access and provide a consistant interface from normal I/O operations.
- *
- * The devices supported are:
- *
- * /dev/hdxy - Hard disk drive x parition y (x = 0 to 9, y =
- * 0 to 9, where 0 is the whole disk) as a block
- * device
- * /dev/fdx - Floppy drive x (x = 0 to 9) as a block device
- * /dev/rhdxy - Hard disk drive as a character device
- * /dev/rfdx - Floppy drive as a character device
- * /dev/kmem - Memory driver
- *
- * It does its best to determine what type of disk you are reading.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in the
- * source form.
- *
- * Version 1.2, 22 June 90
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <unistd.h>
- #include <time.h>
- #include <stdarg.h>
- #include <ms_dio.h>
-
- #undef open
- #undef close
- #undef read
- #undef write
- #undef lseek
- #undef fstat
- #undef stat
- #undef access
- #undef chmod
- #undef creat
- #undef dup
- #undef isatty
- #undef tell
-
- #define SECSIZ 512 /* Sector size */
- #define MS_MODIFIER 30000
- #define BIOS_READ 0x2 /* BIOS functions */
- #define BIOS_WRITE 0x3
- #define HD_FLAG 0x80 /* Hard disk flag */
- #define MEGABYTE 1048576L
- #define DRIVE_RAM 20 /* RAM drive value */
-
- static int dio_do (int, struct fs *, char *, long, unsigned int);
- static struct fs *dio_fpcheck (int);
- static int dio_fncheck (char *, mode_t *);
-
- /* Our internal file handler table */
-
- static struct fs {
- int mode; /* Open mode */
- mode_t st_mode; /* File mode for stat */
- int drive;
- int partition; /* Hard disk partition number */
- off_t location; /* Current offset */
- long m_start; /* Offset for partition */
- long m_cyl; /* Max cylinders */
- int m_head; /* Max heads */
- int m_sector; /* Max sectors */
- long m_scount; /* Total sectors per disk */
- } *MS_io_fs[_NFILE];
-
- /* MSDOS Partition table */
-
- struct partition {
- long f_type; /* Type flags */
- long f_status; /* Status flags */
- long offset; /* Offset in sectors */
- long size; /* Size in sectors */
- };
-
- static int fs_init = 0; /* Initialisation complete */
- static int DIO_Error_Code; /* Last do_dio Error Code */
-
- #define DEC_BADC 0x01 /* Bad command */
- #define DEC_AMNF 0x02 /* Address mark not found */
- #define DEC_WRITEP 0x03 /* Write protected */
- #define DEC_SECNF 0x04 /* Sector not found */
- #define DEC_RESET 0x05 /* Reset failed */
- #define DEC_CHANGE 0x06 /* Diskette remove/changed */
- #define DEC_PARAMETER 0x07 /* Bad parameter table */
- #define DEC_DMAOVER 0x08 /* DMA overrun */
- #define DEC_DMACROSS 0x09 /* DMA across 64K boundary */
- #define DEC_BADSECTOR 0x0a /* Bad sector detected */
- #define DEC_BADTRACK 0x0b /* Bad track detected */
- #define DEC_UNSUPTRK 0x0c /* Unsupported track */
- #define DEC_INVSEC 0x0d /* Invalid number of sectors */
- #define DEC_CDAMD 0x0e /* Control data address mark */
- #define DEC_DMAARB 0x0f /* DMA arbitration error */
- #define DEC_CRC 0x10 /* bad CRC/ECC on read */
- #define DEC_ECC 0x11 /* Data ECC corrected */
- #define DEC_CONTROL 0x20 /* Controller failed */
- #define DEC_SEEK 0x40 /* Seek failed */
- #define DEC_TIMEOUT 0x80 /* Timeout */
- #define DEC_NOTREADY 0xaa /* Drive not ready */
- #define DEC_UNDEF 0xbb /* Undefined error */
- #define DEC_WRITEF 0xcc /* Write fault */
- #define DEC_STATUS 0xe0 /* Status error */
- #define DEC_SENSE 0xff /* Sense operation failed */
-
- /* Do the actual read/write to the disk. This function is not used
- * for the RAM drive
- */
-
- static int dio_do (type, FP, buf, secnum, secknt)
- int type;
- struct fs *FP;
- char *buf;
- long secnum;
- unsigned int secknt;
- {
- int i, j;
- int nsec, cyl;
- long asec;
- union REGS reg;
- #if defined(M_I86LM)
- struct SREGS sreg;
- #endif
-
- DIO_Error_Code = 0;
-
- for (j = 0; j < secknt; j += nsec, buf += (nsec * SECSIZ), secnum += nsec)
- {
-
- /* Check for space - end of drive */
-
- if (secnum > FP->m_scount)
- {
- errno = ENOSPC;
- return j * SECSIZ;
- }
-
- /* Calculate the number of sectors left on the track */
-
- asec = FP->m_start + secnum;
-
- if (((asec % FP->m_sector) + (secknt - j)) > FP->m_sector)
- nsec = (int)(FP->m_sector - (asec % FP->m_sector));
-
- else
- nsec = secknt - j;
-
- /* Read/write it three times */
-
- for (i = 0; i < 3; i++)
- {
- reg.h.ah = (unsigned char)type;
- reg.h.al = (unsigned char)nsec;
- reg.h.dl = (unsigned char)FP->drive;
-
- cyl = (int)(asec / (FP->m_head * FP->m_sector));
- reg.h.cl = (unsigned char)((((asec % FP->m_sector) + 1) & 0x03f) |
- ((cyl & 0x0300) >> 2));
- reg.h.ch = (unsigned char)(cyl & 0xff);
- reg.h.dh = (unsigned char)((asec % (FP->m_head * FP->m_sector)) / FP->m_sector);
-
-
- #if defined(M_I86LM)
- reg.x.bx = FP_OFF(buf);
- sreg.es = FP_SEG(buf);
- int86x (0x13, ®, ®, &sreg);
- #else
- reg.x.bx = (int) buf;
- int86 (0x13, ®, ®);
- #endif
-
- if (!reg.x.cflag)
- break;
-
- /* If we are reading more than one sector - reduce the number of sectors by
- * two
- */
-
- else if (nsec > 1)
- {
- --i;
- nsec /= 2;
- }
- }
-
- /* Check for failure */
-
- if (i == 3)
- {
- DIO_Error_Code = (int)reg.h.ah;
- errno = EIO;
- return -1;
- }
- }
-
- return secknt * SECSIZ;
- }
-
- /*
- * write - Write function
- */
-
- int dio_write (fp, from_buf, from_cnt)
- int fp; /* File handler */
- char *from_buf; /* Output buffer */
- unsigned int from_cnt; /* Number of bytes to write */
- {
- unsigned int amt = 0;
- unsigned int err = 0;
- long fquo;
- unsigned int frem;
- unsigned int cquo = 0;
- unsigned int crem = 0;
- struct fs *FP;
- char buffer[SECSIZ];
-
- /* Direct IO or normal */
-
- if (fp < MS_MODIFIER)
- return write (fp, from_buf, from_cnt);
-
- if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
- ((FP->mode & 0x03) == O_RDONLY))
- {
- errno = EBADF;
- return -1;
- }
-
- /* If RAM - just copy */
-
- if (FP->drive == DRIVE_RAM)
- {
- char huge *cp = (char huge *)from_buf;
- char huge *sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
- | (FP->location & 0x0fL));
-
- amt = from_cnt;
- while (amt--)
- *(sp++) = *(cp++);
-
- return from_cnt;
- }
-
- /* If the current location is not a sector boundary - read in the current
- * sector and write a bit at the end to move to the boundary
- */
-
- fquo = FP->location / SECSIZ;
- frem = (unsigned int) (FP->location % SECSIZ);
-
- if (frem > 0)
- {
- if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- if ((amt = SECSIZ - frem) > from_cnt)
- amt = from_cnt;
-
- /* Update the buffer with the bit at the end */
-
- memcpy (&buffer[frem], from_buf, amt);
-
- if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- /* Increment the location */
-
- FP->location += amt;
-
- if (SECSIZ - frem <= from_cnt)
- fquo++;
-
- from_buf += amt;
- from_cnt -= amt;
- }
-
- /* Calculate the number of full sectors to process now we are on a sector
- * boundary
- */
-
- cquo = from_cnt / SECSIZ;
- crem = from_cnt % SECSIZ;
-
- if (cquo > 0)
- {
- if ((err = dio_do (BIOS_WRITE, FP, from_buf, fquo, cquo)) !=
- (cquo * SECSIZ))
- {
- if (err > 0)
- FP->location += err;
-
- return err;
- }
-
- amt += (cquo * SECSIZ);
- FP->location += (cquo * SECSIZ);
- fquo += cquo;
- from_buf += (cquo * SECSIZ);
- from_cnt -= (cquo * SECSIZ);
- }
-
- /* Is there still more - read in the next sector, update first half and
- * re-write
- */
-
- if (crem > 0)
- {
- if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- memcpy (buffer, from_buf, crem);
-
- if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- amt += crem;
- FP->location += crem;
- }
-
- return amt;
- }
-
- /*
- * read - Read function
- */
-
- int dio_read (fp, to_buf, to_cnt)
- int fp; /* File handler */
- char *to_buf; /* Input buffer */
- unsigned int to_cnt; /* Number of bytes to read */
- {
- unsigned int amt = 0;
- unsigned int err = 0;
- long fquo;
- unsigned int frem;
- unsigned int cquo = 0;
- unsigned int crem = 0;
- struct fs *FP;
- char buffer[SECSIZ];
-
- /* Direct IO or normal */
-
- if (fp < MS_MODIFIER)
- return read (fp, to_buf, to_cnt);
-
- if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
- ((FP->mode & 0x03) == O_WRONLY))
- {
- errno = EBADF;
- return -1;
- }
-
- /* If RAM - just copy */
-
- if (FP->drive == DRIVE_RAM)
- {
- char huge *cp = (char huge *)to_buf;
- char huge *sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
- | (FP->location & 0x0f));
-
-
- amt = to_cnt;
- while (amt--)
- *(cp++) = *(sp++);
-
- return to_cnt;
- }
-
- /* Get the last part of the first sector required */
-
- fquo = FP->location / SECSIZ;
- frem = (unsigned int) (FP->location % SECSIZ);
-
- if (frem > 0)
- {
- if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- if ((amt = SECSIZ - frem) > to_cnt)
- amt = to_cnt;
-
- memcpy (to_buf, &buffer[frem], amt);
-
- FP->location += amt;
- if (SECSIZ - frem <= to_cnt)
- fquo++;
-
- to_buf += amt;
- to_cnt -= amt;
- }
-
- /* Get the middle sectors required */
-
- cquo = to_cnt / SECSIZ;
- crem = to_cnt % SECSIZ;
-
- if (cquo > 0)
- {
- if ((err = dio_do (BIOS_READ, FP, to_buf, fquo, cquo)) !=
- (cquo * SECSIZ))
- {
- if (err > 0)
- FP->location += err;
-
- return err;
- }
-
- amt += (cquo * SECSIZ);
- FP->location += (cquo * SECSIZ);
- fquo += cquo;
- to_buf += (cquo * SECSIZ);
- to_cnt -= (cquo * SECSIZ);
- }
-
- /* Do we still need a partial sector ? */
-
- if (crem > 0)
- {
- if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
- return err;
-
- memcpy (to_buf, buffer, crem);
- amt += crem;
- FP->location += crem;
- }
-
- return (amt);
- }
-
- /*
- * open - Open a file
- */
-
- int dio_open (name, mode)
- char *name;
- int mode;
- {
- struct fs *FP;
- int fp, i, j;
- int drive, ndrive;
- union REGS iregs;
- char buf[SECSIZ];
- va_list ap;
- int permissions;
- mode_t dmode;
-
- /* Check the permission mask if it exists */
-
- va_start (ap, mode);
- permissions = va_arg (ap, int);
- va_end (ap);
-
- /* Check for initialisation */
-
- if (!(fs_init++))
- memset (MS_io_fs, 0, sizeof (struct fs *) * _NFILE);
-
- /* Direct I/o file name */
-
- if ((drive = dio_fncheck (name, &dmode)) != -1)
- {
- for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
- ;
-
- /* Check for available entry and space */
-
- if ((fp == _NFILE) ||
- ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
- {
- errno = ENFILE;
- return -1;
- }
-
- FP->location = 0L;
- FP->mode = mode;
- FP->st_mode = dmode;
-
- /* RAM access ? */
-
- if (drive == DRIVE_RAM)
- {
- FP->drive = drive;
- MS_io_fs[fp] = FP;
- return fp + MS_MODIFIER;
- }
-
- if (drive & HD_FLAG)
- {
- ndrive = (drive & (~HD_FLAG));
- FP->partition = ndrive % 10;
- ndrive /= 10;
- FP->drive = ndrive | HD_FLAG;
- FP->m_start = 0L; /* Offset for partition */
- }
-
- else
- {
- FP->drive = drive;
- ndrive = drive;
- FP->partition = 0;
- FP->m_start = 0L; /* Offset for partition */
- }
-
-
- /* Reset the drive */
-
- iregs.h.ah = 0;
- iregs.h.dl = (unsigned char)FP->drive;
- int86 (0x13, &iregs, &iregs);
-
- /* Get the drive parameters */
-
- iregs.h.ah = 0x08;
- iregs.h.dl = (unsigned char)FP->drive;
- int86 (0x13, &iregs, &iregs);
-
- /* Check for hard disk */
-
- if (FP->drive & HD_FLAG)
- {
- struct partition *pp, tp;
-
- /* System call failed - no device */
-
- if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
- {
- free (FP);
- errno = ENOENT;
- return -1;
- }
-
- /* OK - save the parameters */
-
- FP->m_cyl = (iregs.h.ch | ((iregs.h.cl & 0x0c0) << 2)) + 2;
- FP->m_head = iregs.h.dh + 1;
- FP->m_sector = iregs.h.cl & 0x03f;
- FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
-
- /* If this is not partition 0 - read the partition table */
-
- if (FP->partition)
- {
- if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
- {
- free (FP);
- return -1;
- }
-
- if (*(int *)&buf[510] != 0xaa55)
- {
- errno = ENOENT;
- return -1;
- }
-
- /* Sort the partition table */
-
- pp = (struct partition *)&buf[0x1be];
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 3; j++)
- {
- if (((!pp[j].offset) && pp[j + 1].offset) ||
- ((pp[j].offset > pp[j + 1].offset) &&
- pp[j + 1].offset))
- {
- tp = pp[j];
- pp[j] = pp[j + 1];
- pp[j + 1] = tp;
- }
- }
- }
-
- if (pp[FP->partition - 1].offset == 0L)
- {
- errno = ENOENT;
- return -1;
- }
-
- FP->m_start = pp[FP->partition - 1].offset;
- FP->m_scount = pp[FP->partition - 1].size;
- }
- }
-
- /* Floppy disk - get parameters. We try our best here, but DOS 3.3 allows
- * you to format any number of sectors per track and tracks per disk
- */
-
- else
- {
-
- /* System call failed - think this means we're on an XT. So set up the
- * XT parameters
- */
-
- if ((iregs.x.cflag) && (ndrive < 2))
- {
- iregs.h.bl = 0x01;
- FP->m_cyl = 40;
- FP->m_head = 2;
- FP->m_sector = 9;
- }
-
- /* No Drive */
-
- else if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
- {
- free (FP);
- errno = ENOENT;
- return -1;
- }
-
- /* OK - save the parameters */
-
- else
- {
- FP->m_cyl = iregs.h.ch;
- FP->m_head = iregs.h.dh + 1;
- FP->m_sector = iregs.h.cl;
- }
-
- FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
-
- /* High capacity drive ? */
-
- if ((iregs.h.bl == 0x02) || (iregs.h.bl == 0x03))
- {
-
- /* Try reading sector 0 */
-
- FP->m_sector = (iregs.h.bl == 0x02) ? 9 : 15;
-
- /* If it failed - switch to the other type */
-
- if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
- {
-
- /* If not a sector not found error - abort */
-
- if ((DIO_Error_Code != DEC_SECNF) &&
- (DIO_Error_Code != DEC_UNSUPTRK) &&
- (DIO_Error_Code != DEC_INVSEC))
- {
- free (FP);
- errno = EIO;
- return -1;
- }
-
- /* Otherwise, switch type */
-
- FP->m_sector = (iregs.h.bl == 0x02) ? 15 : 9;
-
- iregs.h.ah = 0x17;
- iregs.h.dl = (unsigned char)FP->drive;
- iregs.h.al = (unsigned char)(5 - iregs.h.bl);
- int86 (0x13, &iregs, &iregs);
- }
- }
-
- /* 8 or 9 Sectors, 1 or 2 heads */
-
- if (((iregs.h.bl > 0x00) || (iregs.h.bl < 0x04)) &&
- (FP->m_sector == 9))
- {
- FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
-
- /* Check to see if sector 8 exists */
-
- if (dio_do (BIOS_READ, FP, buf, 8L, 1) == -1)
- {
-
- /* If not a sector not found error - abort */
-
- if ((DIO_Error_Code != DEC_SECNF) &&
- (DIO_Error_Code != DEC_UNSUPTRK) &&
- (DIO_Error_Code != DEC_INVSEC))
- {
- free (FP);
- errno = EIO;
- return -1;
- }
-
- FP->m_sector = 8;
- }
-
- /* Check to see if sector 380 exists */
-
- if (dio_do (BIOS_READ, FP, buf, 380L, 1) == -1)
- {
-
- /* If not a sector not found error - abort */
-
- if ((DIO_Error_Code != DEC_SECNF) &&
- (DIO_Error_Code != DEC_UNSUPTRK) &&
- (DIO_Error_Code != DEC_INVSEC))
- {
- free (FP);
- errno = EIO;
- return -1;
- }
-
- FP->m_head = 1;
- }
- }
-
- /* 720K drive - read sector 15 to see if 1.4M */
-
- else if (iregs.h.bl == 0x04)
- {
- FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
-
- if (dio_do (BIOS_READ, FP, buf, 17L, 1) == -1)
- {
-
- /* If not a sector not found error - abort */
-
- if ((DIO_Error_Code != DEC_SECNF) &&
- (DIO_Error_Code != DEC_UNSUPTRK) &&
- (DIO_Error_Code != DEC_INVSEC))
- {
- free (FP);
- errno = EIO;
- return -1;
- }
-
- FP->m_sector = 9;
- }
- }
-
- FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- }
-
- /* Set up the file descriptor entry and return the number */
-
- MS_io_fs[fp] = FP;
- return fp + MS_MODIFIER;
- }
-
- else
- return open (name, mode, permissions);
- }
-
- /*
- * fstat - fstat function
- */
-
- int dio_fstat (fp, St)
- int fp;
- struct stat *St;
- {
- struct fs *FP;
-
- if (fp < MS_MODIFIER)
- return fstat (fp, St);
-
- if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- return -1;
-
- /* Dummy values */
-
- memset (St, 0, sizeof (struct stat));
- St->st_mode = FP->st_mode;
- St->st_nlink = 1;
-
- if (FP->drive == DRIVE_RAM)
- {
- St->st_size = MEGABYTE;
- St->st_rdev = 0x0300;
- }
-
- else
- {
- St->st_rdev = ((FP->drive & (~HD_FLAG)) * 10 + FP->partition) |
- ((FP->drive & HD_FLAG) ? 0x0200 : 0x0100);
- St->st_dev = FP->drive;
- }
-
- St->st_atime = time ((time_t *)NULL);
- St->st_ctime = St->st_ctime;
- St->st_mtime = St->st_atime;
- return 0;
- }
-
- /*
- * close - Close function
- */
-
- int dio_close (fp)
- int fp;
- {
- struct fs *FP;
-
- if (fp < MS_MODIFIER)
- return close (fp);
-
- if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- return -1;
-
- free (FP);
- MS_io_fs[fp - MS_MODIFIER] = (struct fs *)NULL;
- return 0;
- }
-
- /*
- * lseek - Seek function
- */
-
- long dio_lseek (fp, off, type)
- int fp;
- off_t off;
- int type;
- {
- off_t check;
- struct fs *FP;
-
- if (fp < MS_MODIFIER)
- return lseek (fp, off, type);
-
- if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- return -1L;
-
- switch (type)
- {
- case SEEK_SET:
- check = off;
- break;
-
- case SEEK_CUR:
- check = off + FP->location;
- break;
-
- case SEEK_END:
- default:
- errno = EINVAL;
- return -1L;
- }
-
- if (check < 0L)
- {
- errno = EINVAL;
- return -1L;
- }
-
- return (FP->location = check);
- }
-
- /*
- * Check for a valid file pointer. Look up the file handler in the table
- * of our file handlers
- */
-
- static struct fs *dio_fpcheck (fp)
- int fp;
- {
- struct fs *FP;
-
- if (((FP = MS_io_fs[fp - MS_MODIFIER]) == (struct fs *)NULL) ||
- (fp - MS_MODIFIER >= _NFILE) || (fp - MS_MODIFIER < 0))
- {
- errno = EBADF;
- return (struct fs *)NULL;
- }
-
- return FP;
- }
-
- /*
- * Check for a valid file name. We are looking for one of 'our' file names
- * /dev/hd??, /dev/fd? or /dev/mem. The device number is returned.
- */
-
- static int dio_fncheck (name, dmode)
- char *name;
- mode_t *dmode;
- {
-
- /* Set up default mode */
-
- if (dmode != (mode_t *)NULL)
- *dmode = 0x61b6;
-
- /* Check for hard disk */
-
- if (isdigit (name[7]) && isdigit (name[8]) && (strlen (name) == 9) &&
- (strnicmp (name, "/dev/hd", 7) == 0))
- {
- int i = atoi (&name[7]);
-
- return ((i % 10) > 4) ? -1 : i | HD_FLAG;
- }
-
- else if (isdigit (name[8]) && isdigit (name[9]) && (strlen (name) == 10) &&
- (strnicmp (name, "/dev/rhd", 8) == 0))
- {
- int i = atoi (&name[8]);
-
- if (dmode != (mode_t *)NULL)
- *dmode = 0x21b6;
-
- return ((i % 10) > 4) ? -1 : i | HD_FLAG;
- }
-
- /* Check for floppy disk */
-
- else if (isdigit (name[7]) && (strlen (name) == 8) &&
- (!strnicmp (name, "/dev/fd", 7)))
- return name[7] - '0';
-
- else if (isdigit(name[8]) && (strlen (name) == 9) &&
- (!strnicmp (name, "/dev/rfd", 8)))
- {
- if (dmode != (mode_t *)NULL)
- *dmode = 0x21b6;
-
- return name[8] - '0';
- }
-
- else if (!stricmp (name, "/dev/kmem"))
- return DRIVE_RAM;
-
- return -1;
- }
-
- /*
- * stat - Get file status
- */
-
- int dio_stat (name, St)
- char *name;
- struct stat *St;
- {
- int drive;
- mode_t dmode;
-
- if ((drive = dio_fncheck (name, &dmode)) == -1)
- return stat (name, St);
-
- memset (St, 0, sizeof (struct stat));
- St->st_mode = dmode;
- St->st_nlink = 1;
- St->st_atime = time ((time_t *)NULL);
- St->st_ctime = St->st_ctime;
- St->st_mtime = St->st_atime;
-
- if (drive == DRIVE_RAM)
- {
- St->st_size = MEGABYTE;
- St->st_rdev = 0x0300;
- }
-
- else
- {
- St->st_rdev = (drive & (~HD_FLAG)) | ((drive & HD_FLAG) ? 0x0200
- : 0x0100);
- St->st_dev = drive;
- }
-
- return 0;
- }
-
- /*
- * access - Check file access
- */
-
- int dio_access (name, mode)
- char *name;
- int mode;
- {
- if (dio_fncheck (name, (mode_t *)NULL) == -1)
- return access (name, mode);
-
- else if (mode & 1)
- {
- errno = EACCES;
- return -1;
- }
-
- return 0;
- }
-
- /*
- * chmod - Change file permissions
- */
-
- int dio_chmod (name, mode)
- char *name;
- int mode;
- {
- return (dio_fncheck (name, (mode_t *)NULL) == -1) ? chmod (name, mode) : 0;
- }
-
- /*
- * create - Create file
- */
-
- int dio_creat (name, mode)
- char *name;
- int mode;
- {
- return (dio_fncheck (name, (mode_t *)NULL) == -1) ? creat (name, mode)
- : dio_open (name, O_WRONLY, mode);
- }
-
- /*
- * dup - Duplicate handler
- */
-
- int dio_dup (fp)
- int fp;
- {
- struct fs *FP; /* New pointer */
- struct fs *FP1; /* Old pointer */
-
- if (fp < MS_MODIFIER)
- return dup (fp);
-
- /* Check valid */
-
- if ((FP1 = dio_fpcheck (fp)) == (struct fs *)NULL)
- return -1;
-
- /* Create a new entry */
-
- for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
- ;
-
- if ((fp == _NFILE) ||
- ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
- {
- errno = EMFILE;
- return -1;
- }
-
- /* Duplicate it */
-
- MS_io_fs[fp] = FP;
- *FP = *FP1;
- return fp;
- }
-
- /*
- * isatty - Check if tty
- */
-
- int dio_isatty (fp)
- int fp;
- {
- if (fp < MS_MODIFIER)
- return isatty (fp);
-
- return 0;
- }
-
- /*
- * tell - Tell location
- */
-
- long dio_tell (fp)
- int fp;
- {
- struct fs *FP;
-
- if (fp < MS_MODIFIER)
- return tell (fp);
-
- return ((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ? -1L : FP->location;
- }
-