You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(35) |
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(37) |
Feb
(10) |
Mar
|
Apr
(2) |
May
(17) |
Jun
(1) |
Jul
(14) |
Aug
(14) |
Sep
(4) |
Oct
|
Nov
(14) |
Dec
(4) |
2005 |
Jan
(6) |
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(92) |
Dec
(12) |
2006 |
Jan
(3) |
Feb
(4) |
Mar
|
Apr
(5) |
May
(3) |
Jun
(15) |
Jul
(3) |
Aug
(1) |
Sep
(29) |
Oct
(1) |
Nov
(6) |
Dec
(5) |
2007 |
Jan
(2) |
Feb
(2) |
Mar
|
Apr
(3) |
May
(14) |
Jun
(2) |
Jul
(16) |
Aug
(73) |
Sep
(12) |
Oct
(9) |
Nov
(27) |
Dec
(3) |
2008 |
Jan
(4) |
Feb
(4) |
Mar
(3) |
Apr
(8) |
May
(23) |
Jun
(4) |
Jul
(1) |
Aug
(3) |
Sep
(7) |
Oct
(5) |
Nov
(1) |
Dec
(1) |
2009 |
Jan
|
Feb
(10) |
Mar
|
Apr
(4) |
May
(4) |
Jun
(10) |
Jul
|
Aug
(1) |
Sep
|
Oct
(7) |
Nov
|
Dec
(1) |
2010 |
Jan
|
Feb
(1) |
Mar
|
Apr
(6) |
May
|
Jun
(3) |
Jul
(11) |
Aug
(1) |
Sep
|
Oct
(15) |
Nov
(1) |
Dec
(5) |
2011 |
Jan
(4) |
Feb
(1) |
Mar
(6) |
Apr
|
May
(22) |
Jun
|
Jul
(8) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
2012 |
Jan
|
Feb
(10) |
Mar
(1) |
Apr
(6) |
May
(27) |
Jun
(48) |
Jul
(30) |
Aug
(4) |
Sep
|
Oct
(3) |
Nov
(1) |
Dec
(11) |
2013 |
Jan
(4) |
Feb
(7) |
Mar
(6) |
Apr
(18) |
May
(28) |
Jun
(20) |
Jul
|
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
(2) |
Dec
(7) |
2014 |
Jan
(3) |
Feb
(2) |
Mar
(4) |
Apr
(9) |
May
(11) |
Jun
(10) |
Jul
|
Aug
(18) |
Sep
(12) |
Oct
(17) |
Nov
(10) |
Dec
(16) |
2015 |
Jan
(5) |
Feb
(1) |
Mar
(5) |
Apr
(4) |
May
(28) |
Jun
(2) |
Jul
|
Aug
|
Sep
(6) |
Oct
|
Nov
(2) |
Dec
(1) |
2016 |
Jan
(14) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
(3) |
Jul
(4) |
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
|
Dec
(1) |
2017 |
Jan
(11) |
Feb
|
Mar
(21) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(2) |
Sep
(4) |
Oct
(4) |
Nov
|
Dec
(1) |
2019 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(13) |
Sep
(4) |
Oct
|
Nov
|
Dec
|
2020 |
Jan
(10) |
Feb
(9) |
Mar
(5) |
Apr
(4) |
May
(3) |
Jun
(18) |
Jul
(4) |
Aug
(2) |
Sep
(20) |
Oct
(2) |
Nov
|
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(1) |
Jun
(2) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
2022 |
Jan
(1) |
Feb
(2) |
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
|
Oct
(1) |
Nov
|
Dec
(1) |
2023 |
Jan
(10) |
Feb
(7) |
Mar
(29) |
Apr
(31) |
May
(29) |
Jun
(34) |
Jul
(3) |
Aug
(24) |
Sep
(22) |
Oct
(10) |
Nov
(38) |
Dec
(27) |
2024 |
Jan
(15) |
Feb
(8) |
Mar
(4) |
Apr
(20) |
May
(33) |
Jun
(18) |
Jul
(15) |
Aug
(23) |
Sep
(26) |
Oct
(32) |
Nov
(6) |
Dec
(4) |
2025 |
Jan
(7) |
Feb
(1) |
Mar
(1) |
Apr
(4) |
May
(46) |
Jun
(19) |
Jul
(26) |
Aug
(17) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Lawrence S. <ljs...@us...> - 2020-02-12 04:39:28
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 956a83c75c40b17197474162beae60d055cf6cbb (commit) from d0187df0c0cc7ce2e7853d8160e1c4eeb3479cb4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 956a83c75c40b17197474162beae60d055cf6cbb Author: Lawrence Sebald <ljs...@us...> Date: Tue Feb 11 23:36:35 2020 -0500 Clean up implicit fallthroughs in the kernel tree. ----------------------------------------------------------------------- Summary of changes: kernel/arch/dreamcast/kernel/gdb_stub.c | 1 + kernel/arch/dreamcast/kernel/init.c | 1 + kernel/net/net_arp.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/kernel/arch/dreamcast/kernel/gdb_stub.c b/kernel/arch/dreamcast/kernel/gdb_stub.c index f837c89..386e58e 100644 --- a/kernel/arch/dreamcast/kernel/gdb_stub.c +++ b/kernel/arch/dreamcast/kernel/gdb_stub.c @@ -819,6 +819,7 @@ gdb_handle_exception(int exceptionVector) { /* sAA..AA Step one instruction from AA..AA(optional) */ case 's': stepping = 1; + __fallthrough; case 'c': { /* tRY, to read optional parameter, pc unchanged if no parm */ if(hexToInt(&ptr, &addr)) diff --git a/kernel/arch/dreamcast/kernel/init.c b/kernel/arch/dreamcast/kernel/init.c index 36392b9..f54e0e6 100644 --- a/kernel/arch/dreamcast/kernel/init.c +++ b/kernel/arch/dreamcast/kernel/init.c @@ -267,6 +267,7 @@ void arch_exit() { switch(arch_exit_path) { default: dbglog(DBG_CRITICAL, "arch: arch_exit_path has invalid value!\n"); + __fallthrough; case ARCH_EXIT_RETURN: arch_return(); break; diff --git a/kernel/net/net_arp.c b/kernel/net/net_arp.c index 360e742..b181497 100644 --- a/kernel/net/net_arp.c +++ b/kernel/net/net_arp.c @@ -288,6 +288,8 @@ int net_arp_input(netif_t *nif, const uint8 *pkt_in, int len) { switch(pkt->opcode[1]) { case 1: /* ARP Request */ net_arp_send(nif, pkt); + __fallthrough; /* Yes, this really should fall through here. */ + case 2: /* ARP Reply */ /* Insert into ARP cache */ net_arp_insert(nif, pkt->hw_send, pkt->pr_send, hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-02-12 04:26:05
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via d0187df0c0cc7ce2e7853d8160e1c4eeb3479cb4 (commit) via 2f38a2fc10c4ada27e0c3e1bd0926c63993f4962 (commit) from 31dae6ebfb38e3f1962fc6c7cfd2bf98c9f5fbd9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d0187df0c0cc7ce2e7853d8160e1c4eeb3479cb4 Author: Lawrence Sebald <ljs...@us...> Date: Tue Feb 11 23:25:10 2020 -0500 Tag all fall-throughs in libppp switch statements explicitly. commit 2f38a2fc10c4ada27e0c3e1bd0926c63993f4962 Author: Lawrence Sebald <ljs...@us...> Date: Tue Feb 11 23:23:45 2020 -0500 Add a __fallthrough attribute to the <kos/cdefs.h> file. This allows us to tag any cases that fall through in a switch statement so that they don't generate implicit fallthrough warnings with newer versions of GCC. ----------------------------------------------------------------------- Summary of changes: addons/libppp/Makefile | 2 +- addons/libppp/ipcp.c | 7 ++++--- addons/libppp/lcp.c | 1 + addons/libppp/ppp.c | 2 +- include/kos/cdefs.h | 10 ++++++++++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/addons/libppp/Makefile b/addons/libppp/Makefile index 64045f4..62018fe 100644 --- a/addons/libppp/Makefile +++ b/addons/libppp/Makefile @@ -5,7 +5,7 @@ TARGET = libppp.a OBJS = ppp.o lcp.o pap.o ipcp.o # Make sure everything compiles nice and cleanly (or not at all). -KOS_CFLAGS += -W -pedantic -std=c99 -I$(KOS_BASE)/kernel/net +KOS_CFLAGS += -W -pedantic -std=c99 -I$(KOS_BASE)/kernel/net -Werror -Wextra # Uncomment the line below to enable all manner of debugging output. KOS_CFLAGS += -DPPP_DEBUG diff --git a/addons/libppp/ipcp.c b/addons/libppp/ipcp.c index 0dce932..d30070f 100644 --- a/addons/libppp/ipcp.c +++ b/addons/libppp/ipcp.c @@ -177,7 +177,7 @@ static int ipcp_handle_configure_req(ppp_protocol_t *self, case PPP_STATE_OPENED: /* XXXX: This layer down. */ - /* Fall through... */ + __fallthrough; case PPP_STATE_STOPPED: ipcp_send_client_cfg(self, 0); @@ -390,7 +390,7 @@ static int ipcp_handle_configure_ack(ppp_protocol_t *self, case PPP_STATE_OPENED: /* Uh oh... Something's gone wrong. */ /* XXXX: This layer down. */ - /* Fall through... */ + __fallthrough; case PPP_STATE_ACK_RECEIVED: /* Well, this isn't good... Resend the configure request and back @@ -440,7 +440,7 @@ static int ipcp_handle_configure_nak(ppp_protocol_t *self, case PPP_STATE_OPENED: /* XXXX: This layer down. */ - /* Fall through... */ + __fallthrough; case PPP_STATE_REQUEST_SENT: case PPP_STATE_ACK_RECEIVED: @@ -555,6 +555,7 @@ static int ipcp_handle_terminate_req(ppp_protocol_t *self, ipcp_state.resend_pkt = NULL; ipcp_state.resend_timeout = NULL; ipcp_state.state = PPP_STATE_STOPPING; + __fallthrough; default: return -1; diff --git a/addons/libppp/lcp.c b/addons/libppp/lcp.c index a8cfce1..220c70f 100644 --- a/addons/libppp/lcp.c +++ b/addons/libppp/lcp.c @@ -843,6 +843,7 @@ static int lcp_handle_terminate_req(ppp_protocol_t *self, const lcp_pkt_t *pkt, lcp_state.resend_pkt = NULL; lcp_state.resend_timeout = NULL; lcp_state.state = PPP_STATE_STOPPING; + __fallthrough; default: return -1; diff --git a/addons/libppp/ppp.c b/addons/libppp/ppp.c index 94c7b5e..2ede6f2 100644 --- a/addons/libppp/ppp.c +++ b/addons/libppp/ppp.c @@ -362,7 +362,7 @@ void *ppp_main(void *arg) { hopefully compressed. Check the flags set by LCP to make sure. */ expect = EXPECT_DATA; - /* Fall through... */ + __fallthrough; } case EXPECT_DATA: diff --git a/include/kos/cdefs.h b/include/kos/cdefs.h index 01e173e..4052cb3 100644 --- a/include/kos/cdefs.h +++ b/include/kos/cdefs.h @@ -2,6 +2,7 @@ kos/cdefs.h Copyright (C) 2002, 2004 Dan Potter + Copyright (C) 2020 Lawrence Sebald Based loosely around some stuff in BSD's sys/cdefs.h */ @@ -13,6 +14,7 @@ shorter forms for use in programs (to aid in optimization, mainly). \author Dan Potter + \author Lawrence Sebald */ #ifndef __KOS_CDEFS_H @@ -101,6 +103,14 @@ __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) #endif +#if __GNUC__ >= 7 +/** \brief Identify a case statement that is expected to fall through to the + statement underneath it. */ +#define __fallthrough __attribute__((__fallthrough__)) +#else +#define __fallthrough /* Fall through */ +#endif + /* GCC macros for special cases */ /* #if __GNUC__ == */ hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-02-11 14:17:02
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 31dae6ebfb38e3f1962fc6c7cfd2bf98c9f5fbd9 (commit) from 2b7068ff7221300a23d147d05893bcf4623be03a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 31dae6ebfb38e3f1962fc6c7cfd2bf98c9f5fbd9 Author: Lawrence Sebald <ljs...@us...> Date: Tue Feb 11 09:16:13 2020 -0500 Fix redefinition of BYTE_ORDER between <arch/types.h> and <arch/byteorder.h>. ----------------------------------------------------------------------- Summary of changes: kernel/arch/dreamcast/include/arch/byteorder.h | 5 +++++ kernel/arch/dreamcast/include/arch/types.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/arch/dreamcast/include/arch/byteorder.h b/kernel/arch/dreamcast/include/arch/byteorder.h index 9b5ffea..fbbb204 100644 --- a/kernel/arch/dreamcast/include/arch/byteorder.h +++ b/kernel/arch/dreamcast/include/arch/byteorder.h @@ -26,6 +26,11 @@ __BEGIN_DECLS #include <sys/_types.h> +#ifdef BYTE_ORDER +/* If we've included <arch/types.h>, this might already be defined... */ +#undef BYTE_ORDER +#endif + /** \brief Define the byte-order of the platform in use. */ #define BYTE_ORDER LITTLE_ENDIAN diff --git a/kernel/arch/dreamcast/include/arch/types.h b/kernel/arch/dreamcast/include/arch/types.h index 83261da..6a47a79 100644 --- a/kernel/arch/dreamcast/include/arch/types.h +++ b/kernel/arch/dreamcast/include/arch/types.h @@ -80,6 +80,7 @@ typedef int handle_t; /**< \brief Generic "handle" type */ typedef handle_t tid_t; /**< \brief Thread ID type */ typedef handle_t prio_t; /**< \brief Priority value type */ +#ifndef BYTE_ORDER /* Make sure to pull in the base endianness defines... */ #ifndef LITTLE_ENDIAN #include <sys/_types.h> @@ -87,8 +88,8 @@ typedef handle_t prio_t; /**< \brief Priority value type */ /** \brief Endianness definition -- Little Endian */ #define BYTE_ORDER LITTLE_ENDIAN +#endif __END_DECLS #endif /* __ARCH_TYPES_H */ - hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-02-11 13:27:02
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 2b7068ff7221300a23d147d05893bcf4623be03a (commit) from cbf93f3411e39826a58bb33632a6663ef005d152 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2b7068ff7221300a23d147d05893bcf4623be03a Author: Lawrence Sebald <ljs...@us...> Date: Tue Feb 11 08:26:41 2020 -0500 Fix init.c for GCC 4.x again. ----------------------------------------------------------------------- Summary of changes: kernel/arch/dreamcast/kernel/init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/arch/dreamcast/kernel/init.c b/kernel/arch/dreamcast/kernel/init.c index 719913c..36392b9 100644 --- a/kernel/arch/dreamcast/kernel/init.c +++ b/kernel/arch/dreamcast/kernel/init.c @@ -24,17 +24,17 @@ extern int _bss_start, end; void _atexit_call_all(); +#if __GNUC__ == 4 +#define _init init +#define _fini fini +#endif + #if __GNUC__ >= 4 void _init(void); void _fini(void); void __verify_newlib_patch(); #endif -#if __GNUC__ == 4 -#define _init init -#define _fini fini -#endif - int main(int argc, char **argv); uint32 _fs_dclsocket_get_ip(void); hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-30 12:46:26
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via cbf93f3411e39826a58bb33632a6663ef005d152 (commit) from d8467393f33411adaeb2b8328346c5b0042ea8b2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cbf93f3411e39826a58bb33632a6663ef005d152 Author: Lawrence Sebald <ljs...@us...> Date: Thu Jan 30 07:46:05 2020 -0500 Add sched_yield function to libc/koslib. ----------------------------------------------------------------------- Summary of changes: kernel/libc/koslib/Makefile | 3 ++- kernel/libc/koslib/sched_yield.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 kernel/libc/koslib/sched_yield.c diff --git a/kernel/libc/koslib/Makefile b/kernel/libc/koslib/Makefile index c8af8d2..dc996d7 100644 --- a/kernel/libc/koslib/Makefile +++ b/kernel/libc/koslib/Makefile @@ -13,7 +13,8 @@ OBJS = abort.o byteorder.o memset2.o memset4.o memcpy2.o memcpy4.o \ telldir.o usleep.o inet_addr.o realpath.o getcwd.o chdir.o mkdir.o \ creat.o sleep.o rmdir.o rename.o inet_pton.o inet_ntop.o \ inet_ntoa.o inet_aton.o poll.o select.o symlink.o readlink.o \ - gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o basename.o dirname.o + gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o basename.o dirname.o \ + sched_yield.o GCC_MAJORMINOR = $(basename $(KOS_GCCVER)) GCC_MAJOR = $(basename $(GCC_MAJORMINOR)) diff --git a/kernel/libc/koslib/sched_yield.c b/kernel/libc/koslib/sched_yield.c new file mode 100644 index 0000000..3e3ec27 --- /dev/null +++ b/kernel/libc/koslib/sched_yield.c @@ -0,0 +1,12 @@ +/* KallistiOS ##version## + + sched_yield.c + Copyright (C) 2020 Lawrence Sebald +*/ + +#include <kos/thread.h> + +int sched_yield(void) { + thd_pass(); + return 0; +} hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-28 02:26:56
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via d8467393f33411adaeb2b8328346c5b0042ea8b2 (commit) from 93175a99ec9211d7e1c6983be93547bb0c418fea (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d8467393f33411adaeb2b8328346c5b0042ea8b2 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 21:26:12 2020 -0500 Add experimental dc-chain patches for GCC 9.2.0 and Newlib 3.3.0. These are by no means recommended for general use yet. ----------------------------------------------------------------------- Summary of changes: .../{gcc-4.8.1-kos.diff => gcc-9.2.0-kos.diff} | 1251 ++++++-------------- ...newlib-2.0.0-kos.diff => newlib-3.3.0-kos.diff} | 150 ++- 2 files changed, 423 insertions(+), 978 deletions(-) copy utils/dc-chain/patches/{gcc-4.8.1-kos.diff => gcc-9.2.0-kos.diff} (60%) copy utils/dc-chain/patches/{newlib-2.0.0-kos.diff => newlib-3.3.0-kos.diff} (71%) diff --git a/utils/dc-chain/patches/gcc-4.8.1-kos.diff b/utils/dc-chain/patches/gcc-9.2.0-kos.diff similarity index 60% copy from utils/dc-chain/patches/gcc-4.8.1-kos.diff copy to utils/dc-chain/patches/gcc-9.2.0-kos.diff index 8f581db..2c2d80b 100644 --- a/utils/dc-chain/patches/gcc-4.8.1-kos.diff +++ b/utils/dc-chain/patches/gcc-9.2.0-kos.diff @@ -1,7 +1,7 @@ -diff -ruN gcc-4.8.1/gcc/configure gcc-4.8.1-kos/gcc/configure ---- gcc-4.8.1/gcc/configure 2013-05-08 07:36:36.000000000 -0400 -+++ gcc-4.8.1-kos/gcc/configure 2013-10-09 14:49:41.000000000 -0400 -@@ -11107,7 +11107,7 @@ +diff -ruN gcc-9.2.0/gcc/configure gcc-9.2.0-kos/gcc/configure +--- gcc-9.2.0/gcc/configure 2019-06-26 05:15:46.000000000 -0400 ++++ gcc-9.2.0-kos/gcc/configure 2020-01-26 16:53:07.946777000 -0500 +@@ -11861,7 +11861,7 @@ target_thread_file='single' ;; aix | dce | lynx | mipssde | posix | rtems | \ @@ -10,11 +10,11 @@ diff -ruN gcc-4.8.1/gcc/configure gcc-4.8.1-kos/gcc/configure target_thread_file=${enable_threads} ;; *) -diff -ruN gcc-4.8.1/libgcc/config/sh/crt1.S gcc-4.8.1-kos/libgcc/config/sh/crt1.S ---- gcc-4.8.1/libgcc/config/sh/crt1.S 2013-02-04 14:06:20.000000000 -0500 -+++ gcc-4.8.1-kos/libgcc/config/sh/crt1.S 2013-10-09 15:02:12.000000000 -0400 -@@ -1,1368 +1,202 @@ --/* Copyright (C) 2000-2013 Free Software Foundation, Inc. +diff -ruN gcc-9.2.0/libgcc/config/sh/crt1.S gcc-9.2.0-kos/libgcc/config/sh/crt1.S +--- gcc-9.2.0/libgcc/config/sh/crt1.S 2019-01-01 07:31:55.000000000 -0500 ++++ gcc-9.2.0-kos/libgcc/config/sh/crt1.S 2020-01-26 23:46:01.472675000 -0500 +@@ -1,724 +1,197 @@ +-/* Copyright (C) 2000-2019 Free Software Foundation, Inc. - This file was pretty much copied from newlib. +! KallistiOS ##version## +! @@ -56,6 +56,7 @@ diff -ruN gcc-4.8.1/libgcc/config/sh/crt1.S gcc-4.8.1-kos/libgcc/config/sh/crt1. -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - +-#include "crt.h" - -#ifdef MMU_SUPPORT - /* Section used for exception/timer interrupt stack area */ @@ -71,648 +72,6 @@ diff -ruN gcc-4.8.1/libgcc/config/sh/crt1.S gcc-4.8.1-kos/libgcc/config/sh/crt1. - /* ;---------------------------------------- - Normal newlib crt1.S */ - --#ifdef __SH5__ -- .section .data,"aw" -- .global ___data --___data: -- -- .section .rodata,"a" -- .global ___rodata --___rodata: -- --#define ICCR_BASE 0x01600000 --#define OCCR_BASE 0x01e00000 --#define MMUIR_BASE 0x00000000 --#define MMUDR_BASE 0x00800000 -- --#define PTE_ENABLED 1 --#define PTE_DISABLED 0 -- --#define PTE_SHARED (1 << 1) --#define PTE_NOT_SHARED 0 -- --#define PTE_CB_UNCACHEABLE 0 --#define PTE_CB_DEVICE 1 --#define PTE_CB_CACHEABLE_WB 2 --#define PTE_CB_CACHEABLE_WT 3 -- --#define PTE_SZ_4KB (0 << 3) --#define PTE_SZ_64KB (1 << 3) --#define PTE_SZ_1MB (2 << 3) --#define PTE_SZ_512MB (3 << 3) -- --#define PTE_PRR (1 << 6) --#define PTE_PRX (1 << 7) --#define PTE_PRW (1 << 8) --#define PTE_PRU (1 << 9) -- --#define SR_MMU_BIT 31 --#define SR_BL_BIT 28 -- --#define ALIGN_4KB (0xfff) --#define ALIGN_1MB (0xfffff) --#define ALIGN_512MB (0x1fffffff) -- --#define DYNACON_BASE 0x0f000000 --#define DM_CB_DLINK_BASE 0x0c000000 --#define DM_DB_DLINK_BASE 0x0b000000 -- --#define FEMI_AREA_0 0x00000000 --#define FEMI_AREA_1 0x04000000 --#define FEMI_AREA_2 0x05000000 --#define FEMI_AREA_3 0x06000000 --#define FEMI_AREA_4 0x07000000 --#define FEMI_CB 0x08000000 -- --#define EMI_BASE 0X80000000 -- --#define DMA_BASE 0X0e000000 -- --#define CPU_BASE 0X0d000000 -- --#define PERIPH_BASE 0X09000000 --#define DMAC_BASE 0x0e000000 --#define INTC_BASE 0x0a000000 --#define CPRC_BASE 0x0a010000 --#define TMU_BASE 0x0a020000 --#define SCIF_BASE 0x0a030000 --#define RTC_BASE 0x0a040000 -- -- -- --#define LOAD_CONST32(val, reg) \ -- movi ((val) >> 16) & 65535, reg; \ -- shori (val) & 65535, reg -- --#define LOAD_PTEH_VAL(sym, align, bits, scratch_reg, reg) \ -- LOAD_ADDR (sym, reg); \ -- LOAD_CONST32 ((align), scratch_reg); \ -- andc reg, scratch_reg, reg; \ -- LOAD_CONST32 ((bits), scratch_reg); \ -- or reg, scratch_reg, reg -- --#define LOAD_PTEL_VAL(sym, align, bits, scratch_reg, reg) \ -- LOAD_ADDR (sym, reg); \ -- LOAD_CONST32 ((align), scratch_reg); \ -- andc reg, scratch_reg, reg; \ -- LOAD_CONST32 ((bits), scratch_reg); \ -- or reg, scratch_reg, reg -- --#define SET_PTE(pte_addr_reg, pteh_val_reg, ptel_val_reg) \ -- putcfg pte_addr_reg, 0, r63; \ -- putcfg pte_addr_reg, 1, ptel_val_reg; \ -- putcfg pte_addr_reg, 0, pteh_val_reg -- --#if __SH5__ == 64 -- .section .text,"ax" --#define LOAD_ADDR(sym, reg) \ -- movi (sym >> 48) & 65535, reg; \ -- shori (sym >> 32) & 65535, reg; \ -- shori (sym >> 16) & 65535, reg; \ -- shori sym & 65535, reg --#else -- .mode SHmedia -- .section .text..SHmedia32,"ax" --#define LOAD_ADDR(sym, reg) \ -- movi (sym >> 16) & 65535, reg; \ -- shori sym & 65535, reg --#endif -- .global start --start: -- LOAD_ADDR (_stack, r15) -- --#ifdef MMU_SUPPORT -- ! Set up the VM using the MMU and caches -- -- ! .vm_ep is first instruction to execute -- ! after VM initialization -- pt/l .vm_ep, tr1 -- -- ! Configure instruction cache (ICCR) -- movi 3, r2 -- movi 0, r3 -- LOAD_ADDR (ICCR_BASE, r1) -- putcfg r1, 0, r2 -- putcfg r1, 1, r3 -- -- ! movi 7, r2 ! write through -- ! Configure operand cache (OCCR) -- LOAD_ADDR (OCCR_BASE, r1) -- putcfg r1, 0, r2 -- putcfg r1, 1, r3 -- -- ! Disable all PTE translations -- LOAD_ADDR (MMUIR_BASE, r1) -- LOAD_ADDR (MMUDR_BASE, r2) -- movi 64, r3 -- pt/l .disable_ptes_loop, tr0 --.disable_ptes_loop: -- putcfg r1, 0, r63 -- putcfg r2, 0, r63 -- addi r1, 16, r1 -- addi r2, 16, r2 -- addi r3, -1, r3 -- bgt r3, r63, tr0 -- -- LOAD_ADDR (MMUIR_BASE, r1) -- -- ! FEMI instruction mappings -- ! Area 0 - 1Mb cacheable at 0x00000000 -- ! Area 1 - None -- ! Area 2 - 1Mb cacheable at 0x05000000 -- ! - 1Mb cacheable at 0x05100000 -- ! Area 3 - None -- ! Area 4 - None -- -- ! Map a 1Mb page for instructions at 0x00000000 -- LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1Mb page for instructions at 0x05000000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1Mb page for instructions at 0x05100000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 512M page for instructions at EMI base -- addi r1, 16, r1 -- LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRX | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for instructions at DM_DB_DLINK_BASE -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRX | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- LOAD_ADDR (MMUDR_BASE, r1) -- -- ! FEMI data mappings -- ! Area 0 - 1Mb cacheable at 0x00000000 -- ! Area 1 - 1Mb device at 0x04000000 -- ! Area 2 - 1Mb cacheable at 0x05000000 -- ! - 1Mb cacheable at 0x05100000 -- ! Area 3 - None -- ! Area 4 - None -- ! CB - 1Mb device at 0x08000000 -- -- ! Map a 1Mb page for data at 0x00000000 -- LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1Mb page for data at 0x04000000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1Mb page for data at 0x05000000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1Mb page for data at 0x05100000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for registers at 0x08000000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL (FEMI_CB, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (FEMI_CB, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 512M page for data at EMI -- addi r1, 16, r1 -- LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for DYNACON at DYNACON_BASE -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DYNACON_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DYNACON_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for instructions at DM_DB_DLINK_BASE -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for data at DM_DB_DLINK_BASE+0x1000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_CB_UNCACHEABLE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for stack DM_DB_DLINK_BASE+0x2000 -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK -- ! 0x0c000000 - 0x0c0fffff -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK -- ! 0x0c100000 - 0x0c1fffff -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK -- ! 0x0c200000 - 0x0c2fffff -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK -- ! 0x0c400000 - 0x0c4fffff -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK -- ! 0x0c800000 - 0x0c8fffff -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map a 4K page for DMA control registers -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DMA_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DMA_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map lots of 4K pages for peripherals -- -- ! /* peripheral */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (PERIPH_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (PERIPH_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* dmac */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (DMAC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (DMAC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* intc */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (INTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (INTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* rtc */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (RTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (RTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* dmac */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (TMU_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (TMU_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* scif */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (SCIF_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (SCIF_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- ! /* cprc */ -- addi r1, 16, r1 -- LOAD_PTEH_VAL (CPRC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (CPRC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Map CPU WPC registers -- addi r1, 16, r1 -- LOAD_PTEH_VAL (CPU_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL (CPU_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- addi r1, 16, r1 -- -- LOAD_PTEH_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- addi r1, 16, r1 -- LOAD_PTEH_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2) -- LOAD_PTEL_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3) -- SET_PTE (r1, r2, r3) -- -- ! Switch over to virtual addressing and enabled cache -- getcon sr, r1 -- movi 1, r2 -- shlli r2, SR_BL_BIT, r2 -- or r1, r2, r1 -- putcon r1, ssr -- getcon sr, r1 -- movi 1, r2 -- shlli r2, SR_MMU_BIT, r2 -- or r1, r2, r1 -- putcon r1, ssr -- gettr tr1, r1 -- putcon r1, spc -- synco -- rte -- -- ! VM entry point. From now on, we are in VM mode. --.vm_ep: -- -- ! Install the trap handler, by seeding vbr with the -- ! correct value, and by assigning sr.bl = 0. -- -- LOAD_ADDR (vbr_start, r1) -- putcon r1, vbr -- movi ~(1<<28), r1 -- getcon sr, r2 -- and r1, r2, r2 -- putcon r2, sr --#endif /* MMU_SUPPORT */ -- -- pt/l .Lzero_bss_loop, tr0 -- pt/l _init, tr5 -- pt/l ___setup_argv_and_call_main, tr6 -- pt/l _exit, tr7 -- -- ! zero out bss -- LOAD_ADDR (_edata, r0) -- LOAD_ADDR (_end, r1) --.Lzero_bss_loop: -- stx.q r0, r63, r63 -- addi r0, 8, r0 -- bgt/l r1, r0, tr0 -- -- LOAD_ADDR (___data, r26) -- LOAD_ADDR (___rodata, r27) -- --#ifdef __SH_FPU_ANY__ -- getcon sr, r0 -- ! enable the FP unit, by resetting SR.FD -- ! also zero out SR.FR, SR.SZ and SR.PR, as mandated by the ABI -- movi 0, r1 -- shori 0xf000, r1 -- andc r0, r1, r0 -- putcon r0, sr --#if __SH5__ == 32 -- pt/l ___set_fpscr, tr0 -- movi 0, r4 -- blink tr0, r18 --#endif --#endif -- -- ! arrange for exit to call fini -- pt/l _atexit, tr1 -- LOAD_ADDR (_fini, r2) -- blink tr1, r18 -- -- ! call init -- blink tr5, r18 -- -- ! call the mainline -- blink tr6, r18 -- -- ! call exit -- blink tr7, r18 -- ! We should never return from _exit but in case we do we would enter the -- ! the following tight loop. This avoids executing any data that might follow. --limbo: -- pt/l limbo, tr0 -- blink tr0, r63 -- --#ifdef MMU_SUPPORT -- ! All these traps are handled in the same place. -- .balign 256 --vbr_start: -- pt/l handler, tr0 ! tr0 trashed. -- blink tr0, r63 -- .balign 256 --vbr_100: -- pt/l handler, tr0 ! tr0 trashed. -- blink tr0, r63 --vbr_100_end: -- .balign 256 --vbr_200: -- pt/l handler, tr0 ! tr0 trashed. -- blink tr0, r63 -- .balign 256 --vbr_300: -- pt/l handler, tr0 ! tr0 trashed. -- blink tr0, r63 -- .balign 256 --vbr_400: ! Should be at vbr+0x400 --handler: -- /* If the trap handler is there call it */ -- LOAD_ADDR (__superh_trap_handler, r2) -- pta chandler,tr2 -- beq r2, r63, tr2 /* If zero, ie not present branch around to chandler */ ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-28 00:25:53
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 93175a99ec9211d7e1c6983be93547bb0c418fea (commit) from 9cb643e2b16366ffe3a03bd0597670f1ef7b4a63 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 93175a99ec9211d7e1c6983be93547bb0c418fea Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 19:25:30 2020 -0500 Only build crtend/crtbegin on GCC 3... Not everything except GCC 4. ----------------------------------------------------------------------- Summary of changes: kernel/libc/koslib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/libc/koslib/Makefile b/kernel/libc/koslib/Makefile index 03a5239..c8af8d2 100644 --- a/kernel/libc/koslib/Makefile +++ b/kernel/libc/koslib/Makefile @@ -18,7 +18,7 @@ OBJS = abort.o byteorder.o memset2.o memset4.o memcpy2.o memcpy4.o \ GCC_MAJORMINOR = $(basename $(KOS_GCCVER)) GCC_MAJOR = $(basename $(GCC_MAJORMINOR)) -ifneq ($(strip $(GCC_MAJOR)), 4) +ifeq ($(strip $(GCC_MAJOR)), 3) OBJS += crtbegin.o crtend.o endif hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-27 16:20:49
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 9cb643e2b16366ffe3a03bd0597670f1ef7b4a63 (commit) via ed113ce4696245151b2c972f46f62e9aa0a36281 (commit) via 83397cba5c03e855b107bef6f8cdebbe04321c93 (commit) via 84320a07c8af05d489e040bbbc44c4c84446bc35 (commit) via 840910462355f1238c0c34f21a64a0498b1b5025 (commit) via 4bd0bd3096537747281b11456839af182ec25489 (commit) via 7adf8f9b05ca668b13c0f20be8bab028d7936f66 (commit) via 37ac7f857b6829135acecbf99bc9d74175c78a01 (commit) via 41be39c6aedb3d24866216942d9da54d7faaf8d9 (commit) from 1c39674de761329d9794e9cee0a9eabfbe4beb53 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9cb643e2b16366ffe3a03bd0597670f1ef7b4a63 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 11:18:09 2020 -0500 Apparently init and fini got renamed at some point. commit ed113ce4696245151b2c972f46f62e9aa0a36281 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 11:02:39 2020 -0500 Don't cause circular includes to break things badly. commit 83397cba5c03e855b107bef6f8cdebbe04321c93 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 11:02:22 2020 -0500 Remove -Werror from addons. commit 84320a07c8af05d489e040bbbc44c4c84446bc35 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:42:43 2020 -0500 Don't use __FUNCTION__ in assert in standard-compliant mode. commit 840910462355f1238c0c34f21a64a0498b1b5025 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:31:42 2020 -0500 Add fd_set and friends to sys/select.h, as it is no longer defined in sys/types.h in Newlib. commit 4bd0bd3096537747281b11456839af182ec25489 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:31:10 2020 -0500 Add types to sys/_types.h that newer versions of Newlib expect. commit 7adf8f9b05ca668b13c0f20be8bab028d7936f66 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:30:34 2020 -0500 Add __assert_func function. commit 37ac7f857b6829135acecbf99bc9d74175c78a01 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:29:41 2020 -0500 Get rid of the use of _EXFUN. Newlib removed this macro in newer versions, so get rid of it. commit 41be39c6aedb3d24866216942d9da54d7faaf8d9 Author: Lawrence Sebald <ljs...@us...> Date: Mon Jan 27 10:27:53 2020 -0500 Rename st_*time members in fs_dcload's stat structure. This is to solve some problems compiling with newer versions of newlib, as st_atime and friends are all declared as macros in <sys/stat.h> now. Thus, using them as variable names in the stat structure like this breaks things. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/Makefile | 2 +- addons/libppp/Makefile | 2 +- include/assert.h | 21 +++- include/pthread.h | 168 +++++++++++---------------- include/sys/_types.h | 58 +++++++++ include/sys/select.h | 40 ++++++- kernel/arch/dreamcast/fs/fs_dcload.c | 8 +- kernel/arch/dreamcast/fs/fs_dclsocket.c | 8 +- kernel/arch/dreamcast/include/dc/fs_dcload.h | 8 +- kernel/arch/dreamcast/kernel/init.c | 13 ++- kernel/libc/koslib/assert.c | 3 + kernel/libc/koslib/gethostbyname.c | 2 +- 12 files changed, 204 insertions(+), 129 deletions(-) diff --git a/addons/libkosfat/Makefile b/addons/libkosfat/Makefile index 66b6667..de4d0ae 100644 --- a/addons/libkosfat/Makefile +++ b/addons/libkosfat/Makefile @@ -5,6 +5,6 @@ TARGET = libkosfat.a OBJS = fat.o bpb.o fatfs.o directory.o ucs.o fs_fat.o # Make sure everything comiles nice and cleanly (or not at all). -KOS_CFLAGS += -W -Wextra -pedantic -std=c99 -Werror +KOS_CFLAGS += -W -Wextra -pedantic -std=c99 include $(KOS_BASE)/addons/Makefile.prefab diff --git a/addons/libppp/Makefile b/addons/libppp/Makefile index 04d897e..64045f4 100644 --- a/addons/libppp/Makefile +++ b/addons/libppp/Makefile @@ -5,7 +5,7 @@ TARGET = libppp.a OBJS = ppp.o lcp.o pap.o ipcp.o # Make sure everything compiles nice and cleanly (or not at all). -KOS_CFLAGS += -W -pedantic -Werror -std=c99 -I$(KOS_BASE)/kernel/net +KOS_CFLAGS += -W -pedantic -std=c99 -I$(KOS_BASE)/kernel/net # Uncomment the line below to enable all manner of debugging output. KOS_CFLAGS += -DPPP_DEBUG diff --git a/include/assert.h b/include/assert.h index 583992e..9c8a66a 100644 --- a/include/assert.h +++ b/include/assert.h @@ -26,12 +26,26 @@ __BEGIN_DECLS error message. */ #define _assert(e) assert(e) -/* __FUNCTION__ is not ANSI, it's GCC, but we depend on GCC anyway.. */ #ifdef NDEBUG # define assert(e) ((void)0) # define assert_msg(e, m) ((void)0) #else +/* This bit of magic borrowed from Newlib's assert.h... */ +/* \cond */ +#ifndef __ASSERT_FUNC +#if defined(__cplusplus) +# define __ASSERT_FUNC __PRETTY_FUNCTION__ +#elif __STDC_VERSION__ >= 199901L +# define __ASSERT_FUNC __func__ +#elif __GNUC__ >= 2 +# define __ASSERT_FUNC __FUNCTION__ +#else +# define __ASSERT_FUNC ((char *)0) +#endif +#endif +/* \endcond */ + /** \brief Standard C assertion macro. This macro does a standard C assertion, wherein the expression is evaluated, @@ -42,7 +56,7 @@ __BEGIN_DECLS \param e A value or expression to be evaluated as true or false. */ -# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, NULL, __FUNCTION__)) +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, NULL, __ASSERT_FUNC)) /** \brief assert() with a custom message. @@ -53,7 +67,7 @@ __BEGIN_DECLS false. \param m A message (const char *). */ -# define assert_msg(e, m) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, m, __FUNCTION__)) +# define assert_msg(e, m) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, m, __ASSERT_FUNC)) #endif /* \cond */ @@ -93,4 +107,3 @@ assert_handler_t assert_set_handler(assert_handler_t hnd); __END_DECLS #endif /* __ASSERT_H */ - diff --git a/include/pthread.h b/include/pthread.h index 300adbd..194eed3 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -66,18 +66,15 @@ extern "C" { /* Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 */ - int _EXFUN(pthread_mutexattr_init, (pthread_mutexattr_t *attr)); - int _EXFUN(pthread_mutexattr_destroy, (pthread_mutexattr_t *attr)); - int _EXFUN(pthread_mutexattr_getpshared, - (const pthread_mutexattr_t *attr, int *pshared)); - int _EXFUN(pthread_mutexattr_setpshared, - (pthread_mutexattr_t *attr, int pshared)); + int pthread_mutexattr_init(pthread_mutexattr_t *attr); + int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); + int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared); + int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); /* Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 */ - int _EXFUN(pthread_mutex_init, - (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)); - int _EXFUN(pthread_mutex_destroy, (pthread_mutex_t *mutex)); + int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); + int pthread_mutex_destroy(pthread_mutex_t *mutex); /* This is used to statically initialize a pthread_mutex_t. Example: @@ -89,31 +86,27 @@ extern "C" { /* Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 */ - int _EXFUN(pthread_mutex_lock, (pthread_mutex_t *mutex)); - int _EXFUN(pthread_mutex_trylock, (pthread_mutex_t *mutex)); - int _EXFUN(pthread_mutex_unlock, (pthread_mutex_t *mutex)); + int pthread_mutex_lock(pthread_mutex_t *mutex); + int pthread_mutex_trylock(pthread_mutex_t *mutex); + int pthread_mutex_unlock(pthread_mutex_t *mutex); #if defined(_POSIX_TIMEOUTS) - int _EXFUN(pthread_mutex_timedlock, - (pthread_mutex_t *mutex, const struct timespec *timeout)); + int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout); #endif /* _POSIX_TIMEOUTS */ /* Condition Variable Initialization Attributes, P1003.1c/Draft 10, p. 96 */ - int _EXFUN(pthread_condattr_init, (pthread_condattr_t *attr)); - int _EXFUN(pthread_condattr_destroy, (pthread_condattr_t *attr)); - int _EXFUN(pthread_condattr_getpshared, - (const pthread_condattr_t *attr, int *pshared)); - int _EXFUN(pthread_condattr_setpshared, - (pthread_condattr_t *attr, int pshared)); + int pthread_condattr_init(pthread_condattr_t *attr); + int pthread_condattr_destroy(pthread_condattr_t *attr); + int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared); + int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared); /* Initializing and Destroying a Condition Variable, P1003.1c/Draft 10, p. 87 */ - int _EXFUN(pthread_cond_init, - (pthread_cond_t *cond, const pthread_condattr_t *attr)); - int _EXFUN(pthread_cond_destroy, (pthread_cond_t *cond)); + int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); + int pthread_cond_destroy(pthread_cond_t *cond); /* This is used to statically initialize a pthread_cond_t. Example: @@ -124,49 +117,38 @@ extern "C" { /* Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 */ - int _EXFUN(pthread_cond_signal, (pthread_cond_t *cond)); - int _EXFUN(pthread_cond_broadcast, (pthread_cond_t *cond)); + int pthread_cond_signal(pthread_cond_t *cond); + int pthread_cond_broadcast(pthread_cond_t *cond); /* Waiting on a Condition, P1003.1c/Draft 10, p. 105 */ - int _EXFUN(pthread_cond_wait, - (pthread_cond_t *cond, pthread_mutex_t *mutex)); + int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); - int _EXFUN(pthread_cond_timedwait, - (pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec *abstime)); + int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime); #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) /* Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 */ - int _EXFUN(pthread_attr_setscope, - (pthread_attr_t *attr, int contentionscope)); - int _EXFUN(pthread_attr_getscope, - (const pthread_attr_t *attr, int *contentionscope)); - int _EXFUN(pthread_attr_setinheritsched, - (pthread_attr_t *attr, int inheritsched)); - int _EXFUN(pthread_attr_getinheritsched, - (const pthread_attr_t *attr, int *inheritsched)); - int _EXFUN(pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy)); - int _EXFUN(pthread_attr_getschedpolicy, - (const pthread_attr_t *attr, int *policy)); + int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope); + int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope); + int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); + int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched); + int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); + int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy); #endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ - int _EXFUN(pthread_attr_setschedparam, - (pthread_attr_t *attr, const struct sched_param *param)); - int _EXFUN(pthread_attr_getschedparam, - (const pthread_attr_t *attr, struct sched_param *param)); + int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); + int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param); #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) /* Dynamic Thread Scheduling Parameters Access, P1003.1c/Draft 10, p. 124 */ - int _EXFUN(pthread_getschedparam, - (pthread_t thread, int *policy, struct sched_param *param)); - int _EXFUN(pthread_setschedparam, - (pthread_t thread, int policy, struct sched_param *param)); + int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param); + int pthread_setschedparam(pthread_t thread, int policy, struct sched_param *param); #endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ @@ -174,14 +156,10 @@ extern "C" { /* Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 */ - int _EXFUN(pthread_mutexattr_setprotocol, - (pthread_mutexattr_t *attr, int protocol)); - int _EXFUN(pthread_mutexattr_getprotocol, - (const pthread_mutexattr_t *attr, int *protocol)); - int _EXFUN(pthread_mutexattr_setprioceiling, - (pthread_mutexattr_t *attr, int prioceiling)); - int _EXFUN(pthread_mutexattr_getprioceiling, - (const pthread_mutexattr_t *attr, int *prioceiling)); + int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol); + int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol); + int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling); + int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling); #endif /* _POSIX_THREAD_PRIO_INHERIT || _POSIX_THREAD_PRIO_PROTECT */ @@ -189,55 +167,46 @@ extern "C" { /* Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131 */ - int _EXFUN(pthread_mutex_setprioceiling, - (pthread_mutex_t *mutex, int prioceiling, int *old_ceiling)); - int _EXFUN(pthread_mutex_getprioceiling, - (pthread_mutex_t *mutex, int *prioceiling)); + int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling); + int pthread_mutex_getprioceiling(pthread_mutex_t *mutex, int *prioceiling); #endif /* _POSIX_THREAD_PRIO_PROTECT */ /* Thread Creation Attributes, P1003.1c/Draft 10, p, 140 */ - int _EXFUN(pthread_attr_init, (pthread_attr_t *attr)); - int _EXFUN(pthread_attr_destroy, (pthread_attr_t *attr)); - int _EXFUN(pthread_attr_getstacksize, - (const pthread_attr_t *attr, size_t *stacksize)); - int _EXFUN(pthread_attr_setstacksize, - (pthread_attr_t *attr, size_t stacksize)); - int _EXFUN(pthread_attr_getstackaddr, - (const pthread_attr_t *attr, void **stackaddr)); - int _EXFUN(pthread_attr_setstackaddr, - (pthread_attr_t *attr, void *stackaddr)); - int _EXFUN(pthread_attr_getdetachstate, - (const pthread_attr_t *attr, int *detachstate)); - int _EXFUN(pthread_attr_setdetachstate, - (pthread_attr_t *attr, int detachstate)); + int pthread_attr_init(pthread_attr_t *attr); + int pthread_attr_destroy(pthread_attr_t *attr); + int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); + int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); + int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr); + int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); + int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); + int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); /* Thread Creation, P1003.1c/Draft 10, p. 144 */ - int _EXFUN(pthread_create, - (pthread_t *thread, const pthread_attr_t *attr, - void * (*start_routine)(void *), void *arg)); + int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg); /* Wait for Thread Termination, P1003.1c/Draft 10, p. 147 */ - int _EXFUN(pthread_join, (pthread_t thread, void **value_ptr)); + int pthread_join(pthread_t thread, void **value_ptr); /* Detaching a Thread, P1003.1c/Draft 10, p. 149 */ - int _EXFUN(pthread_detach, (pthread_t thread)); + int pthread_detach(pthread_t thread); /* Thread Termination, p1003.1c/Draft 10, p. 150 */ - void _EXFUN(pthread_exit, (void *value_ptr)); + void pthread_exit(void *value_ptr); /* Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX */ - pthread_t _EXFUN(pthread_self, (void)); + pthread_t pthread_self(void); /* Compare Thread IDs, p1003.1c/Draft 10, p. 153 */ - int _EXFUN(pthread_equal, (pthread_t t1, pthread_t t2)); + int pthread_equal(pthread_t t1, pthread_t t2); /* Dynamic Package Initialization */ @@ -249,22 +218,20 @@ extern "C" { #define PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */ - int _EXFUN(pthread_once, - (pthread_once_t *once_control, void (*init_routine)(void))); + int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); /* Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 */ - int _EXFUN(pthread_key_create, - (pthread_key_t *key, void (*destructor)(void *))); + int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); /* Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 */ - int _EXFUN(pthread_setspecific, (pthread_key_t key, const void *value)); - void * _EXFUN(pthread_getspecific, (pthread_key_t key)); + int pthread_setspecific(pthread_key_t key, const void *value); + void *pthread_getspecific(pthread_key_t key); /* Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167 */ - int _EXFUN(pthread_key_delete, (pthread_key_t key)); + int pthread_key_delete(pthread_key_t key); /* Execution of a Thread, P1003.1c/Draft 10, p. 181 */ @@ -276,33 +243,30 @@ extern "C" { #define PTHREAD_CANCELED ((void *) -1) - int _EXFUN(pthread_cancel, (pthread_t thread)); + int pthread_cancel(pthread_t thread); /* Setting Cancelability State, P1003.1c/Draft 10, p. 183 */ - int _EXFUN(pthread_setcancelstate, (int state, int *oldstate)); - int _EXFUN(pthread_setcanceltype, (int type, int *oldtype)); - void _EXFUN(pthread_testcancel, (void)); + int pthread_setcancelstate(int state, int *oldstate); + int pthread_setcanceltype(int type, int *oldtype); + void pthread_testcancel(void); /* Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184 */ - void _EXFUN(pthread_cleanup_push, (void (*routine)(void *), void *arg)); - void _EXFUN(pthread_cleanup_pop, (int execute)); + void pthread_cleanup_push(void (*routine)(void *), void *arg); + void pthread_cleanup_pop(int execute); #if defined(_POSIX_THREAD_CPUTIME) /* Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58 */ - int _EXFUN(pthread_getcpuclockid, - (pthread_t thread_id, clockid_t *clock_id)); + int pthread_getcpuclockid(pthread_t thread_id, clockid_t *clock_id); /* CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59 */ - int _EXFUN(pthread_attr_setcputime, - (pthread_attr_t *attr, int clock_allowed)); + int pthread_attr_setcputime(pthread_attr_t *attr, int clock_allowed); - int _EXFUN(pthread_attr_getcputime, - (pthread_attr_t *attr, int *clock_allowed)); + int pthread_attr_getcputime(pthread_attr_t *attr, int *clock_allowed); #endif /* defined(_POSIX_THREAD_CPUTIME) */ diff --git a/include/sys/_types.h b/include/sys/_types.h index 69cb8d0..82a3859 100644 --- a/include/sys/_types.h +++ b/include/sys/_types.h @@ -15,6 +15,7 @@ #ifndef __off_t_defined /** \brief File offset type. */ typedef long _off_t; +typedef _off_t __off_t; #endif #ifndef __dev_t_defined @@ -83,6 +84,63 @@ typedef __newlib_recursive_lock_t _flock_t; typedef void *_iconv_t; #endif +#ifndef __blkcnt_t_defined +typedef long __blkcnt_t; +#endif + +#ifndef __blksize_t_defined +typedef long __blksize_t; +#endif + +#ifndef __fsblkcnt_t_defined +typedef unsigned long long __fsblkcnt_t; +#endif + +#ifndef __fsfilcnt_t_defined +typedef unsigned long __fsfilcnt_t; +#endif + +#ifndef __id_t_defined +typedef unsigned long __id_t; +#endif + +#ifndef __ino_t_defined +typedef unsigned long __ino_t; +#endif + +#ifndef __pid_t_defined +typedef int __pid_t; +#endif + +#ifndef __key_t_defined +typedef long __key_t; +#endif + +#ifndef __mode_t_defined +typedef unsigned long __mode_t; +#endif + +typedef unsigned short __nlink_t; +typedef long __suseconds_t; /* microseconds (signed) */ +typedef unsigned long __useconds_t; /* microseconds (unsigned) */ + +#define _TIME_T_ long +typedef _TIME_T_ __time_t; + +#ifndef __clockid_t_defined +#define _CLOCKID_T_ unsigned long +#endif + +typedef _CLOCKID_T_ __clockid_t; + +#define _TIMER_T_ unsigned long +typedef _TIMER_T_ __timer_t; + +#ifndef __clock_t_defined +#define _CLOCK_T_ unsigned long /* clock() */ +#endif + +typedef _CLOCK_T_ __clock_t; // This part inserted to fix newlib brokenness. /** \brief Size of an fd_set. */ diff --git a/include/sys/select.h b/include/sys/select.h index d394d1d..7f71a67 100644 --- a/include/sys/select.h +++ b/include/sys/select.h @@ -12,7 +12,7 @@ as directed by the POSIX 2008 standard (aka The Open Group Base Specifications Issue 7). Currently the functionality defined herein only really works for sockets, and that is likely how it will stay for some time. - + \author Lawrence Sebald */ @@ -24,11 +24,45 @@ __BEGIN_DECLS +#include <newlib.h> + +#if __NEWLIB__ > 2 || (__NEWLIB__ == 2 && __NEWLIB_MINOR__ > 2) +#include <sys/_timeval.h> +#else #include <time.h> #include <sys/time.h> +#endif + +/* Newlib used to define fd_set and friends in <sys/types.h>, but at some point + that stopped being the case... This should tell us whether we need to define + it here or not... */ +#ifndef _SYS_TYPES_FD_SET + +#define _SYS_TYPES_FD_SET + +#ifndef FD_SETSIZE +/* This matches fs.h. */ +#define FD_SETSIZE 1024 +#endif + +#define NFDBITS 32 + +typedef struct fd_set { + unsigned long fds_bits[FD_SETSIZE / NFDBITS]; +} fd_set; ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-12 06:37:46
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 1c39674de761329d9794e9cee0a9eabfbe4beb53 (commit) via e68d629fed95e4548ca467a0b3ccd8a71d829478 (commit) via bfac3f6ea7bcb01fe6a9d8af93cb1c83e2c70311 (commit) from 7c1c0eab47af5cec0008872ef1971674f282d0e6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1c39674de761329d9794e9cee0a9eabfbe4beb53 Merge: 7c1c0ea e68d629 Author: Lawrence Sebald <ljs...@us...> Date: Sun Jan 12 01:37:20 2020 -0500 Merge pull request #21 from andressbarajas/master Fixed ability to save VMU game to VMU and be playable. Includes an example as well. commit e68d629fed95e4548ca467a0b3ccd8a71d829478 Author: Andy <and...@gm...> Date: Sat Jan 11 22:20:53 2020 -0800 Added documentation to example commit bfac3f6ea7bcb01fe6a9d8af93cb1c83e2c70311 Author: Andy <and...@gm...> Date: Sat Jan 11 21:56:51 2020 -0800 Fixed ability to save VMU game to VMU and be playable. Also included example to show functionality. ----------------------------------------------------------------------- Summary of changes: examples/dreamcast/vmu/Makefile | 5 +- .../dreamcast/vmu/{vmu_pkg => vmu_game}/Makefile | 10 +- examples/dreamcast/vmu/vmu_game/README | 2 + examples/dreamcast/vmu/vmu_game/romdisk/TETRIS.VMS | Bin 0 -> 3584 bytes examples/dreamcast/vmu/vmu_game/tetris.s | 1339 ++++++++++++++++++++ .../vmu/{vmu_pkg/vmu.c => vmu_game/vmu_game.c} | 68 +- kernel/arch/dreamcast/fs/vmufs.c | 2 +- 7 files changed, 1377 insertions(+), 49 deletions(-) copy examples/dreamcast/vmu/{vmu_pkg => vmu_game}/Makefile (90%) create mode 100644 examples/dreamcast/vmu/vmu_game/README create mode 100644 examples/dreamcast/vmu/vmu_game/romdisk/TETRIS.VMS create mode 100644 examples/dreamcast/vmu/vmu_game/tetris.s copy examples/dreamcast/vmu/{vmu_pkg/vmu.c => vmu_game/vmu_game.c} (58%) diff --git a/examples/dreamcast/vmu/Makefile b/examples/dreamcast/vmu/Makefile index fff77c3..86f568f 100644 --- a/examples/dreamcast/vmu/Makefile +++ b/examples/dreamcast/vmu/Makefile @@ -6,11 +6,14 @@ all: $(KOS_MAKE) -C vmu_pkg + $(KOS_MAKE) -C vmu_game clean: $(KOS_MAKE) -C vmu_pkg clean - + $(KOS_MAKE) -C vmu_game clean + dist: $(KOS_MAKE) -C vmu_pkg dist + $(KOS_MAKE) -C vmu_game dist diff --git a/examples/dreamcast/vmu/vmu_pkg/Makefile b/examples/dreamcast/vmu/vmu_game/Makefile similarity index 90% copy from examples/dreamcast/vmu/vmu_pkg/Makefile copy to examples/dreamcast/vmu/vmu_game/Makefile index 3d2a1ce..90c8d67 100644 --- a/examples/dreamcast/vmu/vmu_pkg/Makefile +++ b/examples/dreamcast/vmu/vmu_game/Makefile @@ -1,13 +1,13 @@ # -# vmu_pkg test program -# (c)2002 Dan Potter +# vmu_game test program +# (c)2020 BBHoodsta # # Put the filename of the output binary here -TARGET = vmu.elf +TARGET = vmu_game.elf # List all of your C files here, but change the extension to ".o" -OBJS = vmu.o +OBJS = vmu_game.o all: rm-elf $(TARGET) @@ -36,7 +36,7 @@ romdisk.o: romdisk.img run: $(TARGET) $(KOS_LOADER) $(TARGET) -dist: +dist: $(TARGET) rm -f $(OBJS) romdisk.o romdisk.img $(KOS_STRIP) $(TARGET) diff --git a/examples/dreamcast/vmu/vmu_game/README b/examples/dreamcast/vmu/vmu_game/README new file mode 100644 index 0000000..181cac6 --- /dev/null +++ b/examples/dreamcast/vmu/vmu_game/README @@ -0,0 +1,2 @@ +TETRIS.VMS was programmed by Marcus Comstedt. tetris.s is the source code. +http://mc.pp.se/dc/sw.html \ No newline at end of file diff --git a/examples/dreamcast/vmu/vmu_game/romdisk/TETRIS.VMS b/examples/dreamcast/vmu/vmu_game/romdisk/TETRIS.VMS new file mode 100644 index 0000000..b12b890 Binary files /dev/null and b/examples/dreamcast/vmu/vmu_game/romdisk/TETRIS.VMS differ diff --git a/examples/dreamcast/vmu/vmu_game/tetris.s b/examples/dreamcast/vmu/vmu_game/tetris.s new file mode 100644 index 0000000..aa08cfb --- /dev/null +++ b/examples/dreamcast/vmu/vmu_game/tetris.s @@ -0,0 +1,1339 @@ + + + ;; + ;; tetris.s + ;; + ;; version 1.3 + ;; + ;; by <ma...@id...> + ;; + ;; Need aslc86k v1.6+ to assemble this. + ;; + + + .include "sfr.i" + + + ;; Game variables + +piece_x = $30 ; X position of current piece (0-10) +piece_y = $31 ; Y position of current piece (0-18) +piece_n = $32 ; shape number of current piece (0-6) +piece_r = $33 ; rotation of current piece (0-3) +piece_i0 = $34 ; left half bitmap for current piece +piece_i1 = $35 ; right half bitmap for current piece +gotkeys = $36 ; keys currently being pressed +time = $37 ; time until piece falls down one step +speed = $38 ; current game speed +scorelo = $39 ; low byte of player score +scorehi = $3a ; high byte of player score +keyinhib = $3b ; keys to inhibit at next scan +seed = $3c ; random seed + +hitmap = $3e ; - $69 ; obstacle presence map, 2 bytes/line, + ; 22 lines + + + ;; Reset and interrupt vectors + + .org 0 + + jmpf start + + .org $3 + + jmp nop_irq + + .org $b + + jmp nop_irq + + .org $13 + + jmp nop_irq + + .org $1b + + jmp t1int + + .org $23 + + jmp nop_irq + + .org $2b + + jmp nop_irq + + .org $33 + + jmp nop_irq + + .org $3b + + jmp nop_irq + + .org $43 + + jmp nop_irq + + .org $4b + + clr1 p3int,0 + clr1 p3int,1 +nop_irq: + reti + + + .org $130 + +t1int: + push ie + clr1 ie,7 + not1 ext,0 + jmpf t1int + pop ie + reti + + + .org $1f0 + +goodbye: + not1 ext,0 + jmpf goodbye + + + ;; Header + + .org $200 + + .byte "Tiny Tetris " + .byte "Mini VMU Tetris by marcus " + + ;; Icon header + + .org $240 + + .word 2,10 ; Two frames + + ;; Icon palette + + .org $260 + + .word $0000, $fcfc, $f0a0, $f0f0, $fccf, $f00a, $f00f, $ffff + .word $ffff, $ffff, $ffff, $ffff, $ffff, $ffff, $ffff, $ffff + + ;; Icon + + .org $280 + + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$11,$11,$11,$11,$11,$10,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$33,$33,$31,$33,$33,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$11,$11,$11,$11,$11,$10,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$01,$33,$33,$31,$33,$33,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$44,$44,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$66,$66,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$44,$44,$44,$44,$44,$44,$44,$44,$40,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$66,$66,$64,$66,$66,$64,$66,$66,$60,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$11,$11,$11,$11,$11,$10,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$22,$22,$31,$22,$22,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$01,$33,$33,$31,$33,$33,$30,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$04,$44,$44,$41,$11,$11,$11,$11,$11,$10,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$61,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$61,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$61,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$61,$22,$22,$31,$22,$22,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$66,$66,$61,$33,$33,$31,$33,$33,$30,$00,$00,$00 + .byte $00,$00,$00,$04,$44,$44,$44,$44,$44,$44,$44,$44,$40,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$55,$55,$64,$55,$55,$64,$55,$55,$60,$00,$00,$00 + .byte $00,$00,$00,$04,$66,$66,$64,$66,$66,$64,$66,$66,$60,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + + + ;; Main program + + .org $680 + +start: + clr1 ie,7 + mov #$a1,ocr + mov #$09,mcr + mov #$80,vccr + clr1 p3int,0 + clr1 p1,7 + mov #$ff,p3 + + clr1 psw,1 ; Get random seed from current minute and + ld $1c ; second system variables + xor $1d + set1 psw,1 + st seed + + set1 ie,7 + + call clrscr + + mov #<introscreen,trl + mov #>introscreen,trh + call setscr + +waitstart: + call getkeys + and #$30 + bnz waitstart + + mov #<mainscreen,trl + mov #>mainscreen,trh + call setscr + mov #0,acc + st scorelo + st scorehi + call addscore + call init_hitmap + mov #100,speed + mov #0,keyinhib + +newpiece: + mov #5,piece_x + mov #0,piece_y + call random + st c + mov #0,acc + mov #7,b + div + ld b + st piece_n + mov #0,piece_r + ld speed + st time + + call getpiece + call checkpiece + bnz gameover + call drawpiece + +gameloop: + call kcontrol + bnz fall + dbnz time,gameloop +fall: + ld speed + st time + ld piece_y + be #18,bottom + inc piece_y + call checkpiece + dec piece_y + bnz bottom + call drawpiece + inc piece_y + call drawpiece + br gameloop +bottom: + mov #4,acc + call addscore + call etchpiece + call checklines + br newpiece + +gameover: + mov #<go_sign,trl + mov #>go_sign,trh + call show_go + br waitstart + + +kcontrol: + call getkeys + push acc + or keyinhib + st gotkeys + pop acc + xor #$ff + and #$30 + st keyinhib + + bp gotkeys,2,noleft + ld piece_x + bz noleft + + dec piece_x + call checkpiece + inc piece_x + bnz noleft + call drawpiece + dec piece_x + call drawpiece + +noleft: + bp gotkeys,3,noright + ld piece_x + be #10,noright + + inc piece_x + call checkpiece + dec piece_x + bnz noright + call drawpiece + inc piece_x + call drawpiece + +noright: + bp gotkeys,4,norot + + push piece_r + push piece_i0 + push piece_i1 + ld piece_r + inc acc + and #3 + st piece_r + call getpiece + call checkpiece + pop piece_i1 + pop piece_i0 + bnz norot0 + pop acc + call drawpiece + call getpiece + call drawpiece + push piece_r +norot0: pop piece_r +norot: mov #0,acc + bp gotkeys,1,nodown + inc acc +nodown: ret + + + +getkeys: + bp p7,0,quit + ld p3 + bn acc,6,quit + bn acc,7,sleep + ret + +quit: + jmp goodbye + +sleep: + bn p3,7,sleep ; Wait for SLEEP to be depressed + mov #0,vccr ; Blank LCD +sleepmore: + set1 pcon,0 ; Enter HALT mode + bp p7,0,quit ; Docked? + bp p3,7,sleepmore ; No SLEEP press yet + mov #$80,vccr ; Reenable LCD +waitsleepup: + bn p3,7,waitsleepup + br getkeys + + + ;; Function: addscore + ;; + ;; Adds a number to player score, and displays current score + ;; + ;; Inputs: + ;; acc = score increment + +addscore: + push acc + push b + push c + push 2 + push xbnk + add scorelo + st scorelo + st c + ld scorehi + addc #0 + st scorehi + mov #1,xbnk + call drawdig2 + mov #0,xbnk + call drawdig2 + pop xbnk + pop 2 + pop c + pop b + pop acc + ret + + + ;; Function: drawdig2 + ;; + ;; Draws two digits for the score indicator + ;; + ;; Inputs: + ;; acc,c = a 16-bit number. The two least significant + ;; digits will be displayed. + ;; xbnk = XRAM bank in which to draw the digits + ;; + ;; Outputs: + ;; acc,c = The remaining digits (i.e. input number / 100) + ;; + ;; Scratch: + ;; 2 and b will be scratched by this function + +drawdig2: + mov #$c5,2 + mov #10,b + div + call drawdig ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-12 05:26:46
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 7c1c0eab47af5cec0008872ef1971674f282d0e6 (commit) from 88f65d2022788f0301330ac8c08cdc4a76e8d806 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7c1c0eab47af5cec0008872ef1971674f282d0e6 Author: Lawrence Sebald <ljs...@us...> Date: Sun Jan 12 00:26:32 2020 -0500 Goodbye -fno-strict-aliasing. ----------------------------------------------------------------------- Summary of changes: doc/CHANGELOG | 10 ++++++---- environ_base.sh | 2 +- kernel/arch/dreamcast/hardware/pvr/pvr_misc.c | 7 ++++++- kernel/arch/dreamcast/include/dc/pvr.h | 11 +++++++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 7066b3e..cdf339f 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -5,7 +5,7 @@ versions (where they are missing from early versions, assume that they should be attributed to Dan Potter). KallistiOS version 2.1.0 ----------------------------------------------- -- *** Cleaned up generated stubs files on a make clean [Lawrence Sebald = LS] +- *** Cleaned up generated stubs files on a make clean [Lawrence Sebald == LS] - DC Added a function to detect if the program is being run on a retail Dreamcast or a Set5.xx device [LS] - DC Fixed an issue with the SIP driver that would cause programs to freeze @@ -39,7 +39,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- - DC Fixed potential race conditions between the cdrom code and g1ata [LS] - DC Fixed full sector reading of non-data CDs (thanks to SWAT for pointing out that it needed fixing) [LS] -- DC Added many new matrix/vector math-related macros [Josh Pearson = JP] +- DC Added many new matrix/vector math-related macros [Josh Pearson == JP] - *** Added libppp for dialup internet access to the addons tree [LS] - *** Added DNS resolver functions getaddrinfo() and gethostbyname() [LS] - *** Fixed a problem where poll() would deadlock if the timeout expired [LS] @@ -54,7 +54,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- scale register [LS] - DC Added an example of the PVR's cheap shadow functionality [LS] - DC Added a tool for generation of bumpmaps that was sent to the mailing list - all the way back in 2005 [Fredrik Ehnbom = FE] + all the way back in 2005 [Fredrik Ehnbom == FE] - *** Added the fs_path_append() function to append path components [LS] - *** Added a nanosleep() function to koslib by request [LS] - *** Added rewinddir() support to the VFS and serveral filesystems [LS] @@ -92,13 +92,15 @@ KallistiOS version 2.1.0 ----------------------------------------------- - DC Made it so that PVR register access is done through a volatile pointer, as it should be to ensure GCC doesn't mess with it any [LS] - DC Copy function data from maple device during hot-swap poll if already - attached [Joe Fenton = JF] + attached [Joe Fenton == JF] - DC Fixed the clobber list of several matrix-related assembly blobs. Thanks to kazade at DCEmulation for pointing out the issue [LS] - *** Added the uname() function to retrieve the current kernel version [LS] - *** Added fs_fat for SD cards and g1ata devices [LS] - *** Added thd_each() function to iterate over all current threads [LB] - *** Added dirname() and basename() functions to koslib [LS] +- DC Clean up strict aliasing rule violations and remove -fno-strict-aliasing + from the KOS_CFLAGS [mrneo240 && LS] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Dan Potter == DP] diff --git a/environ_base.sh b/environ_base.sh index 8d7378d..29bc4f7 100644 --- a/environ_base.sh +++ b/environ_base.sh @@ -30,7 +30,7 @@ export KOS_OBJCOPY="${KOS_CC_BASE}/bin/${KOS_CC_PREFIX}-objcopy" export KOS_LD="${KOS_CC_BASE}/bin/${KOS_CC_PREFIX}-ld" export KOS_RANLIB="${KOS_CC_BASE}/bin/${KOS_CC_PREFIX}-ranlib" export KOS_STRIP="${KOS_CC_BASE}/bin/${KOS_CC_PREFIX}-strip" -export KOS_CFLAGS="${KOS_CFLAGS} ${KOS_INC_PATHS} -D_arch_${KOS_ARCH} -D_arch_sub_${KOS_SUBARCH} -Wall -g -fno-builtin -fno-strict-aliasing" +export KOS_CFLAGS="${KOS_CFLAGS} ${KOS_INC_PATHS} -D_arch_${KOS_ARCH} -D_arch_sub_${KOS_SUBARCH} -Wall -g -fno-builtin" export KOS_CPPFLAGS="${KOS_CPPFLAGS} ${KOS_INC_PATHS_CPP} -fno-operator-names -fno-rtti -fno-exceptions" # Which standards modes we want to compile for diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c b/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c index 8df096e..192bef9 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c @@ -168,6 +168,10 @@ void pvr_begin_queued_render() { uint32 vert_end; int i; int bufn = pvr_state.view_target; + union { + float f; + uint32 i; + } zclip; /* Get the appropriate buffer */ tbuf = pvr_state.ta_buffers + (pvr_state.ta_target ^ 1); @@ -220,7 +224,8 @@ void pvr_begin_queued_render() { } PVR_SET(PVR_BGPLANE_CFG, vert_end); /* Bkg plane location */ - PVR_SET(PVR_BGPLANE_Z, *((uint32*)&pvr_state.zclip)); + zclip.f = pvr_state.zclip; + PVR_SET(PVR_BGPLANE_Z, zclip.i); PVR_SET(PVR_PCLIP_X, pvr_state.pclip_x); PVR_SET(PVR_PCLIP_Y, pvr_state.pclip_y); diff --git a/kernel/arch/dreamcast/include/dc/pvr.h b/kernel/arch/dreamcast/include/dc/pvr.h index c71c354..507f143 100644 --- a/kernel/arch/dreamcast/include/dc/pvr.h +++ b/kernel/arch/dreamcast/include/dc/pvr.h @@ -834,8 +834,15 @@ typedef struct { \return The packed coordinates */ static inline uint32 PVR_PACK_16BIT_UV(float u, float v) { - return (((*((uint32 *) &u)) >> 0) & 0xFFFF0000) | - (((*((uint32 *) &v)) >> 16) & 0x0000FFFF); + union { + float f; + uint32 i; + } u2, v2; + + u2.f = u; + v2.f = v; + + return (u2.i & 0xFFFF0000) | (v2.i >> 16); } /** \defgroup pvr_commands TA command values hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-12 05:01:15
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 88f65d2022788f0301330ac8c08cdc4a76e8d806 (commit) from e8e63c1c37018b83336704dc9e406dc81d1a6b3d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 88f65d2022788f0301330ac8c08cdc4a76e8d806 Author: Lawrence Sebald <ljs...@us...> Date: Sun Jan 12 00:01:01 2020 -0500 Update copyrights for 2020. ----------------------------------------------------------------------- Summary of changes: AUTHORS | 2 +- doc/CHANGELOG | 2 ++ doc/README.KOS | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index ae18700..a8b4606 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,7 +22,7 @@ please see the README.KOS file in the doc directory. Contributors list (under the normal KOS license): ------------------------------------------------- Dan Potter: 1997, 2000, 2001, 2002, 2003, 2004 -Lawrence Sebald: 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 +Lawrence Sebald: 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Sam Steele: 2004 Gil Megidish: 2002 Florian Schulze: 2002 diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 7b04182..7066b3e 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -97,6 +97,8 @@ KallistiOS version 2.1.0 ----------------------------------------------- kazade at DCEmulation for pointing out the issue [LS] - *** Added the uname() function to retrieve the current kernel version [LS] - *** Added fs_fat for SD cards and g1ata devices [LS] +- *** Added thd_each() function to iterate over all current threads [LB] +- *** Added dirname() and basename() functions to koslib [LS] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Dan Potter == DP] diff --git a/doc/README.KOS b/doc/README.KOS index 1b7e7cf..c236e96 100644 --- a/doc/README.KOS +++ b/doc/README.KOS @@ -40,10 +40,10 @@ The actual license terms begin below this line: -------------------------------------------------------------------------------- All of the documentation and software included in the KallistiOS Releases -is copyrighted (C) 1997-2019 by Dan Potter, Lawrence Sebald, and others (as +is copyrighted (C) 1997-2020 by Dan Potter, Lawrence Sebald, and others (as noted in each file). -Copyright (C) 1997-2019 KallistiOS Contributors. All rights reserved. +Copyright (C) 1997-2020 KallistiOS Contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-12 04:55:45
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via e8e63c1c37018b83336704dc9e406dc81d1a6b3d (commit) from d595361019fe103b67a4e0e3b96201f40e084dad (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e8e63c1c37018b83336704dc9e406dc81d1a6b3d Author: Lawrence Sebald <ljs...@us...> Date: Sat Jan 11 23:54:40 2020 -0500 Add dirname() and basename() functions. ----------------------------------------------------------------------- Summary of changes: include/libgen.h | 60 ++++++++++++++++++ kernel/libc/koslib/Makefile | 2 +- kernel/libc/koslib/basename.c | 129 +++++++++++++++++++++++++++++++++++++++ kernel/libc/koslib/dirname.c | 138 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 include/libgen.h create mode 100644 kernel/libc/koslib/basename.c create mode 100644 kernel/libc/koslib/dirname.c diff --git a/include/libgen.h b/include/libgen.h new file mode 100644 index 0000000..577e59e --- /dev/null +++ b/include/libgen.h @@ -0,0 +1,60 @@ +/* KallistiOS ##version## + + libgen.h + Copyright (C) 2020 Lawrence Sebald +*/ + +/** \file libgen.h + \brief Definitions for pattern matching functions. + + This file contains the definitions for the functions basename() and + dirname() as specified by the POSIX standard. How the POSIX people came + up with this filename for this stuff, I don't know. + + The GNU C library defines a slightly different version of these functions in + <string.h> instead of here. Please note that these functions, unlike the + GNU versions that are in <string.h> on Linux do modify their input values, + as POSIX allows. + + \author Lawrence Sebald +*/ + +#ifndef __LIBGEN_H +#define __LIBGEN_H + +#include <sys/cdefs.h> +__BEGIN_DECLS + +/** \brief Get the last component of a pathname. + + This function retrieves the basename from a given path. The basename of a + path is the non-directory component thereof, minus any trailing '/' + characters. This function does not attempt to perform any sort of path + resolution. + + \note This function may modify its input and the returned value may be a + pointer to part of its input. + + \param path The path to extract the basename from. + \return A pointer to the basename of the given path. +*/ +char *basename(char *path); + +/** \brief Get the parent directory of a file pathname. + + This function retrieves the name of the parent directory of the file + pathname specified. This function does not attempt to perform any sort of + path resolution to check for the existence of the specified diretory or to + resolve any symbolic links. + + \note This function may modify its input and the returned value may be a + pointer to part of its input. + + \param path The path to extract the parent directory from. + \return A pointer to the parent directory of the given path. +*/ +char *dirname(char *path); + +__END_DECLS + +#endif /* !__LIBGEN_H */ diff --git a/kernel/libc/koslib/Makefile b/kernel/libc/koslib/Makefile index 6fdc05f..03a5239 100644 --- a/kernel/libc/koslib/Makefile +++ b/kernel/libc/koslib/Makefile @@ -13,7 +13,7 @@ OBJS = abort.o byteorder.o memset2.o memset4.o memcpy2.o memcpy4.o \ telldir.o usleep.o inet_addr.o realpath.o getcwd.o chdir.o mkdir.o \ creat.o sleep.o rmdir.o rename.o inet_pton.o inet_ntop.o \ inet_ntoa.o inet_aton.o poll.o select.o symlink.o readlink.o \ - gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o + gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o basename.o dirname.o GCC_MAJORMINOR = $(basename $(KOS_GCCVER)) GCC_MAJOR = $(basename $(GCC_MAJORMINOR)) diff --git a/kernel/libc/koslib/basename.c b/kernel/libc/koslib/basename.c new file mode 100644 index 0000000..a070874 --- /dev/null +++ b/kernel/libc/koslib/basename.c @@ -0,0 +1,129 @@ +/* KallistiOS ##version## + + basename.c + Copyright (C) 2020 Lawrence Sebald + +*/ + +#include <libgen.h> + +#ifdef __BASENAME_UNIT_TEST +#ifdef basename +#undef basename +#endif + +#define basename bn +#endif + +char *basename(char *path) { + char *last = path, *i = path; + char ch; + + /* If the path is empty or NULL, return a pointer to "." */ + if(!path || !*path) + return "."; + + /* If we have a single-character path, just return it. It's probably just + a string of "/", and this simplifies the logic below. */ + if(!path[1]) + return path; + + /* Find the end of the string, keeping track of wherever we find a '/'. */ + while((ch = *i)) { + /* Is this a '/' character? */ + if(ch == '/') { + /* Look ahead. Are we at the end? */ + if(!*(i + 1)) { + /* Break out and overwrite any trailing slashes down below. */ + break; + } + + if(*(i + 1) != '/') + last = i + 1; + } + + ++i; + } + + /* Get rid of any trailing '/' characters. */ + while(i != path && *i == '/') { + *i-- = 0; + } + + return last; +} + +#ifdef __BASENAME_UNIT_TEST +#include <stdio.h> +#include <string.h> + +int main(int argc, char *argv[]) { + char buf[64], buf2[64]; + + /* Throw the test vectors from the POSIX spec at the function, with a few + extras. */ + printf("basename(NULL): '%s'\n", bn(NULL)); + + strcpy(buf, "usr"); + strcpy(buf2, "usr"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "usr/"); + strcpy(buf2, "usr/"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "usr//"); + strcpy(buf2, "usr//"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "usr/lib"); + strcpy(buf2, "usr/lib"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, ""); + strcpy(buf2, ""); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "/"); + strcpy(buf2, "/"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "//"); + strcpy(buf2, "//"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "///"); + strcpy(buf2, "///"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "/usr/"); + strcpy(buf2, "/usr/"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "/usr/lib"); + strcpy(buf2, "/usr/lib"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "/usr/lib/"); + strcpy(buf2, "/usr/lib/"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "//usr//lib//"); + strcpy(buf2, "//usr//lib//"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "//usr//lib///"); + strcpy(buf2, "//usr//lib///"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "///usr///lib///"); + strcpy(buf2, "///usr///lib///"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + strcpy(buf, "//home//dwc//test"); + strcpy(buf2, "//home//dwc//test"); + printf("basename('%s'): '%s'\n", buf, bn(buf2)); + + return 0; +} +#endif diff --git a/kernel/libc/koslib/dirname.c b/kernel/libc/koslib/dirname.c new file mode 100644 index 0000000..a78ca78 --- /dev/null +++ b/kernel/libc/koslib/dirname.c @@ -0,0 +1,138 @@ +/* KallistiOS ##version## + + dirname.c + Copyright (C) 2020 Lawrence Sebald + +*/ + +#include <libgen.h> + +#ifdef __DIRNAME_UNIT_TEST +#ifdef dirname +#undef dirname +#endif + +#define dirname dn +#endif + +char *dirname(char *path) { + char *last = path, *i = path; + char ch; + + /* If the path is empty or NULL, return a pointer to "." */ + if(!path || !*path) + return "."; + + /* Find the end of the string, keeping track of wherever we find a '/'. */ + while((ch = *i)) { + /* Is this a '/' character? */ + if(ch == '/') { + /* Look ahead. Are we at the end? */ + if(!*(i + 1)) { + /* Break out and overwrite any trailing slashes down below. */ + break; + } + + if(*(i + 1) != '/') + last = i + 1; + } + + ++i; + } + + /* Handle a few edge cases, like a string of nothing but slashes and + children of the current directory... */ + if(last == path) { + if(path[1] == '/') + return "/"; + return "."; + } + /* ... or a direct subdirectory of /. */ + else if(last == path + 1) { + return "/"; + } + + /* Get rid of any trailing '/' characters on the dirname. */ + i = last - 1; + + while(i != path && *i == '/') { + *i-- = 0; + } + + return path; +} + +#ifdef __DIRNAME_UNIT_TEST +#include <stdio.h> +#include <string.h> + +int main(int argc, char *argv[]) { + char buf[64], buf2[64]; + + /* Throw the test vectors from the POSIX spec at the function, with a few + extras. */ + printf("dirname(NULL): '%s'\n", dn(NULL)); + + strcpy(buf, "usr"); + strcpy(buf2, "usr"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "usr/"); + strcpy(buf2, "usr/"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "usr//"); + strcpy(buf2, "usr//"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "usr/lib"); + strcpy(buf2, "usr/lib"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, ""); + strcpy(buf2, ""); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "/"); + strcpy(buf2, "/"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "//"); + strcpy(buf2, "//"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "///"); + strcpy(buf2, "///"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "/usr/"); + strcpy(buf2, "/usr/"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "/usr/lib"); + strcpy(buf2, "/usr/lib"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "/usr/lib/"); + strcpy(buf2, "/usr/lib/"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "//usr//lib//"); + strcpy(buf2, "//usr//lib//"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "//usr//lib///"); + strcpy(buf2, "//usr//lib///"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "///usr///lib///"); + strcpy(buf2, "///usr///lib///"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + strcpy(buf, "//home//dwc//test"); + strcpy(buf2, "//home//dwc//test"); + printf("dirname('%s'): '%s'\n", buf, dn(buf2)); + + return 0; +} +#endif hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-11 20:35:48
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via d595361019fe103b67a4e0e3b96201f40e084dad (commit) via 60559c7b1c1675dfc9a2ba187dc5fffbe65bbb6b (commit) from 705b9e074dbb673d721eca5c42ac0f6c9bf3ad9e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d595361019fe103b67a4e0e3b96201f40e084dad Merge: 705b9e0 60559c7 Author: Lawrence Sebald <ljs...@us...> Date: Sat Jan 11 15:35:24 2020 -0500 Merge pull request #20 from Kazade/thd-each Add a thd_each function for iterating the current threads commit 60559c7b1c1675dfc9a2ba187dc5fffbe65bbb6b Author: Luke Benstead <ka...@gm...> Date: Thu Jan 9 09:31:13 2020 +0000 Add a thd_each function for iterating the current threads ----------------------------------------------------------------------- Summary of changes: include/kos/thread.h | 9 +++++++++ kernel/thread/thread.c | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/kos/thread.h b/include/kos/thread.h index 9f68190..847c070 100644 --- a/include/kos/thread.h +++ b/include/kos/thread.h @@ -530,6 +530,15 @@ int thd_join(kthread_t * thd, void **value_ptr); */ int thd_detach(kthread_t *thd); +/** \brief Iterate all threads and call the passed callback for each + + \param cb The callback to call for each thread + \param data User data to be passed to the callback + + \retval 0 On success. +*/ +int thd_each(int (*cb)(kthread_t* thd, void* user_data), void* data); + /** \brief Print a list of all threads using the given print function. \param pf The printf-like function to print with. diff --git a/kernel/thread/thread.c b/kernel/thread/thread.c index f532345..93e8788 100644 --- a/kernel/thread/thread.c +++ b/kernel/thread/thread.c @@ -90,6 +90,16 @@ static const char *thd_state_to_str(kthread_t * thd) { } } +int thd_each(int (*cb)(kthread_t* thd, void* user_data), void* data) { + kthread_t *cur; + + LIST_FOREACH(cur, &thd_list, t_list) { + cb(cur, data); + } + + return 0; +} + int thd_pslist(int (*pf)(const char *fmt, ...)) { kthread_t *cur; hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2020-01-11 20:32:01
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 705b9e074dbb673d721eca5c42ac0f6c9bf3ad9e (commit) via 9a26880ec36401fc9a8d7c9bc326e456ac9f350a (commit) from e8f838ec54b5fbf9d8ce8780cfc48b4bcbcf1b9f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 705b9e074dbb673d721eca5c42ac0f6c9bf3ad9e Merge: e8f838e 9a26880 Author: Lawrence Sebald <ljs...@us...> Date: Wed Oct 16 21:28:46 2019 -0400 Merge pull request #16 from duckinator/patch-1 [utils/dc-chain/download.sh] prefer HTTPS over FTP commit 9a26880ec36401fc9a8d7c9bc326e456ac9f350a Author: Ellen Marie Dash <th...@sm...g> Date: Wed Jul 17 10:42:46 2019 -0400 [utils/dc-chain/download.sh] prefer HTTPS over FTP Change all the FTP URLs to HTTPS for security reasons. Conveniently, all of them use the same URLs, just different protocols. :) ----------------------------------------------------------------------- Summary of changes: utils/dc-chain/download.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/utils/dc-chain/download.sh b/utils/dc-chain/download.sh index d96b28f..a915941 100755 --- a/utils/dc-chain/download.sh +++ b/utils/dc-chain/download.sh @@ -36,47 +36,47 @@ done # Download everything. if command -v wget >/dev/null 2>&1; then echo "Downloading binutils-$BINUTILS_VER..." - wget -c ftp://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.xz || exit 1 + wget -c https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.xz || exit 1 echo "Downloading GCC $GCC_VER..." - wget -c ftp://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2 || exit 1 + wget -c https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2 || exit 1 echo "Downloading Newlib $NEWLIB_VER..." - wget -c ftp://sourceware.org/pub/newlib/newlib-$NEWLIB_VER.tar.gz || exit 1 + wget -c https://sourceware.org/pub/newlib/newlib-$NEWLIB_VER.tar.gz || exit 1 if [ -n "$GMP_VER" ]; then echo "Downloading GMP $GMP_VER..." - wget -c ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-$GMP_VER.tar.bz2 || exit 1 + wget -c https://gcc.gnu.org/pub/gcc/infrastructure/gmp-$GMP_VER.tar.bz2 || exit 1 fi if [ -n "$MPFR_VER" ]; then echo "Downloading MPFR $MPFR_VER..." - wget -c ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-$MPFR_VER.tar.bz2 || exit 1 + wget -c https://gcc.gnu.org/pub/gcc/infrastructure/mpfr-$MPFR_VER.tar.bz2 || exit 1 fi if [ -n "$MPC_VER" ]; then echo "Downloading MPC $MPC_VER..." - wget -c ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-$MPC_VER.tar.gz || exit 1 + wget -c https://gcc.gnu.org/pub/gcc/infrastructure/mpc-$MPC_VER.tar.gz || exit 1 fi elif command -v curl >/dev/null 2>&1; then echo "Downloading Binutils $BINUTILS_VER..." - curl -C - -O ftp://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.xz || exit 1 + curl -C - -O https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.xz || exit 1 echo "Downloading GCC $GCC_VER..." - curl -C - -O ftp://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2 || exit 1 + curl -C - -O https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2 || exit 1 echo "Downloading Newlib $NEWLIB_VER..." - curl -C - -O ftp://sourceware.org/pub/newlib/newlib-$NEWLIB_VER.tar.gz || exit 1 + curl -C - -O https://sourceware.org/pub/newlib/newlib-$NEWLIB_VER.tar.gz || exit 1 if [ -n "$GMP_VER" ]; then echo "Downloading GMP $GMP_VER..." - curl -C - -O ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-$GMP_VER.tar.bz2 || exit 1 + curl -C - -O https://gcc.gnu.org/pub/gcc/infrastructure/gmp-$GMP_VER.tar.bz2 || exit 1 fi if [ -n "$MPFR_VER" ]; then echo "Downloading MPFR $MPFR_VER..." - curl -C - -O ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-$MPFR_VER.tar.bz2 || exit 1 + curl -C - -O https://gcc.gnu.org/pub/gcc/infrastructure/mpfr-$MPFR_VER.tar.bz2 || exit 1 fi if [ -n "$MPC_VER" ]; then echo "Downloading MPC $MPC_VER..." - curl -C - -O ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-$MPC_VER.tar.gz || exit 1 + curl -C - -O https://gcc.gnu.org/pub/gcc/infrastructure/mpc-$MPC_VER.tar.gz || exit 1 fi else echo >&2 "You must have either wget or cURL installed to use this script!" hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-09-10 01:25:33
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via e8f838ec54b5fbf9d8ce8780cfc48b4bcbcf1b9f (commit) from 030c480e9a27a58c4aa228c354d85bb15721551f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e8f838ec54b5fbf9d8ce8780cfc48b4bcbcf1b9f Author: Lawrence Sebald <ljs...@us...> Date: Mon Sep 9 21:19:39 2019 -0400 libkosfat: Fix yet more issues with handling cross-block/cluster longname entries. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index b9c744e..e71ec74 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -306,6 +306,15 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, /* The next entry should be the dentry we want (that is to say, the short name entry for this long name). */ if(i < max) { + if(cluster != cluster2) { + if(!(cl = fat_cluster_read(fs, cluster, &err))) { + dbglog(DBG_ERROR, "Error reading directory at " + "cluster %" PRIu32 ": %s\n", cluster, + strerror(err)); + return -EIO; + } + } + ent = (fat_dentry_t *)(cl + ((i + 1) << 5)); /* Make sure we got a valid short entry... */ @@ -644,6 +653,8 @@ int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, max2 = (int32_t)fs->sb.root_dir; } + i = loff >> 5; + while(!done) { if(!(buf = fat_cluster_read(fs, lcl, &err))) { dbglog(DBG_ERROR, "Error reading directory entry at cluster %" @@ -655,7 +666,7 @@ int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, /* Just go ahead and do this now to save us the trouble later... */ fat_cluster_mark_dirty(fs, lcl); - for(i = loff >> 5; i < max; ++i) { + for(; i < max; ++i) { ent = (fat_dentry_t *)(buf + (i << 5)); /* If name[0] is zero, then we've hit the end of the @@ -704,6 +715,8 @@ int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, ", offset %" PRIu32 "\n", lcl, i << 5); return -EIO; } + + i = 0; } else { ++lcl; @@ -715,6 +728,8 @@ int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, ", offset %" PRIu32 "\n", lcl, i << 5); return -EIO; } + + i = 0; } } } hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-09-09 23:22:59
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 030c480e9a27a58c4aa228c354d85bb15721551f (commit) from b5489497815305c1a174039a853aa6c61ea3a01c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 030c480e9a27a58c4aa228c354d85bb15721551f Author: Lawrence Sebald <ljs...@us...> Date: Mon Sep 9 19:22:19 2019 -0400 libkosfat: Fix longname searches that span a block/cluster. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 087da76..b9c744e 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -130,6 +130,8 @@ static int read_longname(fat_fs_t *fs, uint32_t *cluster, uint32_t *offset, fat_longname_t *lent; uint8_t *cl; + ++*offset; + while(!done) { if(!(cl = fat_cluster_read(fs, *cluster, &err))) { dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 @@ -137,7 +139,7 @@ static int read_longname(fat_fs_t *fs, uint32_t *cluster, uint32_t *offset, return -EIO; } - for(i = (*offset) + 1; i < max; ++i) { + for(i = *offset; i < max; ++i) { ent = (fat_dentry_t *)(cl + (i << 5)); /* If name[0] is zero, then we've hit the end of the directory. */ @@ -175,18 +177,24 @@ static int read_longname(fat_fs_t *fs, uint32_t *cluster, uint32_t *offset, if(!(*cluster & 0x80000000)) { *cluster = fat_read_fat(fs, *cluster, &err); - if(*cluster == 0xFFFFFFFF) + if(*cluster == 0xFFFFFFFF) { return -EIO; + } if(fat_is_eof(fs, *cluster)) done = 1; + + *offset = 0; } else { ++*cluster; *max2 -= max; - if(*max2 <= 0) + if(*max2 <= 0) { return -EIO; + } + + *offset = 0; } } @@ -198,12 +206,12 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, uint32_t *rlcl, uint32_t *rloff) { uint8_t *cl; int err, done = 0; - uint32_t i, max, skip = 0; + uint32_t i = 0, max, skip = 0; int32_t max2; fat_dentry_t *ent; fat_longname_t *lent; size_t l = strlen(fn); - uint32_t fnlen, lcl = 0, loff = 0; + uint32_t fnlen, lcl = 0, loff = 0, cluster2; /* Figure out how many directory entries there are in each cluster/block. */ if(fs->sb.fs_type == FAT_FS_FAT32 || !(cluster & 0x80000000)) { @@ -229,7 +237,8 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, return -EIO; } - for(i = 0; i < max && !done; ++i) { + for(; i < max && !done; ++i) { + cluster2 = cluster; ent = (fat_dentry_t *)(cl + (i << 5)); /* Are we skipping this entry? */ @@ -354,8 +363,12 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, return 0; } } - else + else { skip = 1; + + if(cluster2 != cluster) + break; + } } if(!(cluster & 0x80000000)) { hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-09-09 22:01:20
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via b5489497815305c1a174039a853aa6c61ea3a01c (commit) from f50f568a091da513a40c93e6a3d0c8f5020178f3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b5489497815305c1a174039a853aa6c61ea3a01c Author: Lawrence Sebald <ljs...@us...> Date: Mon Sep 9 18:00:55 2019 -0400 libkosfat: Properly point to the short entry on a long lookup. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 7d6614e..087da76 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -307,7 +307,7 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, *rv = *ent; *rcl = cluster; - *roff = (i << 5); + *roff = ((i + 1) << 5); *rlcl = lcl; *rloff = loff; hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-09-09 21:46:04
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via f50f568a091da513a40c93e6a3d0c8f5020178f3 (commit) from fb6de0708d45fc1b6596bc4f5309e32a1481da09 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f50f568a091da513a40c93e6a3d0c8f5020178f3 Author: Lawrence Sebald <ljs...@us...> Date: Mon Sep 9 17:45:10 2019 -0400 Support creating files with long names. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 427 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 405 insertions(+), 22 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index d9fb7b7..7d6614e 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -11,6 +11,7 @@ #include <stdlib.h> #include <ctype.h> #include <inttypes.h> +#include <time.h> #include "fatfs.h" #include "ucs.h" @@ -30,6 +31,24 @@ static uint16_t longname_buf[256], longname_buf2[256]; #define DOT_NAME ". " #define DOTDOT_NAME ".. " +static uint8_t fat_shortname_checksum(char fn[11]) { + uint8_t rv = fn[0]; + + /* Rotate the existing value right by 1 and add the next character... */ + rv = ((rv << 7) | (rv >> 1)) + fn[1]; + rv = ((rv << 7) | (rv >> 1)) + fn[2]; + rv = ((rv << 7) | (rv >> 1)) + fn[3]; + rv = ((rv << 7) | (rv >> 1)) + fn[4]; + rv = ((rv << 7) | (rv >> 1)) + fn[5]; + rv = ((rv << 7) | (rv >> 1)) + fn[6]; + rv = ((rv << 7) | (rv >> 1)) + fn[7]; + rv = ((rv << 7) | (rv >> 1)) + fn[8]; + rv = ((rv << 7) | (rv >> 1)) + fn[9]; + rv = ((rv << 7) | (rv >> 1)) + fn[10]; + + return rv; +} + static int fat_search_dir(fat_fs_t *fs, const char *fn, uint32_t cluster, fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff) { uint8_t *cl; @@ -274,7 +293,7 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, fat_ucs2_tolower(longname_buf, fnlen); fat_ucs2_tolower(longname_buf2, fnlen); - if(!memcmp(longname_buf, longname_buf2, fnlen)) { + if(!memcmp(longname_buf, longname_buf2, fnlen * sizeof(uint16_t))) { /* The next entry should be the dentry we want (that is to say, the short name entry for this long name). */ if(i < max) { @@ -438,6 +457,16 @@ static int is_component_short(const char *fn) { return 1; } +static int fat_find_child2(fat_fs_t *fs, const char fn[11], + fat_dentry_t *parent) { + uint32_t cl; + uint32_t rcl, roff; + fat_dentry_t tmp; + + cl = parent->cluster_low | (parent->cluster_high << 16); + return fat_search_dir(fs, fn, cl, &tmp, &rcl, &roff); +} + int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff) { @@ -758,11 +787,13 @@ int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster) { } static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, - uint32_t *roff, fat_dentry_t **rv) { + uint32_t *roff, fat_dentry_t **rv, + uint32_t num) { uint8_t *cl; int err, done = 0; - uint32_t i, j = 0, max, old; - fat_dentry_t *ent; + uint32_t i, j = 0, max, old = cluster, ct = 0; + fat_dentry_t *ent, *sent = NULL; + uint32_t scl = cluster, soff = 0; /* Figure out how many directory entries there are in each cluster/block. */ if(fs->sb.fs_type == FAT_FS_FAT32 || !(cluster & 0x80000000)) { @@ -789,21 +820,75 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, /* If name[0] is zero, then we've hit the end of the directory. */ if(ent->name[0] == FAT_ENTRY_EOD) { - *rv = ent; - *rcl = cluster; - *roff = i << 5; - return 0; + ++ct; + + /* Just because we found the end of the directory doesn't mean + that there is necessarily space (in the case of the root + directory on FAT12/FAT16). */ + if((cluster & 0x80000000)) { + if(j + num - ct >= fs->sb.root_dir) { + *rv = NULL; + return -ENOSPC; + } + } + + /* Do we have enough space left in this cluster to store the + entire dentry (long and short)? */ + if(max - i - ct >= num || (cluster & 0x80000000)) { + if(ct == 1) { + *rv = ent; + *rcl = cluster; + *roff = i << 5; + } + else { + *rv = sent; + *rcl = scl; + *roff = soff; + } + + return 0; + } + else { + /* We're gonna have to allocate another cluster to finish + off the entry... */ + if(ct == 1) { + sent = ent; + scl = cluster; + soff = i << 5; + } + + goto alloc_another; + } } /* If name[0] == 0xE5, then this entry is empty (but there might still be additional entries after it). */ else if(ent->name[0] == FAT_ENTRY_FREE) { - *rv = ent; - *rcl = cluster; - *roff = i << 5; - return 0; - } + ++ct; + + /* If this is the first entry, set up the pointers we'll need + later if this turns out to be where we store the directory + entry. */ + if(ct == 1) { + sent = ent; + scl = cluster; + soff = i << 5; + } + /* If we've got enough entries, then we can return success + at this point. */ + if(ct == num) { + *rv = sent; + *rcl = scl; + *roff = soff; + return 0; + } + } /* Just ignore anything else... */ + else { + /* Reset the counter, because we've broken the chain of free + entries. */ + ct = 0; + } } if(!(cluster & 0x80000000)) { @@ -829,6 +914,7 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, for the directory (and it's not the end of the FAT12/FAT16 root). Attempt to allocate a new cluster, clear it out, and return a pointer to the beginning of it. */ +alloc_another: if((j = fat_allocate_cluster(fs, &err)) == FAT_INVALID_CLUSTER) { dbglog(DBG_ERROR, "Error allocating directory cluster: %s\n", strerror(err)); @@ -847,16 +933,26 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, /* Clear the new block and return a pointer to the beginning of it. */ if(!(cl = fat_cluster_clear(fs, j, &err))) { + /* Deallocate the cluster we just allocated. */ fat_write_fat(fs, j, 0); + /* This will get properly truncated for FAT12/FAT16. */ fat_write_fat(fs, old, 0x0FFFFFFF); *rv = NULL; return err; } - *rv = (fat_dentry_t *)cl; - *rcl = j; - *roff = 0; + if(ct == 0) { + *rv = (fat_dentry_t *)cl; + *rcl = j; + *roff = 0; + } + else { + *rv = sent; + *rcl = scl; + *roff = soff; + } + return 0; } @@ -897,6 +993,250 @@ inline void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], fill_timestamp(tmv, &dent->adate, NULL, NULL); } +static int create_shortname(fat_fs_t *fs, const char *fn, size_t fn_len, + char out[11], fat_dentry_t *parent) { + char *fnc; + char denorm[13] = { 0 }; + size_t i, j = 0, k = 0; + int has_ext = 0, last_period = -1, found_char = 0, tail = 0, done = 0; + + if(!(fnc = (char *)malloc(fn_len + 1))) + return -ENOMEM; + + /* Convert our copy to uppercase. */ + for(i = 0; i < fn_len;) { + /* Skip non-usable characters. */ + if(fn[i] <= ' ') { + ++i; + } + /* These should've already been caught. */ + else if(fn[i] == '*' || fn[i] == ':' || fn[i] == '/' || fn[i] == '\\' || + fn[i] == '|' || fn[i] == '"' || fn[i] == '?' || fn[i] == '<' || + fn[i] == '>') { + free(fnc); + return -EILSEQ; + } + /* Convert characters that can't be used in a short name to '_'. */ + else if(fn[i] == '+' || fn[i] == ',' || fn[i] == ';' || fn[i] == '[' || + fn[i] == ']' || fn[i] == '=') { + fnc[j++] = '_'; + found_char = 1; + ++i; + + if(has_ext == 1) + has_ext = 2; + } + else if(fn[i] == '.') { + if(found_char) { + has_ext = 1; + last_period = j; + fnc[j++] = '.'; + } + ++i; + } + /* Convert other normal ASCII to uppercase. */ + else if((uint8_t)fn[i] <= 0x7F) { + fnc[j++] = toupper((int)fn[i++]); + found_char = 1; + + if(has_ext == 1) + has_ext = 2; + } + /* Do we have a 2 byte UTF-8 sequence? */ + else if((fn[i] & 0xE0) == 0xC0) { + fnc[j++] = '_'; + i += 2; + found_char = 1; + + if(has_ext == 1) + has_ext = 2; + } + /* Do we have a 3 UTF-8 byte sequence? */ + else if((fn[i] & 0xF0) == 0xE0) { + fnc[j++] = '_'; + i += 3; + found_char = 1; + + if(has_ext == 1) + has_ext = 2; + } + /* 4 byte UTF-8 sequences can't be encoded as UCS-2. */ + else { + free(fnc); + return -EILSEQ; + } + } + + /* Terminate the end of the copied string. */ + fnc[j] = 0; + + /* Now we create the basis name. */ + for(i = 0; k < 8 && i < j && i < (size_t)last_period; ++i) { + if(fnc[i] != '.') + denorm[k++] = fnc[i]; + } + + if(has_ext) { + denorm[k++] = '.'; + + for(i = 0; i < 3 && i + last_period + 1 < j; ++i) { + denorm[k++] = fnc[i + last_period + 1]; + } + } + + /* We're done with this now. */ + free(fnc); + + /* Next up is generating a numeric tail and seeingif the file already + exists in the directory. */ + normalize_shortname(denorm, out); + + while(!done) { + ++tail; + + if(tail < 10) { + out[6] = '~'; + out[7] = '0' + tail; + } + else if(tail < 100) { + out[5] = '~'; + out[6] = '0' + (tail / 10); + out[7] = '0' + (tail % 10); + } + /* God help us if we ever really get below that one above... */ + else if(tail < 1000) { + out[4] = '~'; + out[5] = '0' + (tail / 100); + out[6] = '0' + ((tail / 10) % 10); + out[7] = '0' + (tail % 10); + } + else if(tail < 10000) { + out[3] = '~'; + out[4] = '0' + (tail / 1000); + out[5] = '0' + ((tail / 100) % 10); + out[6] = '0' + ((tail / 10) % 10); + out[7] = '0' + (tail % 10); + } + else if(tail < 100000) { + out[2] = '~'; + out[3] = '0' + (tail / 10000); + out[4] = '0' + ((tail / 1000) % 10); + out[5] = '0' + ((tail / 100) % 10); + out[6] = '0' + ((tail / 10) % 10); + out[7] = '0' + (tail % 10); + } + else if(tail < 1000000) { + out[1] = '~'; + out[2] = '0' + (tail / 100000); + out[3] = '0' + ((tail / 10000) % 10); + out[4] = '0' + ((tail / 1000) % 10); + out[5] = '0' + ((tail / 100) % 10); + out[6] = '0' + ((tail / 10) % 10); + out[7] = '0' + (tail % 10); + } + else { + /* This really should never happen... There's not really a valid + way for this to ever happen... */ + return -ENOSPC; + } + + /* See if the filename exists that we're trying to use. */ + if(fat_find_child2(fs, out, parent) == -ENOENT) { + done = 1; + } + } + + return 0; +} + +int fat_add_long_entry(fat_fs_t *fs, char sn[11], uint32_t dents, + uint8_t attr, uint32_t cluster, uint32_t *rcl, + uint32_t *roff, uint32_t rlcl, uint32_t rloff, + uint8_t cs) { + fat_longname_t *ent; + fat_dentry_t *ent2; + int pos = (dents - 1) * 13, done = 0, err = 0; + uint32_t i, j = dents, old; + size_t max; + uint8_t *cl; + + /* Figure out how many directory entries there are in each cluster/block. */ + if(fs->sb.fs_type == FAT_FS_FAT32 || !(rlcl & 0x80000000)) { + /* Either we're working with a regular directory or we're working with + the root directory on FAT32 (which is the same as a normal + directory). We care about the number of entries per cluster. */ + max = (fs->sb.bytes_per_sector * fs->sb.sectors_per_cluster); + } + else { + /* We're working with the root directory on FAT12/FAT16, so we need to + look at the number of entries per sector. */ + max = fs->sb.bytes_per_sector; + } + + while(!done) { + if(!(cl = fat_cluster_read(fs, rlcl, &err))) { + dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 + ": %s\n", cluster, strerror(err)); + return -EIO; + } + + /* Save some trouble later... */ + fat_cluster_mark_dirty(fs, rlcl); + + /* Start building the long name directory entries from the end of the + name to the start... */ + for(i = rloff; i < max && j; i += 32, --j, pos -= 13) { + ent = (fat_longname_t *)(cl + i); + + memset(ent, 0, sizeof(fat_longname_t)); + ent->attr = FAT_ATTR_LONG_NAME; + ent->checksum = cs; + if(j == dents) + ent->order = FAT_ORDER_LAST | dents; + else + ent->order = j; + + memcpy(ent->name1, &longname_buf2[pos], 10); + memcpy(ent->name2, &longname_buf2[pos + 5], 12); + memcpy(ent->name3, &longname_buf2[pos + 11], 4); + } + + /* Did we finish with the long entry with space left to spare in the + current block/cluster? If so, drop the short name here. Otherwise, + we'll loop back around and hit this code on the next block/cluster + pass... */ + if(!j && i < max) { + ent2 = (fat_dentry_t *)(cl + i); + + /* Fill it in. */ + fat_add_raw_dentry(ent2, sn, attr, cluster); + done = 1; + *rcl = rlcl; + *roff = i; + } + + if(!done && !(rlcl & 0x80000000)) { + old = rlcl; + rlcl = fat_read_fat(fs, old, &err); + if(rlcl == 0xFFFFFFFF) + return -err; + + if(fat_is_eof(fs, rlcl)) + done = 1; + } + else { + ++rlcl; + + if(j >= fs->sb.root_dir) + return -ENOSPC; + } + + rloff = 0; + } + + return 0; +} + int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, uint8_t attr, uint32_t cluster, uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff) { @@ -904,26 +1244,69 @@ int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, int err; uint32_t cl; char comp[11]; + size_t len, len2; + int dents; + uint8_t cs; + + cl = parent->cluster_low | (parent->cluster_high << 16); - /* XXXX: For now, this only supports short entries... */ if(is_component_short(fn)) { normalize_shortname(fn, comp); - cl = parent->cluster_low | (parent->cluster_high << 16); - if((err = fat_get_free_dentry(fs, cl, rcl, roff, &dent)) < 0) - return -err; + if((err = fat_get_free_dentry(fs, cl, rcl, roff, &dent, 1)) < 0) + return err; /* Fill it in. */ fat_add_raw_dentry(dent, comp, attr, cluster); - /* Clean up... */ + /* Clean up. */ *rlcl = 0; *rloff = 0; fat_cluster_mark_dirty(fs, *rcl); return 0; } else { - return -ENAMETOOLONG; + /* Not exact, but good enough. */ + if((len2 = strlen(fn)) > 255) + return -ENAMETOOLONG; + + /* Convert the filename to UCS-2 first. */ + if(fat_utf8_to_ucs2(longname_buf2, (const uint8_t *)fn, 256, + strlen(fn)) < 0) { + return -EILSEQ; + } + + /* Figure out how long it is in UCS-2 codepoints. */ + len = fat_strlen_ucs2(longname_buf2); + + /* Figure out how many directory entries we're gonna need. */ + dents = len / 13; + + /* Make things easier later... */ + if(len % 13) { + ++dents; + memset(longname_buf2 + len, 0, 13 * sizeof(uint16_t)); + } + + /* Come up with the short name the file will have. */ ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-17 20:21:48
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via fb6de0708d45fc1b6596bc4f5309e32a1481da09 (commit) via 5032bac3efb7aa1eb5f37550487115a4ab0588ae (commit) via e6e4877006f933af83e2401553351fc463539531 (commit) via c0fa8d521ebde8f39a03d62d512bc4aff40fda46 (commit) via 3cbaec9a513952e6d4d50d6aa1b3fe7e36f870f5 (commit) via 3b4584c7f0b25998873e8a8ac332641e932be009 (commit) via 68cc1711e02ab3e957b23299737bd5fa8e46ea59 (commit) via ff3f2c180ee3648decea48ea55dcee2d66462bdb (commit) via 14022525ff129b26bf25dd9c832bdf4c2a3dcdca (commit) via 5625983562f6bd8107c70204842f9f70c89499e5 (commit) from 5a91f9882c3252cae3af66768522791f8568363e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit fb6de0708d45fc1b6596bc4f5309e32a1481da09 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 16:19:31 2019 -0400 libkosfat: Enable read/write support. Please note that there are still a few restrictions on write support: 1. New files/directories can only be created with short (8.3) names. 2. Rename support isn't yet present. Other than that, I think everything should be (hopefully) working. Please test and report any issues that arise! commit 5032bac3efb7aa1eb5f37550487115a4ab0588ae Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 16:16:23 2019 -0400 libkosfat: Make mkdir return -1 properly on error, not some positive errno value. commit e6e4877006f933af83e2401553351fc463539531 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 16:12:57 2019 -0400 libkosfat: When searching for a child entry by short name, it helps if we pass the normalized short name, not the original string. This bug had the fun effect of allowing mkdir to make multiple of the same directory... commit c0fa8d521ebde8f39a03d62d512bc4aff40fda46 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 15:36:01 2019 -0400 libkosfat: Update the dentry on open if opened with O_TRUNC. commit 3cbaec9a513952e6d4d50d6aa1b3fe7e36f870f5 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 15:33:02 2019 -0400 libkosfat: Fix dentry cluster number for files in root directory and write dentries immediately on write. commit 3b4584c7f0b25998873e8a8ac332641e932be009 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 15:08:47 2019 -0400 libkosfat: Fix timestamps to they aren't 70 years in the future. commit 68cc1711e02ab3e957b23299737bd5fa8e46ea59 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 15:08:03 2019 -0400 libkosfat: It would help if we could actually create files/directories in the root of a FAT fs... commit ff3f2c180ee3648decea48ea55dcee2d66462bdb Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 14:24:34 2019 -0400 libkosfat: Make sure long file names completely match, not just mostly match. commit 14022525ff129b26bf25dd9c832bdf4c2a3dcdca Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 14:13:17 2019 -0400 libkosfat: Don't add a dot to short names that don't have an extension. commit 5625983562f6bd8107c70204842f9f70c89499e5 Author: Lawrence Sebald <ljs...@us...> Date: Sat Aug 17 14:02:33 2019 -0400 libkosfat: Fix a bug with reads failing after seeks. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 10 +++---- addons/libkosfat/fs_fat.c | 71 +++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index d45b2ea..d9fb7b7 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -257,7 +257,7 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, /* Now, is the filename length *actually* right? */ fnlen += fat_strlen_ucs2(longname_buf + fnlen); - if(l > fnlen) { + if(l != fnlen) { skip = (lent->order & 0x3F); continue; } @@ -450,7 +450,7 @@ int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, if(is_component_short(fnc)) { normalize_shortname(fnc, comp); - err = fat_search_dir(fs, fnc, cl, rv, rcl, roff); + err = fat_search_dir(fs, comp, cl, rv, rcl, roff); *rlcl = 0; *rloff = 0; } @@ -518,8 +518,6 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, } tok = strtok_r(NULL, "/", &tmp); - cl = cur.cluster_low | (cur.cluster_high << 16); - while(tok) { /* Make sure what we're looking at is a directory... */ @@ -528,6 +526,8 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, goto out; } + cl = cur.cluster_low | (cur.cluster_high << 16); + if(is_component_short(tok)) { normalize_shortname(tok, comp); lcl = loff = 0; @@ -863,7 +863,7 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, static inline void fill_timestamp(struct tm *now, uint16_t *date, uint16_t *ts, uint8_t *tenth) { /* The MS-DOS epoch is January 1, 1980, not January 1, 1970... */ - *date = ((now->tm_year - 10) & 0x7f) << 9; + *date = ((now->tm_year - 80) & 0x7f) << 9; *date |= (now->tm_mon + 1) << 5; *date |= now->tm_mday; diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index c1a05e2..f6815b9 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -7,6 +7,7 @@ #include <time.h> #include <errno.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> @@ -78,9 +79,7 @@ static int fat_create_entry(fat_fs_t *fs, const char *fn, uint8_t attr, /* Figure out where the new directory's name starts in the string... */ newdir_fn = strrchr(parent_fn, '/'); - if(newdir_fn == parent_fn || !newdir_fn) { - /* If it's at the beginning, or non-existent, then the user is trying - to mkdir the root directory, which obviously already exists. */ + if(!newdir_fn) { free(parent_fn); return -EEXIST; } @@ -151,6 +150,8 @@ static int advance_cluster(fat_fs_t *fs, int fd, uint32_t order, int write) { and advance forward. */ clo = 0; cl = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); + fh[fd].cluster = cl; + fh[fd].cluster_order = clo; } /* At this point, we're definitely moving forward, if at all... */ @@ -168,6 +169,7 @@ static int advance_cluster(fat_fs_t *fs, int fd, uint32_t order, int write) { if(!write) { fh[fd].cluster = cl2; fh[fd].cluster_order = clo; + fh[fd].mode &= ~0x80000000; return -EDOM; } else { @@ -194,10 +196,11 @@ static int advance_cluster(fat_fs_t *fs, int fd, uint32_t order, int write) { cl = cl2; ++clo; - fh[fd].cluster = cl; - fh[fd].cluster_order = clo; } + fh[fd].cluster = cl; + fh[fd].cluster_order = clo; + fh[fd].mode &= ~0x80000000; return 0; } @@ -320,6 +323,14 @@ static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { /* Set the size to 0. */ fat_cluster_clear(mnt->fs, cl, &rv); fh[fd].dentry.size = 0; + + if((rv = fat_update_dentry(mnt->fs, &fh[fd].dentry, + fh[fd].dentry_cluster, + fh[fd].dentry_offset)) < 0) { + errno = -rv; + mutex_unlock(&fat_mutex); + return NULL; + } } /* Fill in the rest of the handle */ @@ -338,26 +349,11 @@ created: static int fs_fat_close(void *h) { file_t fd = ((file_t)h) - 1; - int mode, rv; - fat_fs_t *fs; + int rv = 0; mutex_lock(&fat_mutex); if(fd < MAX_FAT_FILES && fh[fd].opened) { - /* If the file was open for writing, then we need to update the dentry - on the disk... */ - mode = fh[fd].mode & O_MODE_MASK; - if(mode == O_WRONLY && mode == O_RDWR) { - fs = fh[fd].fs->fs; - - if((mode = fat_update_dentry(fs, &fh[fd].dentry, - fh[fd].dentry_cluster, - fh[fd].dentry_offset)) < 0) { - rv = -1; - errno = -mode; - } - } - fh[fd].opened = 0; fh[fd].dentry_offset = fh[fd].dentry_cluster = 0; fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; @@ -431,7 +427,7 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { mutex_unlock(&fat_mutex); return 0; } - else { + else if(mode < 0) { mutex_unlock(&fat_mutex); errno = -mode; return -1; @@ -636,6 +632,7 @@ static ssize_t fs_fat_write(void *h, const void *buf, size_t cnt) { /* Is there still more to write after this cluster? */ if(cnt > bs) { memcpy(block, bbuf, bs); + fat_cluster_mark_dirty(fs, fh[fd].cluster); fh[fd].ptr += bs; cnt -= bs; bbuf += bs; @@ -663,8 +660,15 @@ static ssize_t fs_fat_write(void *h, const void *buf, size_t cnt) { /* If the file pointer is past the end of the file as recorded in its directory entry, update the directory entry with the new size. */ - if(fh[fd].ptr > fh[fd].dentry.size) { + if(fh[fd].ptr > fh[fd].dentry.size || mode == O_WRONLY) { fh[fd].dentry.size = fh[fd].ptr; + + if((err = fat_update_dentry(fs, &fh[fd].dentry, + fh[fd].dentry_cluster, + fh[fd].dentry_offset)) < 0) { + rv = -1; + errno = -err; + } } /* Update the file's modification timestamp. */ @@ -757,7 +761,7 @@ static time_t fat_time_to_stat(uint16_t date, uint16_t time) { struct tm tmv; /* The MS-DOS epoch is January 1, 1980, not January 1, 1970... */ - tmv.tm_year = (date >> 9) + 10; + tmv.tm_year = (date >> 9) + 80; tmv.tm_mon = ((date >> 5) & 0x0F) - 1; tmv.tm_mday = date & 0x1F; @@ -787,16 +791,19 @@ static void fill_stat_timestamps(const fat_dentry_t *ent, struct stat *buf) { } static void copy_shortname(fat_dentry_t *dent, char *fn) { - int i, j; + int i, j = 0; for(i = 0; i < 8 && dent->name[i] != ' '; ++i) { fn[i] = dent->name[i]; } - fn[i++] = '.'; + /* Only add a dot if there's actually an extension. */ + if(dent->name[8] != ' ') { + fn[i++] = '.'; - for(j = 0; j < 3 && dent->name[8 + j] != ' '; ++j) { - fn[i + j] = dent->name[8 + j]; + for(; j < 3 && dent->name[8 + j] != ' '; ++j) { + fn[i + j] = dent->name[8 + j]; + } } fn[i + j] = '\0'; @@ -1111,7 +1118,8 @@ static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { if((err = fat_create_entry(fs->fs, fn, FAT_ATTR_DIRECTORY, &cl, &off, &lcl, &loff, &buf, &cl2)) < 0) { mutex_unlock(&fat_mutex); - return -err; + errno = -err; + return -1; } /* Add entries for "." and ".." */ @@ -1343,11 +1351,6 @@ int fs_fat_mount(const char *mp, kos_blockdev_t *dev, uint32_t flags) { return -1; } - if((flags & FS_FAT_MOUNT_READWRITE)) { - dbglog(DBG_DEBUG, "fs_fat: Read/write mode not yet supported.\n"); - return -1; - } - mutex_lock(&fat_mutex); /* Try to initialize the filesystem */ hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-17 01:25:40
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 5a91f9882c3252cae3af66768522791f8568363e (commit) via bff9782fa17901c99b7b74e6673ff017b7ee74c1 (commit) via 1d910f2408aeb948fa3a1917522fa0fd2bce7813 (commit) via b8be3738b3cdf6caf0c94221dd8a130f0d7890c4 (commit) from e2f47e302870d7881f37604e6463e9eaff2c2221 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5a91f9882c3252cae3af66768522791f8568363e Author: Lawrence Sebald <ljs...@us...> Date: Fri Aug 16 21:23:40 2019 -0400 libkosfat: Add implementation of write. This still needs some major testing, along with the last few batches of commits... but otherwise means the last function needed now is rename. commit bff9782fa17901c99b7b74e6673ff017b7ee74c1 Author: Lawrence Sebald <ljs...@us...> Date: Fri Aug 16 21:23:04 2019 -0400 libkosfat: Add a function to update a dentry on the disk and one to update the modification time of a dentry structure. commit 1d910f2408aeb948fa3a1917522fa0fd2bce7813 Author: Lawrence Sebald <ljs...@us...> Date: Thu Aug 15 23:24:41 2019 -0400 libkosfat: Keep track of the cluster order in file descriptors. The cluster order being defined here as the 0-based cluster of the file that is being looked at at the time. The first cluster of the file being order 0, the second being order 1, etc. commit b8be3738b3cdf6caf0c94221dd8a130f0d7890c4 Author: Lawrence Sebald <ljs...@us...> Date: Wed Aug 14 22:08:24 2019 -0400 libkosfat: SEEK_END can have an offset. Respect it. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 24 ++++ addons/libkosfat/directory.h | 3 + addons/libkosfat/fs_fat.c | 302 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 287 insertions(+), 42 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 90a7f16..d45b2ea 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -942,6 +942,30 @@ int fat_get_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t off, return 0; } +void fat_update_mtime(fat_dentry_t *ent) { + time_t now = time(NULL); + struct tm *tmv; + + tmv = localtime(&now); + fill_timestamp(tmv, &ent->mdate, &ent->mtime, NULL); +} + +int fat_update_dentry(fat_fs_t *fs, fat_dentry_t *ent, uint32_t cluster, + uint32_t off) { + uint8_t *cl; + int err; + + if(!(cl = fat_cluster_read(fs, cluster, &err))) { + dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 + ": %s\n", cluster, strerror(err)); + return -EIO; + } + + memcpy(cl + off, ent, sizeof(fat_dentry_t)); + fat_cluster_mark_dirty(fs, cluster); + return 0; +} + #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent) { uint32_t cl = ent->cluster_low | (ent->cluster_high << 16); diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index ecbdac1..f04be5f 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -73,6 +73,9 @@ int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], uint8_t attr, uint32_t cluster); int fat_get_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, fat_dentry_t *rv); +int fat_update_dentry(fat_fs_t *fs, fat_dentry_t *ent, uint32_t cluster, + uint32_t off); +void fat_update_mtime(fat_dentry_t *ent); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index 42d10df..c1a05e2 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -54,6 +54,7 @@ static struct { uint32_t dentry_lcl; uint32_t dentry_loff; uint32_t cluster; + uint32_t cluster_order; int mode; uint32_t ptr; dirent_t dent; @@ -137,6 +138,69 @@ static int fat_create_entry(fat_fs_t *fs, const char *fn, uint8_t attr, return 0; } +static int advance_cluster(fat_fs_t *fs, int fd, uint32_t order, int write) { + uint32_t clo, cl, cl2; + int err; + + cl = fh[fd].cluster; + clo = fh[fd].cluster_order; + + /* Are we moving forward or backward? */ + if(clo > order) { + /* If moving backward, we have to start from the beginning of the file + and advance forward. */ + clo = 0; + cl = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); + } + + /* At this point, we're definitely moving forward, if at all... */ + while(clo < order) { + /* Read the FAT for the current cluster to see where we're going + next... */ + cl2 = fat_read_fat(fs, cl, &err); + + if(cl2 == FAT_INVALID_CLUSTER) { + return -err; + } + else if(fat_is_eof(fs, cl2)) { + /* If we've hit the EOF and we're writing, we need to allocate a new + cluster to the file. If we're reading, then return error. */ + if(!write) { + fh[fd].cluster = cl2; + fh[fd].cluster_order = clo; + return -EDOM; + } + else { + /* Allocate a new cluster */ + cl2 = fat_allocate_cluster(fs, &err); + + if(cl2 == FAT_INVALID_CLUSTER) { + return -err; + } + + /* Clear it. */ + if(!fat_cluster_clear(fs, cl2, &err)) { + fat_write_fat(fs, cl2, 0); + return -err; + } + + /* Write it to the file's FAT chain. */ + if((err = fat_write_fat(fs, cl, cl2)) < 0) { + fat_write_fat(fs, cl2, 0); + return err; + } + } + } + + cl = cl2; + ++clo; + fh[fd].cluster = cl; + fh[fd].cluster_order = clo; + } + + return 0; +} + static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { file_t fd; fs_fat_fs_t *mnt = (fs_fat_fs_t *)vfs->privdata; @@ -265,6 +329,7 @@ created: fh[fd].fs = mnt; fh[fd].cluster = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); + fh[fd].cluster_order = 0; fh[fd].opened = 1; mutex_unlock(&fat_mutex); @@ -273,17 +338,37 @@ created: static int fs_fat_close(void *h) { file_t fd = ((file_t)h) - 1; + int mode, rv; + fat_fs_t *fs; mutex_lock(&fat_mutex); - if(fd < MAX_FAT_FILES && fh[fd].mode) { + if(fd < MAX_FAT_FILES && fh[fd].opened) { + /* If the file was open for writing, then we need to update the dentry + on the disk... */ + mode = fh[fd].mode & O_MODE_MASK; + if(mode == O_WRONLY && mode == O_RDWR) { + fs = fh[fd].fs->fs; + + if((mode = fat_update_dentry(fs, &fh[fd].dentry, + fh[fd].dentry_cluster, + fh[fd].dentry_offset)) < 0) { + rv = -1; + errno = -mode; + } + } + fh[fd].opened = 0; fh[fd].dentry_offset = fh[fd].dentry_cluster = 0; fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; } + else { + rv = -1; + errno = EBADF; + } mutex_unlock(&fat_mutex); - return 0; + return rv; } static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { @@ -338,6 +423,21 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { rv = (ssize_t)cnt; bo = fh[fd].ptr & (bs - 1); + /* Have we had an intervening seek call? */ + if((fh[fd].mode & 0x80000000)) { + mode = advance_cluster(fs, fd, fh[fd].ptr / bs, 0); + + if(mode == -EDOM) { + mutex_unlock(&fat_mutex); + return 0; + } + else { + mutex_unlock(&fat_mutex); + errno = -mode; + return -1; + } + } + /* Handle the first block specially if we are offset within it. */ if(bo) { if(!(block = fat_cluster_read(fs, fh[fd].cluster, &errno))) { @@ -353,7 +453,7 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { bbuf += bs - bo; cl = fat_read_fat(fs, fh[fd].cluster, &errno); - if(cl == 0xFFFFFFFF) { + if(cl == FAT_INVALID_CLUSTER) { mutex_unlock(&fat_mutex); return -1; } @@ -364,6 +464,7 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { } fh[fd].cluster = cl; + ++fh[fd].cluster_order; } else { memcpy(bbuf, block + bo, cnt); @@ -373,12 +474,13 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { if(cnt + bo == bs) { cl = fat_read_fat(fs, fh[fd].cluster, &errno); - if(cl == 0xFFFFFFFF) { + if(cl == FAT_INVALID_CLUSTER) { mutex_unlock(&fat_mutex); return -1; } fh[fd].cluster = cl; + ++fh[fd].cluster_order; } cnt = 0; @@ -400,7 +502,7 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { bbuf += bs; cl = fat_read_fat(fs, fh[fd].cluster, &errno); - if(cl == 0xFFFFFFFF) { + if(cl == FAT_INVALID_CLUSTER) { mutex_unlock(&fat_mutex); return -1; } @@ -411,27 +513,163 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { } fh[fd].cluster = cl; + ++fh[fd].cluster_order; } else { - memcpy(bbuf, block + bo, cnt); + memcpy(bbuf, block, cnt); fh[fd].ptr += cnt; /* Did we hit the end of the cluster? */ - if(cnt + bo == bs) { + if(cnt == bs) { cl = fat_read_fat(fs, fh[fd].cluster, &errno); - if(cl == 0xFFFFFFFF) { + if(cl == FAT_INVALID_CLUSTER) { mutex_unlock(&fat_mutex); return -1; } fh[fd].cluster = cl; + ++fh[fd].cluster_order; + } + + cnt = 0; + } + } + + /* We're done, clean up and return. */ + mutex_unlock(&fat_mutex); + return rv; +} + +static ssize_t fs_fat_write(void *h, const void *buf, size_t cnt) { + file_t fd = ((file_t)h) - 1; + fat_fs_t *fs; + uint32_t bs, bo; + uint8_t *block; + uint8_t *bbuf = (uint8_t *)buf; + ssize_t rv; + int mode, err; + + mutex_lock(&fat_mutex); + + /* Check that the fd is valid */ + if(fd >= MAX_FAT_FILES || !fh[fd].opened) { + mutex_unlock(&fat_mutex); + errno = EBADF; + return -1; + } + + /* Make sure the fd is open for reading */ + mode = fh[fd].mode & O_MODE_MASK; + if(mode != O_WRONLY && mode != O_RDWR) { + mutex_unlock(&fat_mutex); + errno = EBADF; + return -1; + } + + if(!cnt) { + mutex_unlock(&fat_mutex); + return 0; + } + + fs = fh[fd].fs->fs; + bs = fat_cluster_size(fs); + rv = (ssize_t)cnt; + bo = fh[fd].ptr & (bs - 1); + + /* Have we had an intervening seek call (or a write that ended exactly on + a cluster boundary)? */ + if((fh[fd].mode & 0x80000000)) { + if((err = advance_cluster(fs, fd, fh[fd].ptr / bs, 1)) < 0) { + mutex_unlock(&fat_mutex); + errno = -err; + return -1; + } + } + + /* Are we starting our write in the middle of a block? */ + if(bo) { + if(!(block = fat_cluster_read(fs, fh[fd].cluster, &err))) { + mutex_unlock(&fat_mutex); + errno = err; + return -1; + } + + /* Are we writing past the end of this block, or not? */ + if(cnt > bs - bo) { + memcpy(block + bo, bbuf, bs - bo); + fat_cluster_mark_dirty(fs, fh[fd].cluster); + + fh[fd].ptr += bs - bo; + bbuf += bs - bo; + cnt -= bs - bo; + + if((err = advance_cluster(fs, fd, fh[fd].cluster_order + 1, + 1)) < 0) { + mutex_unlock(&fat_mutex); + errno = -err; + return -1; } + } + else { + memcpy(block + bo, bbuf, cnt); + fat_cluster_mark_dirty(fs, fh[fd].cluster); + fh[fd].ptr += cnt; + cnt = 0; + /* We don't want to advance the cluster even if we've hit the end of + the current one here, as that may extend the file unnecessarily + into a new cluster. Set the seek flag and it'll be dealt with + on the next write, if needed. */ + fh[fd].mode |= 0x80000000; + } + } + + /* While we still have more to write, do it. */ + while(cnt) { + if(!(block = fat_cluster_read(fs, fh[fd].cluster, &err))) { + mutex_unlock(&fat_mutex); + errno = err; + return -1; + } + + /* Is there still more to write after this cluster? */ + if(cnt > bs) { + memcpy(block, bbuf, bs); + fh[fd].ptr += bs; + cnt -= bs; + bbuf += bs; + + if((err = advance_cluster(fs, fd, fh[fd].cluster_order + 1, + 1)) < 0) { + mutex_unlock(&fat_mutex); + errno = -err; + return -1; + } + } + else { + memcpy(block, bbuf, cnt); + fat_cluster_mark_dirty(fs, fh[fd].cluster); + fh[fd].ptr += cnt; cnt = 0; + + /* We don't want to advance the cluster even if we've hit the end of + the current one here, as that may extend the file unnecessarily + into a new cluster. Set the seek flag and it'll be dealt with + on the next write, if needed. */ + fh[fd].mode |= 0x80000000; } } + /* If the file pointer is past the end of the file as recorded in its + directory entry, update the directory entry with the new size. */ + if(fh[fd].ptr > fh[fd].dentry.size) { + fh[fd].dentry.size = fh[fd].ptr; + } + + /* Update the file's modification timestamp. */ + fat_update_mtime(&fh[fd].dentry); + /* We're done, clean up and return. */ mutex_unlock(&fat_mutex); return rv; @@ -440,9 +678,7 @@ static ssize_t fs_fat_read(void *h, void *buf, size_t cnt) { static _off64_t fs_fat_seek64(void *h, _off64_t offset, int whence) { file_t fd = ((file_t)h) - 1; off_t rv; - uint32_t pos, tmp, bs, cl; - fat_fs_t *fs; - int err; + uint32_t pos; mutex_lock(&fat_mutex); @@ -464,7 +700,7 @@ static _off64_t fs_fat_seek64(void *h, _off64_t offset, int whence) { break; case SEEK_END: - pos = fh[fd].dentry.size; + pos = fh[fd].dentry.size + offset; break; default: @@ -473,35 +709,12 @@ static _off64_t fs_fat_seek64(void *h, _off64_t offset, int whence) { return -1; } - /* Figure out what cluster we're at... */ - fs = fh[fd].fs->fs; - bs = fat_cluster_size(fs); - cl = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); - tmp = pos; - - while(tmp >= bs) { - /* This really shouldn't happen... */ - if(fat_is_eof(fs, cl)) { - errno = EIO; - mutex_unlock(&fat_mutex); - return -1; - } - - cl = fat_read_fat(fs, cl, &err); - - if(cl == 0xFFFFFFFF) { - errno = err; - mutex_unlock(&fat_mutex); - return -1; - } - - tmp -= bs; - } - + /* Update the file pointer and set the flag so that we know that we have + done a seek. */ fh[fd].ptr = pos; - fh[fd].cluster = cl; + fh[fd].mode |= 0x80000000; - rv = (_off64_t)fh[fd].ptr; + rv = (_off64_t)pos; mutex_unlock(&fat_mutex); return rv; } @@ -677,7 +890,7 @@ static dirent_t *fs_fat_readdir(void *h) { if(fat_fs_type(fs) == FAT_FS_FAT32 || fh[fd].dentry_cluster) { cl = fat_read_fat(fs, fh[fd].cluster, &err); - if(cl == 0xFFFFFFFF) { + if(cl == FAT_INVALID_CLUSTER) { errno = err; mutex_unlock(&fat_mutex); return NULL; @@ -687,16 +900,20 @@ static dirent_t *fs_fat_readdir(void *h) { mutex_unlock(&fat_mutex); return NULL; } + + fh[fd].cluster = cl; + ++fh[fd].cluster_order; } else { /* Are we at the end of the directory? */ if((fh[fd].ptr >> 5) >= fat_rootdir_length(fs)) { - fh[fd].cluster = 0x0FFFFFF8; + fh[fd].cluster = 0x0FFFFFFF; mutex_unlock(&fat_mutex); return NULL; } ++fh[fd].cluster; + ++fh[fd].cluster_order; } } } @@ -996,6 +1213,7 @@ static int fs_fat_rewinddir(void *h) { fh[fd].ptr = 0; fh[fd].cluster = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); + fh[fd].cluster_order = 0; mutex_unlock(&fat_mutex); ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-15 01:48:42
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via e2f47e302870d7881f37604e6463e9eaff2c2221 (commit) via 8813dab3e3a95622d8ab943ba03d0b02f92a5e34 (commit) from cea7b2a4f301e2e5cc07513a8966e01db81ec569 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e2f47e302870d7881f37604e6463e9eaff2c2221 Author: Lawrence Sebald <ljs...@us...> Date: Wed Aug 14 21:47:56 2019 -0400 libkosfat: Untested file creation/truncation code. commit 8813dab3e3a95622d8ab943ba03d0b02f92a5e34 Author: Lawrence Sebald <ljs...@us...> Date: Wed Aug 14 20:32:33 2019 -0400 libkosfat: Fill in timestamps for newly created directory entries. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 43 +++++++- addons/libkosfat/directory.h | 1 + addons/libkosfat/fs_fat.c | 229 +++++++++++++++++++++++++++---------------- 3 files changed, 189 insertions(+), 84 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 0bcd5ed..90a7f16 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -860,15 +860,41 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, return 0; } +static inline void fill_timestamp(struct tm *now, uint16_t *date, + uint16_t *ts, uint8_t *tenth) { + /* The MS-DOS epoch is January 1, 1980, not January 1, 1970... */ + *date = ((now->tm_year - 10) & 0x7f) << 9; + *date |= (now->tm_mon + 1) << 5; + *date |= now->tm_mday; + + if(ts) { + *ts = now->tm_hour << 11; + *ts |= now->tm_min << 5; + *ts |= now->tm_sec >> 1; /* two-second resolution.... */ + + /* Meh, good enough. */ + if(tenth) { + *tenth = (now->tm_sec & 1) * 100; + } + } +} + inline void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], uint8_t attr, uint32_t cluster) { + time_t now = time(NULL); + struct tm *tmv; + memset(dent, 0, sizeof(fat_dentry_t)); memcpy(dent->name, shortname, 11); dent->attr = attr; dent->cluster_high = (uint16_t)(cluster >> 16); dent->cluster_low = (uint16_t)cluster; - /* XXXX: Fill in timestamps... */ + /* Fill in the timestamps... */ + tmv = localtime(&now); + fill_timestamp(tmv, &dent->cdate, &dent->ctime, &dent->ctenth); + fill_timestamp(tmv, &dent->mdate, &dent->mtime, NULL); + fill_timestamp(tmv, &dent->adate, NULL, NULL); } int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, @@ -901,6 +927,21 @@ int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, } } +int fat_get_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t off, + fat_dentry_t *rv) { + uint8_t *cl; + int err; + + if(!(cl = fat_cluster_read(fs, cluster, &err))) { + dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 + ": %s\n", cluster, strerror(err)); + return -EIO; + } + + memcpy(rv, cl + off, sizeof(fat_dentry_t)); + return 0; +} + #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent) { uint32_t cl = ent->cluster_low | (ent->cluster_high << 16); diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index 8f37d79..ecbdac1 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -72,6 +72,7 @@ int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff); void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], uint8_t attr, uint32_t cluster); +int fat_get_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, fat_dentry_t *rv); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index 7d9144c..42d10df 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -62,10 +62,86 @@ static struct { static uint16_t longname_buf[256]; +static int fat_create_entry(fat_fs_t *fs, const char *fn, uint8_t attr, + uint32_t *cl2, uint32_t *off, uint32_t *lcl, + uint32_t *loff, uint8_t **buf, uint32_t *pcl) { + char *parent_fn, *newdir_fn; + fat_dentry_t p_ent, n_ent; + int err; + uint32_t cl; + + /* Make a copy of the filename, as we're gonna split it into two... */ + if(!(parent_fn = strdup(fn))) { + return -ENOMEM; + } + + /* Figure out where the new directory's name starts in the string... */ + newdir_fn = strrchr(parent_fn, '/'); + if(newdir_fn == parent_fn || !newdir_fn) { + /* If it's at the beginning, or non-existent, then the user is trying + to mkdir the root directory, which obviously already exists. */ + free(parent_fn); + return -EEXIST; + } + + /* Split the string. */ + *newdir_fn++ = 0; + + /* Find the parent's dentry. */ + if((err = fat_find_dentry(fs, parent_fn, &p_ent, &cl, off, lcl, + loff)) < 0) { + free(parent_fn); + return err; + } + + /* Make sure the parent is actually a directory. */ + if(!(p_ent.attr & FAT_ATTR_DIRECTORY)) { + free(parent_fn); + return -ENOTDIR; + } + + /* Make sure the child doeesn't exist. */ + if((err = fat_find_child(fs, newdir_fn, &p_ent, &n_ent, &cl, off, lcl, + loff)) != -ENOENT) { + free(parent_fn); + if(!err) + err = -EEXIST; + return err; + } + + /* Allocate a cluster to store the first block of the new thing in. */ + if((cl = fat_allocate_cluster(fs, &err)) == FAT_INVALID_CLUSTER) { + free(parent_fn); + return -err; + } + + /* Clear the target cluster on the disk (well, in the cache, anyway). */ + if(!(*buf = fat_cluster_clear(fs, cl, &err))) { + /* Uh oh... Now things start becoming bad if things fail... */ + fat_erase_chain(fs, cl); + free(parent_fn); + return -err; + } + + /* Add the dentry to the parent. */ + if((err = fat_add_dentry(fs, newdir_fn, &p_ent, attr, cl, cl2, off, lcl, + loff)) < 0) { + fat_erase_chain(fs, cl); + free(parent_fn); + return err; + } + + /* Clean up, because we're done. */ + *pcl = p_ent.cluster_low | (p_ent.cluster_high << 16); + free(parent_fn); + return 0; +} + static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { file_t fd; fs_fat_fs_t *mnt = (fs_fat_fs_t *)vfs->privdata; int rv; + uint32_t cl, cl2; /* Make sure if we're going to be writing to the file that the fs is mounted read/write. */ @@ -94,7 +170,29 @@ static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { if((rv = fat_find_dentry(mnt->fs, fn, &fh[fd].dentry, &fh[fd].dentry_cluster, &fh[fd].dentry_offset, &fh[fd].dentry_lcl, &fh[fd].dentry_loff))) { - /* XXXX Handle creating files... */ + if(rv == -ENOENT) { + if((mode & O_CREAT)) { + uint32_t off, lcl, loff, pcl; + uint8_t *buf; + + if((rv = fat_create_entry(mnt->fs, fn, FAT_ATTR_ARCHIVE, + &cl, &off, &lcl, &loff, &buf, + &pcl)) < 0) { + mutex_unlock(&fat_mutex); + errno = -rv; + return NULL; + } + + /* Fill in the file descriptor... */ + fat_get_dentry(mnt->fs, cl, off, &fh[fd].dentry); + fh[fd].dentry_cluster = cl; + fh[fd].dentry_offset = off; + fh[fd].dentry_lcl = lcl; + fh[fd].dentry_loff = loff; + goto created; + } + } + mutex_unlock(&fat_mutex); errno = -rv; return NULL; @@ -118,9 +216,50 @@ static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { return NULL; } - /* XXXX: Handle truncating the file if we need to (for writing). */ + /* Handle truncating the file if we need to (for writing). */ + if((mode & (O_WRONLY | O_RDWR)) && (mode & O_TRUNC)) { + /* Read the FAT for the first cluster of the file and clear the entire + chain after that point. Then, blank the first cluster and fix up + the directory entry. */ + cl = fh[fd].dentry.cluster_low | (fh[fd].dentry.cluster_high << 16); + cl2 = fat_read_fat(mnt->fs, cl, &rv); + + if(cl2 == FAT_INVALID_CLUSTER) { + errno = rv; + fh[fd].dentry_cluster = fh[fd].dentry_offset = 0; + fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; + mutex_unlock(&fat_mutex); + return NULL; + } + else if(!fat_is_eof(mnt->fs, cl2)) { + /* Erase all but the first block. */ + if((rv = fat_erase_chain(mnt->fs, cl2)) < 0) { + /* Uh oh... this could be really bad... */ + errno = -rv; + fh[fd].dentry_cluster = fh[fd].dentry_offset = 0; + fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; + mutex_unlock(&fat_mutex); + return NULL; + } + + /* Set the first block's fat value to the end of chain marker. */ + if((rv = fat_write_fat(mnt->fs, cl, 0x0FFFFFFF)) < 0) { + /* Uh oh... this could be really bad... */ + errno = -rv; + fh[fd].dentry_cluster = fh[fd].dentry_offset = 0; + fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; + mutex_unlock(&fat_mutex); + return NULL; + } + } + + /* Set the size to 0. */ + fat_cluster_clear(mnt->fs, cl, &rv); + fh[fd].dentry.size = 0; + } /* Fill in the rest of the handle */ +created: fh[fd].mode = mode; fh[fd].ptr = 0; fh[fd].fs = mnt; @@ -739,11 +878,9 @@ static int fs_fat_stat(vfs_handler_t *vfs, const char *path, struct stat *buf, static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; - char *parent_fn, *newdir_fn; - fat_dentry_t p_ent, n_ent; int err; - uint32_t cl, off, lcl, loff, cl2; - uint8_t *buf; + uint32_t cl, off, lcl, loff, cl2 = 0; + uint8_t *buf = NULL; mutex_lock(&fat_mutex); @@ -754,94 +891,20 @@ static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { return -1; } - /* Make a copy of the filename, as we're gonna split it into two... */ - if(!(parent_fn = strdup(fn))) { - mutex_unlock(&fat_mutex); - errno = ENOMEM; - return -1; - } - - /* Figure out where the new directory's name starts in the string... */ - newdir_fn = strrchr(parent_fn, '/'); - if(newdir_fn == parent_fn || !newdir_fn) { - /* If it's at the beginning, or non-existent, then the user is trying - to mkdir the root directory, which obviously already exists. */ - mutex_unlock(&fat_mutex); - free(parent_fn); - errno = EEXIST; - return -1; - } - - /* Split the string. */ - *newdir_fn++ = 0; - - /* Find the parent's dentry. */ - if((err = fat_find_dentry(fs->fs, parent_fn, &p_ent, &cl, &off, &lcl, - &loff)) < 0) { - mutex_unlock(&fat_mutex); - free(parent_fn); - errno = -err; - return -1; - } - - /* Make sure the parent is actually a directory. */ - if(!(p_ent.attr & FAT_ATTR_DIRECTORY)) { - mutex_unlock(&fat_mutex); - free(parent_fn); - errno = ENOTDIR; - return -1; - } - - /* Make sure the child doeesn't exist. */ - if((err = fat_find_child(fs->fs, newdir_fn, &p_ent, &n_ent, &cl, &off, &lcl, - &loff)) != -ENOENT) { - mutex_unlock(&fat_mutex); - free(parent_fn); - if(err) - errno = -err; - else - errno = EEXIST; - return -1; - } - - /* Allocate a cluster to store the directory in. */ - if((cl = fat_allocate_cluster(fs->fs, &err)) == FAT_INVALID_CLUSTER) { - mutex_unlock(&fat_mutex); - free(parent_fn); - errno = err; - return -1; - } - - /* Clear the target cluster on the disk (well, in the cache, anyway). */ - if(!(buf = fat_cluster_clear(fs->fs, cl, &err))) { - /* Uh oh... Now things start becoming bad if things fail... */ - fat_erase_chain(fs->fs, cl); - mutex_unlock(&fat_mutex); - free(parent_fn); - errno = -err; - return -1; - } - - /* Add the dentry to the parent. */ - if((err = fat_add_dentry(fs->fs, newdir_fn, &p_ent, FAT_ATTR_DIRECTORY, - cl, &cl2, &off, &lcl, &loff)) < 0) { - fat_erase_chain(fs->fs, cl); + if((err = fat_create_entry(fs->fs, fn, FAT_ATTR_DIRECTORY, &cl, &off, &lcl, + &loff, &buf, &cl2)) < 0) { mutex_unlock(&fat_mutex); - free(parent_fn); - errno = -err; - return -1; + return -err; } /* Add entries for "." and ".." */ fat_add_raw_dentry((fat_dentry_t *)buf, ". ", FAT_ATTR_DIRECTORY, cl); - cl2 = p_ent.cluster_low | (p_ent.cluster_high << 16); fat_add_raw_dentry((fat_dentry_t *)(buf + sizeof(fat_dentry_t)), ".. ", FAT_ATTR_DIRECTORY, cl2); /* And we're done... Clean up. */ mutex_unlock(&fat_mutex); - free(parent_fn); return 0; } hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-14 17:13:38
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via cea7b2a4f301e2e5cc07513a8966e01db81ec569 (commit) via 4b7f4e3f05c380e6f282c973ec06bca12ef592e9 (commit) from 1dddfafba71d8532b50c31a3e30339e1856478b9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cea7b2a4f301e2e5cc07513a8966e01db81ec569 Author: Lawrence Sebald <ljs...@us...> Date: Wed Aug 14 13:02:48 2019 -0400 libkosfat: Add "." and ".." entries to new directories. commit 4b7f4e3f05c380e6f282c973ec06bca12ef592e9 Author: Lawrence Sebald <ljs...@us...> Date: Wed Aug 14 11:44:45 2019 -0400 libkosfat: fix empty directory detection to properly handle . and .. entries. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 36 +++++++++++++++++++++++++----------- addons/libkosfat/directory.h | 2 ++ addons/libkosfat/fs_fat.c | 10 +++++++++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 40a74a9..0bcd5ed 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -27,6 +27,9 @@ char *strdup(const char *); static uint16_t longname_buf[256], longname_buf2[256]; +#define DOT_NAME ". " +#define DOTDOT_NAME ".. " + static int fat_search_dir(fat_fs_t *fs, const char *fn, uint32_t cluster, fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff) { uint8_t *cl; @@ -720,8 +723,15 @@ int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster) { continue; } - /* If we find a valid short entry, the directory is not empty. Bail - out now. */ + /* There's only two valid entries we can have in an empty directory, + "." and "..". */ + if(!memcmp(ent->name, DOT_NAME, 11) || + !memcmp(ent->name, DOTDOT_NAME, 11)) { + continue; + } + + /* If we find a valid short entry, other than "." or "..", then + the directory is not empty. Return failure. */ return 0; } @@ -850,6 +860,17 @@ static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, return 0; } +inline void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], + uint8_t attr, uint32_t cluster) { + memset(dent, 0, sizeof(fat_dentry_t)); + memcpy(dent->name, shortname, 11); + dent->attr = attr; + dent->cluster_high = (uint16_t)(cluster >> 16); + dent->cluster_low = (uint16_t)cluster; + + /* XXXX: Fill in timestamps... */ +} + int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, uint8_t attr, uint32_t cluster, uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff) { @@ -866,15 +887,8 @@ int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, if((err = fat_get_free_dentry(fs, cl, rcl, roff, &dent)) < 0) return -err; - /* Clear it. */ - memset(dent, 0, sizeof(fat_dentry_t)); - - /* Fill in what we care about. */ - memcpy(dent->name, comp, 11); - dent->attr = attr; - dent->cluster_high = (uint16_t)(cluster >> 16); - dent->cluster_low = (uint16_t)cluster; - /* XXXX: Fill in timestamps... */ + /* Fill it in. */ + fat_add_raw_dentry(dent, comp, attr, cluster); /* Clean up... */ *rlcl = 0; diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index 3e45929..8f37d79 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -70,6 +70,8 @@ int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster); int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, uint8_t attr, uint32_t cluster, uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff); +void fat_add_raw_dentry(fat_dentry_t *dent, const char shortname[11], + uint8_t attr, uint32_t cluster); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index a019888..7d9144c 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -743,6 +743,7 @@ static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { fat_dentry_t p_ent, n_ent; int err; uint32_t cl, off, lcl, loff, cl2; + uint8_t *buf; mutex_lock(&fat_mutex); @@ -812,7 +813,7 @@ static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { } /* Clear the target cluster on the disk (well, in the cache, anyway). */ - if(!(fat_cluster_clear(fs->fs, cl, &err))) { + if(!(buf = fat_cluster_clear(fs->fs, cl, &err))) { /* Uh oh... Now things start becoming bad if things fail... */ fat_erase_chain(fs->fs, cl); mutex_unlock(&fat_mutex); @@ -831,6 +832,13 @@ static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { return -1; } + /* Add entries for "." and ".." */ + fat_add_raw_dentry((fat_dentry_t *)buf, ". ", FAT_ATTR_DIRECTORY, + cl); + cl2 = p_ent.cluster_low | (p_ent.cluster_high << 16); + fat_add_raw_dentry((fat_dentry_t *)(buf + sizeof(fat_dentry_t)), + ".. ", FAT_ATTR_DIRECTORY, cl2); + /* And we're done... Clean up. */ mutex_unlock(&fat_mutex); free(parent_fn); hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-14 02:06:03
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 1dddfafba71d8532b50c31a3e30339e1856478b9 (commit) from 1b79175ac39ec0d7e66c6416ce6c6842fc380b3c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1dddfafba71d8532b50c31a3e30339e1856478b9 Author: Lawrence Sebald <ljs...@us...> Date: Tue Aug 13 22:03:01 2019 -0400 libkosfat: Add initial implementation of mkdir. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 140 +++++++++++++++++++++++++++++++++++++++++++ addons/libkosfat/directory.h | 3 + addons/libkosfat/fatfs.c | 42 +++++++++++++ addons/libkosfat/fatfs.h | 1 + addons/libkosfat/fs_fat.c | 106 +++++++++++++++++++++++++++++++- 5 files changed, 289 insertions(+), 3 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 6c10782..40a74a9 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -747,6 +747,146 @@ int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster) { return 1; } +static int fat_get_free_dentry(fat_fs_t *fs, uint32_t cluster, uint32_t *rcl, + uint32_t *roff, fat_dentry_t **rv) { + uint8_t *cl; + int err, done = 0; + uint32_t i, j = 0, max, old; + fat_dentry_t *ent; + + /* Figure out how many directory entries there are in each cluster/block. */ + if(fs->sb.fs_type == FAT_FS_FAT32 || !(cluster & 0x80000000)) { + /* Either we're working with a regular directory or we're working with + the root directory on FAT32 (which is the same as a normal + directory). We care about the number of entries per cluster. */ + max = (fs->sb.bytes_per_sector * fs->sb.sectors_per_cluster) >> 5; + } + else { + /* We're working with the root directory on FAT12/FAT16, so we need to + look at the number of entries per sector. */ + max = fs->sb.bytes_per_sector >> 5; + } + + while(!done) { + if(!(cl = fat_cluster_read(fs, cluster, &err))) { + dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 + ": %s\n", cluster, strerror(err)); + return -EIO; + } + + for(i = 0; i < max && !done; ++i, ++j) { + ent = (fat_dentry_t *)(cl + (i << 5)); + + /* If name[0] is zero, then we've hit the end of the directory. */ + if(ent->name[0] == FAT_ENTRY_EOD) { + *rv = ent; + *rcl = cluster; + *roff = i << 5; + return 0; + } + /* If name[0] == 0xE5, then this entry is empty (but there might + still be additional entries after it). */ + else if(ent->name[0] == FAT_ENTRY_FREE) { + *rv = ent; + *rcl = cluster; + *roff = i << 5; + return 0; + } + + /* Just ignore anything else... */ + } + + if(!(cluster & 0x80000000)) { + old = cluster; + cluster = fat_read_fat(fs, old, &err); + if(cluster == 0xFFFFFFFF) + return -err; + + if(fat_is_eof(fs, cluster)) + done = 1; + } + else { + ++cluster; + + if(j >= fs->sb.root_dir) { + *rv = NULL; + return -ENOSPC; + } + } + } + + /* If we get here, that means we've run out of space in what's allocated + for the directory (and it's not the end of the FAT12/FAT16 root). + Attempt to allocate a new cluster, clear it out, and return a pointer to + the beginning of it. */ + if((j = fat_allocate_cluster(fs, &err)) == FAT_INVALID_CLUSTER) { + dbglog(DBG_ERROR, "Error allocating directory cluster: %s\n", + strerror(err)); + *rv = NULL; + return err; + } + + /* Update the FAT chain. */ + if((err = fat_write_fat(fs, old, j)) < 0) { + dbglog(DBG_ERROR, "Error writing fat for new allocation: %s\n", + strerror(err)); + fat_write_fat(fs, j, 0); + *rv = NULL; + return -err; + } + + /* Clear the new block and return a pointer to the beginning of it. */ + if(!(cl = fat_cluster_clear(fs, j, &err))) { + fat_write_fat(fs, j, 0); + /* This will get properly truncated for FAT12/FAT16. */ + fat_write_fat(fs, old, 0x0FFFFFFF); + *rv = NULL; + return err; + } + + *rv = (fat_dentry_t *)cl; + *rcl = j; + *roff = 0; + return 0; +} + +int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, + uint8_t attr, uint32_t cluster, uint32_t *rcl, + uint32_t *roff, uint32_t *rlcl, uint32_t *rloff) { + fat_dentry_t *dent; + int err; + uint32_t cl; + char comp[11]; + + /* XXXX: For now, this only supports short entries... */ + if(is_component_short(fn)) { + normalize_shortname(fn, comp); + cl = parent->cluster_low | (parent->cluster_high << 16); + + if((err = fat_get_free_dentry(fs, cl, rcl, roff, &dent)) < 0) + return -err; + + /* Clear it. */ + memset(dent, 0, sizeof(fat_dentry_t)); + + /* Fill in what we care about. */ + memcpy(dent->name, comp, 11); + dent->attr = attr; + dent->cluster_high = (uint16_t)(cluster >> 16); + dent->cluster_low = (uint16_t)cluster; + /* XXXX: Fill in timestamps... */ + + /* Clean up... */ + *rlcl = 0; + *rloff = 0; + fat_cluster_mark_dirty(fs, *rcl); + return 0; + } + else { + return -ENAMETOOLONG; + } +} + #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent) { uint32_t cl = ent->cluster_low | (ent->cluster_high << 16); diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index 1ce9d71..3e45929 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -67,6 +67,9 @@ int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, uint32_t loff); int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster); +int fat_add_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, + uint8_t attr, uint32_t cluster, uint32_t *rcl, + uint32_t *roff, uint32_t *rlcl, uint32_t *rloff); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fatfs.c b/addons/libkosfat/fatfs.c index 83700df..3e45880 100644 --- a/addons/libkosfat/fatfs.c +++ b/addons/libkosfat/fatfs.c @@ -81,6 +81,48 @@ out: return rv; } +uint8_t *fat_cluster_clear(fat_fs_t *fs, uint32_t cl, int *err) { + int i; + uint8_t *rv; + fat_cache_t **cache = fs->bcache; + + /* Look through the cache from the most recently used to the least recently + used entry. */ + for(i = fs->cache_size - 1; i >= 0; --i) { + if(cache[i]->block == cl && cache[i]->flags) { + rv = cache[i]->data; + make_mru(fs, cache, i); + goto out; + } + } + + /* If we didn't get anything, did we end up with an invalid entry or do we + need to boot someone out? */ + if(i < 0) { + i = 0; + + /* Make sure that if the block is dirty, we write it back out. */ + if(cache[0]->flags & FAT_CACHE_FLAG_DIRTY) { + if(fat_cluster_write_nc(fs, cache[0]->block, cache[0]->data)) { + /* XXXX: Uh oh... */ + *err = EIO; + return NULL; + } + } + } + + /* Don't bother reading the cluster from disk, since we're erasing it + anyway... */ + cache[i]->block = cl; + cache[i]->flags = FAT_CACHE_FLAG_VALID | FAT_CACHE_FLAG_DIRTY; + rv = cache[i]->data; + make_mru(fs, cache, i); + +out: + memset(rv, 0, fs->sb.bytes_per_sector * fs->sb.sectors_per_cluster); + return rv; +} + int fat_cluster_read_nc(fat_fs_t *fs, uint32_t cluster, uint8_t *rv) { int fs_per_block = (int)fs->sb.sectors_per_cluster; diff --git a/addons/libkosfat/fatfs.h b/addons/libkosfat/fatfs.h index dfad699..3ade2d0 100644 --- a/addons/libkosfat/fatfs.h +++ b/addons/libkosfat/fatfs.h @@ -85,6 +85,7 @@ void fat_fs_shutdown(fat_fs_t *fs); int fat_cluster_read_nc(fat_fs_t *fs, uint32_t cluster, uint8_t *rv); uint8_t *fat_cluster_read(fat_fs_t *fs, uint32_t cluster, int *err); +uint8_t *fat_cluster_clear(fat_fs_t *fs, uint32_t cl, int *err); int fat_cluster_write_nc(fat_fs_t *fs, uint32_t cluster, const uint8_t *blk); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index 3abed6e..a019888 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -614,7 +614,7 @@ static int fs_fat_fcntl(void *h, int cmd, va_list ap) { return rv; } -static int fs_fat_unlink(struct vfs_handler *vfs, const char *fn) { +static int fs_fat_unlink(vfs_handler_t *vfs, const char *fn) { fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; fat_dentry_t ent; int irv = 0, err; @@ -737,7 +737,107 @@ static int fs_fat_stat(vfs_handler_t *vfs, const char *path, struct stat *buf, return irv; } -static int fs_fat_rmdir(struct vfs_handler *vfs, const char *fn) { +static int fs_fat_mkdir(vfs_handler_t *vfs, const char *fn) { + fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; + char *parent_fn, *newdir_fn; + fat_dentry_t p_ent, n_ent; + int err; + uint32_t cl, off, lcl, loff, cl2; + + mutex_lock(&fat_mutex); + + /* Make sure the filesystem isn't mounted read-only. */ + if(!(fs->mount_flags & FS_FAT_MOUNT_READWRITE)) { + mutex_unlock(&fat_mutex); + errno = EROFS; + return -1; + } + + /* Make a copy of the filename, as we're gonna split it into two... */ + if(!(parent_fn = strdup(fn))) { + mutex_unlock(&fat_mutex); + errno = ENOMEM; + return -1; + } + + /* Figure out where the new directory's name starts in the string... */ + newdir_fn = strrchr(parent_fn, '/'); + if(newdir_fn == parent_fn || !newdir_fn) { + /* If it's at the beginning, or non-existent, then the user is trying + to mkdir the root directory, which obviously already exists. */ + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = EEXIST; + return -1; + } + + /* Split the string. */ + *newdir_fn++ = 0; + + /* Find the parent's dentry. */ + if((err = fat_find_dentry(fs->fs, parent_fn, &p_ent, &cl, &off, &lcl, + &loff)) < 0) { + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = -err; + return -1; + } + + /* Make sure the parent is actually a directory. */ + if(!(p_ent.attr & FAT_ATTR_DIRECTORY)) { + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = ENOTDIR; + return -1; + } + + /* Make sure the child doeesn't exist. */ + if((err = fat_find_child(fs->fs, newdir_fn, &p_ent, &n_ent, &cl, &off, &lcl, + &loff)) != -ENOENT) { + mutex_unlock(&fat_mutex); + free(parent_fn); + if(err) + errno = -err; + else + errno = EEXIST; + return -1; + } + + /* Allocate a cluster to store the directory in. */ + if((cl = fat_allocate_cluster(fs->fs, &err)) == FAT_INVALID_CLUSTER) { + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = err; + return -1; + } + + /* Clear the target cluster on the disk (well, in the cache, anyway). */ + if(!(fat_cluster_clear(fs->fs, cl, &err))) { + /* Uh oh... Now things start becoming bad if things fail... */ + fat_erase_chain(fs->fs, cl); + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = -err; + return -1; + } + + /* Add the dentry to the parent. */ + if((err = fat_add_dentry(fs->fs, newdir_fn, &p_ent, FAT_ATTR_DIRECTORY, + cl, &cl2, &off, &lcl, &loff)) < 0) { + fat_erase_chain(fs->fs, cl); + mutex_unlock(&fat_mutex); + free(parent_fn); + errno = -err; + return -1; + } + + /* And we're done... Clean up. */ + mutex_unlock(&fat_mutex); + free(parent_fn); + return 0; +} + +static int fs_fat_rmdir(vfs_handler_t *vfs, const char *fn) { fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; fat_dentry_t ent; int irv = 0, err; @@ -923,7 +1023,7 @@ static vfs_handler_t vh = { NULL, /* mmap */ NULL, /* complete */ fs_fat_stat, /* stat */ - NULL, /* mkdir */ + fs_fat_mkdir, /* mkdir */ fs_fat_rmdir, /* rmdir */ fs_fat_fcntl, /* fcntl */ NULL, /* poll */ hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-13 00:37:30
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 1b79175ac39ec0d7e66c6416ce6c6842fc380b3c (commit) from 74382b5cdcaebd7bfba63d4d8823f077760c037d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1b79175ac39ec0d7e66c6416ce6c6842fc380b3c Author: Lawrence Sebald <ljs...@us...> Date: Mon Aug 12 20:36:19 2019 -0400 libkosfat: Implement unlink and rmdir. Note: These aren't usable at the moment, as it is not possible to mount the filesystem read/write yet. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 188 +++++++++++++++++++++++++++++++++++++++++++ addons/libkosfat/directory.h | 3 + addons/libkosfat/fs_fat.c | 132 +++++++++++++++++++++++++++++- 3 files changed, 321 insertions(+), 2 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 3d8df3d..6c10782 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -488,6 +488,8 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, *rcl = 0; *roff = 0; + *rlcl = 0; + *rloff = 0; err = 0; goto out; } @@ -559,6 +561,192 @@ out: return err; } +int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, + uint32_t loff) { + fat_dentry_t *ent; + uint8_t *buf; + uint32_t max, max2, i; + int done = 0, err; + + /* Read the cluster/block where the short name lives. */ + if(!(buf = fat_cluster_read(fs, cl, &err))) { + dbglog(DBG_ERROR, "Error reading directory entry at cluster %" PRIu32 + ", offset %" PRIu32 ": %s\n", cl, off, strerror(err)); + return -EIO; + } + + /* Mark the short entry as free. */ + ent = (fat_dentry_t *)(buf + off); + ent->name[0] = FAT_ENTRY_FREE; + + fat_cluster_mark_dirty(fs, cl); + + /* If there is a long name chain, mark it all as free too... */ + if(lcl) { + /* Figure out how many directory entries there are in each + cluster/block. */ + if(fs->sb.fs_type == FAT_FS_FAT32 || !(lcl & 0x80000000)) { + /* Either we're working with a regular directory or we're working + with the root directory on FAT32 (which is the same as a normal + directory). We care about the number of entries per cluster. */ + max = (fs->sb.bytes_per_sector * fs->sb.sectors_per_cluster) >> 5; + max2 = 0xFFFFFFFF; + } + else { + /* We're working with the root directory on FAT12/FAT16, so we need + to look at the number of entries per sector. */ + max = fs->sb.bytes_per_sector >> 5; + max2 = (int32_t)fs->sb.root_dir; + } + + while(!done) { + if(!(buf = fat_cluster_read(fs, lcl, &err))) { + dbglog(DBG_ERROR, "Error reading directory entry at cluster %" + PRIu32 ", offst %" PRIu32 ": %s\n", lcl, loff, + strerror(err)); + return -EIO; + } + + /* Just go ahead and do this now to save us the trouble later... */ + fat_cluster_mark_dirty(fs, lcl); + + for(i = loff >> 5; i < max; ++i) { + ent = (fat_dentry_t *)(buf + (i << 5)); + + /* If name[0] is zero, then we've hit the end of the + directory. */ + if(ent->name[0] == FAT_ENTRY_EOD) { + dbglog(DBG_ERROR, "End of directory hit while reading long " + "name entry for deletion at cluster %" PRIu32 + ", offset %" PRIu32 "\n", lcl, i << 5); + return -EIO; + } + /* If name[0] == 0xE5, then this entry is empty. We previously + marked the short name entry (which should be right after the + long name chain) as empty, so this means we have finished + deleting the long name. */ + else if(ent->name[0] == FAT_ENTRY_FREE) { + done = 1; + break; + } + /* We shouldn't have any entries that aren't long names in the + middle of a long name chain... */ + else if(!FAT_IS_LONG_NAME(ent)) { + dbglog(DBG_ERROR, "Invalid dentry hit while reading long " + "name entry for deletion at cluster %" PRIu32 + ", offset %" PRIu32 "\n", lcl, i << 5); + return -EIO; + } + + /* Mark the entry as empty and move on... */ + ent->name[0] = FAT_ENTRY_FREE; + } + + /* Move onto the next cluster. */ + if(!(lcl & 0x80000000)) { + lcl = fat_read_fat(fs, lcl, &err); + if(lcl == 0xFFFFFFFF) { + dbglog(DBG_ERROR, "Invalid FAT value hit while reading long" + " name entry for deletion at cluster %" PRIu32 + ", offset %" PRIu32 "\n", lcl, i << 5); + return -err; + } + + /* This shouldn't happen either... */ + if(fat_is_eof(fs, lcl)) { + dbglog(DBG_ERROR, "End of directory hit while reading long " + "name entry for deletion at cluster %" PRIu32 + ", offset %" PRIu32 "\n", lcl, i << 5); + return -EIO; + } + } + else { + ++lcl; + max2 -= max; + + if(max2 <= 0) { + dbglog(DBG_ERROR, "End of directory hit while reading long " + "name entry for deletion at cluster %" PRIu32 + ", offset %" PRIu32 "\n", lcl, i << 5); + return -EIO; + } + } + } + } + + return 0; +} + +int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster) { + uint8_t *cl; + int err, done = 0; + uint32_t i, j = 0, max; + fat_dentry_t *ent; + + /* Figure out how many directory entries there are in each cluster/block. */ + if(fs->sb.fs_type == FAT_FS_FAT32 || !(cluster & 0x80000000)) { + /* Either we're working with a regular directory or we're working with + the root directory on FAT32 (which is the same as a normal + directory). We care about the number of entries per cluster. */ + max = (fs->sb.bytes_per_sector * fs->sb.sectors_per_cluster) >> 5; + } + else { + /* We're working with the root directory on FAT12/FAT16, so we need to + look at the number of entries per sector. */ + max = fs->sb.bytes_per_sector >> 5; + } + + while(!done) { + if(!(cl = fat_cluster_read(fs, cluster, &err))) { + dbglog(DBG_ERROR, "Error reading directory at cluster %" PRIu32 + ": %s\n", cluster, strerror(err)); + return -EIO; + } + + for(i = 0; i < max && !done; ++i, ++j) { + ent = (fat_dentry_t *)(cl + (i << 5)); + + /* If name[0] is zero, then we've hit the end of the directory. */ + if(ent->name[0] == FAT_ENTRY_EOD) { + return 1; + } + /* If name[0] == 0xE5, then this entry is empty (but there might + still be additional entries after it). */ + else if(ent->name[0] == FAT_ENTRY_FREE) { + continue; + } + /* Ignore long name entries. */ + else if(FAT_IS_LONG_NAME(ent)) { + continue; + } + + /* If we find a valid short entry, the directory is not empty. Bail + out now. */ + return 0; + } + + if(!(cluster & 0x80000000)) { + cluster = fat_read_fat(fs, cluster, &err); + if(cluster == 0xFFFFFFFF) + return -err; + + if(fat_is_eof(fs, cluster)) + done = 1; + } + else { + ++cluster; + + if(j >= fs->sb.root_dir) + done = 1; + } + } + + /* If we get here, we hit the end of chain marker in the FAT (or the max + entries in the root dir of FAT12/FAT16). Thus, there's nothing in the + directory or we would have bailed out before now. */ + return 1; +} + #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent) { uint32_t cl = ent->cluster_low | (ent->cluster_high << 16); diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index c69df88..1ce9d71 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -64,6 +64,9 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, uint32_t *rloff); +int fat_erase_dentry(fat_fs_t *fs, uint32_t cl, uint32_t off, uint32_t lcl, + uint32_t loff); +int fat_is_dir_empty(fat_fs_t *fs, uint32_t cluster); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index 9e22ca7..3abed6e 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -614,6 +614,62 @@ static int fs_fat_fcntl(void *h, int cmd, va_list ap) { return rv; } +static int fs_fat_unlink(struct vfs_handler *vfs, const char *fn) { + fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; + fat_dentry_t ent; + int irv = 0, err; + uint32_t cl, off, lcl, loff, cluster; + + mutex_lock(&fat_mutex); + + /* Make sure the filesystem isn't mounted read-only. */ + if(!(fs->mount_flags & FS_FAT_MOUNT_READWRITE)) { + mutex_unlock(&fat_mutex); + errno = EROFS; + return -1; + } + + /* Find the object in question */ + if((irv = fat_find_dentry(fs->fs, fn, &ent, &cl, &off, &lcl, &loff)) < 0) { + mutex_unlock(&fat_mutex); + errno = -irv; + return -1; + } + + /* Make sure that the user isn't trying to delete a directory. */ + if((ent.attr & FAT_ATTR_DIRECTORY)) { + mutex_unlock(&fat_mutex); + errno = EISDIR; + return -1; + } + + if((ent.attr & FAT_ATTR_VOLUME_ID)) { + mutex_unlock(&fat_mutex); + errno = ENOENT; + return -1; + } + + /* First clean up the clusters of the file... */ + cluster = ent.cluster_low | (ent.cluster_high << 16); + if((err = fat_erase_chain(fs->fs, cluster))) { + /* Uh oh... This is really bad... */ + dbglog(DBG_ERROR, "fs_fat: Error erasing FAT chain for file %s\n", fn); + irv = -1; + errno = -err; + } + + /* Next, erase the directory entry (and long name, if applicable). */ + if((irv = fat_erase_dentry(fs->fs, cl, off, lcl, loff)) < 0) { + dbglog(DBG_ERROR, "fs_fat: Error erasing directory entry for file %s\n", + fn); + irv = -1; + errno = -err; + } + + mutex_unlock(&fat_mutex); + return irv; +} + static int fs_fat_stat(vfs_handler_t *vfs, const char *path, struct stat *buf, int flag) { fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; @@ -681,6 +737,78 @@ static int fs_fat_stat(vfs_handler_t *vfs, const char *path, struct stat *buf, return irv; } +static int fs_fat_rmdir(struct vfs_handler *vfs, const char *fn) { + fs_fat_fs_t *fs = (fs_fat_fs_t *)vfs->privdata; + fat_dentry_t ent; + int irv = 0, err; + uint32_t cl, off, lcl, loff, cluster; + + mutex_lock(&fat_mutex); + + /* Make sure the filesystem isn't mounted read-only. */ + if(!(fs->mount_flags & FS_FAT_MOUNT_READWRITE)) { + mutex_unlock(&fat_mutex); + errno = EROFS; + return -1; + } + + /* Find the object in question */ + if((irv = fat_find_dentry(fs->fs, fn, &ent, &cl, &off, &lcl, &loff)) < 0) { + mutex_unlock(&fat_mutex); + errno = -irv; + return -1; + } + + /* Make sure that the user isn't trying to rmdir a file. */ + if(!(ent.attr & FAT_ATTR_DIRECTORY)) { + mutex_unlock(&fat_mutex); + errno = ENOTDIR; + return -1; + } + + /* Make sure they're not trying to delete the root directory... */ + if(!cl) { + mutex_unlock(&fat_mutex); + errno = EPERM; + return -1; + } + + /* Make sure the directory is empty... */ + cluster = ent.cluster_low | (ent.cluster_high << 16); + irv = fat_is_dir_empty(fs->fs, cluster); + + if(irv < 0) { + mutex_unlock(&fat_mutex); + errno = -irv; + return -1; + } + else if(irv == 0) { + mutex_unlock(&fat_mutex); + errno = ENOTEMPTY; + return -1; + } + + /* First clean up the clusters of the directory... */ + if((err = fat_erase_chain(fs->fs, cluster))) { + /* Uh oh... This is really bad... */ + dbglog(DBG_ERROR, "fs_fat: Error erasing FAT chain for directory %s\n", + fn); + irv = -1; + errno = -err; + } + + /* Next, erase the directory entry (and long name, if applicable). */ + if((irv = fat_erase_dentry(fs->fs, cl, off, lcl, loff)) < 0) { + dbglog(DBG_ERROR, "fs_fat: Error erasing directory entry for directory " + "%s\n", fn); + irv = -1; + errno = -err; + } + + mutex_unlock(&fat_mutex); + return irv; +} + static int fs_fat_rewinddir(void *h) { file_t fd = ((file_t)h) - 1; @@ -791,12 +919,12 @@ static vfs_handler_t vh = { fs_fat_readdir, /* readdir */ NULL, /* ioctl */ NULL, /* rename */ - NULL, /* unlink */ + fs_fat_unlink, /* unlink */ NULL, /* mmap */ NULL, /* complete */ fs_fat_stat, /* stat */ NULL, /* mkdir */ - NULL, /* rmdir */ + fs_fat_rmdir, /* rmdir */ fs_fat_fcntl, /* fcntl */ NULL, /* poll */ NULL, /* link */ hooks/post-receive -- A pseudo Operating System for the Dreamcast. |
From: Lawrence S. <ljs...@us...> - 2019-08-12 21:26:45
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 74382b5cdcaebd7bfba63d4d8823f077760c037d (commit) from 0ba8ba974ee2c9dfa0fc935c74c748658ae71279 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 74382b5cdcaebd7bfba63d4d8823f077760c037d Author: Lawrence Sebald <ljs...@us...> Date: Mon Aug 12 17:25:56 2019 -0400 libkosfat: Keep track of the start of the longname entry when we keep track of dentry starting points. ----------------------------------------------------------------------- Summary of changes: addons/libkosfat/directory.c | 52 +++++++++++++++++++++++++++++++++++--------- addons/libkosfat/directory.h | 6 +++-- addons/libkosfat/fs_fat.c | 12 +++++++--- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/addons/libkosfat/directory.c b/addons/libkosfat/directory.c index 6186882..3d8df3d 100644 --- a/addons/libkosfat/directory.c +++ b/addons/libkosfat/directory.c @@ -143,7 +143,7 @@ static int read_longname(fat_fs_t *fs, uint32_t *cluster, uint32_t *offset, memcpy(&longname_buf[fnlen + 5], lent->name2, 12); memcpy(&longname_buf[fnlen + 11], lent->name3, 4); - /* XXXX: Check the checksum here. */ + /* XXXX: Calculate the checksum here. */ if((lent->order & 0x3F) == 1) { *offset = i; @@ -172,7 +172,8 @@ static int read_longname(fat_fs_t *fs, uint32_t *cluster, uint32_t *offset, } static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, - fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff) { + fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff, + uint32_t *rlcl, uint32_t *rloff) { uint8_t *cl; int err, done = 0; uint32_t i, max, skip = 0; @@ -180,7 +181,7 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, fat_dentry_t *ent; fat_longname_t *lent; size_t l = strlen(fn); - uint32_t fnlen; + uint32_t fnlen, lcl = 0, loff = 0; /* Figure out how many directory entries there are in each cluster/block. */ if(fs->sb.fs_type == FAT_FS_FAT32 || !(cluster & 0x80000000)) { @@ -249,7 +250,7 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, memcpy(&longname_buf[fnlen + 11], lent->name3, 4); longname_buf[fnlen + 14] = 0; - /* XXXX: Check the checksum here. */ + /* XXXX: Calculate the checksum here. */ /* Now, is the filename length *actually* right? */ fnlen += fat_strlen_ucs2(longname_buf + fnlen); @@ -258,6 +259,9 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, continue; } + lcl = cluster; + loff = i << 5; + /* Is this the only long name entry needed? */ if(lent->order != 0x41) { if(read_longname(fs, &cluster, &i, max, &max2)) @@ -272,9 +276,19 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, the short name entry for this long name). */ if(i < max) { ent = (fat_dentry_t *)(cl + ((i + 1) << 5)); + + /* Make sure we got a valid short entry... */ + if(ent->name[0] == FAT_ENTRY_EOD || + ent->name[0] == FAT_ENTRY_FREE) { + return -ENOENT; + } + *rv = *ent; *rcl = cluster; *roff = (i << 5); + *rlcl = lcl; + *rloff = loff; + return 0; } else { @@ -303,9 +317,18 @@ static int fat_search_long(fat_fs_t *fs, const char *fn, uint32_t cluster, } ent = (fat_dentry_t *)cl; + + /* Make sure we got a valid short entry... */ + if(ent->name[0] == FAT_ENTRY_EOD || + ent->name[0] == FAT_ENTRY_FREE) { + return -ENOENT; + } + *rv = *ent; *rcl = cluster; *roff = 0; + *rlcl = lcl; + *rloff = loff; return 0; } } @@ -413,7 +436,8 @@ static int is_component_short(const char *fn) { } int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, - fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff) { + fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff, + uint32_t *rlcl, uint32_t *rloff) { char *fnc = strdup(fn), comp[11]; uint32_t cl; int err; @@ -424,9 +448,11 @@ int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, normalize_shortname(fnc, comp); err = fat_search_dir(fs, fnc, cl, rv, rcl, roff); + *rlcl = 0; + *rloff = 0; } else { - err = fat_search_long(fs, fnc, cl, rv, rcl, roff); + err = fat_search_long(fs, fnc, cl, rv, rcl, roff, rlcl, rloff); } free(fnc); @@ -434,11 +460,12 @@ int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, } int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, - uint32_t *rcl, uint32_t *roff) { + uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, + uint32_t *rloff) { char *fnc = strdup(fn), comp[11], *tmp, *tok; int err = -ENOENT; fat_dentry_t cur; - uint32_t cl, off; + uint32_t cl, off, lcl = 0, loff = 0; /* First thing is first, tokenize the filename into components... */ tok = strtok_r(fnc, "/", &tmp); @@ -480,7 +507,8 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, goto out; } else { - if((err = fat_search_long(fs, tok, cl, &cur, &cl, &off)) < 0) + if((err = fat_search_long(fs, tok, cl, &cur, &cl, &off, &lcl, + &loff)) < 0) goto out; } @@ -497,13 +525,15 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, if(is_component_short(tok)) { normalize_shortname(tok, comp); + lcl = loff = 0; if((err = fat_search_dir(fs, comp, cl, &cur, &cl, &off)) < 0) { goto out; } } else { - if((err = fat_search_long(fs, tok, cl, &cur, &cl, &off)) < 0) + if((err = fat_search_long(fs, tok, cl, &cur, &cl, &off, &lcl, + &loff)) < 0) goto out; } @@ -521,6 +551,8 @@ int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, *rv = cur; *rcl = cl; *roff = off; + *rlcl = lcl; + *rloff = loff; out: free(fnc); diff --git a/addons/libkosfat/directory.h b/addons/libkosfat/directory.h index ccec9bb..c69df88 100644 --- a/addons/libkosfat/directory.h +++ b/addons/libkosfat/directory.h @@ -59,9 +59,11 @@ typedef struct fat_longname { #define FAT_ORDER_LAST 0x40 int fat_find_dentry(fat_fs_t *fs, const char *fn, fat_dentry_t *rv, - uint32_t *rcl, uint32_t *roff); + uint32_t *rcl, uint32_t *roff, uint32_t *rlcl, + uint32_t *rloff); int fat_find_child(fat_fs_t *fs, const char *fn, fat_dentry_t *parent, - fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff); + fat_dentry_t *rv, uint32_t *rcl, uint32_t *roff, + uint32_t *rlcl, uint32_t *rloff); #ifdef FAT_DEBUG void fat_dentry_print(const fat_dentry_t *ent); diff --git a/addons/libkosfat/fs_fat.c b/addons/libkosfat/fs_fat.c index 50adaab..9e22ca7 100644 --- a/addons/libkosfat/fs_fat.c +++ b/addons/libkosfat/fs_fat.c @@ -51,6 +51,8 @@ static struct { fat_dentry_t dentry; uint32_t dentry_cluster; uint32_t dentry_offset; + uint32_t dentry_lcl; + uint32_t dentry_loff; uint32_t cluster; int mode; uint32_t ptr; @@ -90,7 +92,8 @@ static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { /* Find the object in question... */ if((rv = fat_find_dentry(mnt->fs, fn, &fh[fd].dentry, - &fh[fd].dentry_cluster, &fh[fd].dentry_offset))) { + &fh[fd].dentry_cluster, &fh[fd].dentry_offset, + &fh[fd].dentry_lcl, &fh[fd].dentry_loff))) { /* XXXX Handle creating files... */ mutex_unlock(&fat_mutex); errno = -rv; @@ -110,6 +113,7 @@ static void *fs_fat_open(vfs_handler_t *vfs, const char *fn, int mode) { if((mode & O_DIR) && !(fh[fd].dentry.attr & FAT_ATTR_DIRECTORY)) { errno = ENOTDIR; fh[fd].dentry_cluster = fh[fd].dentry_offset = 0; + fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; mutex_unlock(&fat_mutex); return NULL; } @@ -136,6 +140,7 @@ static int fs_fat_close(void *h) { if(fd < MAX_FAT_FILES && fh[fd].mode) { fh[fd].opened = 0; fh[fd].dentry_offset = fh[fd].dentry_cluster = 0; + fh[fd].dentry_lcl = fh[fd].dentry_loff = 0; } mutex_unlock(&fat_mutex); @@ -615,14 +620,15 @@ static int fs_fat_stat(vfs_handler_t *vfs, const char *path, struct stat *buf, uint32_t sz, bs; int irv = 0; fat_dentry_t ent; - uint32_t cl, off; + uint32_t cl, off, lcl, loff; (void)flag; mutex_lock(&fat_mutex); /* Find the object in question */ - if((irv = fat_find_dentry(fs->fs, path, &ent, &cl, &off)) < 0) { + if((irv = fat_find_dentry(fs->fs, path, &ent, &cl, &off, &lcl, + &loff)) < 0) { errno = -irv; mutex_unlock(&fat_mutex); return -1; hooks/post-receive -- A pseudo Operating System for the Dreamcast. |