plat/msdos86: add open( ), lseek( ), and getpid()
This commit is contained in:
parent
0d2b55cd29
commit
466cf20805
|
@ -1,7 +1,7 @@
|
|||
#ifndef _SYS_TYPES_H
|
||||
#define _SYS_TYPES_H
|
||||
|
||||
typedef int pid_t;
|
||||
typedef long pid_t;
|
||||
typedef int mode_t;
|
||||
typedef long time_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 int _sys_isopen(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
|
||||
|
|
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
|
||||
* `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]))
|
||||
errno = err_map[dos_err];
|
||||
|
|
|
@ -13,20 +13,26 @@
|
|||
.sect .text
|
||||
|
||||
! .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
|
||||
! code in ax, and return -1. If the carry flag is clear, just return ax as
|
||||
! a return value.
|
||||
! code in ax, and return a shortword -1. If the carry flag is clear, just
|
||||
! 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_axret
|
||||
.extern .sys_dxaxret
|
||||
.sys_zret:
|
||||
jc error
|
||||
xor ax, ax
|
||||
no_error:
|
||||
ret
|
||||
.sys_axret:
|
||||
.sys_dxaxret:
|
||||
jnc no_error
|
||||
error:
|
||||
push ax
|
||||
|
|
Loading…
Reference in a new issue