plat/msdos86: add open( ), lseek( ), and getpid()

This commit is contained in:
Tee-Kiah Chia 2021-03-28 12:09:52 +00:00
parent 0d2b55cd29
commit 466cf20805
11 changed files with 270 additions and 6 deletions

View file

@ -1,7 +1,7 @@
#ifndef _SYS_TYPES_H #ifndef _SYS_TYPES_H
#define _SYS_TYPES_H #define _SYS_TYPES_H
typedef int pid_t; typedef long pid_t;
typedef int mode_t; typedef int mode_t;
typedef long time_t; typedef long time_t;
typedef long suseconds_t; typedef long suseconds_t;

View file

@ -0,0 +1,27 @@
#
! $Source$
! $State$
! $Revision$
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! Get the current process identifier. For MS-DOS, use the Program Segment
! Prefix (PSP) segment as the PID.
!
! (Note that pid_t is a 32-bit type. This is to allow for PSP addresses
! above 0x7FFF:0.)
.define _getpid
_getpid:
movb ah, 0x51
int 0x21
xchg bx, ax
xor dx, dx
ret

View file

@ -49,5 +49,10 @@ extern ssize_t _sys_rawread(int, char *, size_t);
extern ssize_t _sys_rawwrite(int, const char *, size_t); extern ssize_t _sys_rawwrite(int, const char *, size_t);
extern int _sys_isopen(int); extern int _sys_isopen(int);
extern int _sys_isreadyr(int); extern int _sys_isreadyr(int);
extern int _sys_exists(const char *);
extern int _sys_rawcreat(const char *, unsigned);
extern int _sys_rawopen(const char *, int);
extern off_t _sys_rawlseek(int, off_t, int);
#endif #endif

View file

@ -0,0 +1,26 @@
/* $Source$
* $State$
* $Revision$
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "libsys.h"
off_t lseek(int fd, off_t offset, int whence)
{
off_t newoff;
if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)
{
errno = EINVAL;
return -1L;
}
newoff = _sys_rawlseek(fd, offset, whence);
if (newoff != -1L)
_sys_seteof(fd, 0);
return newoff;
}

101
plat/msdos86/libsys/open.c Normal file
View file

@ -0,0 +1,101 @@
/* $Source$
* $State$
* $Revision$
*/
/*
* Derived from dos-open.c for newlib-ia16 which was written for the
* gcc-ia16 toolchain.
*
* Copyright (c) 2018 Bart Oldeman
* Copyright (c) 2019--2021 TK Chia
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include "libsys.h"
int open(const char* pathname, int flags, ...)
{
int fd = -1, binmode;
off_t ret;
if ((flags & ~(O_ACCMODE | O_CREAT | O_TRUNC | O_APPEND
| O_TEXT | O_BINARY)))
{
/* bail out if there are unknown flags */
errno = EINVAL;
return -1;
}
binmode = flags & (O_TEXT | O_BINARY);
if (binmode != O_TEXT && binmode != O_BINARY && binmode != 0)
{
/* bail out if both O_TEXT and O_BINARY are specified (!) */
errno = EINVAL;
return -1;
}
if ((flags & O_CREAT))
{
/* special but common case O_WRONLY | O_CREAT | O_TRUNC
* should be handled by only calling _sys_rawcreat */
int fileexists = 0;
if (!(flags & O_TRUNC))
fileexists = _sys_exists(pathname);
if (!fileexists)
{
va_list ap;
mode_t mode;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
fd = _sys_rawcreat(pathname, mode & 0200 ? 0 : 1);
if (fd != -1)
{
if ((flags & O_ACCMODE) == O_WRONLY)
return fd;
close(fd);
fd = -1;
}
}
}
/* try to open file with mode */
if (fd == -1)
fd = _sys_rawopen(pathname, flags & O_ACCMODE);
if (fd == -1)
return fd;
ret = 0;
/* handle O_TRUNC and O_APPEND */
if ((flags & O_TRUNC))
ret = _sys_rawwrite(fd, NULL, 0);
else if ((flags & O_APPEND))
ret = _sys_rawlseek(fd, 0L, SEEK_END);
if (ret == -1)
{
close(fd);
return -1;
}
/* handle O_TEXT and O_BINARY, and reset "end of file encountered" */
_sys_setmode(fd, binmode == O_BINARY ? O_BINARY : O_TEXT);
_sys_seteof(fd, 0);
return fd;
}

View file

@ -0,0 +1,25 @@
#
! $Source$
! $State$
! $Revision$
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! Say whether a file exists with the given name.
.define __sys_exists
__sys_exists:
mov bx, sp
mov dx, 2(bx)
mov ax, 0x4300
int 0x21
sbb ax, ax
inc ax
ret

View file

@ -0,0 +1,24 @@
#
! $Source$
! $State$
! $Revision$
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! Create or truncate a file.
.define __sys_rawcreat
__sys_rawcreat:
movb ah, 0x3c
mov bx, sp
mov dx, 2(bx)
mov cx, 4(bx)
int 0x21
jmp .sys_axret

View file

@ -0,0 +1,26 @@
#
! $Source$
! $State$
! $Revision$
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! Move the current file position for a file descriptor.
.define __sys_rawlseek
__sys_rawlseek:
movb ah, 0x42
mov bx, sp
mov dx, 4(bx)
mov cx, 6(bx)
movb al, 8(bx)
mov bx, 2(bx)
int 0x21
jmp .sys_dxaxret

View file

@ -0,0 +1,24 @@
#
! $Source$
! $State$
! $Revision$
! Declare segments (the order is important).
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! Open an existing file.
.define __sys_rawopen
__sys_rawopen:
movb ah, 0x3d
mov bx, sp
mov dx, 2(bx)
movb al, 4(bx)
int 0x21
jmp .sys_axret

View file

@ -33,9 +33,9 @@ static const signed char err_map[] =
/* /*
* Map an MS-DOS 2+ system error code to an `errno' value and store that in * Map an MS-DOS 2+ system error code to an `errno' value and store that in
* `errno'. Return -1. * `errno'. Return a longword -1.
*/ */
int _sys_seterrno(unsigned dos_err) long _sys_seterrno(unsigned dos_err)
{ {
if (dos_err < sizeof(err_map) / sizeof(err_map[0])) if (dos_err < sizeof(err_map) / sizeof(err_map[0]))
errno = err_map[dos_err]; errno = err_map[dos_err];

View file

@ -13,20 +13,26 @@
.sect .text .sect .text
! .sys_zret: if the carry flag is set, then set `errno' from the DOS error ! .sys_zret: if the carry flag is set, then set `errno' from the DOS error
! code in ax, and return -1. If the carry flag is clear, just return zero. ! code in ax, and return a shortword -1. If the carry flag is clear, just
! return a shortword zero.
! !
! .sys_axret: if the carry flag is set, then set `errno' from the DOS error ! .sys_axret: if the carry flag is set, then set `errno' from the DOS error
! code in ax, and return -1. If the carry flag is clear, just return ax as ! code in ax, and return a shortword -1. If the carry flag is clear, just
! a return value. ! return ax as a return value.
!
! .sys_dxaxret: same as .sys_axret, but return a longword -1 or dx:ax as a
! return value.
.extern .sys_zret .extern .sys_zret
.extern .sys_axret .extern .sys_axret
.extern .sys_dxaxret
.sys_zret: .sys_zret:
jc error jc error
xor ax, ax xor ax, ax
no_error: no_error:
ret ret
.sys_axret: .sys_axret:
.sys_dxaxret:
jnc no_error jnc no_error
error: error:
push ax push ax