# HG changeset patch
# User jfp <jf.pieronne@laposte.net>
# Date 1715864547 -7200
#      Thu May 16 15:02:27 2024 +0200
# Node ID a2fa6fce86cf6a3f0fdc5505fb8d93297e3ef80b
# Parent  dfc18f05ce766ea0e6ca248cb744143c56705eda
fileqio.py: Add atrdef/fatdef argument to qio access and daccess. Fix bug with mode argument

diff --git a/python/local/ovms_module/ovms/fileqio.py b/python/local/ovms_module/ovms/fileqio.py
--- a/python/local/ovms_module/ovms/fileqio.py
+++ b/python/local/ovms_module/ovms/fileqio.py
@@ -4,6 +4,8 @@
 from ovms import iosbdef
 from ovms import fibdef
 from ovms import rms
+from ovms import fatdef
+from ovms import atrdef
 from ovms import starlet
 from ovms import stsdef
 from ovms import ast
@@ -14,6 +16,8 @@
     filename: bytes | str
     channel: int | None
     fibdesc: fibdef.FIBDESC | None
+    fat: fatdef.FAT
+    atrs: ctypes.Array[atrdef.ATR]
 
     def __init__(self, fn: str | bytes, mode: str | None = None) -> None:
         self.filename = fn
@@ -22,12 +26,8 @@
         self.fibdesc = None
 
     def _open_p1(self, mode: str | None) -> Tuple[int, fibdef.FIBDEF]:
-        if self.mode is not None:
-            self.mode = mode
-        elif mode is None:
-            self.mode = 'r'
-        else:
-            self.mode = mode
+        if mode is None:
+            mode = "r" if self.mode is None else self.mode
         dev = rms.search(self.filename)[1]
 
         ifid = rms.getrmsattr(self.filename, rms.RMSATTR_K_FID)
@@ -39,7 +39,7 @@
 
         fib = fibdef.FIBDEF()
         fib.fib_r_fid_fields = fid
-        if mode == 'w':
+        if mode == "w":
             fib.fib_l_acctl = fibdef.FIB_M_NOWRITE | fibdef.FIB_M_WRITE
         else:
             fib.fib_l_acctl = 0
@@ -68,6 +68,16 @@
         else:
             c_ast_completion = ctypes.c_uint64(ast.vms_ast_completion)
             c_ast_param = ctypes.c_uint64(id(astctxt))
+        self.fat = fatdef.FAT()
+        atr1 = atrdef.ATR()
+        atrdef.set_atr_item(
+            atr1,
+            atrdef.ATR_S_RECATTR,
+            atrdef.ATR_C_RECATTR,
+            ctypes.pointer(self.fat),
+        )
+        atr2 = atrdef.ATR()  # default fill with zeros
+        self.atrs = (atrdef.ATR * 2)(atr1, atr2)
         status = qio_call(
             efn,
             ichan,
@@ -79,29 +89,29 @@
             zero64,
             zero64,
             zero64,
-            zero64,
+            ctypes.byref(self.atrs),
             zero64,
         )
         if not stsdef.vms_status_success(status):
             starlet.dassgn(chan)
-            raise IOError(status, 'qio ACCESS error')
+            raise IOError(status, "qio ACCESS error")
         return chan, iosb
 
-    def open(self, mode: str | None = None) -> 'FILEQIO':
+    def open(self, mode: str | None = None) -> "FILEQIO":
         chan, fib = self._open_p1(mode)
         chan, iosb = self._open_p2(mode)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'iosb open error')
+            raise IOError(iosb.iosb_w_status, "iosb open error")
         self.channel = chan
         return self
 
-    async def aopen(self, mode: str | None = None) -> 'FILEQIO':
+    async def aopen(self, mode: str | None = None) -> "FILEQIO":
         astctxt = ast.AstContext()
         chan, iosb = self._open_p2(mode, astctxt)
         await ast.wait_completion(astctxt)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
             starlet.dassgn(chan)
-            raise IOError(iosb.iosb_w_status, 'iosb aopen error')
+            raise IOError(iosb.iosb_w_status, "iosb aopen error")
         self.channel = chan
         return self
 
@@ -119,7 +129,6 @@
         zero64 = ctypes.c_uint64(0)
         if astctxt is None:
             c_ast_completion = None
-            ast_ctxt = None
             c_ast_param = zero64
         else:
             c_ast_completion = ctypes.c_uint64(ast.vms_ast_completion)
@@ -135,11 +144,11 @@
             zero64,
             zero64,
             zero64,
-            zero64,
+            ctypes.byref(self.atrs),
             zero64,
         )
         if not stsdef.vms_status_success(status):
-            raise IOError(status, 'qio DEACCESS error')
+            raise IOError(status, "qio DEACCESS error")
         return iosb
 
     def close(self) -> None:
@@ -147,7 +156,7 @@
         if iosb is None:
             return
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'close error')
+            raise IOError(iosb.iosb_w_status, "close error")
         starlet.dassgn(self.channel)  # type: ignore
 
     async def aclose(self) -> None:
@@ -157,10 +166,10 @@
             return
         await ast.wait_completion(astctxt)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'aclose error')
+            raise IOError(iosb.iosb_w_status, "aclose error")
         starlet.dassgn(self.channel)  # type: ignore
 
-    def __enter__(self) -> 'FILEQIO':
+    def __enter__(self) -> "FILEQIO":
         self.open(self.mode)
         return self
 
@@ -182,15 +191,15 @@
         buff: ctypes.Array[ctypes.c_char] | None = None,
     ) -> Tuple[iosbdef.IOSB_r_io_64, ctypes.Array[ctypes.c_char]]:
         if self.channel is None or self.fibdesc is None:
-            raise ValueError('I/O operation on closed file.')
+            raise ValueError("I/O operation on closed file.")
         if buff is None:
             if sz is None:
-                raise ValueError('Both sz and buff are None')
+                raise ValueError("Both sz and buff are None")
             buff = ctypes.create_string_buffer(sz)
         elif sz is None:
             sz = len(buff)
         elif len(buff) < sz:
-            raise BufferError('len(buff) < sz')
+            raise BufferError("len(buff) < sz")
         qio_call = starlet.vms_qiow if astctxt is None else starlet.vms_qio
         efn = ctypes.c_uint32(efndef.EFN_C_ENF)
         ichan = ctypes.c_uint16(self.channel)
@@ -202,7 +211,6 @@
         csz = ctypes.c_uint64(sz)
         if astctxt is None:
             c_ast_completion = None
-            ast_ctxt = None
             c_ast_param = zero64
         else:
             c_ast_completion = ctypes.c_uint64(ast.vms_ast_completion)
@@ -222,7 +230,7 @@
             zero64,
         )
         if not stsdef.vms_status_success(status):
-            raise IOError(status, 'readvblk error')
+            raise IOError(status, "readvblk error")
         return iosb, buff
 
     def readblk(
@@ -233,7 +241,7 @@
     ) -> bytes:
         iosb, buff = self._readblk(vblk, sz, None, buff)[:2]
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'IOSB readblk error')
+            raise IOError(iosb.iosb_w_status, "IOSB readblk error")
         return buff.raw
 
     def readblk_nowait(
@@ -256,14 +264,14 @@
         iosb, buff = self._readblk(vblk, sz, astctxt, buff)
         await ast.wait_completion(astctxt)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'IOSB areadblk error')
+            raise IOError(iosb.iosb_w_status, "IOSB areadblk error")
         return buff.raw
 
     def _writeblk(
         self, buff: bytes, vblk: int, astctxt: ast.AstContext | None = None
     ) -> iosbdef.IOSB_r_io_64:
         if self.channel is None or self.fibdesc is None:
-            raise ValueError('I/O operation on closed file.')
+            raise ValueError("I/O operation on closed file.")
         qio_call = starlet.vms_qiow if astctxt is None else starlet.vms_qio
         efn = ctypes.c_uint32(efndef.EFN_C_ENF)
         ichan = ctypes.c_uint16(self.channel)
@@ -294,13 +302,13 @@
             zero64,
         )
         if not stsdef.vms_status_success(status):
-            raise IOError(status, 'writeblk error')
+            raise IOError(status, "writeblk error")
         return iosb
 
     def writeblk(self, buff: bytes, vblk: int) -> None:
         iosb = self._writeblk(buff, vblk)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'IOSB writeblk error')
+            raise IOError(iosb.iosb_w_status, "IOSB writeblk error")
 
     def writeblk_nowait(
         self, buff: bytes, vblk: int, astctxt: ast.AstContext
@@ -313,4 +321,4 @@
         iosb = self._writeblk(buff, vblk, astctxt)
         await ast.wait_completion(astctxt)
         if not stsdef.vms_status_success(iosb.iosb_w_status):
-            raise IOError(iosb.iosb_w_status, 'IOSB awriteblk error')
+            raise IOError(iosb.iosb_w_status, "IOSB awriteblk error")