Apple2: implement stat(2) and statvfs(3)

This commit is contained in:
Colin Leroy-Mira 2023-12-28 21:50:13 +01:00 committed by Oliver Schmidt
parent 4343eebe67
commit 75461e1319
23 changed files with 999 additions and 124 deletions

64
asminc/stat.inc Normal file
View File

@ -0,0 +1,64 @@
;****************************************************************************
;* *
;* stat.inc *
;* *
;* Stat struct *
;* *
;* *
;* *
;*(C) 2023 Colin Leroy-Mira <colin@colino.net> *
;* *
;* *
;*This software is provided 'as-is', without any expressed or implied *
;*warranty. In no event will the authors be held liable for any damages *
;*arising from the use of this software. *
;* *
;*Permission is granted to anyone to use this software for any purpose, *
;*including commercial applications, and to alter it and redistribute it *
;*freely, subject to the following restrictions: *
;* *
;*1. The origin of this software must not be misrepresented; you must not *
;* claim that you wrote the original software. If you use this software *
;* in a product, an acknowledgment in the product documentation would be *
;* appreciated but is not required. *
;*2. Altered source versions must be plainly marked as such, and must not *
;* be misrepresented as being the original software. *
;*3. This notice may not be removed or altered from any source *
;* distribution. *
;* *
;****************************************************************************
.include "time.inc"
;------------------------------------------------------------------------------
; st_mode values
S_IFDIR = $01
S_IFREG = $02
;------------------------------------------------------------------------------
; struct stat
.struct stat
st_dev .dword
st_ino .dword
st_mode .byte
st_nlink .dword
st_uid .byte
st_gid .byte
st_size .dword
st_atim .tag timespec
st_ctim .tag timespec
st_mtim .tag timespec
.ifdef __APPLE2__
st_access .byte
st_type .byte
st_auxtype .word
st_storagetype .byte
st_blocks .word
st_mod_date .word
st_mod_time .word
st_create_date .word
st_create_time .word
.endif
.endstruct

46
asminc/statvfs.inc Normal file
View File

@ -0,0 +1,46 @@
;****************************************************************************
;* *
;* statvfs.inc *
;* *
;* Statvfs struct *
;* *
;* *
;* *
;*(C) 2023 Colin Leroy-Mira <colin@colino.net> *
;* *
;* *
;*This software is provided 'as-is', without any expressed or implied *
;*warranty. In no event will the authors be held liable for any damages *
;*arising from the use of this software. *
;* *
;*Permission is granted to anyone to use this software for any purpose, *
;*including commercial applications, and to alter it and redistribute it *
;*freely, subject to the following restrictions: *
;* *
;*1. The origin of this software must not be misrepresented; you must not *
;* claim that you wrote the original software. If you use this software *
;* in a product, an acknowledgment in the product documentation would be *
;* appreciated but is not required. *
;*2. Altered source versions must be plainly marked as such, and must not *
;* be misrepresented as being the original software. *
;*3. This notice may not be removed or altered from any source *
;* distribution. *
;* *
;****************************************************************************
;------------------------------------------------------------------------------
; struct statvfs
.struct statvfs
f_bsize .dword
f_frsize .dword
f_blocks .dword
f_bfree .dword
f_bavail .dword
f_files .dword
f_ffree .dword
f_favail .dword
f_fsid .dword
f_flag .dword
f_namemax .dword
.endstruct

View File

@ -321,14 +321,15 @@ Programs containing Apple&nbsp;&rsqb;&lsqb; specific code may use the
<sect1>Apple&nbsp;&rsqb;&lsqb; specific functions<p>
The functions listed below are special for the Apple&nbsp;&rsqb;&lsqb;. See
the <url url="funcref.html" name="function reference"> for declaration and
The functions and variables listed below are special for the Apple&nbsp;&rsqb;&lsqb;.
See the <url url="funcref.html" name="function reference"> for declaration and
usage.
<itemize>
<item>_auxtype
<item>_dos_type
<item>_filetype
<item>_datetime
<item>get_ostype
<item>rebootafterexit
<item>ser_apple2_slot
@ -569,6 +570,28 @@ program. See the discussion of the <tt/.CONDES/ feature in the <url
url="ca65.html" name="assembler manual">.
<sect1>ProDOS date/time manipulation<p>
<descrip>
The readdir and stat function return ProDOS timestamps in their file
creation/modification time attributes. You can convert them to more portable
time representations using either:
<tag/struct tm/
<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
Converts a <tt/struct datetime/ into a <tt/struct tm/. Returns NULL in case
of error and sets errno.
<tag/time_t/
<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
Parses a <tt/struct datetime/ and returns a UNIX timestamp. Returns 0 on error and
sets errno.
</descrip>
<sect1>DIO<p>
<descrip>
@ -630,6 +653,16 @@ url="ca65.html" name="assembler manual">.
that can be used to set these variables. It is included in
<tt/apple2.h/.
The global variable <tt/_datetime/ allows the file creation date/time
to be set before a call to <tt/fopen()/
or <tt/open()/ that creates the file. It is defined in <tt/apple2.h/:
<tscreen>
<verb>
extern struct datetime _datetime;
</verb>
</tscreen>
<tag>Example</tag>
A text file cannot be created with just the

View File

@ -322,14 +322,15 @@ Programs containing enhanced&nbsp;Apple&nbsp;//e specific code may use the
<sect1>Enhanced&nbsp;Apple&nbsp;//e specific functions<p>
The functions listed below are special for the enhanced&nbsp;Apple&nbsp;//e. See
the <url url="funcref.html" name="function reference"> for declaration and
The functions and variables listed below are special for the Apple&nbsp;&rsqb;&lsqb;.
See the <url url="funcref.html" name="function reference"> for declaration and
usage.
<itemize>
<item>_auxtype
<item>_dos_type
<item>_filetype
<item>_datetime
<item>get_ostype
<item>rebootafterexit
<item>ser_apple2_slot
@ -575,6 +576,28 @@ program. See the discussion of the <tt/.CONDES/ feature in the <url
url="ca65.html" name="assembler manual">.
<sect1>ProDOS date/time manipulation<p>
<descrip>
The readdir and stat function return ProDOS timestamps in their file
creation/modification time attributes. You can convert them to more portable
time representations using either:
<tag/struct tm/
<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
Converts a <tt/struct datetime/ into a <tt/struct tm/. Returns -1 in case
of error and sets errno, 0 on success.
<tag/time_t/
<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
Parses a <tt/struct datetime/ and returns a UNIX timestamp. Returns 0 on error and
sets errno.
</descrip>
<sect1>DIO<p>
<descrip>
@ -619,7 +642,7 @@ url="ca65.html" name="assembler manual">.
auxiliary type. Therefore, some additional mechanism for specifying
the file types is needed.
<tag>Specifying the File Type and Auxiliary Type</tag>
<tag>Specifying the File Type, Auxiliary Type and creation date</tag>
There are two global variables provided that allow the file type
and auxiliary type to be specified before a call to <tt/fopen()/
@ -636,6 +659,16 @@ url="ca65.html" name="assembler manual">.
that can be used to set these variables. It is included in
<tt/apple2.h/, which is in turn included in <tt/apple2enh.h/.
The global variable <tt/_datetime/ allows the file creation date/time
to be set before a call to <tt/fopen()/
or <tt/open()/ that creates the file. It is defined in <tt/apple2.h/:
<tscreen>
<verb>
extern struct datetime _datetime;
</verb>
</tscreen>
<tag>Example</tag>
A text file cannot be created with just the

View File

@ -93,6 +93,8 @@ function.
<itemize>
<item>_dos_type
<item><ref id="get_ostype" name="get_ostype">
<item><ref id="gmtime_dt" name="gmtime_dt">
<item><ref id="mktime_dt" name="mktime_dt">
<item>rebootafterexit
</itemize>
@ -846,6 +848,20 @@ communication, see also <tt>testcode/lib/ser-test.c</tt>.
(incomplete)
<sect1><tt/stat.h/<label id="sys/stat.h"><p>
<itemize>
<item><ref id="stat" name="stat">
</itemize>
<sect1><tt/statvfs.h/<label id="sys/statvfs.h"><p>
<itemize>
<item><ref id="statvfs" name="statvfs">
</itemize>
<sect1><tt/vic20.h/<label id="vic20.h"><p>
(incomplete)
@ -2851,6 +2867,79 @@ setting the time may not work. See also the platform-specific information.
</quote>
<sect1>gmtime_dt<label id="gmtime_dt"><p>
<quote>
<descrip>
<tag/Function/Converts a ProDOS date to a struct tm.
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">/
<tag/Declaration/<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
<tag/Description/The <tt/gmtime_dt/ function converts the given
proDOS date/time to a struct tm. On error, NULL is returned and <tt/errno/ is set
to an error code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>This function is only available on Apple II.
<item>On Apple II, you can't stat() an opened file. stat() before opening.
</itemize>
<tag/Availability/cc65
<tag/Example/
<verb>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int main(void)
{
struct stat st;
struct tm* tm;
if (stat ("/disk/file", &amp;st) == 0) {
tm = gmtime_dt (&amp;st.st_ctime);
if (tm)
printf ("File created on %s\n", asctime(tm));
}
}
</verb>
</descrip>
</quote>
<sect1>mktime_dt<label id="mktime_dt"><p>
<quote>
<descrip>
<tag/Function/Converts a ProDOS date to a time_t.
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">/
<tag/Declaration/<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
<tag/Description/The <tt/mktime_dt/ function parses the given
proDOS date/time and returns a time_t timestamp. On error, 0 is returned,
and errno is set.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>This function is only available on Apple II.
</itemize>
<tag/Availability/cc65
<tag/Example/
<verb>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int main(void)
{
struct stat st;
if (stat ("/disk/file", &amp;st) == 0) {
printf ("File created on %s\n",
localtime (mktime_dt (&amp;st.st_ctime)));
}
}
</verb>
</descrip>
</quote>
<sect1>clrscr<label id="clrscr"><p>
<quote>
@ -6229,6 +6318,9 @@ be used in presence of a prototype.
<item>The returned pointer may point to a statically allocated instance of
<tt/struct dirent/, so it may get overwritten by subsequent calls to
<tt/readdir/.
<item>On the Apple II platform, the d_ctime and d_mtime returned are in the
ProDOS format. You can convert them to more portable time representations using
the ProDOS datetime conversion functions.
<item>On several platforms, namely the CBMs and the Atari, the disk drives get
confused when opening/closing files between directory reads. So for example a
program that reads the list of files on a disk, and after each call to
@ -7075,6 +7167,85 @@ be used in presence of a prototype.
</quote>
<sect1>stat<label id="stat"><p>
<quote>
<descrip>
<tag/Function/Get file status.
<tag/Header/<tt/<ref id="sys/stat.h" name="sys/stat.h">/
<tag/Declaration/<tt/int __fastcall__ stat (const char* pathname, struct stat* statbuf);/
<tag/Description/<tt/stat/ gets information for the file with the given name. On success,
zero is returned. On error, -1 is returned and <tt/errno/ is set to an error
code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>On the Apple II platform, the st_ctim, st_mtim and st_atim members are left
to zero, for size and performance reasons. The ProDOS creation and modification dates
are returned in the ProDOS format in st_ctime and st_mtime. The access date does
not exist. You can convert them to POSIX-style time representations using
the <url url="apple2.html#ss9.3" name="ProDOS datetime conversion functions">.
</itemize>
<tag/Availability/POSIX 1003.1
<tag/See also/
<ref id="statvfs" name="statvfs">
<tag/Example/
<verb>
#include &lt;sys/stat.h&gt;
#define FILENAME "helloworld"
struct stat stbuf;
if (stat (FILENAME, &amp;stbuf) == 0) {
printf ("%s size is %lu bytes (created on %s)\n", FILENAME, stbuf.st_size,
#ifndef __APPLE2__
localtime (&amp;stbuf.st_ctim.tv_sec)
#else
localtime (mktime_dt (&amp;stbuf.st_ctime))
#endif
);
} else {
printf ("There was a problem stat'ing %s: %d\n", FILENAME, errno);
}
</verb>
</descrip>
</quote>
<sect1>statvfs<label id="statvfs"><p>
<quote>
<descrip>
<tag/Function/Get filesystem statistics.
<tag/Header/<tt/<ref id="sys/statvfs.h" name="sys/statvfs.h">/
<tag/Declaration/<tt/int __fastcall__ statvfs (const char* pathname, struct statvfs* buf);/
<tag/Description/<tt/statvfs/ gets information for the filesytem on which the given file
resides. On success,
zero is returned. On error, -1 is returned and <tt/errno/ is set to an error
code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>The function requires an absolute pathname.
</itemize>
<tag/Availability/POSIX 1003.1
<tag/See also/
<ref id="stat" name="stat">
<tag/Example/
<verb>
#include &lt;sys/statvfs.h&gt;
#define FILENAME "/disk/helloworld"
struct statvfs stvbuf;
if (statvfs (FILENAME, &amp;stvbuf) == 0) {
printf ("%s filesystem has %u blocks of %u size, %u of them free.\n", FILENAME, stvbuf.f_blocks, stvbuf.f_bsize, stvbuf.f_bfree);
} else {
printf ("There was a problem statvfs'ing %s: %d\n", FILENAME, errno);
}
</verb>
</descrip>
</quote>
<sect1>strcasecmp<label id="strcasecmp"><p>
<quote>

View File

@ -41,6 +41,7 @@
# error This module may only be used when compiling for the Apple ][!
#endif
#include <time.h>
#include <apple2_filetype.h>
@ -142,6 +143,27 @@ extern unsigned char _dos_type;
** ProDOS 8 2.4.x - 0x24
*/
/* struct stat.st_mode values */
#define S_IFDIR 0x01
#define S_IFREG 0x02
#define S_IFBLK 0xFF
#define S_IFCHR 0xFF
#define S_IFIFO 0xFF
#define S_IFLNK 0xFF
#define S_IFSOCK 0xFF
struct datetime {
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} date;
struct {
unsigned char min;
unsigned char hour;
} time;
};
/*****************************************************************************/
@ -151,20 +173,10 @@ extern unsigned char _dos_type;
/* The file stream implementation and the POSIX I/O functions will use the
** following struct to set the date and time stamp on files. This specificially
** following struct to set the date and time stamp on files. This specifically
** applies to the open and fopen functions.
*/
extern struct {
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} createdate; /* Current date: 0 */
struct {
unsigned char min;
unsigned char hour;
} createtime; /* Current time: 0 */
} _datetime;
extern struct datetime _datetime;
/* The addresses of the static drivers */
#if !defined(__APPLE2ENH__)
@ -211,6 +223,12 @@ void rebootafterexit (void);
#define _cpeekcolor() COLOR_WHITE
#define _cpeekrevers() 0
struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);
/* Converts a ProDOS date/time structure to a struct tm */
time_t __fastcall__ mktime_dt (const struct datetime* dt);
/* Converts a ProDOS date/time structure to a time_t UNIX timestamp */
/* End of apple2.h */

View File

@ -33,6 +33,8 @@
#ifndef _DIRENT_H
#define _DIRENT_H
#include <target.h>
/*****************************************************************************/
@ -46,31 +48,15 @@ typedef struct DIR DIR;
#if defined(__APPLE2__)
struct dirent {
char d_name[16];
unsigned d_ino;
unsigned d_blocks;
unsigned long d_size;
unsigned char d_type;
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} d_cdate;
struct {
unsigned char min;
unsigned char hour;
} d_ctime;
unsigned char d_access;
unsigned d_auxtype;
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} d_mdate;
struct {
unsigned char min;
unsigned char hour;
} d_mtime;
char d_name[16];
unsigned d_ino;
unsigned d_blocks;
unsigned long d_size;
unsigned char d_type;
struct datetime d_ctime;
unsigned char d_access;
unsigned d_auxtype;
struct datetime d_mtime;
};
#define _DE_ISREG(t) ((t) != 0x0F)

View File

@ -2,7 +2,7 @@
/* */
/* stat.h */
/* */
/* Constants for the mode argument of open and creat */
/* stat(2) definition */
/* */
/* */
/* */
@ -11,6 +11,9 @@
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* (C) 2023 Colin Leroy-Mira */
/* EMail: colin@colino.net */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
@ -36,6 +39,10 @@
#ifndef _STAT_H
#define _STAT_H
#include <time.h>
#include <target.h>
#include <sys/types.h>
/*****************************************************************************/
@ -47,6 +54,30 @@
#define S_IREAD 0x01
#define S_IWRITE 0x02
#define S_IFMT 0x03
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
struct timespec st_atim;
struct timespec st_ctim;
struct timespec st_mtim;
#ifdef __APPLE2__
unsigned char st_access;
unsigned char st_type;
unsigned int st_auxtype;
unsigned char st_storagetype;
unsigned int st_blocks;
struct datetime st_mtime;
struct datetime st_ctime;
#endif
};
/*****************************************************************************/
@ -55,5 +86,9 @@
int __fastcall__ stat (const char* pathname, struct stat* statbuf);
/* End of stat.h */
#endif

74
include/sys/statvfs.h Normal file
View File

@ -0,0 +1,74 @@
/*****************************************************************************/
/* */
/* statvfs.h */
/* */
/* statvfs(3) definition */
/* */
/* */
/* */
/* (C) 2023 Colin Leroy-Mira */
/* EMail: colin@colino.net */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _STATVFS_H
#define _STATVFS_H
#include <sys/types.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
struct statvfs {
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
unsigned long f_fsid;
unsigned long f_flag;
unsigned long f_namemax;
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int __fastcall__ statvfs (const char* pathname, struct statvfs* buf);
/* End of statvfs.h */
#endif

View File

@ -50,6 +50,46 @@
typedef long int off_t;
#endif
#ifndef _HAVE_dev_t
#define _HAVE_dev_t
typedef unsigned long int dev_t;
#endif
#ifndef _HAVE_ino_t
#define _HAVE_ino_t
typedef unsigned long int ino_t;
#endif
#ifndef _HAVE_nlink_t
#define _HAVE_nlink_t
typedef unsigned long int nlink_t;
#endif
#ifndef _HAVE_uid_t
#define _HAVE_uid_t
typedef unsigned char uid_t;
#endif
#ifndef _HAVE_gid_t
#define _HAVE_gid_t
typedef unsigned char gid_t;
#endif
#ifndef _HAVE_mode_t
#define _HAVE_mode_t
typedef unsigned char mode_t;
#endif
#ifndef _HAVE_fsblkcnt_t
#define _HAVE_fsblkcnt_t
typedef unsigned long int fsblkcnt_t;
#endif
#ifndef _HAVE_fsfilcnt_t
#define _HAVE_fsfilcnt_t
typedef unsigned long int fsfilcnt_t;
#endif
/*****************************************************************************/
@ -60,6 +100,3 @@ typedef long int off_t;
/* End of types.h */
#endif

View File

@ -37,6 +37,15 @@
#define _TIME_H
/* Forward declaration for target.h */
typedef unsigned long time_t;
typedef unsigned long clock_t;
#include <target.h>
/* NULL pointer */
#ifndef NULL
@ -49,9 +58,6 @@
typedef unsigned size_t;
#endif
typedef unsigned long time_t;
typedef unsigned long clock_t;
/* Structure for broken down time */
struct tm {
int tm_sec;

View File

@ -5,8 +5,8 @@
;
.export _exec
.import pushname, popname
.import popax, done, _exit
.import mli_file_info_direct
.import pushname, popname, popax, done, _exit
.include "zeropage.inc"
.include "errno.inc"
@ -17,13 +17,12 @@
typerr: lda #$4A ; "Incompatible file format"
; Cleanup name
oserr: jsr popname ; Preserves A
; Set ___oserror
jmp ___mappederrno
mlierr: jsr popname
oserr: jmp ___mappederrno
_exec:
; Save cmdline
; Store cmdline
sta ptr4
stx ptr4+1
@ -32,6 +31,9 @@ _exec:
jsr pushname
bne oserr
jsr mli_file_info_direct
bcs mlierr
; ProDOS TechRefMan, chapter 5.1.5.1:
; "The complete or partial pathname of the system program
; is stored at $280, starting with a length byte."
@ -46,18 +48,6 @@ _exec:
dey
bpl :-
; Set pushed name
lda sp
ldx sp+1
sta mliparam + MLI::INFO::PATHNAME
stx mliparam + MLI::INFO::PATHNAME+1
; Get file_type and aux_type
lda #GET_INFO_CALL
ldx #GET_INFO_COUNT
jsr callmli
bcs oserr
; If we get here the program file at least exists so we copy
; the loader stub right now and patch it later to set params
ldx #size - 1

View File

@ -8,6 +8,7 @@
.import subysp, addysp, decsp1
.include "zeropage.inc"
.include "apple2.inc"
.include "mli.inc"
pushname:
@ -15,7 +16,7 @@ pushname:
stx ptr1+1
; Alloc pathname buffer
ldy #64+1 ; Max pathname length + zero
ldy #FILENAME_MAX
jsr subysp
; Check for full pathname
@ -71,14 +72,14 @@ copy: lda (ptr1),y
sta (sp),y
beq setlen
iny
cpy #64+1 ; Max pathname length + zero
cpy #FILENAME_MAX
bcc copy
; Load oserror code
lda #$40 ; "Invalid pathname"
; Free pathname buffer
addsp65:ldy #64+1
addsp65:ldy #FILENAME_MAX
bne addsp ; Branch always
; Alloc and set length byte
@ -93,5 +94,5 @@ setlen: tya
popname:
; Cleanup stack
ldy #1 + 64+1 ; Length byte + max pathname length + zero
addsp: jmp addysp ; Preserves A
ldy #1 + FILENAME_MAX
addsp: jmp addysp ; Preserves A and X

View File

@ -4,7 +4,8 @@
; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp);
;
.import pushax, steaxspidx, incsp1, incsp3, return0
.import pushax, incsp1, incsp3, steaxspidx, return0
.import _mktime_dt
.include "time.inc"
.include "zeropage.inc"
@ -29,42 +30,12 @@ _clock_gettime:
jsr callmli
bcs oserr
; Get date
lda DATELO+1
lsr
php ; Save month msb
cmp #70 ; Year < 70?
bcs :+ ; No, leave alone
adc #100 ; Move 19xx to 20xx
: sta TM + tm::tm_year
lda DATELO
tax ; Save day
plp ; Restore month msb
ror
lsr
lsr
lsr
lsr
beq erange ; [1..12] allows for validity check
tay
dey ; Move [1..12] to [0..11]
sty TM + tm::tm_mon
txa ; Restore day
and #%00011111
sta TM + tm::tm_mday
; Convert DATELO/TIMELO to time_t
lda #<DATELO
ldx #>DATELO
jsr _mktime_dt
; Get time
lda TIMELO+1
sta TM + tm::tm_hour
lda TIMELO
sta TM + tm::tm_min
; Make time_t
lda #<TM
ldx #>TM
jsr _mktime
; Store tv_sec
; Store
ldy #timespec::tv_sec
jsr steaxspidx
@ -74,21 +45,8 @@ _clock_gettime:
; Return success
jmp return0
; Load errno code
erange: lda #ERANGE
; Cleanup stack
jsr incsp3 ; Preserves A
; Set __errno
jmp ___directerrno
; Cleanup stack
oserr: jsr incsp3 ; Preserves A
; Set ___oserror
jmp ___mappederrno
.bss
TM: .tag tm

73
libsrc/apple2/gmtime_dt.s Normal file
View File

@ -0,0 +1,73 @@
;
; Oliver Schmidt, 14.08.2018
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; struct tm * __fastcall__ gmtime_dt(const struct datetime *dt)
;
.export _gmtime_dt, tm_buf
.include "time.inc"
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Convert ProDOS date/time to a struct tm
; source date address in AX
; on stack:
; destination struct
_gmtime_dt:
sta ptr1
stx ptr1+1
; Get time
ldy #$03
lda (ptr1),y
sta tm_buf + tm::tm_hour
dey
lda (ptr1),y
sta tm_buf + tm::tm_min
; Get date
dey
lda (ptr1),y
lsr
php ; Save month msb
cmp #70 ; Year < 70?
bcs :+ ; No, leave alone
adc #100 ; Move 19xx to 20xx
: sta tm_buf + tm::tm_year
dey
lda (ptr1),y
tax ; Save day
plp ; Restore month msb
ror
lsr
lsr
lsr
lsr
beq erange ; [1..12] allows for validity check
tay
dey ; Move [1..12] to [0..11]
sty tm_buf + tm::tm_mon
txa ; Restore day
and #%00011111
sta tm_buf + tm::tm_mday
lda #<tm_buf ; Return pointer to tm_buf
ldx #>tm_buf
rts
; Load errno code and return NULL
erange: lda #ERANGE
sta ___errno
lda #$00
tax
rts
.bss
tm_buf:
.tag tm

37
libsrc/apple2/mktime_dt.s Normal file
View File

@ -0,0 +1,37 @@
;
; Oliver Schmidt, 14.08.2018
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; time_t __fastcall__ mktime_dt(const struct datetime *dt)
;
.import steaxspidx, pushax, incsp2, _gmtime_dt
.import tm_buf
.export _mktime_dt
.include "time.inc"
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Convert ProDOS date/time to UNIX timestamp
; source date address in AX
_mktime_dt:
; Convert to internal tm
jsr _gmtime_dt
cpx #$00
bne :+
cmp #$00
beq err
; Make time_t
: lda #<tm_buf
ldx #>tm_buf
jmp _mktime
err: lda #$00
tax
sta sreg
sta sreg+1
rts

View File

@ -83,8 +83,8 @@ EOF_COUNT = 2
AUX_TYPE .word
STORAGE_TYPE .byte
BLOCKS .word
MODE_DATE .word
MODE_TIME .word
MOD_DATE .word
MOD_TIME .word
CREATE_DATE .word
CREATE_TIME .word
.endstruct
@ -139,3 +139,6 @@ LEVEL := $BF94 ; File level: used in open, flush, close
MACHID := $BF98 ; Machine identification
PFIXPTR := $BF9A ; If = 0, no prefix active
KVERSION:= $BFFF ; Kernel version number
; Max filename length
FILENAME_MAX = 64+1

View File

@ -0,0 +1,33 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
.export mli_file_info
.import pushname, popname, mli_file_info_direct
.import popax
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Calls ProDOS MLI GET_FILE_INFO on the filename
; stored as C string in AX at top of stack
; Returns with carry set on error, and sets errno
mli_file_info:
; Get pathname
jsr popax
jsr pushname
bne oserr
jsr mli_file_info_direct
php ; Save return status
jsr popname ; Preserves A
plp
bcs oserr
rts
oserr:
jsr ___mappederrno
sec
rts

View File

@ -0,0 +1,22 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
.export mli_file_info_direct
.include "zeropage.inc"
.include "mli.inc"
; Calls ProDOS MLI GET_FILE_INFO on the ProDOS style
; filename stored on top of stack
; Returns with carry set on error, and sets errno
mli_file_info_direct:
; Set pushed name
lda sp
ldx sp+1
sta mliparam + MLI::INFO::PATHNAME
stx mliparam + MLI::INFO::PATHNAME+1
; Get file information
lda #GET_INFO_CALL
ldx #GET_INFO_COUNT
jmp callmli

View File

@ -18,6 +18,7 @@
.include "fcntl.inc"
.include "mli.inc"
.include "filedes.inc"
.include "time.inc"
.segment "ONCE"

129
libsrc/apple2/stat.s Normal file
View File

@ -0,0 +1,129 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; int __fastcall__ stat(const char *pathname, struct stat *statbuf);
;
.export _stat
.import __errno, _open,_close
.import mli_file_info
.import popax, pushax, pusha0, incsp2
.include "zeropage.inc"
.include "errno.inc"
.include "fcntl.inc"
.include "filedes.inc"
.include "mli.inc"
.include "stat.inc"
_stat:
; Store statbuf pointer
sta ptr4
sta stbuf
stx ptr4+1
stx stbuf+1
; Clear statbuf
lda #$00
ldy #.sizeof(stat)-1
: sta (ptr4),y
dey
bpl :-
; Reset errno
sta ___errno
; Store pathname
jsr popax
jsr pushax ; Push it back for mli_file_info
jsr pushax ; and for open
jsr mli_file_info
bcc got_info
jmp incsp2 ; Drop filename copy for open
got_info:
; st_dev
lda DEVNUM
lsr ; Shift right to cc65 representation
lsr
lsr
lsr
ldy #stat::st_dev
sta (ptr4),y
; st_mode (S_IFDIR/S_IFREG only)
lda mliparam + MLI::INFO::FILE_TYPE
ldy #stat::st_mode
cmp #$0f
bne is_reg
lda #S_IFDIR
bne set_st_mode
is_reg: lda #S_IFREG
set_st_mode:
sta (ptr4),y
; st_access through st_create_time
ldx #MLI::INFO::ACCESS
ldy #stat::st_access
: lda mliparam,x
sta (ptr4),y
inx
iny
cpy #stat::st_create_time + .sizeof(stat::st_create_time)
bne :-
; st_size
lda #O_RDONLY
jsr pusha0
ldy #$04
jsr _open
cmp #$FF
beq done
pha ; Save file descriptor for closing
; Get ProDOS's REF_NUM from file descriptor
jsr getfd
; Get file information
sta mliparam + MLI::EOF::REF_NUM
lda #GET_EOF_CALL
ldx #EOF_COUNT
jsr callmli
bcs eoferr
; Get struct stat in ptr4 back, open destroyed it
lda stbuf
ldx stbuf+1
sta ptr4
stx ptr4+1
; Store size
ldy #stat::st_size
lda mliparam + MLI::EOF::EOF
sta (ptr4),y
lda mliparam + MLI::EOF::EOF+1
iny
sta (ptr4),y
lda mliparam + MLI::EOF::EOF+2
iny
sta (ptr4),y
; Close file
eoferr:
pla
ldx #$00
jsr _close
; Set return value if we had an error
lda ___errno
beq done
lda #$FF
done:
tax
rts
.bss
stbuf: .res 2

125
libsrc/apple2/statvfs.s Normal file
View File

@ -0,0 +1,125 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; int __fastcall__ statvfs(const char *pathname, struct statvfs *statvfsbuf);
;
.export _statvfs
.import _dio_query_sectsize
.import mli_file_info, pushax, popax, popptr1
.include "zeropage.inc"
.include "apple2.inc"
.include "errno.inc"
.include "mli.inc"
.include "statvfs.inc"
_statvfs:
; Store statbuf
sta ptr4
stx ptr4+1
; Clear statbuf
lda #$00
ldy #.sizeof(statvfs)-1
: sta (ptr4),y
dey
bpl :-
; Store pathname, keeping only volume name
jsr popptr1
ldy #$00
sty vol_sep
lda (ptr1),y
cmp #'/' ; Is the path absolute?
beq :+
lda #EINVAL
jmp ___directerrno
: iny
lda (ptr1),y
beq :+ ; End of string, no other /
cpy #FILENAME_MAX
beq :+ ; Max filename length reached
cmp #'/'
bne :- ; Not a slash, keep looking
sty vol_sep ; Register '/' index
lda #$00
sta (ptr1),y ; Cut pathname at first slash
: lda ptr1
ldx ptr1+1
jsr pushax
jsr mli_file_info
php
ldy vol_sep ; Put slash back in pathname
lda #'/'
sta (ptr1),y
plp
bcc got_info
jmp ___mappederrno
got_info:
; f_fsid
lda DEVNUM
lsr ; Shift right to cc65 representation
lsr
lsr
lsr
ldy #statvfs::f_fsid
sta (ptr4),y
; total number of blocks
lda mliparam + MLI::INFO::AUX_TYPE
ldy #statvfs::f_blocks
sta (ptr4),y
lda mliparam + MLI::INFO::AUX_TYPE+1
iny
sta (ptr4),y
; blocks free & avail
sec
lda mliparam + MLI::INFO::AUX_TYPE
sbc mliparam + MLI::INFO::BLOCKS
ldy #statvfs::f_bfree
sta (ptr4),y
ldy #statvfs::f_bavail
sta (ptr4),y
lda mliparam + MLI::INFO::AUX_TYPE+1
sbc mliparam + MLI::INFO::BLOCKS+1
iny
sta (ptr4),y
ldy #statvfs::f_bfree+1
sta (ptr4),y
; block sizes
jsr _dio_query_sectsize
; low bytes
ldy #statvfs::f_bsize
sta (ptr4),y
ldy #statvfs::f_frsize
sta (ptr4),y
; f_frsize high byte
iny
txa
sta (ptr4),y
; f_bsize high byte
ldy #statvfs::f_bsize+1
sta (ptr4),y
; f_namemax
lda #FILENAME_MAX
ldy #statvfs::f_namemax
sta (ptr4),y
lda #$00
sta ___errno
tax
rts
.bss
vol_sep:.res 1

View File

@ -108,7 +108,7 @@ static unsigned get_dir_entry(char* p_name)
}
/* Field header_pointer directly follows field last_mod */
cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1);
cur_addr = *(unsigned*)(&dirent->d_mtime.time.hour + 1);
dhandle = dio_open(getcurrentdevice());
if (!dhandle) {