plat/msdos86: add open( ), lseek( ), and getpid()
This commit is contained in:
parent
0d2b55cd29
commit
466cf20805
|
@ -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;
|
||||||
|
|
27
plat/msdos86/libsys/getpid.s
Normal file
27
plat/msdos86/libsys/getpid.s
Normal 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
|
|
@ -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
|
||||||
|
|
26
plat/msdos86/libsys/lseek.c
Normal file
26
plat/msdos86/libsys/lseek.c
Normal 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
101
plat/msdos86/libsys/open.c
Normal 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;
|
||||||
|
}
|
25
plat/msdos86/libsys/sys_exists.s
Normal file
25
plat/msdos86/libsys/sys_exists.s
Normal 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
|
24
plat/msdos86/libsys/sys_rawcreat.s
Normal file
24
plat/msdos86/libsys/sys_rawcreat.s
Normal 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
|
26
plat/msdos86/libsys/sys_rawlseek.s
Normal file
26
plat/msdos86/libsys/sys_rawlseek.s
Normal 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
|
24
plat/msdos86/libsys/sys_rawopen.s
Normal file
24
plat/msdos86/libsys/sys_rawopen.s
Normal 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
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue